Repository: mikolalysenko/mikolalysenko.github.com Branch: master Commit: a32772903845 Files: 581 Total size: 6.4 MB Directory structure: gitextract_98ry2z6h/ ├── Arrays/ │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── data_structures/ │ │ ├── linked_list.js │ │ ├── ordered_array.js │ │ └── unordered_array.js │ ├── particles.html │ ├── require.js │ └── test_cases/ │ ├── particles.js │ ├── test_construct.js │ └── test_particles.js ├── DataStructures/ │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── index.html │ ├── require.js │ ├── structures/ │ │ ├── list.js │ │ ├── pma.js │ │ ├── unordered_vector.js │ │ └── vector.js │ └── tests/ │ ├── particles.js │ └── test_particles.js ├── Downsample/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── experiment.txt │ ├── index.html │ ├── js/ │ │ ├── boxfilter.js │ │ ├── closing.js │ │ ├── marchingcubes.js │ │ ├── marchingtetrahedra.js │ │ ├── maxfilter.js │ │ ├── medianfilter.js │ │ ├── minfilter.js │ │ ├── nearestfilter.js │ │ ├── opening.js │ │ ├── perlinnoise.js │ │ ├── surfacenets.js │ │ └── testdata.js │ └── vendor/ │ ├── dsp.js │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── Isosurface/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── experiment.txt │ ├── index.html │ ├── js/ │ │ ├── benchmark.js │ │ ├── marchingcubes.js │ │ ├── marchingtetrahedra.js │ │ ├── perlinnoise.js │ │ ├── surfacenets.js │ │ └── testdata.js │ └── vendor/ │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── LevelOfDetail/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── js/ │ │ ├── boxfilter.js │ │ ├── closing.js │ │ ├── marchingcubes.js │ │ ├── marchingtetrahedra.js │ │ ├── maxfilter.js │ │ ├── medianfilter.js │ │ ├── minfilter.js │ │ ├── nearestfilter.js │ │ ├── opening.js │ │ ├── perlinnoise.js │ │ ├── surfacenets.js │ │ └── testdata.js │ └── vendor/ │ ├── dsp.js │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── MeshLife/ │ ├── bundle.js │ ├── index.html │ └── main.css ├── MeshSimplify/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── experiment.txt │ ├── index.html │ ├── js/ │ │ ├── marchingcubes.js │ │ ├── marchingtetrahedra.js │ │ ├── montecarlo.js │ │ ├── surfacenets.js │ │ ├── testdata.js │ │ └── triangle_index.js │ └── vendor/ │ ├── dsp.js │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── MinecraftMeshes/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── index.html │ ├── js/ │ │ ├── culled.js │ │ ├── greedy.js │ │ ├── stupid.js │ │ └── testdata.js │ └── vendor/ │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── MinecraftMeshes2/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── experiments.txt │ ├── index.html │ ├── js/ │ │ ├── benchmark.js │ │ ├── culled.js │ │ ├── greedy.js │ │ ├── greedy_tri.js │ │ ├── monotone.js │ │ ├── stupid.js │ │ └── testdata.js │ └── vendor/ │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── Pictures/ │ └── test_smooth.py ├── Resources/ │ ├── brep.js │ ├── glow_shell.js │ ├── lib/ │ │ └── GLOW.js │ ├── models/ │ │ ├── bunny.js │ │ ├── bunny.obj │ │ ├── convert_three.js │ │ └── teapot.js │ ├── surfacenets.js │ └── tools/ │ └── convert_obj.js ├── ShapeCarving/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── experiments.txt │ ├── index.html │ ├── js/ │ │ ├── benchmark.js │ │ ├── culled.js │ │ ├── greedy.js │ │ ├── greedy_tri.js │ │ ├── monotone.js │ │ ├── shapecarve.js │ │ ├── stupid.js │ │ └── testdata.js │ ├── jscolor/ │ │ ├── demo.html │ │ └── jscolor.js │ └── vendor/ │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── TJunctions/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── index.html │ └── vendor/ │ ├── three.js/ │ │ ├── Detector.js │ │ ├── ShaderExtras.js │ │ ├── Stats.js │ │ ├── Three.js │ │ └── postprocessing/ │ │ ├── BloomPass.js │ │ ├── DotScreenPass.js │ │ ├── EffectComposer.js │ │ ├── FilmPass.js │ │ ├── MaskPass.js │ │ ├── RenderPass.js │ │ ├── SavePass.js │ │ ├── ShaderPass.js │ │ └── TexturePass.js │ ├── threex/ │ │ ├── Makefile │ │ ├── README.md │ │ ├── THREEx.CelShader.js │ │ ├── THREEx.DeviceOrientationState.js │ │ ├── THREEx.FullScreen.js │ │ ├── THREEx.GeometryUtils.js │ │ ├── THREEx.GeometryWobble.js │ │ ├── THREEx.KeyboardState.js │ │ ├── THREEx.LogoTurtle.js │ │ ├── THREEx.PlasmaShader.js │ │ ├── THREEx.SkyMap.js │ │ ├── THREEx.WindowResize.js │ │ ├── THREEx.glCapability.js │ │ ├── THREEx.requestAnimationFrame.js │ │ ├── THREEx.screenshot.js │ │ ├── docs/ │ │ │ ├── THREEx.CelShader.html │ │ │ ├── THREEx.CubeMap.html │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.FullScreen.html │ │ │ ├── THREEx.GeometryUtils.html │ │ │ ├── THREEx.GeometryWobble.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── THREEx.LogoTurtle.html │ │ │ ├── THREEx.PlasmaShader.html │ │ │ ├── THREEx.SkyMap.html │ │ │ ├── THREEx.WindowResize.html │ │ │ ├── THREEx.glCapability.html │ │ │ ├── THREEx.requestAnimationFrame.html │ │ │ ├── THREEx.screenshot.html │ │ │ └── docco.css │ │ ├── examples/ │ │ │ ├── THREEx.DeviceOrientationState.html │ │ │ ├── THREEx.KeyboardState.html │ │ │ ├── threex.embedded/ │ │ │ │ ├── noshield-host.html │ │ │ │ ├── noshield-iframe.html │ │ │ │ ├── withshield-host.html │ │ │ │ └── withshield-iframe.html │ │ │ └── threex.fullscreen.html │ │ ├── threex.chromeWebStoreInstall.js │ │ ├── threex.embedded.js │ │ ├── threex.sparks.js │ │ └── threex.texturePoolBall.js │ └── threex.dragpancontrols.js ├── Terrain/ │ ├── MIT-LICENSE.txt │ ├── Makefile │ ├── css/ │ │ └── main.css │ ├── index.html │ ├── index.html~ │ ├── js/ │ │ ├── dualcontour.js │ │ ├── events.js │ │ ├── perlinnoise.js │ │ ├── testdata.js │ │ └── webgl.js │ └── require.js └── resume.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: Arrays/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: Arrays/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info { position : absolute; top : 10px; left : 10px; padding : 5px; z-index: 10; } #particleCanvas { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; } ================================================ FILE: Arrays/data_structures/linked_list.js ================================================ function Cell(prev, next, value) { this.prev = prev; this.next = next; this.value = value; } function List(head, tail) { this.head = head; this.tail = tail; } exports.create = function() { return new List(null, null); } exports.append = function(list, value) { var ncell = new Cell(list.tail, null, value); if(!list.head) { list.head = ncell; list.tail = ncell; } else { list.tail.next = ncell; list.tail = ncell; } } exports.insert = function(list, iter, value) { if(iter === null) { exports.append(list, value); return; } var ncell = new Cell(iter.prev, iter, value); iter.prev = ncell; if(iter.prev) { iter.prev.next = ncell; } else { list.head = ncell; } } exports.remove = function(list, iter) { if(iter.prev) { iter.prev.next = iter.next; } else { list.head = iter.next; } if(iter.next) { iter.next.prev = iter.prev; } else { list.tail = iter.prev; } } exports.read = function(list, iter) { return iter.value; } exports.begin = function(list) { return list.head; } exports.next = function(list, iter) { return iter.next; } exports.prev = function(list, iter) { return iter.prev; } exports.end = function(list) { return null; } ================================================ FILE: Arrays/data_structures/ordered_array.js ================================================ exports.create = function() { return []; } exports.insert = function(array, iter, value) { array.splice(iter, 0, value); } exports.remove = function(array, iter) { array.splice(iter, 1); } exports.append = function(array, value) { array.push(value); } exports.read = function(array, iter) { return array[iter]; } exports.begin = function(array) { return array.length-1; } exports.prev = function(array, iter) { return iter + 1; } exports.next = function(array, iter) { return iter - 1; } exports.end = function(array) { return -1; } ================================================ FILE: Arrays/data_structures/unordered_array.js ================================================ exports.create = function() { return []; } exports.insert = function(array, iter, value) { //Not supported throw new Error("Unsupported operation"); } exports.remove = function(array, iter) { array[iter] = array[array.length - 1]; array.pop(); } exports.append = function(array, value) { array.push(value); } exports.read = function(array, iter) { return array[iter]; } exports.begin = function(array) { return array.length - 1; } exports.prev = function(array, iter) { //Not supported throw new Error("Unsupported operation"); } exports.next = function(array, iter) { return iter - 1; } exports.end = function(array) { return -1; } ================================================ FILE: Arrays/particles.html ================================================ Particle Test

================================================ FILE: Arrays/require.js ================================================ // ==Closure.compiler== // @compilation_level SIMPLE_OPTIMIZATIONS // ==/Closure.compiler== // Require() 0.3.2 unstable // // Copyright 2012 Torben Schulz // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////// (function() { 'use strict'; if (window.require !== undefined) throw 'RequireException: \'require\' already defined in global scope'; window.require = function(module, callback) { var url = window.require.resolve(module); if (require.cache[url]) { // NOTE The callback should always be called asynchronously callback && setTimeout(callback, 0); return require.cache[url]; } require.cache[url] = new Object(); var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState != 4) return; if (request.status != 200) throw 'RequireException: '+request.status+' '+request.statustext+' ('+url+')'; if (request.getResponseHeader('content-type').indexOf('application/json') != -1) window.require.cache[url] = JSON.parse(request.responseText); else eval('(function(){'+(window.require.strict?'\'use strict\';':'')+'var exports=window.require.cache[\''+url+'\'];'+request.responseText+'\n})();\n//@ sourceURL='+url); callback && callback(); } request.open('GET', url, !!callback); request.send(); return require.cache[url]; } window.require.resolve = function(module) { var r = module.match(/^(\.{0,2}\/)?([^\.]*)(\..*)?$/); return (r[1]?r[1]:'/js_modules/')+r[2]+(r[3]?r[3]:'/index.js'); } // INFO initializing module cache window.require.cache = new Object(); // INFO initializing strict mode toggle window.require.strict = false; })(); ================================================ FILE: Arrays/test_cases/particles.js ================================================ function Particle() { this.x = 0.0; this.y = 0.0; var t = Math.random() * Math.PI * 2.0 , r = Math.random() * 0.1; this.vx = Math.cos(t) * r; this.vy = Math.sin(t) * r; this.color = Math.random(); } exports.create_particle_system = function(options) { var Seq = options.data_structure , particles = Seq.create() , accumulator = 0.0; return { particles: particles , emitter_rate: options.emitter_rate , tick: function() { accumulator += Math.random() * this.emitter_rate * 2.0; while(accumulator > 1) { Seq.append(particles, new Particle()); accumulator -= 1.0; } for(var iter = Seq.begin(particles); iter!== Seq.end(particles); iter = Seq.next(particles, iter)) { var particle = Seq.read(particles, iter); particle.x += particle.vx; particle.y += particle.vy; if(Math.abs(particle.x) > 10.0 || Math.abs(particle.y) > 10.0) { Seq.remove(particles, iter); } } } } } ================================================ FILE: Arrays/test_cases/test_construct.js ================================================ var Seq = require(process.argv[2]); //Create initial data structure for(var i=5; i<23; ++i) { var n = (1< Particle Test

================================================ FILE: DataStructures/require.js ================================================ // ==Closure.compiler== // @compilation_level SIMPLE_OPTIMIZATIONS // ==/Closure.compiler== // Require() 0.3.2 unstable // // Copyright 2012 Torben Schulz // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////// (function() { 'use strict'; if (window.require !== undefined) throw 'RequireException: \'require\' already defined in global scope'; window.require = function(module, callback, base_url) { base_url = base_url || ""; //Munge tokens var toks = module.split("/"); if(toks[0] == '.') { toks = base_url.split('/').concat(toks.slice(1)); } for(var i=0; i 0) { toks.splice(i-1, 2); i -= 2; } else if(toks[i] == "." || toks[i].length === 0) { toks.splice(i, 1); i -= 1; } } var dirname = toks.slice(0,toks.length-1).join("/") , url = toks.join("/"); if (require.cache[url]) { // NOTE The callback should always be called asynchronously var obj = require.cache[url]; if(obj.loaded) { callback && setTimeout(function(){callback(obj.exports);}, 0); return obj.exports; } else if(callback) { obj.listeners.push(callback); return obj.exports; } } else { window.require.cache[url] = { loaded: false , listeners: [] , exports: new Object() }; } var request = new XMLHttpRequest(); request.onreadystatechange = function() { var obj = window.require.cache[url]; if(obj.loaded) { return; } if (request.readyState != 4) return; if (request.status != 200) throw 'RequireException: '+request.status+' '+request.statustext+' ('+url+')'; if (request.getResponseHeader('content-type').indexOf('application/json') != -1) window.require.cache[url] = JSON.parse(request.responseText); else eval('(function(){\'use strict\';\nvar exports=window.require.cache[\''+url+'\'].exports;\nvar __DIRNAME="'+dirname+'";\nvar require=function(module,cb){return window.require(module,cb,"'+dirname+'");};\n'+request.responseText+'\n})();\n//@ sourceURL='+url); //Set loaded flag obj.loaded = true; //Wake up all listeners var listeners = obj.listeners; for(var i=0; i= 1.0) { var t = Math.random() * Math.PI * 2.0 , v = Math.random() * 0.1 + 0.01; particles.push(new Float32Array([ 0.0, 0.0 , Math.cos(t) * v, Math.sin(t) * v , Math.random() ])); accumulator -= 1.0; } for(var iter = particles.prev(particles.end()); particles.valid(iter); iter = particles.prev(iter)) { var buf = particles.buffer(iter) , idx = particles.index(iter); buf[idx+0] += buf[idx+2]; buf[idx+1] += buf[idx+3]; if(Math.abs(buf[idx]) > 10.0 || Math.abs(buf[idx+1]) > 10.0) { particles.remove(iter); } } } , foreachParticle: function(visitor) { for(var iter = particles.begin(); iter !== particles.end(); iter = particles.next(iter)) { var buf = particles.buffer(iter) , idx = particles.index(iter); visitor(buf[idx+0], buf[idx+1], buf[idx+2], buf[idx+3], buf[idx+4]); } } , count : function() { return particles.count(); } } } ================================================ FILE: DataStructures/tests/test_particles.js ================================================ var particles = require('./particles.js').create_particle_system({ data_structure: require(process.argv[2]).create , emitter_rate: 200.0 }); //Warm up console.log("Warming up..."); for(var i=0; i<2000; ++i) { particles.tick(); } console.log("Initial population:", particles.count()); //Do simulation console.log("Running benchmark"); var NUM_ITERS = 10000; var start = new Date(); for(var i=0; i Volume Sampling Toolbox
Volume Resampling
- p for screenshot

Input Data:

Filter:

Scale:

Show facets:

Show edges:

Volume Resolution:

Vertex count:

Face count:

================================================ FILE: Downsample/js/boxfilter.js ================================================ //Naive box filter for downsampling volume function BoxFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k= dims[2]) { iz = 2*dims[2]-2-iz; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0) { iy = -iy; } if(iy >= dims[1]) { iy = 2*dims[1]-2-iy; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0) { ix = -ix; } if(ix >= dims[0]) { ix = 2*dims[0]-2-ix; } s += volume[ix+dims[0]*(iy+dims[1]*(iz))] / (1 << (Math.abs(dx) + Math.abs(dy) + Math.abs(dz))); } } } nvolume[n++] = s / 8.0; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/closing.js ================================================ //Morophological closing filter function ClosingFilter(volume, dims) { "use strict"; //Dilate var pvolume = new Float32Array(dims[0] * dims[1] * dims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } pvolume[n++] = s; } //Erode and downsample var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]); n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = 2*j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = 2*i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, pvolume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/marchingcubes.js ================================================ /** * Javascript Marching Cubes * * Based on Paul Bourke's classic implementation: * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ * * JS port by Mikola Lysenko */ var MarchingCubes = (function() { var edgeTable= new Uint32Array([ 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ]) , triTable = [ [], [0, 8, 3], [0, 1, 9], [1, 8, 3, 9, 8, 1], [1, 2, 10], [0, 8, 3, 1, 2, 10], [9, 2, 10, 0, 2, 9], [2, 8, 3, 2, 10, 8, 10, 9, 8], [3, 11, 2], [0, 11, 2, 8, 11, 0], [1, 9, 0, 2, 3, 11], [1, 11, 2, 1, 9, 11, 9, 8, 11], [3, 10, 1, 11, 10, 3], [0, 10, 1, 0, 8, 10, 8, 11, 10], [3, 9, 0, 3, 11, 9, 11, 10, 9], [9, 8, 10, 10, 8, 11], [4, 7, 8], [4, 3, 0, 7, 3, 4], [0, 1, 9, 8, 4, 7], [4, 1, 9, 4, 7, 1, 7, 3, 1], [1, 2, 10, 8, 4, 7], [3, 4, 7, 3, 0, 4, 1, 2, 10], [9, 2, 10, 9, 0, 2, 8, 4, 7], [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4], [8, 4, 7, 3, 11, 2], [11, 4, 7, 11, 2, 4, 2, 0, 4], [9, 0, 1, 8, 4, 7, 2, 3, 11], [4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1], [3, 10, 1, 3, 11, 10, 7, 8, 4], [1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4], [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3], [4, 7, 11, 4, 11, 9, 9, 11, 10], [9, 5, 4], [9, 5, 4, 0, 8, 3], [0, 5, 4, 1, 5, 0], [8, 5, 4, 8, 3, 5, 3, 1, 5], [1, 2, 10, 9, 5, 4], [3, 0, 8, 1, 2, 10, 4, 9, 5], [5, 2, 10, 5, 4, 2, 4, 0, 2], [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8], [9, 5, 4, 2, 3, 11], [0, 11, 2, 0, 8, 11, 4, 9, 5], [0, 5, 4, 0, 1, 5, 2, 3, 11], [2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5], [10, 3, 11, 10, 1, 3, 9, 5, 4], [4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10], [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3], [5, 4, 8, 5, 8, 10, 10, 8, 11], [9, 7, 8, 5, 7, 9], [9, 3, 0, 9, 5, 3, 5, 7, 3], [0, 7, 8, 0, 1, 7, 1, 5, 7], [1, 5, 3, 3, 5, 7], [9, 7, 8, 9, 5, 7, 10, 1, 2], [10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3], [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2], [2, 10, 5, 2, 5, 3, 3, 5, 7], [7, 9, 5, 7, 8, 9, 3, 11, 2], [9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11], [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7], [11, 2, 1, 11, 1, 7, 7, 1, 5], [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11], [5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0], [11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0], [11, 10, 5, 7, 11, 5], [10, 6, 5], [0, 8, 3, 5, 10, 6], [9, 0, 1, 5, 10, 6], [1, 8, 3, 1, 9, 8, 5, 10, 6], [1, 6, 5, 2, 6, 1], [1, 6, 5, 1, 2, 6, 3, 0, 8], [9, 6, 5, 9, 0, 6, 0, 2, 6], [5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8], [2, 3, 11, 10, 6, 5], [11, 0, 8, 11, 2, 0, 10, 6, 5], [0, 1, 9, 2, 3, 11, 5, 10, 6], [5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11], [6, 3, 11, 6, 5, 3, 5, 1, 3], [0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6], [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9], [6, 5, 9, 6, 9, 11, 11, 9, 8], [5, 10, 6, 4, 7, 8], [4, 3, 0, 4, 7, 3, 6, 5, 10], [1, 9, 0, 5, 10, 6, 8, 4, 7], [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4], [6, 1, 2, 6, 5, 1, 4, 7, 8], [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7], [8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6], [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9], [3, 11, 2, 7, 8, 4, 10, 6, 5], [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11], [0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6], [9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6], [8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6], [5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11], [0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7], [6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9], [10, 4, 9, 6, 4, 10], [4, 10, 6, 4, 9, 10, 0, 8, 3], [10, 0, 1, 10, 6, 0, 6, 4, 0], [8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10], [1, 4, 9, 1, 2, 4, 2, 6, 4], [3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4], [0, 2, 4, 4, 2, 6], [8, 3, 2, 8, 2, 4, 4, 2, 6], [10, 4, 9, 10, 6, 4, 11, 2, 3], [0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6], [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10], [6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1], [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3], [8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1], [3, 11, 6, 3, 6, 0, 0, 6, 4], [6, 4, 8, 11, 6, 8], [7, 10, 6, 7, 8, 10, 8, 9, 10], [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10], [10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0], [10, 6, 7, 10, 7, 1, 1, 7, 3], [1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7], [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9], [7, 8, 0, 7, 0, 6, 6, 0, 2], [7, 3, 2, 6, 7, 2], [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7], [2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7], [1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11], [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1], [8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6], [0, 9, 1, 11, 6, 7], [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0], [7, 11, 6], [7, 6, 11], [3, 0, 8, 11, 7, 6], [0, 1, 9, 11, 7, 6], [8, 1, 9, 8, 3, 1, 11, 7, 6], [10, 1, 2, 6, 11, 7], [1, 2, 10, 3, 0, 8, 6, 11, 7], [2, 9, 0, 2, 10, 9, 6, 11, 7], [6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8], [7, 2, 3, 6, 2, 7], [7, 0, 8, 7, 6, 0, 6, 2, 0], [2, 7, 6, 2, 3, 7, 0, 1, 9], [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6], [10, 7, 6, 10, 1, 7, 1, 3, 7], [10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8], [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7], [7, 6, 10, 7, 10, 8, 8, 10, 9], [6, 8, 4, 11, 8, 6], [3, 6, 11, 3, 0, 6, 0, 4, 6], [8, 6, 11, 8, 4, 6, 9, 0, 1], [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6], [6, 8, 4, 6, 11, 8, 2, 10, 1], [1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6], [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9], [10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3], [8, 2, 3, 8, 4, 2, 4, 6, 2], [0, 4, 2, 4, 6, 2], [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8], [1, 9, 4, 1, 4, 2, 2, 4, 6], [8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1], [10, 1, 0, 10, 0, 6, 6, 0, 4], [4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3], [10, 9, 4, 6, 10, 4], [4, 9, 5, 7, 6, 11], [0, 8, 3, 4, 9, 5, 11, 7, 6], [5, 0, 1, 5, 4, 0, 7, 6, 11], [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5], [9, 5, 4, 10, 1, 2, 7, 6, 11], [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5], [7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2], [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6], [7, 2, 3, 7, 6, 2, 5, 4, 9], [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7], [3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0], [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8], [9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7], [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4], [4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10], [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10], [6, 9, 5, 6, 11, 9, 11, 8, 9], [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5], [0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11], [6, 11, 3, 6, 3, 5, 5, 3, 1], [1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6], [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10], [11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5], [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3], [5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2], [9, 5, 6, 9, 6, 0, 0, 6, 2], [1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8], [1, 5, 6, 2, 1, 6], [1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6], [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0], [0, 3, 8, 5, 6, 10], [10, 5, 6], [11, 5, 10, 7, 5, 11], [11, 5, 10, 11, 7, 5, 8, 3, 0], [5, 11, 7, 5, 10, 11, 1, 9, 0], [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1], [11, 1, 2, 11, 7, 1, 7, 5, 1], [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11], [9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7], [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2], [2, 5, 10, 2, 3, 5, 3, 7, 5], [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5], [9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2], [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2], [1, 3, 5, 3, 7, 5], [0, 8, 7, 0, 7, 1, 1, 7, 5], [9, 0, 3, 9, 3, 5, 5, 3, 7], [9, 8, 7, 5, 9, 7], [5, 8, 4, 5, 10, 8, 10, 11, 8], [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0], [0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5], [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4], [2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8], [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11], [0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5], [9, 4, 5, 2, 11, 3], [2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4], [5, 10, 2, 5, 2, 4, 4, 2, 0], [3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9], [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2], [8, 4, 5, 8, 5, 3, 3, 5, 1], [0, 4, 5, 1, 0, 5], [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5], [9, 4, 5], [4, 11, 7, 4, 9, 11, 9, 10, 11], [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11], [1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11], [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4], [4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2], [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3], [11, 7, 4, 11, 4, 2, 2, 4, 0], [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4], [2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9], [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7], [3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10], [1, 10, 2, 8, 7, 4], [4, 9, 1, 4, 1, 7, 7, 1, 3], [4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1], [4, 0, 3, 7, 4, 3], [4, 8, 7], [9, 10, 8, 10, 11, 8], [3, 0, 9, 3, 9, 11, 11, 9, 10], [0, 1, 10, 0, 10, 8, 8, 10, 11], [3, 1, 10, 11, 3, 10], [1, 2, 11, 1, 11, 9, 9, 11, 8], [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9], [0, 2, 11, 8, 0, 11], [3, 2, 11], [2, 3, 8, 2, 8, 10, 10, 8, 9], [9, 10, 2, 0, 9, 2], [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8], [1, 10, 2], [1, 3, 8, 9, 1, 8], [0, 9, 1], [0, 3, 8], []] , cubeVerts = [ [0,0,0] ,[1,0,0] ,[1,1,0] ,[0,1,0] ,[0,0,1] ,[1,0,1] ,[1,1,1] ,[0,1,1]] , edgeIndex = [ [0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7] ]; return function(data, dims) { var vertices = [] , faces = [] , n = 0 , grid = new Float32Array(8) , edges = new Int32Array(12) , x = new Int32Array(3); //March over the volume for(x[2]=0; x[2] 0) ? 1 << i : 0; } //Compute vertices var edge_mask = edgeTable[cube_index]; if(edge_mask === 0) { continue; } for(var i=0; i<12; ++i) { if((edge_mask & (1< 1e-6) { t = a / d; } for(var j=0; j<3; ++j) { nv[j] = (x[j] + p0[j]) + t * (p1[j] - p0[j]); } vertices.push(nv); } //Add faces var f = triTable[cube_index]; for(var i=0; i 1e-6) { t = g0 / t; } for(var i=0; i<3; ++i) { v[i] += p0[i] + t * (p1[i] - p0[i]); } vertices.push(v); return vertices.length - 1; } //March over the volume for(x[2]=0; x[2]=dims[2]) { continue; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/medianfilter.js ================================================ //Median filter function MedianFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0 , ranks = new Array(27); for(var k=0; k= dims[2]) { iz = 2*dims[2]-2-iz; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0) { iy = -iy; } if(iy >= dims[1]) { iy = 2*dims[1]-2-iy; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0) { ix = -ix; } if(ix >= dims[0]) { ix = 2*dims[0]-2-ix; } ranks[idx++] = volume[ix+dims[0]*(iy+dims[1]*(iz))]; } } } var ranked = ranks.sort(function(a,b){ return b < a ? -1 : b>a ? 1 : 0; }); nvolume[n++] = 0.5 * (ranked[Math.floor(idx/2)] + ranked[Math.floor(idx/2)+1]); } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/minfilter.js ================================================ //Minimum filter function MinFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/nearestfilter.js ================================================ //Naive box filter for downsampling volume function NearestFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } pvolume[n++] = s; } //Dilate var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.ceil(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]); n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = 2*j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = 2*i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, pvolume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: Downsample/js/perlinnoise.js ================================================ //This code is from Kas Thomas' blog: // http://asserttrue.blogspot.de/2011/12/perlin-noise-in-javascript_31.html // This is a port of Ken Perlin's Java code. The // original Java code is at http://cs.nyu.edu/%7Eperlin/noise/. // Note that in this version, a number from 0 to 1 is returned. PerlinNoise = new function() { this.noise = function(x, y, z) { var p = new Array(512) var permutation = [ 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ]; for (var i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; var X = Math.floor(x) & 255, // FIND UNIT CUBE THAT Y = Math.floor(y) & 255, // CONTAINS POINT. Z = Math.floor(z) & 255; x -= Math.floor(x); // FIND RELATIVE X,Y,Z y -= Math.floor(y); // OF POINT IN CUBE. z -= Math.floor(z); var u = fade(x), // COMPUTE FADE CURVES v = fade(y), // FOR EACH OF X,Y,Z. w = fade(z); var A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, return scale(lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD grad(p[BA ], x-1, y , z )), // BLENDED lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS grad(p[BB ], x-1, y-1, z ))),// FROM 8 lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS grad(p[BA+1], x-1, y , z-1 )), // OF CUBE lerp(u, grad(p[AB+1], x , y-1, z-1 ), grad(p[BB+1], x-1, y-1, z-1 ))))); } function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); } function lerp( t, a, b) { return a + t * (b - a); } function grad(hash, x, y, z) { var h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE var u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. v = h<4 ? y : h==12||h==14 ? x : z; return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); } function scale(n) { return (1 + n)/2; } } ================================================ FILE: Downsample/js/surfacenets.js ================================================ /** * SurfaceNets in JavaScript * * Written by Mikola Lysenko (C) 2012 * * MIT License * * Based on: S.F. Gibson, "Constrained Elastic Surface Nets". (1998) MERL Tech Report. */ var SurfaceNets = (function() { "use strict"; //Precompute edge table, like Paul Bourke does. // This saves a bit of time when computing the centroid of each boundary cell var cube_edges = new Int32Array(24) , edge_table = new Int32Array(256); (function() { //Initialize the cube_edges table // This is just the vertex number of each cube var k = 0; for(var i=0; i<8; ++i) { for(var j=1; j<=4; j<<=1) { var p = i^j; if(i <= p) { cube_edges[k++] = i; cube_edges[k++] = p; } } } //Initialize the intersection table. // This is a 2^(cube configuration) -> 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Int32Array(4096); return function(data, dims) { var vertices = [] , faces = [] , n = 0 , x = new Int32Array(3) , R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[0]+1)]) , grid = new Float32Array(8) , buf_no = 1; //Resize buffer if necessary if(R[2] * 2 > buffer.length) { buffer = new Int32Array(R[2] * 2); } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1< 54 ) { t = Math.max(t, x - 54); } if( y > 54 ) { t = Math.max(t, y - 54); } if( z > 54 ) { t = Math.max(t, z - 54); } return t; } ); result["Goursat's Surface"] = makeVolume( [[-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0]], function(x,y,z) { return Math.pow(x,4) + Math.pow(y,4) + Math.pow(z,4) - 1.5 * (x*x + y*y + z*z) + 1; } ); result["Heart"] = makeVolume( [[-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0]], function(x,y,z) { y *= 1.5; z *= 1.5; return Math.pow(2*x*x+y*y+2*z*z-1, 3) - 0.1 * z*z*y*y*y - y*y*y*x*x; } ); result['Noise (Slow)'] = makeVolume( [[-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0]], function(x,y,z) { if(x < -1.0 || x > 1.0 || y < -1.0 || y > 1.0 || z < -1.0 || z > 1.0 ) { return 0.6; } return 0.6 - PerlinNoise.noise(4.0 * x, 4.0 * y, 4.0 * z); } ); result['Asteroid (Slow)'] = makeVolume( [[-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0]], function(x,y,z) { return (x*x + y*y + z*z) - PerlinNoise.noise(x*2,y*2,z*2); } ); result['Terrain (Slow)'] = makeVolume( [[-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0]], function(x,y,z) { return y + PerlinNoise.noise(x*2+5,y*2+3,z*2+0.6); } ); result['Empty'] = function(){ return { volume: new Float32Array(32*32*32), dims:[32,32,32] } }; return result; } ================================================ FILE: Downsample/vendor/dsp.js ================================================ /* * DSP.js - a comprehensive digital signal processing library for javascript * * Created by Corban Brook on 2010-01-01. * Copyright 2010 Corban Brook. All rights reserved. * */ //////////////////////////////////////////////////////////////////////////////// // CONSTANTS // //////////////////////////////////////////////////////////////////////////////// /** * DSP is an object which contains general purpose utility functions and constants */ var DSP = { // Channels LEFT: 0, RIGHT: 1, MIX: 2, // Waveforms SINE: 1, TRIANGLE: 2, SAW: 3, SQUARE: 4, // Filters LOWPASS: 0, HIGHPASS: 1, BANDPASS: 2, NOTCH: 3, // Window functions BARTLETT: 1, BARTLETTHANN: 2, BLACKMAN: 3, COSINE: 4, GAUSS: 5, HAMMING: 6, HANN: 7, LANCZOS: 8, RECTANGULAR: 9, TRIANGULAR: 10, // Loop modes OFF: 0, FW: 1, BW: 2, FWBW: 3, // Math TWO_PI: 2*Math.PI }; // Setup arrays for platforms which do not support byte arrays function setupTypedArray(name, fallback) { // check if TypedArray exists // typeof on Minefield and Chrome return function, typeof on Webkit returns object. if (typeof this[name] !== "function" && typeof this[name] !== "object") { // nope.. check if WebGLArray exists if (typeof this[fallback] === "function" && typeof this[fallback] !== "object") { this[name] = this[fallback]; } else { // nope.. set as Native JS array this[name] = function(obj) { if (obj instanceof Array) { return obj; } else if (typeof obj === "number") { return new Array(obj); } }; } } } setupTypedArray("Float32Array", "WebGLFloatArray"); setupTypedArray("Int32Array", "WebGLIntArray"); setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"); setupTypedArray("Uint8Array", "WebGLUnsignedByteArray"); //////////////////////////////////////////////////////////////////////////////// // DSP UTILITY FUNCTIONS // //////////////////////////////////////////////////////////////////////////////// /** * Inverts the phase of a signal * * @param {Array} buffer A sample buffer * * @returns The inverted sample buffer */ DSP.invert = function(buffer) { for (var i = 0, len = buffer.length; i < len; i++) { buffer[i] *= -1; } return buffer; }; /** * Converts split-stereo (dual mono) sample buffers into a stereo interleaved sample buffer * * @param {Array} left A sample buffer * @param {Array} right A sample buffer * * @returns The stereo interleaved buffer */ DSP.interleave = function(left, right) { if (left.length !== right.length) { throw "Can not interleave. Channel lengths differ."; } var stereoInterleaved = new Float32Array(left.length * 2); for (var i = 0, len = left.length; i < len; i++) { stereoInterleaved[2*i] = left[i]; stereoInterleaved[2*i+1] = right[i]; } return stereoInterleaved; }; /** * Converts a stereo-interleaved sample buffer into split-stereo (dual mono) sample buffers * * @param {Array} buffer A stereo-interleaved sample buffer * * @returns an Array containing left and right channels */ DSP.deinterleave = (function() { var left, right, mix, deinterleaveChannel = []; deinterleaveChannel[DSP.MIX] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { mix[i] = (buffer[2*i] + buffer[2*i+1]) / 2; } return mix; }; deinterleaveChannel[DSP.LEFT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { left[i] = buffer[2*i]; } return left; }; deinterleaveChannel[DSP.RIGHT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { right[i] = buffer[2*i+1]; } return right; }; return function(channel, buffer) { left = left || new Float32Array(buffer.length/2); right = right || new Float32Array(buffer.length/2); mix = mix || new Float32Array(buffer.length/2); if (buffer.length/2 !== left.length) { left = new Float32Array(buffer.length/2); right = new Float32Array(buffer.length/2); mix = new Float32Array(buffer.length/2); } return deinterleaveChannel[channel](buffer); }; }()); /** * Separates a channel from a stereo-interleaved sample buffer * * @param {Array} buffer A stereo-interleaved sample buffer * @param {Number} channel A channel constant (LEFT, RIGHT, MIX) * * @returns an Array containing a signal mono sample buffer */ DSP.getChannel = DSP.deinterleave; /** * Helper method (for Reverb) to mix two (interleaved) samplebuffers. It's possible * to negate the second buffer while mixing and to perform a volume correction * on the final signal. * * @param {Array} sampleBuffer1 Array containing Float values or a Float32Array * @param {Array} sampleBuffer2 Array containing Float values or a Float32Array * @param {Boolean} negate When true inverts/flips the audio signal * @param {Number} volumeCorrection When you add multiple sample buffers, use this to tame your signal ;) * * @returns A new Float32Array interleaved buffer. */ DSP.mixSampleBuffers = function(sampleBuffer1, sampleBuffer2, negate, volumeCorrection){ var outputSamples = new Float32Array(sampleBuffer1); for(var i = 0; i peak) ? Math.abs(buffer[i]) : peak; } return peak; }; // Fourier Transform Module used by DFT, FFT, RFFT function FourierTransform(bufferSize, sampleRate) { this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.bandwidth = 2 / bufferSize * sampleRate / 2; this.spectrum = new Float32Array(bufferSize/2); this.real = new Float32Array(bufferSize); this.imag = new Float32Array(bufferSize); this.peakBand = 0; this.peak = 0; /** * Calculates the *middle* frequency of an FFT band. * * @param {Number} index The index of the FFT band. * * @returns The middle frequency in Hz. */ this.getBandFrequency = function(index) { return this.bandwidth * index + this.bandwidth / 2; }; this.calculateSpectrum = function() { var spectrum = this.spectrum, real = this.real, imag = this.imag, bSi = 2 / this.bufferSize, sqrt = Math.sqrt, rval, ival, mag; for (var i = 0, N = bufferSize/2; i < N; i++) { rval = real[i]; ival = imag[i]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } }; } /** * DFT is a class for calculating the Discrete Fourier Transform of a signal. * * @param {Number} bufferSize The size of the sample buffer to be computed * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function DFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); var N = bufferSize/2 * bufferSize; var TWO_PI = 2 * Math.PI; this.sinTable = new Float32Array(N); this.cosTable = new Float32Array(N); for (var i = 0; i < N; i++) { this.sinTable[i] = Math.sin(i * TWO_PI / bufferSize); this.cosTable[i] = Math.cos(i * TWO_PI / bufferSize); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer * * @returns The frequency spectrum array */ DFT.prototype.forward = function(buffer) { var real = this.real, imag = this.imag, rval, ival; for (var k = 0; k < this.bufferSize/2; k++) { rval = 0.0; ival = 0.0; for (var n = 0; n < buffer.length; n++) { rval += this.cosTable[k*n] * buffer[n]; ival += this.sinTable[k*n] * buffer[n]; } real[k] = rval; imag[k] = ival; } return this.calculateSpectrum(); }; /** * FFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function FFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.reverseTable = new Uint32Array(bufferSize); var limit = 1; var bit = bufferSize >> 1; var i; while (limit < bufferSize) { for (i = 0; i < limit; i++) { this.reverseTable[i + limit] = this.reverseTable[i] + bit; } limit = limit << 1; bit = bit >> 1; } this.sinTable = new Float32Array(bufferSize); this.cosTable = new Float32Array(bufferSize); for (i = 0; i < bufferSize; i++) { this.sinTable[i] = Math.sin(-Math.PI/i); this.cosTable[i] = Math.cos(-Math.PI/i); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer. Buffer Length must be power of 2 * * @returns The frequency spectrum array */ FFT.prototype.forward = function(buffer) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, real = this.real, imag = this.imag, spectrum = this.spectrum; var k = Math.floor(Math.log(bufferSize) / Math.LN2); if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; } if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; } var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { real[i] = buffer[reverseTable[i]]; imag[i] = 0; } while (halfSize < bufferSize) { //phaseShiftStepReal = Math.cos(-Math.PI/halfSize); //phaseShiftStepImag = Math.sin(-Math.PI/halfSize); phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } return this.calculateSpectrum(); }; FFT.prototype.inverse = function(real, imag) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, spectrum = this.spectrum; real = real || this.real; imag = imag || this.imag; var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { imag[i] *= -1; } var revReal = new Float32Array(bufferSize); var revImag = new Float32Array(bufferSize); for (i = 0; i < real.length; i++) { revReal[i] = real[reverseTable[i]]; revImag[i] = imag[reverseTable[i]]; } real = revReal; imag = revImag; while (halfSize < bufferSize) { phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } var buffer = new Float32Array(bufferSize); // this should be reused instead for (i = 0; i < bufferSize; i++) { buffer[i] = real[i] / bufferSize; } return buffer; }; /** * RFFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * This method currently only contains a forward transform but is highly optimized. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ // lookup tables don't really gain us any speed, but they do increase // cache footprint, so don't use them in here // also we don't use sepearate arrays for real/imaginary parts // this one a little more than twice as fast as the one in FFT // however I only did the forward transform // the rest of this was translated from C, see http://www.jjj.de/fxt/ // this is the real split radix FFT function RFFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.trans = new Float32Array(bufferSize); this.reverseTable = new Uint32Array(bufferSize); // don't use a lookup table to do the permute, use this instead this.reverseBinPermute = function (dest, source) { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; dest[0] = source[0]; do { r += halfSize; dest[i] = source[r]; dest[r] = source[i]; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { dest[i] = source[r]; dest[r] = source[i]; dest[nm1-i] = source[nm1-r]; dest[nm1-r] = source[nm1-i]; } i++; } while (i < halfSize); dest[nm1] = source[nm1]; }; this.generateReverseTable = function () { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; this.reverseTable[0] = 0; do { r += halfSize; this.reverseTable[i] = r; this.reverseTable[r] = i; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { this.reverseTable[i] = r; this.reverseTable[r] = i; this.reverseTable[nm1-i] = nm1-r; this.reverseTable[nm1-r] = nm1-i; } i++; } while (i < halfSize); this.reverseTable[nm1] = nm1; }; this.generateReverseTable(); } // Ordering of output: // // trans[0] = re[0] (==zero frequency, purely real) // trans[1] = re[1] // ... // trans[n/2-1] = re[n/2-1] // trans[n/2] = re[n/2] (==nyquist frequency, purely real) // // trans[n/2+1] = im[n/2-1] // trans[n/2+2] = im[n/2-2] // ... // trans[n-1] = im[1] RFFT.prototype.forward = function(buffer) { var n = this.bufferSize, spectrum = this.spectrum, x = this.trans, TWO_PI = 2*Math.PI, sqrt = Math.sqrt, i = n >>> 1, bSi = 2 / n, n2, n4, n8, nn, t1, t2, t3, t4, i1, i2, i3, i4, i5, i6, i7, i8, st1, cc1, ss1, cc3, ss3, e, a, rval, ival, mag; this.reverseBinPermute(x, buffer); /* var reverseTable = this.reverseTable; for (var k = 0, len = reverseTable.length; k < len; k++) { x[k] = buffer[reverseTable[k]]; } */ for (var ix = 0, id = 4; ix < n; id *= 4) { for (var i0 = ix; i0 < n; i0 += id) { //sumdiff(x[i0], x[i0+1]); // {a, b} <--| {a+b, a-b} st1 = x[i0] - x[i0+1]; x[i0] += x[i0+1]; x[i0+1] = st1; } ix = 2*(id-1); } n2 = 2; nn = n >>> 1; while((nn = nn >>> 1)) { ix = 0; n2 = n2 << 1; id = n2 << 1; n4 = n2 >>> 2; n8 = n2 >>> 3; do { if(n4 !== 1) { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; i1 += n8; i2 += n8; i3 += n8; i4 += n8; //sumdiff(x[i3], x[i4], t1, t2); // {s, d} <--| {a+b, a-b} t1 = x[i3] + x[i4]; t2 = x[i3] - x[i4]; t1 = -t1 * Math.SQRT1_2; t2 *= Math.SQRT1_2; // sumdiff(t1, x[i2], x[i4], x[i3]); // {s, d} <--| {a+b, a-b} st1 = x[i2]; x[i4] = t1 + st1; x[i3] = t1 - st1; //sumdiff3(x[i1], t2, x[i2]); // {a, b, d} <--| {a+b, b, a-b} x[i2] = x[i1] - t2; x[i1] += t2; } } else { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; } } ix = (id << 1) - n2; id = id << 2; } while (ix < n); e = TWO_PI / n2; for (var j = 1; j < n8; j++) { a = j * e; ss1 = Math.sin(a); cc1 = Math.cos(a); //ss3 = sin(3*a); cc3 = cos(3*a); cc3 = 4*cc1*(cc1*cc1-0.75); ss3 = 4*ss1*(0.75-ss1*ss1); ix = 0; id = n2 << 1; do { for (i0 = ix; i0 < n; i0 += id) { i1 = i0 + j; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; i5 = i0 + n4 - j; i6 = i5 + n4; i7 = i6 + n4; i8 = i7 + n4; //cmult(c, s, x, y, &u, &v) //cmult(cc1, ss1, x[i7], x[i3], t2, t1); // {u,v} <--| {x*c-y*s, x*s+y*c} t2 = x[i7]*cc1 - x[i3]*ss1; t1 = x[i7]*ss1 + x[i3]*cc1; //cmult(cc3, ss3, x[i8], x[i4], t4, t3); t4 = x[i8]*cc3 - x[i4]*ss3; t3 = x[i8]*ss3 + x[i4]*cc3; //sumdiff(t2, t4); // {a, b} <--| {a+b, a-b} st1 = t2 - t4; t2 += t4; t4 = st1; //sumdiff(t2, x[i6], x[i8], x[i3]); // {s, d} <--| {a+b, a-b} //st1 = x[i6]; x[i8] = t2 + st1; x[i3] = t2 - st1; x[i8] = t2 + x[i6]; x[i3] = t2 - x[i6]; //sumdiff_r(t1, t3); // {a, b} <--| {a+b, b-a} st1 = t3 - t1; t1 += t3; t3 = st1; //sumdiff(t3, x[i2], x[i4], x[i7]); // {s, d} <--| {a+b, a-b} //st1 = x[i2]; x[i4] = t3 + st1; x[i7] = t3 - st1; x[i4] = t3 + x[i2]; x[i7] = t3 - x[i2]; //sumdiff3(x[i1], t1, x[i6]); // {a, b, d} <--| {a+b, b, a-b} x[i6] = x[i1] - t1; x[i1] += t1; //diffsum3_r(t4, x[i5], x[i2]); // {a, b, s} <--| {a, b-a, a+b} x[i2] = t4 + x[i5]; x[i5] -= t4; } ix = (id << 1) - n2; id = id << 2; } while (ix < n); } } while (--i) { rval = x[i]; ival = x[n-i-1]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } spectrum[0] = bSi * x[0]; return spectrum; }; function Sampler(file, bufferSize, sampleRate, playStart, playEnd, loopStart, loopEnd, loopMode) { this.file = file; this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.playStart = playStart || 0; // 0% this.playEnd = playEnd || 1; // 100% this.loopStart = loopStart || 0; this.loopEnd = loopEnd || 1; this.loopMode = loopMode || DSP.OFF; this.loaded = false; this.samples = []; this.signal = new Float32Array(bufferSize); this.frameCount = 0; this.envelope = null; this.amplitude = 1; this.rootFrequency = 110; // A2 110 this.frequency = 550; this.step = this.frequency / this.rootFrequency; this.duration = 0; this.samplesProcessed = 0; this.playhead = 0; var audio = /* new Audio();*/ document.createElement("AUDIO"); var self = this; this.loadSamples = function(event) { var buffer = DSP.getChannel(DSP.MIX, event.frameBuffer); for ( var i = 0; i < buffer.length; i++) { self.samples.push(buffer[i]); } }; this.loadComplete = function() { // convert flexible js array into a fast typed array self.samples = new Float32Array(self.samples); self.loaded = true; }; this.loadMetaData = function() { self.duration = audio.duration; }; audio.addEventListener("MozAudioAvailable", this.loadSamples, false); audio.addEventListener("loadedmetadata", this.loadMetaData, false); audio.addEventListener("ended", this.loadComplete, false); audio.muted = true; audio.src = file; audio.play(); } Sampler.prototype.applyEnvelope = function() { this.envelope.process(this.signal); return this.signal; }; Sampler.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var loopWidth = this.playEnd * this.samples.length - this.playStart * this.samples.length; var playStartSamples = this.playStart * this.samples.length; // ie 0.5 -> 50% of the length var playEndSamples = this.playEnd * this.samples.length; // ie 0.5 -> 50% of the length var offset; for ( var i = 0; i < this.bufferSize; i++ ) { switch (this.loopMode) { case DSP.OFF: this.playhead = Math.round(this.samplesProcessed * this.step + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } else { this.signal[i] = 0; } break; case DSP.FW: this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.BW: this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.FWBW: if ( Math.floor(this.samplesProcessed * this.step / loopWidth) % 2 === 0 ) { this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); } else { this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); } if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; } this.samplesProcessed++; } this.frameCount++; return this.signal; }; Sampler.prototype.setFreq = function(frequency) { var totalProcessed = this.samplesProcessed * this.step; this.frequency = frequency; this.step = this.frequency / this.rootFrequency; this.samplesProcessed = Math.round(totalProcessed/this.step); }; Sampler.prototype.reset = function() { this.samplesProcessed = 0; this.playhead = 0; }; /** * Oscillator class for generating and modifying signals * * @param {Number} type A waveform constant (eg. DSP.SINE) * @param {Number} frequency Initial frequency of the signal * @param {Number} amplitude Initial amplitude of the signal * @param {Number} bufferSize Size of the sample buffer to generate * @param {Number} sampleRate The sample rate of the signal * * @contructor */ function Oscillator(type, frequency, amplitude, bufferSize, sampleRate) { this.frequency = frequency; this.amplitude = amplitude; this.bufferSize = bufferSize; this.sampleRate = sampleRate; //this.pulseWidth = pulseWidth; this.frameCount = 0; this.waveTableLength = 2048; this.cyclesPerSample = frequency / sampleRate; this.signal = new Float32Array(bufferSize); this.envelope = null; switch(parseInt(type, 10)) { case DSP.TRIANGLE: this.func = Oscillator.Triangle; break; case DSP.SAW: this.func = Oscillator.Saw; break; case DSP.SQUARE: this.func = Oscillator.Square; break; default: case DSP.SINE: this.func = Oscillator.Sine; break; } this.generateWaveTable = function() { Oscillator.waveTable[this.func] = new Float32Array(2048); var waveTableTime = this.waveTableLength / this.sampleRate; var waveTableHz = 1 / waveTableTime; for (var i = 0; i < this.waveTableLength; i++) { Oscillator.waveTable[this.func][i] = this.func(i * waveTableHz/this.sampleRate); } }; if ( typeof Oscillator.waveTable === 'undefined' ) { Oscillator.waveTable = {}; } if ( typeof Oscillator.waveTable[this.func] === 'undefined' ) { this.generateWaveTable(); } this.waveTable = Oscillator.waveTable[this.func]; } /** * Set the amplitude of the signal * * @param {Number} amplitude The amplitude of the signal (between 0 and 1) */ Oscillator.prototype.setAmp = function(amplitude) { if (amplitude >= 0 && amplitude <= 1) { this.amplitude = amplitude; } else { throw "Amplitude out of range (0..1)."; } }; /** * Set the frequency of the signal * * @param {Number} frequency The frequency of the signal */ Oscillator.prototype.setFreq = function(frequency) { this.frequency = frequency; this.cyclesPerSample = frequency / this.sampleRate; }; // Add an oscillator Oscillator.prototype.add = function(oscillator) { for ( var i = 0; i < this.bufferSize; i++ ) { //this.signal[i] += oscillator.valueAt(i); this.signal[i] += oscillator.signal[i]; } return this.signal; }; // Add a signal to the current generated osc signal Oscillator.prototype.addSignal = function(signal) { for ( var i = 0; i < signal.length; i++ ) { if ( i >= this.bufferSize ) { break; } this.signal[i] += signal[i]; /* // Constrain amplitude if ( this.signal[i] > 1 ) { this.signal[i] = 1; } else if ( this.signal[i] < -1 ) { this.signal[i] = -1; } */ } return this.signal; }; // Add an envelope to the oscillator Oscillator.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; Oscillator.prototype.applyEnvelope = function() { this.envelope.process(this.signal); }; Oscillator.prototype.valueAt = function(offset) { return this.waveTable[offset % this.waveTableLength]; }; Oscillator.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var step = this.waveTableLength * this.frequency / this.sampleRate; var offset; for ( var i = 0; i < this.bufferSize; i++ ) { //var step = (frameOffset + i) * this.cyclesPerSample % 1; //this.signal[i] = this.func(step) * this.amplitude; //this.signal[i] = this.valueAt(Math.round((frameOffset + i) * step)) * this.amplitude; offset = Math.round((frameOffset + i) * step); this.signal[i] = this.waveTable[offset % this.waveTableLength] * this.amplitude; } this.frameCount++; return this.signal; }; Oscillator.Sine = function(step) { return Math.sin(DSP.TWO_PI * step); }; Oscillator.Square = function(step) { return step < 0.5 ? 1 : -1; }; Oscillator.Saw = function(step) { return 2 * (step - Math.round(step)); }; Oscillator.Triangle = function(step) { return 1 - 4 * Math.abs(Math.round(step) - step); }; Oscillator.Pulse = function(step) { // stub }; function ADSR(attackLength, decayLength, sustainLevel, sustainLength, releaseLength, sampleRate) { this.sampleRate = sampleRate; // Length in seconds this.attackLength = attackLength; this.decayLength = decayLength; this.sustainLevel = sustainLevel; this.sustainLength = sustainLength; this.releaseLength = releaseLength; this.sampleRate = sampleRate; // Length in samples this.attackSamples = attackLength * sampleRate; this.decaySamples = decayLength * sampleRate; this.sustainSamples = sustainLength * sampleRate; this.releaseSamples = releaseLength * sampleRate; // Updates the envelope sample positions this.update = function() { this.attack = this.attackSamples; this.decay = this.attack + this.decaySamples; this.sustain = this.decay + this.sustainSamples; this.release = this.sustain + this.releaseSamples; }; this.update(); this.samplesProcessed = 0; } ADSR.prototype.noteOn = function() { this.samplesProcessed = 0; this.sustainSamples = this.sustainLength * this.sampleRate; this.update(); }; // Send a note off when using a sustain of infinity to let the envelope enter the release phase ADSR.prototype.noteOff = function() { this.sustainSamples = this.samplesProcessed - this.decaySamples; this.update(); }; ADSR.prototype.processSample = function(sample) { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return sample * amplitude; }; ADSR.prototype.value = function() { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return amplitude; }; ADSR.prototype.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { buffer[i] *= this.value(); this.samplesProcessed++; } return buffer; }; ADSR.prototype.isActive = function() { if ( this.samplesProcessed > this.release || this.samplesProcessed === -1 ) { return false; } else { return true; } }; ADSR.prototype.disable = function() { this.samplesProcessed = -1; }; function IIRFilter(type, cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; switch(type) { case DSP.LOWPASS: case DSP.LP12: this.func = new IIRFilter.LP12(cutoff, resonance, sampleRate); break; } } IIRFilter.prototype.__defineGetter__('cutoff', function() { return this.func.cutoff; } ); IIRFilter.prototype.__defineGetter__('resonance', function() { return this.func.resonance; } ); IIRFilter.prototype.set = function(cutoff, resonance) { this.func.calcCoeff(cutoff, resonance); }; IIRFilter.prototype.process = function(buffer) { this.func.process(buffer); }; // Add an envelope to the filter IIRFilter.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.func.addEnvelope(envelope); } else { throw "Not an envelope."; } }; IIRFilter.LP12 = function(cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; this.vibraPos = 0; this.vibraSpeed = 0; this.envelope = false; this.calcCoeff = function(cutoff, resonance) { this.w = 2.0 * Math.PI * cutoff / this.sampleRate; this.q = 1.0 - this.w / (2.0 * (resonance + 0.5 / (1.0 + this.w)) + this.w - 2.0); this.r = this.q * this.q; this.c = this.r + 1.0 - 2.0 * Math.cos(this.w) * this.q; this.cutoff = cutoff; this.resonance = resonance; }; this.calcCoeff(cutoff, resonance); this.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { this.vibraSpeed += (buffer[i] - this.vibraPos) * this.c; this.vibraPos += this.vibraSpeed; this.vibraSpeed *= this.r; /* var temp = this.vibraPos; if ( temp > 1.0 ) { temp = 1.0; } else if ( temp < -1.0 ) { temp = -1.0; } else if ( temp != temp ) { temp = 1; } buffer[i] = temp; */ if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (this.vibraPos * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = this.vibraPos; } } }; }; IIRFilter.LP12.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; function IIRFilter2(type, cutoff, resonance, sampleRate) { this.type = type; this.cutoff = cutoff; this.resonance = resonance; this.sampleRate = sampleRate; this.f = Float32Array(4); this.f[0] = 0.0; // lp this.f[1] = 0.0; // hp this.f[2] = 0.0; // bp this.f[3] = 0.0; // br this.calcCoeff = function(cutoff, resonance) { this.freq = 2 * Math.sin(Math.PI * Math.min(0.25, cutoff/(this.sampleRate*2))); this.damp = Math.min(2 * (1 - Math.pow(resonance, 0.25)), Math.min(2, 2/this.freq - this.freq * 0.5)); }; this.calcCoeff(cutoff, resonance); } IIRFilter2.prototype.process = function(buffer) { var input, output; var f = this.f; for ( var i = 0; i < buffer.length; i++ ) { input = buffer[i]; // first pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output = 0.5 * f[this.type]; // second pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output += 0.5 * f[this.type]; if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (output * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = output; } } }; IIRFilter2.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.envelope = envelope; } else { throw "This is not an envelope."; } }; IIRFilter2.prototype.set = function(cutoff, resonance) { this.calcCoeff(cutoff, resonance); }; function WindowFunction(type, alpha) { this.alpha = alpha; switch(type) { case DSP.BARTLETT: this.func = WindowFunction.Bartlett; break; case DSP.BARTLETTHANN: this.func = WindowFunction.BartlettHann; break; case DSP.BLACKMAN: this.func = WindowFunction.Blackman; this.alpha = this.alpha || 0.16; break; case DSP.COSINE: this.func = WindowFunction.Cosine; break; case DSP.GAUSS: this.func = WindowFunction.Gauss; this.alpha = this.alpha || 0.25; break; case DSP.HAMMING: this.func = WindowFunction.Hamming; break; case DSP.HANN: this.func = WindowFunction.Hann; break; case DSP.LANCZOS: this.func = WindowFunction.Lanczoz; break; case DSP.RECTANGULAR: this.func = WindowFunction.Rectangular; break; case DSP.TRIANGULAR: this.func = WindowFunction.Triangular; break; } } WindowFunction.prototype.process = function(buffer) { var length = buffer.length; for ( var i = 0; i < length; i++ ) { buffer[i] *= this.func(length, i, this.alpha); } return buffer; }; WindowFunction.Bartlett = function(length, index) { return 2 / (length - 1) * ((length - 1) / 2 - Math.abs(index - (length - 1) / 2)); }; WindowFunction.BartlettHann = function(length, index) { return 0.62 - 0.48 * Math.abs(index / (length - 1) - 0.5) - 0.38 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Blackman = function(length, index, alpha) { var a0 = (1 - alpha) / 2; var a1 = 0.5; var a2 = alpha / 2; return a0 - a1 * Math.cos(DSP.TWO_PI * index / (length - 1)) + a2 * Math.cos(4 * Math.PI * index / (length - 1)); }; WindowFunction.Cosine = function(length, index) { return Math.cos(Math.PI * index / (length - 1) - Math.PI / 2); }; WindowFunction.Gauss = function(length, index, alpha) { return Math.pow(Math.E, -0.5 * Math.pow((index - (length - 1) / 2) / (alpha * (length - 1) / 2), 2)); }; WindowFunction.Hamming = function(length, index) { return 0.54 - 0.46 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Hann = function(length, index) { return 0.5 * (1 - Math.cos(DSP.TWO_PI * index / (length - 1))); }; WindowFunction.Lanczos = function(length, index) { var x = 2 * index / (length - 1) - 1; return Math.sin(Math.PI * x) / (Math.PI * x); }; WindowFunction.Rectangular = function(length, index) { return 1; }; WindowFunction.Triangular = function(length, index) { return 2 / length * (length / 2 - Math.abs(index - (length - 1) / 2)); }; function sinh (arg) { // Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 // // version: 1004.2314 // discuss at: http://phpjs.org/functions/sinh // + original by: Onno Marsman // * example 1: sinh(-0.9834330348825909); // * returns 1: -1.1497971402636502 return (Math.exp(arg) - Math.exp(-arg))/2; } /* * Biquad filter * * Created by Ricard Marxer on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ // Implementation based on: // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt function Biquad(type, sampleRate) { this.Fs = sampleRate; this.type = type; // type of the filter this.parameterType = DSP.Q; // type of the parameter this.x_1_l = 0; this.x_2_l = 0; this.y_1_l = 0; this.y_2_l = 0; this.x_1_r = 0; this.x_2_r = 0; this.y_1_r = 0; this.y_2_r = 0; this.b0 = 1; this.a0 = 1; this.b1 = 0; this.a1 = 0; this.b2 = 0; this.a2 = 0; this.b0a0 = this.b0 / this.a0; this.b1a0 = this.b1 / this.a0; this.b2a0 = this.b2 / this.a0; this.a1a0 = this.a1 / this.a0; this.a2a0 = this.a2 / this.a0; this.f0 = 3000; // "wherever it's happenin', man." Center Frequency or // Corner Frequency, or shelf midpoint frequency, depending // on which filter type. The "significant frequency". this.dBgain = 12; // used only for peaking and shelving filters this.Q = 1; // the EE kind of definition, except for peakingEQ in which A*Q is // the classic EE Q. That adjustment in definition was made so that // a boost of N dB followed by a cut of N dB for identical Q and // f0/Fs results in a precisely flat unity gain filter or "wire". this.BW = -3; // the bandwidth in octaves (between -3 dB frequencies for BPF // and notch or between midpoint (dBgain/2) gain frequencies for // peaking EQ this.S = 1; // a "shelf slope" parameter (for shelving EQ only). When S = 1, // the shelf slope is as steep as it can be and remain monotonically // increasing or decreasing gain with frequency. The shelf slope, in // dB/octave, remains proportional to S for all other values for a // fixed f0/Fs and dBgain. this.coefficients = function() { var b = [this.b0, this.b1, this.b2]; var a = [this.a0, this.a1, this.a2]; return {b: b, a:a}; }; this.setFilterType = function(type) { this.type = type; this.recalculateCoefficients(); }; this.setSampleRate = function(rate) { this.Fs = rate; this.recalculateCoefficients(); }; this.setQ = function(q) { this.parameterType = DSP.Q; this.Q = Math.max(Math.min(q, 115.0), 0.001); this.recalculateCoefficients(); }; this.setBW = function(bw) { this.parameterType = DSP.BW; this.BW = bw; this.recalculateCoefficients(); }; this.setS = function(s) { this.parameterType = DSP.S; this.S = Math.max(Math.min(s, 5.0), 0.0001); this.recalculateCoefficients(); }; this.setF0 = function(freq) { this.f0 = freq; this.recalculateCoefficients(); }; this.setDbGain = function(g) { this.dBgain = g; this.recalculateCoefficients(); }; this.recalculateCoefficients = function() { var A; if (type === DSP.PEAKING_EQ || type === DSP.LOW_SHELF || type === DSP.HIGH_SHELF ) { A = Math.pow(10, (this.dBgain/40)); // for peaking and shelving EQ filters only } else { A = Math.sqrt( Math.pow(10, (this.dBgain/20)) ); } var w0 = DSP.TWO_PI * this.f0 / this.Fs; var cosw0 = Math.cos(w0); var sinw0 = Math.sin(w0); var alpha = 0; switch (this.parameterType) { case DSP.Q: alpha = sinw0/(2*this.Q); break; case DSP.BW: alpha = sinw0 * sinh( Math.LN2/2 * this.BW * w0/sinw0 ); break; case DSP.S: alpha = sinw0/2 * Math.sqrt( (A + 1/A)*(1/this.S - 1) + 2 ); break; } /** FYI: The relationship between bandwidth and Q is 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT) or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype) The relationship between shelf slope and Q is 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2) */ var coeff; switch (this.type) { case DSP.LPF: // H(s) = 1 / (s^2 + s/Q + 1) this.b0 = (1 - cosw0)/2; this.b1 = 1 - cosw0; this.b2 = (1 - cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.HPF: // H(s) = s^2 / (s^2 + s/Q + 1) this.b0 = (1 + cosw0)/2; this.b1 = -(1 + cosw0); this.b2 = (1 + cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_SKIRT: // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) this.b0 = sinw0/2; this.b1 = 0; this.b2 = -sinw0/2; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_PEAK: // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) this.b0 = alpha; this.b1 = 0; this.b2 = -alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.NOTCH: // H(s) = (s^2 + 1) / (s^2 + s/Q + 1) this.b0 = 1; this.b1 = -2*cosw0; this.b2 = 1; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.APF: // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) this.b0 = 1 - alpha; this.b1 = -2*cosw0; this.b2 = 1 + alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.PEAKING_EQ: // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) this.b0 = 1 + alpha*A; this.b1 = -2*cosw0; this.b2 = 1 - alpha*A; this.a0 = 1 + alpha/A; this.a1 = -2*cosw0; this.a2 = 1 - alpha/A; break; case DSP.LOW_SHELF: // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) - (A-1)*cosw0 + coeff); this.b1 = 2*A*((A-1) - (A+1)*cosw0); this.b2 = A*((A+1) - (A-1)*cosw0 - coeff); this.a0 = (A+1) + (A-1)*cosw0 + coeff; this.a1 = -2*((A-1) + (A+1)*cosw0); this.a2 = (A+1) + (A-1)*cosw0 - coeff; break; case DSP.HIGH_SHELF: // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) + (A-1)*cosw0 + coeff); this.b1 = -2*A*((A-1) + (A+1)*cosw0); this.b2 = A*((A+1) + (A-1)*cosw0 - coeff); this.a0 = (A+1) - (A-1)*cosw0 + coeff; this.a1 = 2*((A-1) - (A+1)*cosw0); this.a2 = (A+1) - (A-1)*cosw0 - coeff; break; } this.b0a0 = this.b0/this.a0; this.b1a0 = this.b1/this.a0; this.b2a0 = this.b2/this.a0; this.a1a0 = this.a1/this.a0; this.a2a0 = this.a2/this.a0; }; this.process = function(buffer) { //y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] // - (a1/a0)*y[n-1] - (a2/a0)*y[n-2] var len = buffer.length; var output = new Float32Array(len); for ( var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * @buffer array of magnitudes to convert to decibels * * @returns the array in decibels * */ DSP.mag2db = function(buffer) { var minDb = -120; var minMag = Math.pow(10.0, minDb / 20.0); var log = Math.log; var max = Math.max; var result = Float32Array(buffer.length); for (var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * Calculates the frequency response at the given points. * * @b b coefficients of the filter * @a a coefficients of the filter * @w w points (normally between -PI and PI) where to calculate the frequency response * * @returns the frequency response in magnitude * */ DSP.freqz = function(b, a, w) { var i, j; if (!w) { w = Float32Array(200); for (i=0;i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ function GraphicalEq(sampleRate) { this.FS = sampleRate; this.minFreq = 40.0; this.maxFreq = 16000.0; this.bandsPerOctave = 1.0; this.filters = []; this.freqzs = []; this.calculateFreqzs = true; this.recalculateFilters = function() { var bandCount = Math.round(Math.log(this.maxFreq/this.minFreq) * this.bandsPerOctave/ Math.LN2); this.filters = []; for (var i=0; i (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds."; } if (!gain) { throw "A gain must be passed."; } this.filters[bandIndex].setDbGain(gain); this.recalculateFreqz(bandIndex); }; this.recalculateFreqz = function(bandIndex) { if (!this.calculateFreqzs) { return; } if (bandIndex < 0 || bandIndex > (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds. " + bandIndex + " is out of [" + 0 + ", " + this.filters.length-1 + "]"; } if (!this.w) { this.w = Float32Array(400); for (var i=0; i1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function MultiDelay(maxDelayInSamplesSize, delayInSamples, masterVolume, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ MultiDelay.prototype.setDelayInSamples = function (delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setMasterVolume = function(masterVolume) { this.masterVolume = masterVolume; }; /** * Change the delay feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and adds the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ MultiDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * SingleDelay effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: See usage in Reverb class * * This is a delay that does NOT feeds it's own delayed signal back into its * circular buffer, neither does it return the original signal. Also known as * an AllPassFilter(?). * * Compatible with interleaved stereo (or more channel) buffers and * non-interleaved mono buffers. * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffer) * @param {Number} delayInSamples Initial delay in samples * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function SingleDelay(maxDelayInSamplesSize, delayInSamples, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ SingleDelay.prototype.setDelayInSamples = function(delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the return signal volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ SingleDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and * returns the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ SingleDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * Reverb effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: http://code.almeros.com/code-examples/reverb-firefox-audio-api/ * * This reverb consists of 6 SingleDelays, 6 MultiDelays and an IIRFilter2 * for each of the two stereo channels. * * Compatible with interleaved stereo buffers only! * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffers) * @param {Number} delayInSamples Initial delay in samples for internal (Single/Multi)delays * @param {Number} masterVolume Initial master volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} mixVolume Initial reverb signal mix volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume for internal (Single/Multi)delays. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} dampFrequency Initial low pass filter frequency. 0 to 44100 (depending on your maximum sampling frequency) * * @constructor */ function Reverb(maxDelayInSamplesSize, delayInSamples, masterVolume, mixVolume, delayVolume, dampFrequency) { this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.mixVolume = mixVolume; this.delayVolume = delayVolume; this.dampFrequency = dampFrequency; this.NR_OF_MULTIDELAYS = 6; this.NR_OF_SINGLEDELAYS = 6; this.LOWPASSL = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.LOWPASSR = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.singleDelays = []; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i] = new SingleDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.delayVolume); } this.multiDelays = []; for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i] = new MultiDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.masterVolume, this.delayVolume); } } /** * Change the delay time in samples as a base for all delays. * * @param {Number} delayInSamples Delay in samples */ Reverb.prototype.setDelayInSamples = function (delayInSamples){ this.delayInSamples = delayInSamples; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMasterVolume = function (masterVolume){ this.masterVolume = masterVolume; }; /** * Change the reverb signal mix level. * * @param {Number} mixVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMixVolume = function (mixVolume){ this.mixVolume = mixVolume; }; /** * Change all delays feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setDelayVolume = function (delayVolume){ this.delayVolume = delayVolume; var i; for (i = 0; iWebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: Downsample/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: Downsample/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: Downsample/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: Downsample/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: Downsample/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: Downsample/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: Downsample/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: Downsample/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: Downsample/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: Downsample/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: Downsample/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: Downsample/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: Downsample/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: Downsample/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: Downsample/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: Downsample/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: Downsample/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: Downsample/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: Downsample/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: Downsample/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: Downsample/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: Downsample/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: Isosurface/MIT-LICENSE.txt ================================================ Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Isosurface/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: Isosurface/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: Isosurface/experiment.txt ================================================ Method: tested each algorithm on 65^3 grid. Plotted the function sin(omega * x) + sin(omega * y) + sin(omega * z) in the range [-pi/2, pi/2] x [-pi/2, pi/2] x [-pi/2, pi/2] To control for garbage collection and other unpredictable run time events, each run was repeated 100x to get an averaged measurement. Also, since v8 has a JIT, we ran each method on a grid initialized with omega = 5 for 100 iterations in an attempt to trigger v8's optimizer. Measurements were taken on my laptop: node.js version: 0.6.14 Linux Mint 12 CPU: Intel Core2 Duo P8700 @ 2.53GHz RAM: 4 GB First column is omega, second column is time taken. All measurements are in milliseconds (ms) mc: 0, 29.93 1, 43.62 2, 61.48 3, 93.31 4, 138.2 5, 145.8 6, 186.0 7, 213.2 8, 255.9 9, 272.1 10, 274.6 sn (no precalc): 0, 26.79 1, 33.95 2, 44.87 3, 54.74 4, 59.81 5, 86.61 6, 98.45 7, 114.5 8, 131.2 9, 131.0 10, 147.7 sn (w/ edge precalculation): 0, 24.06 1, 29.42 2, 37.78 3, 47.72 4, 51.36 5, 74.54 6, 83.99 7, 97.34 8, 112.4 9, 109.2 10, 124.3 mt (NOTE: Number of iterations was reduced to 20 in order to get benchmark to complete in a reasonable time): 0, 57 1, 171 2, 250 3, 392 4, 510 5, 620 6, 784 7, 922 8, 1070 9, 1220 10, 1420 Mesh sizes: vertices/faces: sn: 0, 0 7759, 7569 15261, 14513 23247, 22695 30590, 29132 38627, 37749 45957, 43861 53899, 52755 60978, 58304 68991, 67665 76193, 73133 mc: 0, 0 31038, 15520 61034, 30512 93042, 46548 122378, 61204 154758, 77504 184138, 92224 216282, 108484 244514, 122576 277422, 139440 306554, 154168 mt: 0, 0 139770, 42701 214610, 65071 338766, 102805 431466, 130840 553458, 167781 652046, 197603 769878, 233265 869174, 263474 986538, 298725 1087086, 329083 ================================================ FILE: Isosurface/index.html ================================================ Isosurface Toolbox
Isosurface Algorithm Tester
- p for screenshot

Input Data:

Algorithm:

Show facets:

Show edges:

Resolution:

Vertex count:

Face count:

(Approx.) Time:

================================================ FILE: Isosurface/js/benchmark.js ================================================ require('nodetime').profile(); var mesher = require(process.argv[2]).mesher , res = parseInt(process.argv[3]) , max_freq = parseInt(process.argv[4]) , iter_count = parseInt(process.argv[5]); var nr = 2*res + 1 , volume = new Float32Array(nr * nr * nr) , dims = new Int32Array([nr, nr, nr]); function init_volume(freq) { var n = 0, s = 0.5 * freq * Math.PI / res; for(var z=-res; z<=res; ++z) for(var y=-res; y<=res; ++y) for(var x=-res; x<=res; ++x, ++n) { volume[n] = Math.sin(s * x) + Math.sin(s * y) + Math.sin(s * z); } } //Warm up run on noisy volume, try to get JIT to compile meser init_volume(res / 4.0); for(var i=0; i 0) ? 1 << i : 0; } //Compute vertices var edge_mask = edgeTable[cube_index]; if(edge_mask === 0) { continue; } for(var i=0; i<12; ++i) { if((edge_mask & (1< 1e-6) { t = a / d; } for(var j=0; j<3; ++j) { nv[j] = (x[j] + p0[j]) + t * (p1[j] - p0[j]); } vertices.push(nv); } //Add faces var f = triTable[cube_index]; for(var i=0; i 1e-6) { t = g0 / t; } for(var i=0; i<3; ++i) { v[i] += p0[i] + t * (p1[i] - p0[i]); } vertices.push(v); return vertices.length - 1; } //March over the volume for(x[2]=0; x[2] 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Int32Array(4096); return function(data, dims) { var vertices = [] , faces = [] , n = 0 , x = new Int32Array(3) , R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[1]+1)]) , grid = new Float32Array(8) , buf_no = 1; //Resize buffer if necessary if(R[2] * 2 > buffer.length) { buffer = new Int32Array(R[2] * 2); } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1<WebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: Isosurface/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: Isosurface/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: Isosurface/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: Isosurface/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: Isosurface/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: Isosurface/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: Isosurface/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: Isosurface/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: Isosurface/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: Isosurface/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: Isosurface/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: Isosurface/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: Isosurface/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: Isosurface/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: Isosurface/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: Isosurface/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: Isosurface/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: Isosurface/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: Isosurface/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: LevelOfDetail/MIT-LICENSE.txt ================================================ Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: LevelOfDetail/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: LevelOfDetail/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: LevelOfDetail/js/boxfilter.js ================================================ //Naive box filter for downsampling volume function BoxFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k= dims[2]) { iz = 2*dims[2]-2-iz; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0) { iy = -iy; } if(iy >= dims[1]) { iy = 2*dims[1]-2-iy; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0) { ix = -ix; } if(ix >= dims[0]) { ix = 2*dims[0]-2-ix; } s += volume[ix+dims[0]*(iy+dims[1]*(iz))] / (1 << (Math.abs(dx) + Math.abs(dy) + Math.abs(dz))); } } } nvolume[n++] = s / 8.0; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/closing.js ================================================ //Morophological closing filter function ClosingFilter(volume, dims) { "use strict"; //Dilate var pvolume = new Float32Array(dims[0] * dims[1] * dims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } pvolume[n++] = s; } //Erode and downsample var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]); n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = 2*j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = 2*i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, pvolume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/marchingcubes.js ================================================ /** * Javascript Marching Cubes * * Based on Paul Bourke's classic implementation: * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ * * JS port by Mikola Lysenko */ var MarchingCubes = (function() { var edgeTable= new Uint32Array([ 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ]) , triTable = [ [], [0, 8, 3], [0, 1, 9], [1, 8, 3, 9, 8, 1], [1, 2, 10], [0, 8, 3, 1, 2, 10], [9, 2, 10, 0, 2, 9], [2, 8, 3, 2, 10, 8, 10, 9, 8], [3, 11, 2], [0, 11, 2, 8, 11, 0], [1, 9, 0, 2, 3, 11], [1, 11, 2, 1, 9, 11, 9, 8, 11], [3, 10, 1, 11, 10, 3], [0, 10, 1, 0, 8, 10, 8, 11, 10], [3, 9, 0, 3, 11, 9, 11, 10, 9], [9, 8, 10, 10, 8, 11], [4, 7, 8], [4, 3, 0, 7, 3, 4], [0, 1, 9, 8, 4, 7], [4, 1, 9, 4, 7, 1, 7, 3, 1], [1, 2, 10, 8, 4, 7], [3, 4, 7, 3, 0, 4, 1, 2, 10], [9, 2, 10, 9, 0, 2, 8, 4, 7], [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4], [8, 4, 7, 3, 11, 2], [11, 4, 7, 11, 2, 4, 2, 0, 4], [9, 0, 1, 8, 4, 7, 2, 3, 11], [4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1], [3, 10, 1, 3, 11, 10, 7, 8, 4], [1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4], [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3], [4, 7, 11, 4, 11, 9, 9, 11, 10], [9, 5, 4], [9, 5, 4, 0, 8, 3], [0, 5, 4, 1, 5, 0], [8, 5, 4, 8, 3, 5, 3, 1, 5], [1, 2, 10, 9, 5, 4], [3, 0, 8, 1, 2, 10, 4, 9, 5], [5, 2, 10, 5, 4, 2, 4, 0, 2], [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8], [9, 5, 4, 2, 3, 11], [0, 11, 2, 0, 8, 11, 4, 9, 5], [0, 5, 4, 0, 1, 5, 2, 3, 11], [2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5], [10, 3, 11, 10, 1, 3, 9, 5, 4], [4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10], [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3], [5, 4, 8, 5, 8, 10, 10, 8, 11], [9, 7, 8, 5, 7, 9], [9, 3, 0, 9, 5, 3, 5, 7, 3], [0, 7, 8, 0, 1, 7, 1, 5, 7], [1, 5, 3, 3, 5, 7], [9, 7, 8, 9, 5, 7, 10, 1, 2], [10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3], [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2], [2, 10, 5, 2, 5, 3, 3, 5, 7], [7, 9, 5, 7, 8, 9, 3, 11, 2], [9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11], [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7], [11, 2, 1, 11, 1, 7, 7, 1, 5], [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11], [5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0], [11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0], [11, 10, 5, 7, 11, 5], [10, 6, 5], [0, 8, 3, 5, 10, 6], [9, 0, 1, 5, 10, 6], [1, 8, 3, 1, 9, 8, 5, 10, 6], [1, 6, 5, 2, 6, 1], [1, 6, 5, 1, 2, 6, 3, 0, 8], [9, 6, 5, 9, 0, 6, 0, 2, 6], [5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8], [2, 3, 11, 10, 6, 5], [11, 0, 8, 11, 2, 0, 10, 6, 5], [0, 1, 9, 2, 3, 11, 5, 10, 6], [5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11], [6, 3, 11, 6, 5, 3, 5, 1, 3], [0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6], [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9], [6, 5, 9, 6, 9, 11, 11, 9, 8], [5, 10, 6, 4, 7, 8], [4, 3, 0, 4, 7, 3, 6, 5, 10], [1, 9, 0, 5, 10, 6, 8, 4, 7], [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4], [6, 1, 2, 6, 5, 1, 4, 7, 8], [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7], [8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6], [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9], [3, 11, 2, 7, 8, 4, 10, 6, 5], [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11], [0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6], [9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6], [8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6], [5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11], [0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7], [6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9], [10, 4, 9, 6, 4, 10], [4, 10, 6, 4, 9, 10, 0, 8, 3], [10, 0, 1, 10, 6, 0, 6, 4, 0], [8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10], [1, 4, 9, 1, 2, 4, 2, 6, 4], [3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4], [0, 2, 4, 4, 2, 6], [8, 3, 2, 8, 2, 4, 4, 2, 6], [10, 4, 9, 10, 6, 4, 11, 2, 3], [0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6], [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10], [6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1], [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3], [8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1], [3, 11, 6, 3, 6, 0, 0, 6, 4], [6, 4, 8, 11, 6, 8], [7, 10, 6, 7, 8, 10, 8, 9, 10], [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10], [10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0], [10, 6, 7, 10, 7, 1, 1, 7, 3], [1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7], [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9], [7, 8, 0, 7, 0, 6, 6, 0, 2], [7, 3, 2, 6, 7, 2], [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7], [2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7], [1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11], [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1], [8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6], [0, 9, 1, 11, 6, 7], [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0], [7, 11, 6], [7, 6, 11], [3, 0, 8, 11, 7, 6], [0, 1, 9, 11, 7, 6], [8, 1, 9, 8, 3, 1, 11, 7, 6], [10, 1, 2, 6, 11, 7], [1, 2, 10, 3, 0, 8, 6, 11, 7], [2, 9, 0, 2, 10, 9, 6, 11, 7], [6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8], [7, 2, 3, 6, 2, 7], [7, 0, 8, 7, 6, 0, 6, 2, 0], [2, 7, 6, 2, 3, 7, 0, 1, 9], [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6], [10, 7, 6, 10, 1, 7, 1, 3, 7], [10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8], [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7], [7, 6, 10, 7, 10, 8, 8, 10, 9], [6, 8, 4, 11, 8, 6], [3, 6, 11, 3, 0, 6, 0, 4, 6], [8, 6, 11, 8, 4, 6, 9, 0, 1], [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6], [6, 8, 4, 6, 11, 8, 2, 10, 1], [1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6], [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9], [10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3], [8, 2, 3, 8, 4, 2, 4, 6, 2], [0, 4, 2, 4, 6, 2], [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8], [1, 9, 4, 1, 4, 2, 2, 4, 6], [8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1], [10, 1, 0, 10, 0, 6, 6, 0, 4], [4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3], [10, 9, 4, 6, 10, 4], [4, 9, 5, 7, 6, 11], [0, 8, 3, 4, 9, 5, 11, 7, 6], [5, 0, 1, 5, 4, 0, 7, 6, 11], [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5], [9, 5, 4, 10, 1, 2, 7, 6, 11], [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5], [7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2], [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6], [7, 2, 3, 7, 6, 2, 5, 4, 9], [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7], [3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0], [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8], [9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7], [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4], [4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10], [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10], [6, 9, 5, 6, 11, 9, 11, 8, 9], [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5], [0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11], [6, 11, 3, 6, 3, 5, 5, 3, 1], [1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6], [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10], [11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5], [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3], [5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2], [9, 5, 6, 9, 6, 0, 0, 6, 2], [1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8], [1, 5, 6, 2, 1, 6], [1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6], [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0], [0, 3, 8, 5, 6, 10], [10, 5, 6], [11, 5, 10, 7, 5, 11], [11, 5, 10, 11, 7, 5, 8, 3, 0], [5, 11, 7, 5, 10, 11, 1, 9, 0], [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1], [11, 1, 2, 11, 7, 1, 7, 5, 1], [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11], [9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7], [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2], [2, 5, 10, 2, 3, 5, 3, 7, 5], [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5], [9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2], [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2], [1, 3, 5, 3, 7, 5], [0, 8, 7, 0, 7, 1, 1, 7, 5], [9, 0, 3, 9, 3, 5, 5, 3, 7], [9, 8, 7, 5, 9, 7], [5, 8, 4, 5, 10, 8, 10, 11, 8], [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0], [0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5], [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4], [2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8], [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11], [0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5], [9, 4, 5, 2, 11, 3], [2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4], [5, 10, 2, 5, 2, 4, 4, 2, 0], [3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9], [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2], [8, 4, 5, 8, 5, 3, 3, 5, 1], [0, 4, 5, 1, 0, 5], [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5], [9, 4, 5], [4, 11, 7, 4, 9, 11, 9, 10, 11], [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11], [1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11], [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4], [4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2], [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3], [11, 7, 4, 11, 4, 2, 2, 4, 0], [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4], [2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9], [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7], [3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10], [1, 10, 2, 8, 7, 4], [4, 9, 1, 4, 1, 7, 7, 1, 3], [4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1], [4, 0, 3, 7, 4, 3], [4, 8, 7], [9, 10, 8, 10, 11, 8], [3, 0, 9, 3, 9, 11, 11, 9, 10], [0, 1, 10, 0, 10, 8, 8, 10, 11], [3, 1, 10, 11, 3, 10], [1, 2, 11, 1, 11, 9, 9, 11, 8], [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9], [0, 2, 11, 8, 0, 11], [3, 2, 11], [2, 3, 8, 2, 8, 10, 10, 8, 9], [9, 10, 2, 0, 9, 2], [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8], [1, 10, 2], [1, 3, 8, 9, 1, 8], [0, 9, 1], [0, 3, 8], []] , cubeVerts = [ [0,0,0] ,[1,0,0] ,[1,1,0] ,[0,1,0] ,[0,0,1] ,[1,0,1] ,[1,1,1] ,[0,1,1]] , edgeIndex = [ [0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7] ]; return function(data, dims) { var vertices = [] , faces = [] , n = 0 , grid = new Float32Array(8) , edges = new Int32Array(12) , x = new Int32Array(3); //March over the volume for(x[2]=0; x[2] 0) ? 1 << i : 0; } //Compute vertices var edge_mask = edgeTable[cube_index]; if(edge_mask === 0) { continue; } for(var i=0; i<12; ++i) { if((edge_mask & (1< 1e-6) { t = a / d; } for(var j=0; j<3; ++j) { nv[j] = (x[j] + p0[j]) + t * (p1[j] - p0[j]); } vertices.push(nv); } //Add faces var f = triTable[cube_index]; for(var i=0; i 1e-6) { t = g0 / t; } for(var i=0; i<3; ++i) { v[i] += p0[i] + t * (p1[i] - p0[i]); } vertices.push(v); return vertices.length - 1; } //March over the volume for(x[2]=0; x[2]=dims[2]) { continue; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/medianfilter.js ================================================ //Median filter function MedianFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0 , ranks = new Array(27); for(var k=0; k= dims[2]) { iz = 2*dims[2]-2-iz; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0) { iy = -iy; } if(iy >= dims[1]) { iy = 2*dims[1]-2-iy; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0) { ix = -ix; } if(ix >= dims[0]) { ix = 2*dims[0]-2-ix; } ranks[idx++] = volume[ix+dims[0]*(iy+dims[1]*(iz))]; } } } var ranked = ranks.sort(function(a,b){ return b < a ? -1 : b>a ? 1 : 0; }); nvolume[n++] = 0.5 * (ranked[Math.floor(idx/2)] + ranked[Math.floor(idx/2)+1]); } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/minfilter.js ================================================ //Minimum filter function MinFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i] / 2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<2; ++dy) { var iy = 2*(j)+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<2; ++dx) { var ix = 2*(i)+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/nearestfilter.js ================================================ //Naive box filter for downsampling volume function NearestFilter(volume, dims) { "use strict"; var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.floor(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]) , n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.max(s, volume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } pvolume[n++] = s; } //Dilate var ndims = new Int32Array(3); for(var i=0; i<3; ++i) { ndims[i] = Math.ceil(dims[i]/2); } var nvolume = new Float32Array(ndims[0] * ndims[1] * ndims[2]); n = 0; for(var k=0; k=dims[2]) { continue; } for(var dy=-1; dy<=1; ++dy) { var iy = 2*j+dy; if(iy < 0 || iy >= dims[1]) { continue; } for(var dx=-1; dx<=1; ++dx) { var ix = 2*i+dx; if(ix < 0 || ix >= dims[0]) { continue; } s = Math.min(s, pvolume[ix+dims[0]*(iy+dims[1]*(iz))]); } } } nvolume[n++] = s; } return { volume: nvolume, dims:ndims }; } ================================================ FILE: LevelOfDetail/js/perlinnoise.js ================================================ //This code is from Kas Thomas' blog: // http://asserttrue.blogspot.de/2011/12/perlin-noise-in-javascript_31.html // This is a port of Ken Perlin's Java code. The // original Java code is at http://cs.nyu.edu/%7Eperlin/noise/. // Note that in this version, a number from 0 to 1 is returned. PerlinNoise = new function() { this.noise = function(x, y, z) { var p = new Array(512) var permutation = [ 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ]; for (var i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; var X = Math.floor(x) & 255, // FIND UNIT CUBE THAT Y = Math.floor(y) & 255, // CONTAINS POINT. Z = Math.floor(z) & 255; x -= Math.floor(x); // FIND RELATIVE X,Y,Z y -= Math.floor(y); // OF POINT IN CUBE. z -= Math.floor(z); var u = fade(x), // COMPUTE FADE CURVES v = fade(y), // FOR EACH OF X,Y,Z. w = fade(z); var A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, return scale(lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD grad(p[BA ], x-1, y , z )), // BLENDED lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS grad(p[BB ], x-1, y-1, z ))),// FROM 8 lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS grad(p[BA+1], x-1, y , z-1 )), // OF CUBE lerp(u, grad(p[AB+1], x , y-1, z-1 ), grad(p[BB+1], x-1, y-1, z-1 ))))); } function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); } function lerp( t, a, b) { return a + t * (b - a); } function grad(hash, x, y, z) { var h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE var u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. v = h<4 ? y : h==12||h==14 ? x : z; return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); } function scale(n) { return (1 + n)/2; } } ================================================ FILE: LevelOfDetail/js/surfacenets.js ================================================ /** * SurfaceNets in JavaScript * * Written by Mikola Lysenko (C) 2012 * * MIT License * * Based on: S.F. Gibson, "Constrained Elastic Surface Nets". (1998) MERL Tech Report. */ var SurfaceNets = (function() { "use strict"; //Precompute edge table, like Paul Bourke does. // This saves a bit of time when computing the centroid of each boundary cell var cube_edges = new Int32Array(24) , edge_table = new Int32Array(256); (function() { //Initialize the cube_edges table // This is just the vertex number of each cube var k = 0; for(var i=0; i<8; ++i) { for(var j=1; j<=4; j<<=1) { var p = i^j; if(i <= p) { cube_edges[k++] = i; cube_edges[k++] = p; } } } //Initialize the intersection table. // This is a 2^(cube configuration) -> 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Int32Array(4096); return function(data, dims) { var vertices = [] , faces = [] , n = 0 , x = new Int32Array(3) , R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[0]+1)]) , grid = new Float32Array(8) , buf_no = 1; //Resize buffer if necessary if(R[2] * 2 > buffer.length) { buffer = new Int32Array(R[2] * 2); } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1< 54 ) { t = Math.max(t, x - 54); } if( y > 54 ) { t = Math.max(t, y - 54); } if( z > 54 ) { t = Math.max(t, z - 54); } return t; } ); result["Goursat's Surface"] = makeVolume( [[-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0]], function(x,y,z) { return Math.pow(x,4) + Math.pow(y,4) + Math.pow(z,4) - 1.5 * (x*x + y*y + z*z) + 1; } ); result["Heart"] = makeVolume( [[-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0]], function(x,y,z) { y *= 1.5; z *= 1.5; return Math.pow(2*x*x+y*y+2*z*z-1, 3) - 0.1 * z*z*y*y*y - y*y*y*x*x; } ); result['Noise (Slow)'] = makeVolume( [[-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0]], function(x,y,z) { if(x < -1.0 || x > 1.0 || y < -1.0 || y > 1.0 || z < -1.0 || z > 1.0 ) { return 0.6; } return 0.6 - PerlinNoise.noise(4.0 * x, 4.0 * y, 4.0 * z); } ); result['Asteroid (Slow)'] = makeVolume( [[-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0]], function(x,y,z) { return (x*x + y*y + z*z) - PerlinNoise.noise(x*2,y*2,z*2); } ); result['Terrain (Slow)'] = makeVolume( [[-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0]], function(x,y,z) { return y + PerlinNoise.noise(x*2+5,y*2+3,z*2+0.6); } ); result['Empty'] = function(){ return { volume: new Float32Array(32*32*32), dims:[32,32,32] } }; return result; } ================================================ FILE: LevelOfDetail/vendor/dsp.js ================================================ /* * DSP.js - a comprehensive digital signal processing library for javascript * * Created by Corban Brook on 2010-01-01. * Copyright 2010 Corban Brook. All rights reserved. * */ //////////////////////////////////////////////////////////////////////////////// // CONSTANTS // //////////////////////////////////////////////////////////////////////////////// /** * DSP is an object which contains general purpose utility functions and constants */ var DSP = { // Channels LEFT: 0, RIGHT: 1, MIX: 2, // Waveforms SINE: 1, TRIANGLE: 2, SAW: 3, SQUARE: 4, // Filters LOWPASS: 0, HIGHPASS: 1, BANDPASS: 2, NOTCH: 3, // Window functions BARTLETT: 1, BARTLETTHANN: 2, BLACKMAN: 3, COSINE: 4, GAUSS: 5, HAMMING: 6, HANN: 7, LANCZOS: 8, RECTANGULAR: 9, TRIANGULAR: 10, // Loop modes OFF: 0, FW: 1, BW: 2, FWBW: 3, // Math TWO_PI: 2*Math.PI }; // Setup arrays for platforms which do not support byte arrays function setupTypedArray(name, fallback) { // check if TypedArray exists // typeof on Minefield and Chrome return function, typeof on Webkit returns object. if (typeof this[name] !== "function" && typeof this[name] !== "object") { // nope.. check if WebGLArray exists if (typeof this[fallback] === "function" && typeof this[fallback] !== "object") { this[name] = this[fallback]; } else { // nope.. set as Native JS array this[name] = function(obj) { if (obj instanceof Array) { return obj; } else if (typeof obj === "number") { return new Array(obj); } }; } } } setupTypedArray("Float32Array", "WebGLFloatArray"); setupTypedArray("Int32Array", "WebGLIntArray"); setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"); setupTypedArray("Uint8Array", "WebGLUnsignedByteArray"); //////////////////////////////////////////////////////////////////////////////// // DSP UTILITY FUNCTIONS // //////////////////////////////////////////////////////////////////////////////// /** * Inverts the phase of a signal * * @param {Array} buffer A sample buffer * * @returns The inverted sample buffer */ DSP.invert = function(buffer) { for (var i = 0, len = buffer.length; i < len; i++) { buffer[i] *= -1; } return buffer; }; /** * Converts split-stereo (dual mono) sample buffers into a stereo interleaved sample buffer * * @param {Array} left A sample buffer * @param {Array} right A sample buffer * * @returns The stereo interleaved buffer */ DSP.interleave = function(left, right) { if (left.length !== right.length) { throw "Can not interleave. Channel lengths differ."; } var stereoInterleaved = new Float32Array(left.length * 2); for (var i = 0, len = left.length; i < len; i++) { stereoInterleaved[2*i] = left[i]; stereoInterleaved[2*i+1] = right[i]; } return stereoInterleaved; }; /** * Converts a stereo-interleaved sample buffer into split-stereo (dual mono) sample buffers * * @param {Array} buffer A stereo-interleaved sample buffer * * @returns an Array containing left and right channels */ DSP.deinterleave = (function() { var left, right, mix, deinterleaveChannel = []; deinterleaveChannel[DSP.MIX] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { mix[i] = (buffer[2*i] + buffer[2*i+1]) / 2; } return mix; }; deinterleaveChannel[DSP.LEFT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { left[i] = buffer[2*i]; } return left; }; deinterleaveChannel[DSP.RIGHT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { right[i] = buffer[2*i+1]; } return right; }; return function(channel, buffer) { left = left || new Float32Array(buffer.length/2); right = right || new Float32Array(buffer.length/2); mix = mix || new Float32Array(buffer.length/2); if (buffer.length/2 !== left.length) { left = new Float32Array(buffer.length/2); right = new Float32Array(buffer.length/2); mix = new Float32Array(buffer.length/2); } return deinterleaveChannel[channel](buffer); }; }()); /** * Separates a channel from a stereo-interleaved sample buffer * * @param {Array} buffer A stereo-interleaved sample buffer * @param {Number} channel A channel constant (LEFT, RIGHT, MIX) * * @returns an Array containing a signal mono sample buffer */ DSP.getChannel = DSP.deinterleave; /** * Helper method (for Reverb) to mix two (interleaved) samplebuffers. It's possible * to negate the second buffer while mixing and to perform a volume correction * on the final signal. * * @param {Array} sampleBuffer1 Array containing Float values or a Float32Array * @param {Array} sampleBuffer2 Array containing Float values or a Float32Array * @param {Boolean} negate When true inverts/flips the audio signal * @param {Number} volumeCorrection When you add multiple sample buffers, use this to tame your signal ;) * * @returns A new Float32Array interleaved buffer. */ DSP.mixSampleBuffers = function(sampleBuffer1, sampleBuffer2, negate, volumeCorrection){ var outputSamples = new Float32Array(sampleBuffer1); for(var i = 0; i peak) ? Math.abs(buffer[i]) : peak; } return peak; }; // Fourier Transform Module used by DFT, FFT, RFFT function FourierTransform(bufferSize, sampleRate) { this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.bandwidth = 2 / bufferSize * sampleRate / 2; this.spectrum = new Float32Array(bufferSize/2); this.real = new Float32Array(bufferSize); this.imag = new Float32Array(bufferSize); this.peakBand = 0; this.peak = 0; /** * Calculates the *middle* frequency of an FFT band. * * @param {Number} index The index of the FFT band. * * @returns The middle frequency in Hz. */ this.getBandFrequency = function(index) { return this.bandwidth * index + this.bandwidth / 2; }; this.calculateSpectrum = function() { var spectrum = this.spectrum, real = this.real, imag = this.imag, bSi = 2 / this.bufferSize, sqrt = Math.sqrt, rval, ival, mag; for (var i = 0, N = bufferSize/2; i < N; i++) { rval = real[i]; ival = imag[i]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } }; } /** * DFT is a class for calculating the Discrete Fourier Transform of a signal. * * @param {Number} bufferSize The size of the sample buffer to be computed * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function DFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); var N = bufferSize/2 * bufferSize; var TWO_PI = 2 * Math.PI; this.sinTable = new Float32Array(N); this.cosTable = new Float32Array(N); for (var i = 0; i < N; i++) { this.sinTable[i] = Math.sin(i * TWO_PI / bufferSize); this.cosTable[i] = Math.cos(i * TWO_PI / bufferSize); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer * * @returns The frequency spectrum array */ DFT.prototype.forward = function(buffer) { var real = this.real, imag = this.imag, rval, ival; for (var k = 0; k < this.bufferSize/2; k++) { rval = 0.0; ival = 0.0; for (var n = 0; n < buffer.length; n++) { rval += this.cosTable[k*n] * buffer[n]; ival += this.sinTable[k*n] * buffer[n]; } real[k] = rval; imag[k] = ival; } return this.calculateSpectrum(); }; /** * FFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function FFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.reverseTable = new Uint32Array(bufferSize); var limit = 1; var bit = bufferSize >> 1; var i; while (limit < bufferSize) { for (i = 0; i < limit; i++) { this.reverseTable[i + limit] = this.reverseTable[i] + bit; } limit = limit << 1; bit = bit >> 1; } this.sinTable = new Float32Array(bufferSize); this.cosTable = new Float32Array(bufferSize); for (i = 0; i < bufferSize; i++) { this.sinTable[i] = Math.sin(-Math.PI/i); this.cosTable[i] = Math.cos(-Math.PI/i); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer. Buffer Length must be power of 2 * * @returns The frequency spectrum array */ FFT.prototype.forward = function(buffer) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, real = this.real, imag = this.imag, spectrum = this.spectrum; var k = Math.floor(Math.log(bufferSize) / Math.LN2); if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; } if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; } var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { real[i] = buffer[reverseTable[i]]; imag[i] = 0; } while (halfSize < bufferSize) { //phaseShiftStepReal = Math.cos(-Math.PI/halfSize); //phaseShiftStepImag = Math.sin(-Math.PI/halfSize); phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } return this.calculateSpectrum(); }; FFT.prototype.inverse = function(real, imag) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, spectrum = this.spectrum; real = real || this.real; imag = imag || this.imag; var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { imag[i] *= -1; } var revReal = new Float32Array(bufferSize); var revImag = new Float32Array(bufferSize); for (i = 0; i < real.length; i++) { revReal[i] = real[reverseTable[i]]; revImag[i] = imag[reverseTable[i]]; } real = revReal; imag = revImag; while (halfSize < bufferSize) { phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } var buffer = new Float32Array(bufferSize); // this should be reused instead for (i = 0; i < bufferSize; i++) { buffer[i] = real[i] / bufferSize; } return buffer; }; /** * RFFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * This method currently only contains a forward transform but is highly optimized. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ // lookup tables don't really gain us any speed, but they do increase // cache footprint, so don't use them in here // also we don't use sepearate arrays for real/imaginary parts // this one a little more than twice as fast as the one in FFT // however I only did the forward transform // the rest of this was translated from C, see http://www.jjj.de/fxt/ // this is the real split radix FFT function RFFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.trans = new Float32Array(bufferSize); this.reverseTable = new Uint32Array(bufferSize); // don't use a lookup table to do the permute, use this instead this.reverseBinPermute = function (dest, source) { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; dest[0] = source[0]; do { r += halfSize; dest[i] = source[r]; dest[r] = source[i]; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { dest[i] = source[r]; dest[r] = source[i]; dest[nm1-i] = source[nm1-r]; dest[nm1-r] = source[nm1-i]; } i++; } while (i < halfSize); dest[nm1] = source[nm1]; }; this.generateReverseTable = function () { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; this.reverseTable[0] = 0; do { r += halfSize; this.reverseTable[i] = r; this.reverseTable[r] = i; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { this.reverseTable[i] = r; this.reverseTable[r] = i; this.reverseTable[nm1-i] = nm1-r; this.reverseTable[nm1-r] = nm1-i; } i++; } while (i < halfSize); this.reverseTable[nm1] = nm1; }; this.generateReverseTable(); } // Ordering of output: // // trans[0] = re[0] (==zero frequency, purely real) // trans[1] = re[1] // ... // trans[n/2-1] = re[n/2-1] // trans[n/2] = re[n/2] (==nyquist frequency, purely real) // // trans[n/2+1] = im[n/2-1] // trans[n/2+2] = im[n/2-2] // ... // trans[n-1] = im[1] RFFT.prototype.forward = function(buffer) { var n = this.bufferSize, spectrum = this.spectrum, x = this.trans, TWO_PI = 2*Math.PI, sqrt = Math.sqrt, i = n >>> 1, bSi = 2 / n, n2, n4, n8, nn, t1, t2, t3, t4, i1, i2, i3, i4, i5, i6, i7, i8, st1, cc1, ss1, cc3, ss3, e, a, rval, ival, mag; this.reverseBinPermute(x, buffer); /* var reverseTable = this.reverseTable; for (var k = 0, len = reverseTable.length; k < len; k++) { x[k] = buffer[reverseTable[k]]; } */ for (var ix = 0, id = 4; ix < n; id *= 4) { for (var i0 = ix; i0 < n; i0 += id) { //sumdiff(x[i0], x[i0+1]); // {a, b} <--| {a+b, a-b} st1 = x[i0] - x[i0+1]; x[i0] += x[i0+1]; x[i0+1] = st1; } ix = 2*(id-1); } n2 = 2; nn = n >>> 1; while((nn = nn >>> 1)) { ix = 0; n2 = n2 << 1; id = n2 << 1; n4 = n2 >>> 2; n8 = n2 >>> 3; do { if(n4 !== 1) { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; i1 += n8; i2 += n8; i3 += n8; i4 += n8; //sumdiff(x[i3], x[i4], t1, t2); // {s, d} <--| {a+b, a-b} t1 = x[i3] + x[i4]; t2 = x[i3] - x[i4]; t1 = -t1 * Math.SQRT1_2; t2 *= Math.SQRT1_2; // sumdiff(t1, x[i2], x[i4], x[i3]); // {s, d} <--| {a+b, a-b} st1 = x[i2]; x[i4] = t1 + st1; x[i3] = t1 - st1; //sumdiff3(x[i1], t2, x[i2]); // {a, b, d} <--| {a+b, b, a-b} x[i2] = x[i1] - t2; x[i1] += t2; } } else { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; } } ix = (id << 1) - n2; id = id << 2; } while (ix < n); e = TWO_PI / n2; for (var j = 1; j < n8; j++) { a = j * e; ss1 = Math.sin(a); cc1 = Math.cos(a); //ss3 = sin(3*a); cc3 = cos(3*a); cc3 = 4*cc1*(cc1*cc1-0.75); ss3 = 4*ss1*(0.75-ss1*ss1); ix = 0; id = n2 << 1; do { for (i0 = ix; i0 < n; i0 += id) { i1 = i0 + j; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; i5 = i0 + n4 - j; i6 = i5 + n4; i7 = i6 + n4; i8 = i7 + n4; //cmult(c, s, x, y, &u, &v) //cmult(cc1, ss1, x[i7], x[i3], t2, t1); // {u,v} <--| {x*c-y*s, x*s+y*c} t2 = x[i7]*cc1 - x[i3]*ss1; t1 = x[i7]*ss1 + x[i3]*cc1; //cmult(cc3, ss3, x[i8], x[i4], t4, t3); t4 = x[i8]*cc3 - x[i4]*ss3; t3 = x[i8]*ss3 + x[i4]*cc3; //sumdiff(t2, t4); // {a, b} <--| {a+b, a-b} st1 = t2 - t4; t2 += t4; t4 = st1; //sumdiff(t2, x[i6], x[i8], x[i3]); // {s, d} <--| {a+b, a-b} //st1 = x[i6]; x[i8] = t2 + st1; x[i3] = t2 - st1; x[i8] = t2 + x[i6]; x[i3] = t2 - x[i6]; //sumdiff_r(t1, t3); // {a, b} <--| {a+b, b-a} st1 = t3 - t1; t1 += t3; t3 = st1; //sumdiff(t3, x[i2], x[i4], x[i7]); // {s, d} <--| {a+b, a-b} //st1 = x[i2]; x[i4] = t3 + st1; x[i7] = t3 - st1; x[i4] = t3 + x[i2]; x[i7] = t3 - x[i2]; //sumdiff3(x[i1], t1, x[i6]); // {a, b, d} <--| {a+b, b, a-b} x[i6] = x[i1] - t1; x[i1] += t1; //diffsum3_r(t4, x[i5], x[i2]); // {a, b, s} <--| {a, b-a, a+b} x[i2] = t4 + x[i5]; x[i5] -= t4; } ix = (id << 1) - n2; id = id << 2; } while (ix < n); } } while (--i) { rval = x[i]; ival = x[n-i-1]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } spectrum[0] = bSi * x[0]; return spectrum; }; function Sampler(file, bufferSize, sampleRate, playStart, playEnd, loopStart, loopEnd, loopMode) { this.file = file; this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.playStart = playStart || 0; // 0% this.playEnd = playEnd || 1; // 100% this.loopStart = loopStart || 0; this.loopEnd = loopEnd || 1; this.loopMode = loopMode || DSP.OFF; this.loaded = false; this.samples = []; this.signal = new Float32Array(bufferSize); this.frameCount = 0; this.envelope = null; this.amplitude = 1; this.rootFrequency = 110; // A2 110 this.frequency = 550; this.step = this.frequency / this.rootFrequency; this.duration = 0; this.samplesProcessed = 0; this.playhead = 0; var audio = /* new Audio();*/ document.createElement("AUDIO"); var self = this; this.loadSamples = function(event) { var buffer = DSP.getChannel(DSP.MIX, event.frameBuffer); for ( var i = 0; i < buffer.length; i++) { self.samples.push(buffer[i]); } }; this.loadComplete = function() { // convert flexible js array into a fast typed array self.samples = new Float32Array(self.samples); self.loaded = true; }; this.loadMetaData = function() { self.duration = audio.duration; }; audio.addEventListener("MozAudioAvailable", this.loadSamples, false); audio.addEventListener("loadedmetadata", this.loadMetaData, false); audio.addEventListener("ended", this.loadComplete, false); audio.muted = true; audio.src = file; audio.play(); } Sampler.prototype.applyEnvelope = function() { this.envelope.process(this.signal); return this.signal; }; Sampler.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var loopWidth = this.playEnd * this.samples.length - this.playStart * this.samples.length; var playStartSamples = this.playStart * this.samples.length; // ie 0.5 -> 50% of the length var playEndSamples = this.playEnd * this.samples.length; // ie 0.5 -> 50% of the length var offset; for ( var i = 0; i < this.bufferSize; i++ ) { switch (this.loopMode) { case DSP.OFF: this.playhead = Math.round(this.samplesProcessed * this.step + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } else { this.signal[i] = 0; } break; case DSP.FW: this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.BW: this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.FWBW: if ( Math.floor(this.samplesProcessed * this.step / loopWidth) % 2 === 0 ) { this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); } else { this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); } if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; } this.samplesProcessed++; } this.frameCount++; return this.signal; }; Sampler.prototype.setFreq = function(frequency) { var totalProcessed = this.samplesProcessed * this.step; this.frequency = frequency; this.step = this.frequency / this.rootFrequency; this.samplesProcessed = Math.round(totalProcessed/this.step); }; Sampler.prototype.reset = function() { this.samplesProcessed = 0; this.playhead = 0; }; /** * Oscillator class for generating and modifying signals * * @param {Number} type A waveform constant (eg. DSP.SINE) * @param {Number} frequency Initial frequency of the signal * @param {Number} amplitude Initial amplitude of the signal * @param {Number} bufferSize Size of the sample buffer to generate * @param {Number} sampleRate The sample rate of the signal * * @contructor */ function Oscillator(type, frequency, amplitude, bufferSize, sampleRate) { this.frequency = frequency; this.amplitude = amplitude; this.bufferSize = bufferSize; this.sampleRate = sampleRate; //this.pulseWidth = pulseWidth; this.frameCount = 0; this.waveTableLength = 2048; this.cyclesPerSample = frequency / sampleRate; this.signal = new Float32Array(bufferSize); this.envelope = null; switch(parseInt(type, 10)) { case DSP.TRIANGLE: this.func = Oscillator.Triangle; break; case DSP.SAW: this.func = Oscillator.Saw; break; case DSP.SQUARE: this.func = Oscillator.Square; break; default: case DSP.SINE: this.func = Oscillator.Sine; break; } this.generateWaveTable = function() { Oscillator.waveTable[this.func] = new Float32Array(2048); var waveTableTime = this.waveTableLength / this.sampleRate; var waveTableHz = 1 / waveTableTime; for (var i = 0; i < this.waveTableLength; i++) { Oscillator.waveTable[this.func][i] = this.func(i * waveTableHz/this.sampleRate); } }; if ( typeof Oscillator.waveTable === 'undefined' ) { Oscillator.waveTable = {}; } if ( typeof Oscillator.waveTable[this.func] === 'undefined' ) { this.generateWaveTable(); } this.waveTable = Oscillator.waveTable[this.func]; } /** * Set the amplitude of the signal * * @param {Number} amplitude The amplitude of the signal (between 0 and 1) */ Oscillator.prototype.setAmp = function(amplitude) { if (amplitude >= 0 && amplitude <= 1) { this.amplitude = amplitude; } else { throw "Amplitude out of range (0..1)."; } }; /** * Set the frequency of the signal * * @param {Number} frequency The frequency of the signal */ Oscillator.prototype.setFreq = function(frequency) { this.frequency = frequency; this.cyclesPerSample = frequency / this.sampleRate; }; // Add an oscillator Oscillator.prototype.add = function(oscillator) { for ( var i = 0; i < this.bufferSize; i++ ) { //this.signal[i] += oscillator.valueAt(i); this.signal[i] += oscillator.signal[i]; } return this.signal; }; // Add a signal to the current generated osc signal Oscillator.prototype.addSignal = function(signal) { for ( var i = 0; i < signal.length; i++ ) { if ( i >= this.bufferSize ) { break; } this.signal[i] += signal[i]; /* // Constrain amplitude if ( this.signal[i] > 1 ) { this.signal[i] = 1; } else if ( this.signal[i] < -1 ) { this.signal[i] = -1; } */ } return this.signal; }; // Add an envelope to the oscillator Oscillator.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; Oscillator.prototype.applyEnvelope = function() { this.envelope.process(this.signal); }; Oscillator.prototype.valueAt = function(offset) { return this.waveTable[offset % this.waveTableLength]; }; Oscillator.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var step = this.waveTableLength * this.frequency / this.sampleRate; var offset; for ( var i = 0; i < this.bufferSize; i++ ) { //var step = (frameOffset + i) * this.cyclesPerSample % 1; //this.signal[i] = this.func(step) * this.amplitude; //this.signal[i] = this.valueAt(Math.round((frameOffset + i) * step)) * this.amplitude; offset = Math.round((frameOffset + i) * step); this.signal[i] = this.waveTable[offset % this.waveTableLength] * this.amplitude; } this.frameCount++; return this.signal; }; Oscillator.Sine = function(step) { return Math.sin(DSP.TWO_PI * step); }; Oscillator.Square = function(step) { return step < 0.5 ? 1 : -1; }; Oscillator.Saw = function(step) { return 2 * (step - Math.round(step)); }; Oscillator.Triangle = function(step) { return 1 - 4 * Math.abs(Math.round(step) - step); }; Oscillator.Pulse = function(step) { // stub }; function ADSR(attackLength, decayLength, sustainLevel, sustainLength, releaseLength, sampleRate) { this.sampleRate = sampleRate; // Length in seconds this.attackLength = attackLength; this.decayLength = decayLength; this.sustainLevel = sustainLevel; this.sustainLength = sustainLength; this.releaseLength = releaseLength; this.sampleRate = sampleRate; // Length in samples this.attackSamples = attackLength * sampleRate; this.decaySamples = decayLength * sampleRate; this.sustainSamples = sustainLength * sampleRate; this.releaseSamples = releaseLength * sampleRate; // Updates the envelope sample positions this.update = function() { this.attack = this.attackSamples; this.decay = this.attack + this.decaySamples; this.sustain = this.decay + this.sustainSamples; this.release = this.sustain + this.releaseSamples; }; this.update(); this.samplesProcessed = 0; } ADSR.prototype.noteOn = function() { this.samplesProcessed = 0; this.sustainSamples = this.sustainLength * this.sampleRate; this.update(); }; // Send a note off when using a sustain of infinity to let the envelope enter the release phase ADSR.prototype.noteOff = function() { this.sustainSamples = this.samplesProcessed - this.decaySamples; this.update(); }; ADSR.prototype.processSample = function(sample) { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return sample * amplitude; }; ADSR.prototype.value = function() { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return amplitude; }; ADSR.prototype.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { buffer[i] *= this.value(); this.samplesProcessed++; } return buffer; }; ADSR.prototype.isActive = function() { if ( this.samplesProcessed > this.release || this.samplesProcessed === -1 ) { return false; } else { return true; } }; ADSR.prototype.disable = function() { this.samplesProcessed = -1; }; function IIRFilter(type, cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; switch(type) { case DSP.LOWPASS: case DSP.LP12: this.func = new IIRFilter.LP12(cutoff, resonance, sampleRate); break; } } IIRFilter.prototype.__defineGetter__('cutoff', function() { return this.func.cutoff; } ); IIRFilter.prototype.__defineGetter__('resonance', function() { return this.func.resonance; } ); IIRFilter.prototype.set = function(cutoff, resonance) { this.func.calcCoeff(cutoff, resonance); }; IIRFilter.prototype.process = function(buffer) { this.func.process(buffer); }; // Add an envelope to the filter IIRFilter.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.func.addEnvelope(envelope); } else { throw "Not an envelope."; } }; IIRFilter.LP12 = function(cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; this.vibraPos = 0; this.vibraSpeed = 0; this.envelope = false; this.calcCoeff = function(cutoff, resonance) { this.w = 2.0 * Math.PI * cutoff / this.sampleRate; this.q = 1.0 - this.w / (2.0 * (resonance + 0.5 / (1.0 + this.w)) + this.w - 2.0); this.r = this.q * this.q; this.c = this.r + 1.0 - 2.0 * Math.cos(this.w) * this.q; this.cutoff = cutoff; this.resonance = resonance; }; this.calcCoeff(cutoff, resonance); this.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { this.vibraSpeed += (buffer[i] - this.vibraPos) * this.c; this.vibraPos += this.vibraSpeed; this.vibraSpeed *= this.r; /* var temp = this.vibraPos; if ( temp > 1.0 ) { temp = 1.0; } else if ( temp < -1.0 ) { temp = -1.0; } else if ( temp != temp ) { temp = 1; } buffer[i] = temp; */ if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (this.vibraPos * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = this.vibraPos; } } }; }; IIRFilter.LP12.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; function IIRFilter2(type, cutoff, resonance, sampleRate) { this.type = type; this.cutoff = cutoff; this.resonance = resonance; this.sampleRate = sampleRate; this.f = Float32Array(4); this.f[0] = 0.0; // lp this.f[1] = 0.0; // hp this.f[2] = 0.0; // bp this.f[3] = 0.0; // br this.calcCoeff = function(cutoff, resonance) { this.freq = 2 * Math.sin(Math.PI * Math.min(0.25, cutoff/(this.sampleRate*2))); this.damp = Math.min(2 * (1 - Math.pow(resonance, 0.25)), Math.min(2, 2/this.freq - this.freq * 0.5)); }; this.calcCoeff(cutoff, resonance); } IIRFilter2.prototype.process = function(buffer) { var input, output; var f = this.f; for ( var i = 0; i < buffer.length; i++ ) { input = buffer[i]; // first pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output = 0.5 * f[this.type]; // second pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output += 0.5 * f[this.type]; if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (output * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = output; } } }; IIRFilter2.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.envelope = envelope; } else { throw "This is not an envelope."; } }; IIRFilter2.prototype.set = function(cutoff, resonance) { this.calcCoeff(cutoff, resonance); }; function WindowFunction(type, alpha) { this.alpha = alpha; switch(type) { case DSP.BARTLETT: this.func = WindowFunction.Bartlett; break; case DSP.BARTLETTHANN: this.func = WindowFunction.BartlettHann; break; case DSP.BLACKMAN: this.func = WindowFunction.Blackman; this.alpha = this.alpha || 0.16; break; case DSP.COSINE: this.func = WindowFunction.Cosine; break; case DSP.GAUSS: this.func = WindowFunction.Gauss; this.alpha = this.alpha || 0.25; break; case DSP.HAMMING: this.func = WindowFunction.Hamming; break; case DSP.HANN: this.func = WindowFunction.Hann; break; case DSP.LANCZOS: this.func = WindowFunction.Lanczoz; break; case DSP.RECTANGULAR: this.func = WindowFunction.Rectangular; break; case DSP.TRIANGULAR: this.func = WindowFunction.Triangular; break; } } WindowFunction.prototype.process = function(buffer) { var length = buffer.length; for ( var i = 0; i < length; i++ ) { buffer[i] *= this.func(length, i, this.alpha); } return buffer; }; WindowFunction.Bartlett = function(length, index) { return 2 / (length - 1) * ((length - 1) / 2 - Math.abs(index - (length - 1) / 2)); }; WindowFunction.BartlettHann = function(length, index) { return 0.62 - 0.48 * Math.abs(index / (length - 1) - 0.5) - 0.38 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Blackman = function(length, index, alpha) { var a0 = (1 - alpha) / 2; var a1 = 0.5; var a2 = alpha / 2; return a0 - a1 * Math.cos(DSP.TWO_PI * index / (length - 1)) + a2 * Math.cos(4 * Math.PI * index / (length - 1)); }; WindowFunction.Cosine = function(length, index) { return Math.cos(Math.PI * index / (length - 1) - Math.PI / 2); }; WindowFunction.Gauss = function(length, index, alpha) { return Math.pow(Math.E, -0.5 * Math.pow((index - (length - 1) / 2) / (alpha * (length - 1) / 2), 2)); }; WindowFunction.Hamming = function(length, index) { return 0.54 - 0.46 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Hann = function(length, index) { return 0.5 * (1 - Math.cos(DSP.TWO_PI * index / (length - 1))); }; WindowFunction.Lanczos = function(length, index) { var x = 2 * index / (length - 1) - 1; return Math.sin(Math.PI * x) / (Math.PI * x); }; WindowFunction.Rectangular = function(length, index) { return 1; }; WindowFunction.Triangular = function(length, index) { return 2 / length * (length / 2 - Math.abs(index - (length - 1) / 2)); }; function sinh (arg) { // Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 // // version: 1004.2314 // discuss at: http://phpjs.org/functions/sinh // + original by: Onno Marsman // * example 1: sinh(-0.9834330348825909); // * returns 1: -1.1497971402636502 return (Math.exp(arg) - Math.exp(-arg))/2; } /* * Biquad filter * * Created by Ricard Marxer on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ // Implementation based on: // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt function Biquad(type, sampleRate) { this.Fs = sampleRate; this.type = type; // type of the filter this.parameterType = DSP.Q; // type of the parameter this.x_1_l = 0; this.x_2_l = 0; this.y_1_l = 0; this.y_2_l = 0; this.x_1_r = 0; this.x_2_r = 0; this.y_1_r = 0; this.y_2_r = 0; this.b0 = 1; this.a0 = 1; this.b1 = 0; this.a1 = 0; this.b2 = 0; this.a2 = 0; this.b0a0 = this.b0 / this.a0; this.b1a0 = this.b1 / this.a0; this.b2a0 = this.b2 / this.a0; this.a1a0 = this.a1 / this.a0; this.a2a0 = this.a2 / this.a0; this.f0 = 3000; // "wherever it's happenin', man." Center Frequency or // Corner Frequency, or shelf midpoint frequency, depending // on which filter type. The "significant frequency". this.dBgain = 12; // used only for peaking and shelving filters this.Q = 1; // the EE kind of definition, except for peakingEQ in which A*Q is // the classic EE Q. That adjustment in definition was made so that // a boost of N dB followed by a cut of N dB for identical Q and // f0/Fs results in a precisely flat unity gain filter or "wire". this.BW = -3; // the bandwidth in octaves (between -3 dB frequencies for BPF // and notch or between midpoint (dBgain/2) gain frequencies for // peaking EQ this.S = 1; // a "shelf slope" parameter (for shelving EQ only). When S = 1, // the shelf slope is as steep as it can be and remain monotonically // increasing or decreasing gain with frequency. The shelf slope, in // dB/octave, remains proportional to S for all other values for a // fixed f0/Fs and dBgain. this.coefficients = function() { var b = [this.b0, this.b1, this.b2]; var a = [this.a0, this.a1, this.a2]; return {b: b, a:a}; }; this.setFilterType = function(type) { this.type = type; this.recalculateCoefficients(); }; this.setSampleRate = function(rate) { this.Fs = rate; this.recalculateCoefficients(); }; this.setQ = function(q) { this.parameterType = DSP.Q; this.Q = Math.max(Math.min(q, 115.0), 0.001); this.recalculateCoefficients(); }; this.setBW = function(bw) { this.parameterType = DSP.BW; this.BW = bw; this.recalculateCoefficients(); }; this.setS = function(s) { this.parameterType = DSP.S; this.S = Math.max(Math.min(s, 5.0), 0.0001); this.recalculateCoefficients(); }; this.setF0 = function(freq) { this.f0 = freq; this.recalculateCoefficients(); }; this.setDbGain = function(g) { this.dBgain = g; this.recalculateCoefficients(); }; this.recalculateCoefficients = function() { var A; if (type === DSP.PEAKING_EQ || type === DSP.LOW_SHELF || type === DSP.HIGH_SHELF ) { A = Math.pow(10, (this.dBgain/40)); // for peaking and shelving EQ filters only } else { A = Math.sqrt( Math.pow(10, (this.dBgain/20)) ); } var w0 = DSP.TWO_PI * this.f0 / this.Fs; var cosw0 = Math.cos(w0); var sinw0 = Math.sin(w0); var alpha = 0; switch (this.parameterType) { case DSP.Q: alpha = sinw0/(2*this.Q); break; case DSP.BW: alpha = sinw0 * sinh( Math.LN2/2 * this.BW * w0/sinw0 ); break; case DSP.S: alpha = sinw0/2 * Math.sqrt( (A + 1/A)*(1/this.S - 1) + 2 ); break; } /** FYI: The relationship between bandwidth and Q is 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT) or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype) The relationship between shelf slope and Q is 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2) */ var coeff; switch (this.type) { case DSP.LPF: // H(s) = 1 / (s^2 + s/Q + 1) this.b0 = (1 - cosw0)/2; this.b1 = 1 - cosw0; this.b2 = (1 - cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.HPF: // H(s) = s^2 / (s^2 + s/Q + 1) this.b0 = (1 + cosw0)/2; this.b1 = -(1 + cosw0); this.b2 = (1 + cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_SKIRT: // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) this.b0 = sinw0/2; this.b1 = 0; this.b2 = -sinw0/2; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_PEAK: // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) this.b0 = alpha; this.b1 = 0; this.b2 = -alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.NOTCH: // H(s) = (s^2 + 1) / (s^2 + s/Q + 1) this.b0 = 1; this.b1 = -2*cosw0; this.b2 = 1; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.APF: // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) this.b0 = 1 - alpha; this.b1 = -2*cosw0; this.b2 = 1 + alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.PEAKING_EQ: // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) this.b0 = 1 + alpha*A; this.b1 = -2*cosw0; this.b2 = 1 - alpha*A; this.a0 = 1 + alpha/A; this.a1 = -2*cosw0; this.a2 = 1 - alpha/A; break; case DSP.LOW_SHELF: // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) - (A-1)*cosw0 + coeff); this.b1 = 2*A*((A-1) - (A+1)*cosw0); this.b2 = A*((A+1) - (A-1)*cosw0 - coeff); this.a0 = (A+1) + (A-1)*cosw0 + coeff; this.a1 = -2*((A-1) + (A+1)*cosw0); this.a2 = (A+1) + (A-1)*cosw0 - coeff; break; case DSP.HIGH_SHELF: // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) + (A-1)*cosw0 + coeff); this.b1 = -2*A*((A-1) + (A+1)*cosw0); this.b2 = A*((A+1) + (A-1)*cosw0 - coeff); this.a0 = (A+1) - (A-1)*cosw0 + coeff; this.a1 = 2*((A-1) - (A+1)*cosw0); this.a2 = (A+1) - (A-1)*cosw0 - coeff; break; } this.b0a0 = this.b0/this.a0; this.b1a0 = this.b1/this.a0; this.b2a0 = this.b2/this.a0; this.a1a0 = this.a1/this.a0; this.a2a0 = this.a2/this.a0; }; this.process = function(buffer) { //y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] // - (a1/a0)*y[n-1] - (a2/a0)*y[n-2] var len = buffer.length; var output = new Float32Array(len); for ( var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * @buffer array of magnitudes to convert to decibels * * @returns the array in decibels * */ DSP.mag2db = function(buffer) { var minDb = -120; var minMag = Math.pow(10.0, minDb / 20.0); var log = Math.log; var max = Math.max; var result = Float32Array(buffer.length); for (var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * Calculates the frequency response at the given points. * * @b b coefficients of the filter * @a a coefficients of the filter * @w w points (normally between -PI and PI) where to calculate the frequency response * * @returns the frequency response in magnitude * */ DSP.freqz = function(b, a, w) { var i, j; if (!w) { w = Float32Array(200); for (i=0;i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ function GraphicalEq(sampleRate) { this.FS = sampleRate; this.minFreq = 40.0; this.maxFreq = 16000.0; this.bandsPerOctave = 1.0; this.filters = []; this.freqzs = []; this.calculateFreqzs = true; this.recalculateFilters = function() { var bandCount = Math.round(Math.log(this.maxFreq/this.minFreq) * this.bandsPerOctave/ Math.LN2); this.filters = []; for (var i=0; i (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds."; } if (!gain) { throw "A gain must be passed."; } this.filters[bandIndex].setDbGain(gain); this.recalculateFreqz(bandIndex); }; this.recalculateFreqz = function(bandIndex) { if (!this.calculateFreqzs) { return; } if (bandIndex < 0 || bandIndex > (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds. " + bandIndex + " is out of [" + 0 + ", " + this.filters.length-1 + "]"; } if (!this.w) { this.w = Float32Array(400); for (var i=0; i1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function MultiDelay(maxDelayInSamplesSize, delayInSamples, masterVolume, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ MultiDelay.prototype.setDelayInSamples = function (delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setMasterVolume = function(masterVolume) { this.masterVolume = masterVolume; }; /** * Change the delay feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and adds the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ MultiDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * SingleDelay effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: See usage in Reverb class * * This is a delay that does NOT feeds it's own delayed signal back into its * circular buffer, neither does it return the original signal. Also known as * an AllPassFilter(?). * * Compatible with interleaved stereo (or more channel) buffers and * non-interleaved mono buffers. * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffer) * @param {Number} delayInSamples Initial delay in samples * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function SingleDelay(maxDelayInSamplesSize, delayInSamples, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ SingleDelay.prototype.setDelayInSamples = function(delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the return signal volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ SingleDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and * returns the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ SingleDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * Reverb effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: http://code.almeros.com/code-examples/reverb-firefox-audio-api/ * * This reverb consists of 6 SingleDelays, 6 MultiDelays and an IIRFilter2 * for each of the two stereo channels. * * Compatible with interleaved stereo buffers only! * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffers) * @param {Number} delayInSamples Initial delay in samples for internal (Single/Multi)delays * @param {Number} masterVolume Initial master volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} mixVolume Initial reverb signal mix volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume for internal (Single/Multi)delays. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} dampFrequency Initial low pass filter frequency. 0 to 44100 (depending on your maximum sampling frequency) * * @constructor */ function Reverb(maxDelayInSamplesSize, delayInSamples, masterVolume, mixVolume, delayVolume, dampFrequency) { this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.mixVolume = mixVolume; this.delayVolume = delayVolume; this.dampFrequency = dampFrequency; this.NR_OF_MULTIDELAYS = 6; this.NR_OF_SINGLEDELAYS = 6; this.LOWPASSL = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.LOWPASSR = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.singleDelays = []; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i] = new SingleDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.delayVolume); } this.multiDelays = []; for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i] = new MultiDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.masterVolume, this.delayVolume); } } /** * Change the delay time in samples as a base for all delays. * * @param {Number} delayInSamples Delay in samples */ Reverb.prototype.setDelayInSamples = function (delayInSamples){ this.delayInSamples = delayInSamples; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMasterVolume = function (masterVolume){ this.masterVolume = masterVolume; }; /** * Change the reverb signal mix level. * * @param {Number} mixVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMixVolume = function (mixVolume){ this.mixVolume = mixVolume; }; /** * Change all delays feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setDelayVolume = function (delayVolume){ this.delayVolume = delayVolume; var i; for (i = 0; iWebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: LevelOfDetail/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: LevelOfDetail/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: LevelOfDetail/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: LevelOfDetail/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: LevelOfDetail/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: LevelOfDetail/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: LevelOfDetail/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: LevelOfDetail/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: LevelOfDetail/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: LevelOfDetail/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: LevelOfDetail/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: LevelOfDetail/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: LevelOfDetail/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: LevelOfDetail/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: LevelOfDetail/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: LevelOfDetail/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: LevelOfDetail/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: MeshLife/bundle.js ================================================ (function(){var require = function (file, cwd) { var resolved = require.resolve(file, cwd || '/'); var mod = require.modules[resolved]; if (!mod) throw new Error( 'Failed to resolve module ' + file + ', tried ' + resolved ); var cached = require.cache[resolved]; var res = cached? cached.exports : mod(); return res; }; require.paths = []; require.modules = {}; require.cache = {}; require.extensions = [".js",".coffee",".json"]; require._core = { 'assert': true, 'events': true, 'fs': true, 'path': true, 'vm': true }; require.resolve = (function () { return function (x, cwd) { if (!cwd) cwd = '/'; if (require._core[x]) return x; var path = require.modules.path(); cwd = path.resolve('/', cwd); var y = cwd || '/'; if (x.match(/^(?:\.\.?\/|\/)/)) { var m = loadAsFileSync(path.resolve(y, x)) || loadAsDirectorySync(path.resolve(y, x)); if (m) return m; } var n = loadNodeModulesSync(x, y); if (n) return n; throw new Error("Cannot find module '" + x + "'"); function loadAsFileSync (x) { x = path.normalize(x); if (require.modules[x]) { return x; } for (var i = 0; i < require.extensions.length; i++) { var ext = require.extensions[i]; if (require.modules[x + ext]) return x + ext; } } function loadAsDirectorySync (x) { x = x.replace(/\/+$/, ''); var pkgfile = path.normalize(x + '/package.json'); if (require.modules[pkgfile]) { var pkg = require.modules[pkgfile](); var b = pkg.browserify; if (typeof b === 'object' && b.main) { var m = loadAsFileSync(path.resolve(x, b.main)); if (m) return m; } else if (typeof b === 'string') { var m = loadAsFileSync(path.resolve(x, b)); if (m) return m; } else if (pkg.main) { var m = loadAsFileSync(path.resolve(x, pkg.main)); if (m) return m; } } return loadAsFileSync(x + '/index'); } function loadNodeModulesSync (x, start) { var dirs = nodeModulesPathsSync(start); for (var i = 0; i < dirs.length; i++) { var dir = dirs[i]; var m = loadAsFileSync(dir + '/' + x); if (m) return m; var n = loadAsDirectorySync(dir + '/' + x); if (n) return n; } var m = loadAsFileSync(x); if (m) return m; } function nodeModulesPathsSync (start) { var parts; if (start === '/') parts = [ '' ]; else parts = path.normalize(start).split('/'); var dirs = []; for (var i = parts.length - 1; i >= 0; i--) { if (parts[i] === 'node_modules') continue; var dir = parts.slice(0, i + 1).join('/') + '/node_modules'; dirs.push(dir); } return dirs; } }; })(); require.alias = function (from, to) { var path = require.modules.path(); var res = null; try { res = require.resolve(from + '/package.json', '/'); } catch (err) { res = require.resolve(from, '/'); } var basedir = path.dirname(res); var keys = (Object.keys || function (obj) { var res = []; for (var key in obj) res.push(key); return res; })(require.modules); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (key.slice(0, basedir.length + 1) === basedir + '/') { var f = key.slice(basedir.length); require.modules[to + f] = require.modules[basedir + f]; } else if (key === basedir) { require.modules[to] = require.modules[basedir]; } } }; (function () { var process = {}; var global = typeof window !== 'undefined' ? window : {}; var definedProcess = false; require.define = function (filename, fn) { if (!definedProcess && require.modules.__browserify_process) { process = require.modules.__browserify_process(); definedProcess = true; } var dirname = require._core[filename] ? '' : require.modules.path().dirname(filename) ; var require_ = function (file) { var requiredModule = require(file, dirname); var cached = require.cache[require.resolve(file, dirname)]; if (cached && cached.parent === null) { cached.parent = module_; } return requiredModule; }; require_.resolve = function (name) { return require.resolve(name, dirname); }; require_.modules = require.modules; require_.define = require.define; require_.cache = require.cache; var module_ = { id : filename, filename: filename, exports : {}, loaded : false, parent: null }; require.modules[filename] = function () { require.cache[filename] = module_; fn.call( module_.exports, require_, module_, module_.exports, dirname, filename, process, global ); module_.loaded = true; return module_.exports; }; }; })(); require.define("path",function(require,module,exports,__dirname,__filename,process,global){function filter (xs, fn) { var res = []; for (var i = 0; i < xs.length; i++) { if (fn(xs[i], i, xs)) res.push(xs[i]); } return res; } // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length; i >= 0; i--) { var last = parts[i]; if (last == '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } // Regex to split a filename into [*, dir, basename, ext] // posix version var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string' || !path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = path.charAt(0) === '/', trailingSlash = path.slice(-1) === '/'; // Normalize the path path = normalizeArray(filter(path.split('/'), function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(filter(paths, function(p, index) { return p && typeof p === 'string'; }).join('/')); }; exports.dirname = function(path) { var dir = splitPathRe.exec(path)[1] || ''; var isWindows = false; if (!dir) { // No dirname return '.'; } else if (dir.length === 1 || (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { // It is just a slash or a drive letter with a slash return dir; } else { // It is a full dirname, strip trailing slash return dir.substring(0, dir.length - 1); } }; exports.basename = function(path, ext) { var f = splitPathRe.exec(path)[2] || ''; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPathRe.exec(path)[3] || ''; }; }); require.define("__browserify_process",function(require,module,exports,__dirname,__filename,process,global){var process = module.exports = {}; process.nextTick = (function () { var canSetImmediate = typeof window !== 'undefined' && window.setImmediate; var canPost = typeof window !== 'undefined' && window.postMessage && window.addEventListener ; if (canSetImmediate) { return function (f) { return window.setImmediate(f) }; } if (canPost) { var queue = []; window.addEventListener('message', function (ev) { if (ev.source === window && ev.data === 'browserify-tick') { ev.stopPropagation(); if (queue.length > 0) { var fn = queue.shift(); fn(); } } }, true); return function nextTick(fn) { queue.push(fn); window.postMessage('browserify-tick', '*'); }; } return function nextTick(fn) { setTimeout(fn, 0); }; })(); process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.binding = function (name) { if (name === 'evals') return (require)('vm') else throw new Error('No such module. (Possibly not yet loaded)') }; (function () { var cwd = '/'; var path; process.cwd = function () { return cwd }; process.chdir = function (dir) { if (!path) path = require('path'); cwd = path.resolve(dir, cwd); }; })(); }); require.define("/node_modules/trimesh/package.json",function(require,module,exports,__dirname,__filename,process,global){module.exports = {"main":"index.js"} }); require.define("/node_modules/trimesh/index.js",function(require,module,exports,__dirname,__filename,process,global){//Topology functions var topology = require('./src/topology.js'); exports.vertex_stars = topology.vertex_stars; exports.edges = topology.edges; //Mesh repair var repair = require('./src/repair.js'); exports.fuse_vertices = repair.fuse_vertices; //Isosurface functions exports.marching_cubes = require('./src/marchingcubes.js').marching_cubes; exports.marching_tetrahedra = require('./src/marchingtetrahedra.js').marching_tetrahedra; exports.surface_nets = require('./src/surfacenets.js').surface_nets; //Surface normal estimation var normals = require('./src/normals.js'); exports.vertex_normals = normals.vertex_normals; exports.face_normals = normals.face_normals; //Surface distance exports.geodesic_distance = require('./src/distance.js').geodesic_distance; //Test shapes var shapes = require('./src/shapes.js'); exports.grid_mesh = shapes.grid_mesh; exports.cube_mesh = shapes.cube_mesh; exports.sphere_mesh = shapes.sphere_mesh; //Subdivisions exports.loop_subdivision = require('./src/loop_subdivision.js').loop_subdivision; }); require.define("/node_modules/trimesh/src/topology.js",function(require,module,exports,__dirname,__filename,process,global){function vmax(faces) { var vc = 0; for(var i=0; i 0) ? 1 << i : 0; } //Compute vertices var edge_mask = edgeTable[cube_index]; if(edge_mask === 0) { continue; } for(var i=0; i<12; ++i) { if((edge_mask & (1< 1e-6) { t = a / d; } for(var j=0; j<3; ++j) { nv[j] = scale[j] * ((x[j] + p0[j]) + t * (p1[j] - p0[j])) + shift[j]; } vertices.push(nv); } //Add faces var f = triTable[cube_index]; for(var i=0; i 1e-6) { t = g0 / t; } for(var i=0; i<3; ++i) { v[i] = scale[i] * (v[i] + p0[i] + t * (p1[i] - p0[i])) + shift[i]; } vertices.push(v); return vertices.length - 1; } //March over the volume for(x[2]=0; x[2] 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Array(4096); (function() { for(var i=0; i buffer.length) { var ol = buffer.length; buffer.length = R[2] * 2; while(ol < buffer.length) { buffer[ol++] = 0; } } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = scale[i] * (x[i] + s * v[i]) + shift[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1< EPSILON) { var norm = normals[c]; var w = 1.0 / Math.sqrt(m01 * m21); for(var k=0; k<3; ++k) { var u = (k+1)%3; var v = (k+2)%3; norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]); } } } } //Scale all normals to unit length for(var i=0; i EPSILON) { var w = 1.0 / Math.sqrt(m); for(var k=0; k<3; ++k) { norm[k] *= w; } } else { for(var k=0; k<3; ++k) { norm[k] = 0.0; } } } //Return the resulting set of patches return normals; } //Compute face normals of a mesh exports.face_normals = function(args) { var positions = args.positions; var faces = args.faces; var N = faces.length; var normals = new Array(N); for(var i=0; i EPSILON) { l = 1.0 / Math.sqrt(l); } else { l = 0.0; } for(var j=0; j<3; ++j) { n[j] *= l; } normals[i] = n; } return normals; } }); require.define("/node_modules/trimesh/src/distance.js",function(require,module,exports,__dirname,__filename,process,global){var assert = require('assert'); var BinaryHeap = require('./heap.js').BinaryHeap; var vertex_stars = require('./topology.js').vertex_stars; var EPSILON = 1e-6; //Computes quadratic distance to point c function quadratic_distance(a, b, c, dpa, dpb, orientation) { var ab = new Array(3); var ac = new Array(3); var dab2 = 0.0; for(var i=0; i<3; ++i) { ab[i] = b[i] - a[i]; dab2 += ab[i] * ab[i]; ac[i] = c[i] - a[i]; } if(dab2 < EPSILON) { return 1e30; } //Transform c into triangle coordinate system var dab = Math.sqrt(dab2); var s = 1.0 / dab; var c0 = 0.0; for(var i=0; i<3; ++i) { ab[i] *= s; c0 += ab[i] * ac[i]; } var c1 = 0.0; for(var i=0; i<3; ++i) { c1 += Math.pow(ac[i] - c0 * ab[i], 2); } c1 = Math.sqrt(c1); //Compute center of distance field var dpa2 = dpa*dpa; var dpb2 = dpb*dpb; var p0 = (dpa2 - dpb2 + dab2) / (2.0 * dab); var p1 = dpa2 - p0*p0; if(p1 < 0.0) { return 1e30; } p1 = Math.sqrt(p1); if(orientation < 0) { p1 *= -1; } //Compute new distance bound var d = Math.sqrt(Math.pow(c0 - p0, 2) + Math.pow(c1 - p1, 2)); //Return min return d; } function Pair(d,v) { this.d = d; this.v = v; } function dijkstra(p, stars, faces, positions, max_distance) { var to_visit = new BinaryHeap(new Function("a", "return a.d;")); var distances = {}; to_visit.push(new Pair(0, p)); var center = positions[p]; var msquared = max_distance * max_distance; while(to_visit.size() > 0) { var node = to_visit.pop(); if(node.v in distances) { continue; } var d = node.d; var v = node.v; distances[v] = d; var a = positions[v]; var nbhd = stars[v]; for(var i=0; i max_distance) { break; } //Iterate over all faces incident to v var nbhd = stars[v]; for(var nn=0; nn max_distance) { continue; } var o_distance = distances[face[2]]; //Update distance if(n_distance < o_distance && Math.abs(n_distance - o_distance) > tolerance) { distances[face[2]] = Math.min(o_distance, n_distance); stabilized = false; } } } } } //Computes a distances to a vertex p function geodesic_distance(args) { var positions = args.positions; var faces = args.faces; var p = args.initial_vertex; var stars = args.stars || vertex_stars({ vertex_count: positions.length, faces: faces }); var max_distance = args.max_distance || Number.POSITIVE_INFINITY; var tolerance = args.tolerance || 1e-4; //First, run Dijkstra's algorithm to get an initial bound on the distance from each vertex // to the base point just using edge lengths var distances = dijkstra(p, stars, faces, positions, max_distance); //Then refine distances to acceptable threshold refine_distances(p, distances, positions, stars, faces, max_distance, tolerance); return distances; } exports.quadratic_distance = quadratic_distance; exports.geodesic_distance = geodesic_distance; }); require.define("assert",function(require,module,exports,__dirname,__filename,process,global){// UTILITY var util = require('util'); var Buffer = require("buffer").Buffer; var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.message = options.message; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) { Error.captureStackTrace(this, stackStartFunction); } }; util.inherits(assert.AssertionError, Error); function replacer(key, value) { if (value === undefined) { return '' + value; } if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) { return value.toString(); } if (typeof value === 'function' || value instanceof RegExp) { return value.toString(); } return value; } function truncate(s, n) { if (typeof s == 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } assert.AssertionError.prototype.toString = function() { if (this.message) { return [this.name + ':', this.message].join(' '); } else { return [ this.name + ':', truncate(JSON.stringify(this.actual, replacer), 128), this.operator, truncate(JSON.stringify(this.expected, replacer), 128) ].join(' '); } }; // assert.AssertionError instanceof Error assert.AssertionError.__proto__ = Error.prototype; // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!!!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); // 7.3. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { return actual == expected; // 7.4. For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected); } } function isUndefinedOrNull(value) { return value === null || value === undefined; } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; //~~~I've managed to break Object.keys through screwy arguments passing. // Converting to array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } try { var ka = Object.keys(a), kb = Object.keys(b), key, i; } catch (e) {//happens when one is a string literal and the other isn't return false; } // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key])) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (expected instanceof RegExp) { return expected.test(actual); } else if (actual instanceof expected) { return true; } else if (expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof expected === 'string') { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail('Missing expected exception' + message); } if (!shouldThrow && expectedException(actual, expected)) { fail('Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; assert.ifError = function(err) { if (err) {throw err;}}; }); require.define("util",function(require,module,exports,__dirname,__filename,process,global){var events = require('events'); exports.print = function () {}; exports.puts = function () {}; exports.debug = function() {}; exports.inspect = function(obj, showHidden, depth, colors) { var seen = []; var stylize = function(str, styleType) { // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics var styles = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; var style = { 'special': 'cyan', 'number': 'blue', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }[styleType]; if (style) { return '\033[' + styles[style][0] + 'm' + str + '\033[' + styles[style][1] + 'm'; } else { return str; } }; if (! colors) { stylize = function(str, styleType) { return str; }; } function format(value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value !== exports && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { return value.inspect(recurseTimes); } // Primitive types cannot have properties switch (typeof value) { case 'undefined': return stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return stylize(simple, 'string'); case 'number': return stylize('' + value, 'number'); case 'boolean': return stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return stylize('null', 'null'); } // Look up the keys of the object. var visible_keys = Object_keys(value); var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys; // Functions without properties can be shortcutted. if (typeof value === 'function' && keys.length === 0) { if (isRegExp(value)) { return stylize('' + value, 'regexp'); } else { var name = value.name ? ': ' + value.name : ''; return stylize('[Function' + name + ']', 'special'); } } // Dates without properties can be shortcutted if (isDate(value) && keys.length === 0) { return stylize(value.toUTCString(), 'date'); } var base, type, braces; // Determine the object type if (isArray(value)) { type = 'Array'; braces = ['[', ']']; } else { type = 'Object'; braces = ['{', '}']; } // Make functions say that they are functions if (typeof value === 'function') { var n = value.name ? ': ' + value.name : ''; base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; } else { base = ''; } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + value.toUTCString(); } if (keys.length === 0) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return stylize('' + value, 'regexp'); } else { return stylize('[Object]', 'special'); } } seen.push(value); var output = keys.map(function(key) { var name, str; if (value.__lookupGetter__) { if (value.__lookupGetter__(key)) { if (value.__lookupSetter__(key)) { str = stylize('[Getter/Setter]', 'special'); } else { str = stylize('[Getter]', 'special'); } } else { if (value.__lookupSetter__(key)) { str = stylize('[Setter]', 'special'); } } } if (visible_keys.indexOf(key) < 0) { name = '[' + key + ']'; } if (!str) { if (seen.indexOf(value[key]) < 0) { if (recurseTimes === null) { str = format(value[key]); } else { str = format(value[key], recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (isArray(value)) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (type === 'Array' && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = stylize(name, 'string'); } } return name + ': ' + str; }); seen.pop(); var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 50) { output = braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } else { output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } return output; } return format(obj, (typeof depth === 'undefined' ? 2 : depth)); }; function isArray(ar) { return ar instanceof Array || Array.isArray(ar) || (ar && ar !== Object.prototype && isArray(ar.__proto__)); } function isRegExp(re) { return re instanceof RegExp || (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]'); } function isDate(d) { if (d instanceof Date) return true; if (typeof d !== 'object') return false; var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype); var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__); return JSON.stringify(proto) === JSON.stringify(properties); } function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } exports.log = function (msg) {}; exports.pump = null; var Object_keys = Object.keys || function (obj) { var res = []; for (var key in obj) res.push(key); return res; }; var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) { var res = []; for (var key in obj) { if (Object.hasOwnProperty.call(obj, key)) res.push(key); } return res; }; var Object_create = Object.create || function (prototype, properties) { // from es5-shim var object; if (prototype === null) { object = { '__proto__' : null }; } else { if (typeof prototype !== 'object') { throw new TypeError( 'typeof prototype[' + (typeof prototype) + '] != \'object\'' ); } var Type = function () {}; Type.prototype = prototype; object = new Type(); object.__proto__ = prototype; } if (typeof properties !== 'undefined' && Object.defineProperties) { Object.defineProperties(object, properties); } return object; }; exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object_create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(exports.inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': return JSON.stringify(args[i++]); default: return x; } }); for(var x = args[i]; i < len; x = args[++i]){ if (x === null || typeof x !== 'object') { str += ' ' + x; } else { str += ' ' + exports.inspect(x); } } return str; }; }); require.define("events",function(require,module,exports,__dirname,__filename,process,global){if (!process.EventEmitter) process.EventEmitter = function () {}; var EventEmitter = exports.EventEmitter = process.EventEmitter; var isArray = typeof Array.isArray === 'function' ? Array.isArray : function (xs) { return Object.prototype.toString.call(xs) === '[object Array]' } ; function indexOf (xs, x) { if (xs.indexOf) return xs.indexOf(x); for (var i = 0; i < xs.length; i++) { if (x === xs[i]) return i; } return -1; } // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (!this._events) this._events = {}; this._events.maxListeners = n; }; EventEmitter.prototype.emit = function(type) { // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events || !this._events.error || (isArray(this._events.error) && !this._events.error.length)) { if (arguments[1] instanceof Error) { throw arguments[1]; // Unhandled 'error' event } else { throw new Error("Uncaught, unspecified 'error' event."); } return false; } } if (!this._events) return false; var handler = this._events[type]; if (!handler) return false; if (typeof handler == 'function') { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: var args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } return true; } else if (isArray(handler)) { var args = Array.prototype.slice.call(arguments, 1); var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } return true; } else { return false; } }; // EventEmitter is defined in src/node_events.cc // EventEmitter.prototype.emit() is also defined there. EventEmitter.prototype.addListener = function(type, listener) { if ('function' !== typeof listener) { throw new Error('addListener only takes instances of Function'); } if (!this._events) this._events = {}; // To avoid recursion in the case that type == "newListeners"! Before // adding it to the listeners, first emit "newListeners". this.emit('newListener', type, listener); if (!this._events[type]) { // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; } else if (isArray(this._events[type])) { // Check for listener leak if (!this._events[type].warned) { var m; if (this._events.maxListeners !== undefined) { m = this._events.maxListeners; } else { m = defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } // If we've already got an array, just append. this._events[type].push(listener); } else { // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { var self = this; self.on(type, function g() { self.removeListener(type, g); listener.apply(this, arguments); }); return this; }; EventEmitter.prototype.removeListener = function(type, listener) { if ('function' !== typeof listener) { throw new Error('removeListener only takes instances of Function'); } // does not use listeners(), so no side effect of creating _events[type] if (!this._events || !this._events[type]) return this; var list = this._events[type]; if (isArray(list)) { var i = indexOf(list, listener); if (i < 0) return this; list.splice(i, 1); if (list.length == 0) delete this._events[type]; } else if (this._events[type] === listener) { delete this._events[type]; } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { // does not use listeners(), so no side effect of creating _events[type] if (type && this._events && this._events[type]) this._events[type] = null; return this; }; EventEmitter.prototype.listeners = function(type) { if (!this._events) this._events = {}; if (!this._events[type]) this._events[type] = []; if (!isArray(this._events[type])) { this._events[type] = [this._events[type]]; } return this._events[type]; }; }); require.define("buffer",function(require,module,exports,__dirname,__filename,process,global){module.exports = require("buffer-browserify") }); require.define("/node_modules/buffer-browserify/package.json",function(require,module,exports,__dirname,__filename,process,global){module.exports = {"main":"index.js","browserify":"index.js"} }); require.define("/node_modules/buffer-browserify/index.js",function(require,module,exports,__dirname,__filename,process,global){function SlowBuffer (size) { this.length = size; }; var assert = require('assert'); exports.INSPECT_MAX_BYTES = 50; function toHex(n) { if (n < 16) return '0' + n.toString(16); return n.toString(16); } function utf8ToBytes(str) { var byteArray = []; for (var i = 0; i < str.length; i++) if (str.charCodeAt(i) <= 0x7F) byteArray.push(str.charCodeAt(i)); else { var h = encodeURIComponent(str.charAt(i)).substr(1).split('%'); for (var j = 0; j < h.length; j++) byteArray.push(parseInt(h[j], 16)); } return byteArray; } function asciiToBytes(str) { var byteArray = [] for (var i = 0; i < str.length; i++ ) // Node's code seems to be doing this and not & 0x7F.. byteArray.push( str.charCodeAt(i) & 0xFF ); return byteArray; } function base64ToBytes(str) { return require("base64-js").toByteArray(str); } SlowBuffer.byteLength = function (str, encoding) { switch (encoding || "utf8") { case 'hex': return str.length / 2; case 'utf8': case 'utf-8': return utf8ToBytes(str).length; case 'ascii': return str.length; case 'base64': return base64ToBytes(str).length; default: throw new Error('Unknown encoding'); } }; function blitBuffer(src, dst, offset, length) { var pos, i = 0; while (i < length) { if ((i+offset >= dst.length) || (i >= src.length)) break; dst[i + offset] = src[i]; i++; } return i; } SlowBuffer.prototype.utf8Write = function (string, offset, length) { var bytes, pos; return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length); }; SlowBuffer.prototype.asciiWrite = function (string, offset, length) { var bytes, pos; return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length); }; SlowBuffer.prototype.base64Write = function (string, offset, length) { var bytes, pos; return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length); }; SlowBuffer.prototype.base64Slice = function (start, end) { var bytes = Array.prototype.slice.apply(this, arguments) return require("base64-js").fromByteArray(bytes); } function decodeUtf8Char(str) { try { return decodeURIComponent(str); } catch (err) { return String.fromCharCode(0xFFFD); // UTF 8 invalid char } } SlowBuffer.prototype.utf8Slice = function () { var bytes = Array.prototype.slice.apply(this, arguments); var res = ""; var tmp = ""; var i = 0; while (i < bytes.length) { if (bytes[i] <= 0x7F) { res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]); tmp = ""; } else tmp += "%" + bytes[i].toString(16); i++; } return res + decodeUtf8Char(tmp); } SlowBuffer.prototype.asciiSlice = function () { var bytes = Array.prototype.slice.apply(this, arguments); var ret = ""; for (var i = 0; i < bytes.length; i++) ret += String.fromCharCode(bytes[i]); return ret; } SlowBuffer.prototype.inspect = function() { var out = [], len = this.length; for (var i = 0; i < len; i++) { out[i] = toHex(this[i]); if (i == exports.INSPECT_MAX_BYTES) { out[i + 1] = '...'; break; } } return ''; }; SlowBuffer.prototype.hexSlice = function(start, end) { var len = this.length; if (!start || start < 0) start = 0; if (!end || end < 0 || end > len) end = len; var out = ''; for (var i = start; i < end; i++) { out += toHex(this[i]); } return out; }; SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; if (typeof end == 'undefined') end = this.length; // Fastpath empty strings if (+end == start) { return ''; } switch (encoding) { case 'hex': return this.hexSlice(start, end); case 'utf8': case 'utf-8': return this.utf8Slice(start, end); case 'ascii': return this.asciiSlice(start, end); case 'binary': return this.binarySlice(start, end); case 'base64': return this.base64Slice(start, end); case 'ucs2': case 'ucs-2': return this.ucs2Slice(start, end); default: throw new Error('Unknown encoding'); } }; SlowBuffer.prototype.hexWrite = function(string, offset, length) { offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } // must be an even number of digits var strLen = string.length; if (strLen % 2) { throw new Error('Invalid hex string'); } if (length > strLen / 2) { length = strLen / 2; } for (var i = 0; i < length; i++) { var byte = parseInt(string.substr(i * 2, 2), 16); if (isNaN(byte)) throw new Error('Invalid hex string'); this[offset + i] = byte; } SlowBuffer._charsWritten = i * 2; return i; }; SlowBuffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); switch (encoding) { case 'hex': return this.hexWrite(string, offset, length); case 'utf8': case 'utf-8': return this.utf8Write(string, offset, length); case 'ascii': return this.asciiWrite(string, offset, length); case 'binary': return this.binaryWrite(string, offset, length); case 'base64': return this.base64Write(string, offset, length); case 'ucs2': case 'ucs-2': return this.ucs2Write(string, offset, length); default: throw new Error('Unknown encoding'); } }; // slice(start, end) SlowBuffer.prototype.slice = function(start, end) { if (end === undefined) end = this.length; if (end > this.length) { throw new Error('oob'); } if (start > end) { throw new Error('oob'); } return new Buffer(this, end - start, +start); }; SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) { var temp = []; for (var i=sourcestart; i Buffer.poolSize) { // Big buffer, just alloc one. this.parent = new SlowBuffer(this.length); this.offset = 0; } else { // Small buffer. if (!pool || pool.length - pool.used < this.length) allocPool(); this.parent = pool; this.offset = pool.used; pool.used += this.length; } // Treat array-ish objects as a byte array. if (isArrayIsh(subject)) { for (var i = 0; i < this.length; i++) { this.parent[i + this.offset] = subject[i]; } } else if (type == 'string') { // We are a string this.length = this.write(subject, 0, encoding); } } } function isArrayIsh(subject) { return Array.isArray(subject) || Buffer.isBuffer(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } exports.SlowBuffer = SlowBuffer; exports.Buffer = Buffer; Buffer.poolSize = 8 * 1024; var pool; function allocPool() { pool = new SlowBuffer(Buffer.poolSize); pool.used = 0; } // Static methods Buffer.isBuffer = function isBuffer(b) { return b instanceof Buffer || b instanceof SlowBuffer; }; Buffer.concat = function (list, totalLength) { if (!Array.isArray(list)) { throw new Error("Usage: Buffer.concat(list, [totalLength])\n \ list should be an Array."); } if (list.length === 0) { return new Buffer(0); } else if (list.length === 1) { return list[0]; } if (typeof totalLength !== 'number') { totalLength = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; totalLength += buf.length; } } var buffer = new Buffer(totalLength); var pos = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; buf.copy(buffer, pos); pos += buf.length; } return buffer; }; // Inspect Buffer.prototype.inspect = function inspect() { var out = [], len = this.length; for (var i = 0; i < len; i++) { out[i] = toHex(this.parent[i + this.offset]); if (i == exports.INSPECT_MAX_BYTES) { out[i + 1] = '...'; break; } } return ''; }; Buffer.prototype.get = function get(i) { if (i < 0 || i >= this.length) throw new Error('oob'); return this.parent[this.offset + i]; }; Buffer.prototype.set = function set(i, v) { if (i < 0 || i >= this.length) throw new Error('oob'); return this.parent[this.offset + i] = v; }; // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8') Buffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); var ret; switch (encoding) { case 'hex': ret = this.parent.hexWrite(string, this.offset + offset, length); break; case 'utf8': case 'utf-8': ret = this.parent.utf8Write(string, this.offset + offset, length); break; case 'ascii': ret = this.parent.asciiWrite(string, this.offset + offset, length); break; case 'binary': ret = this.parent.binaryWrite(string, this.offset + offset, length); break; case 'base64': // Warning: maxLength not taken into account in base64Write ret = this.parent.base64Write(string, this.offset + offset, length); break; case 'ucs2': case 'ucs-2': ret = this.parent.ucs2Write(string, this.offset + offset, length); break; default: throw new Error('Unknown encoding'); } Buffer._charsWritten = SlowBuffer._charsWritten; return ret; }; // toString(encoding, start=0, end=buffer.length) Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); if (typeof start == 'undefined' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } if (typeof end == 'undefined' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; } start = start + this.offset; end = end + this.offset; switch (encoding) { case 'hex': return this.parent.hexSlice(start, end); case 'utf8': case 'utf-8': return this.parent.utf8Slice(start, end); case 'ascii': return this.parent.asciiSlice(start, end); case 'binary': return this.parent.binarySlice(start, end); case 'base64': return this.parent.base64Slice(start, end); case 'ucs2': case 'ucs-2': return this.parent.ucs2Slice(start, end); default: throw new Error('Unknown encoding'); } }; // byteLength Buffer.byteLength = SlowBuffer.byteLength; // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill(value, start, end) { value || (value = 0); start || (start = 0); end || (end = this.length); if (typeof value === 'string') { value = value.charCodeAt(0); } if (!(typeof value === 'number') || isNaN(value)) { throw new Error('value is not a number'); } if (end < start) throw new Error('end < start'); // Fill 0 bytes; we're done if (end === start) return 0; if (this.length == 0) return 0; if (start < 0 || start >= this.length) { throw new Error('start out of bounds'); } if (end < 0 || end > this.length) { throw new Error('end out of bounds'); } return this.parent.fill(value, start + this.offset, end + this.offset); }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function(target, target_start, start, end) { var source = this; start || (start = 0); end || (end = this.length); target_start || (target_start = 0); if (end < start) throw new Error('sourceEnd < sourceStart'); // Copy 0 bytes; we're done if (end === start) return 0; if (target.length == 0 || source.length == 0) return 0; if (target_start < 0 || target_start >= target.length) { throw new Error('targetStart out of bounds'); } if (start < 0 || start >= source.length) { throw new Error('sourceStart out of bounds'); } if (end < 0 || end > source.length) { throw new Error('sourceEnd out of bounds'); } // Are we oob? if (end > this.length) { end = this.length; } if (target.length - target_start < end - start) { end = target.length - target_start + start; } return this.parent.copy(target.parent, target_start + target.offset, start + this.offset, end + this.offset); }; // slice(start, end) Buffer.prototype.slice = function(start, end) { if (end === undefined) end = this.length; if (end > this.length) throw new Error('oob'); if (start > end) throw new Error('oob'); return new Buffer(this.parent, end - start, +start + this.offset); }; // Legacy methods for backwards compatibility. Buffer.prototype.utf8Slice = function(start, end) { return this.toString('utf8', start, end); }; Buffer.prototype.binarySlice = function(start, end) { return this.toString('binary', start, end); }; Buffer.prototype.asciiSlice = function(start, end) { return this.toString('ascii', start, end); }; Buffer.prototype.utf8Write = function(string, offset) { return this.write(string, offset, 'utf8'); }; Buffer.prototype.binaryWrite = function(string, offset) { return this.write(string, offset, 'binary'); }; Buffer.prototype.asciiWrite = function(string, offset) { return this.write(string, offset, 'ascii'); }; Buffer.prototype.readUInt8 = function(offset, noAssert) { var buffer = this; if (!noAssert) { assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset < buffer.length, 'Trying to read beyond buffer length'); } return buffer.parent[buffer.offset + offset]; }; function readUInt16(buffer, offset, isBigEndian, noAssert) { var val = 0; if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 1 < buffer.length, 'Trying to read beyond buffer length'); } if (isBigEndian) { val = buffer.parent[buffer.offset + offset] << 8; val |= buffer.parent[buffer.offset + offset + 1]; } else { val = buffer.parent[buffer.offset + offset]; val |= buffer.parent[buffer.offset + offset + 1] << 8; } return val; } Buffer.prototype.readUInt16LE = function(offset, noAssert) { return readUInt16(this, offset, false, noAssert); }; Buffer.prototype.readUInt16BE = function(offset, noAssert) { return readUInt16(this, offset, true, noAssert); }; function readUInt32(buffer, offset, isBigEndian, noAssert) { var val = 0; if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 3 < buffer.length, 'Trying to read beyond buffer length'); } if (isBigEndian) { val = buffer.parent[buffer.offset + offset + 1] << 16; val |= buffer.parent[buffer.offset + offset + 2] << 8; val |= buffer.parent[buffer.offset + offset + 3]; val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0); } else { val = buffer.parent[buffer.offset + offset + 2] << 16; val |= buffer.parent[buffer.offset + offset + 1] << 8; val |= buffer.parent[buffer.offset + offset]; val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0); } return val; } Buffer.prototype.readUInt32LE = function(offset, noAssert) { return readUInt32(this, offset, false, noAssert); }; Buffer.prototype.readUInt32BE = function(offset, noAssert) { return readUInt32(this, offset, true, noAssert); }; /* * Signed integer types, yay team! A reminder on how two's complement actually * works. The first bit is the signed bit, i.e. tells us whether or not the * number should be positive or negative. If the two's complement value is * positive, then we're done, as it's equivalent to the unsigned representation. * * Now if the number is positive, you're pretty much done, you can just leverage * the unsigned translations and return those. Unfortunately, negative numbers * aren't quite that straightforward. * * At first glance, one might be inclined to use the traditional formula to * translate binary numbers between the positive and negative values in two's * complement. (Though it doesn't quite work for the most negative value) * Mainly: * - invert all the bits * - add one to the result * * Of course, this doesn't quite work in Javascript. Take for example the value * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of * course, Javascript will do the following: * * > ~0xff80 * -65409 * * Whoh there, Javascript, that's not quite right. But wait, according to * Javascript that's perfectly correct. When Javascript ends up seeing the * constant 0xff80, it has no notion that it is actually a signed number. It * assumes that we've input the unsigned value 0xff80. Thus, when it does the * binary negation, it casts it into a signed value, (positive 0xff80). Then * when you perform binary negation on that, it turns it into a negative number. * * Instead, we're going to have to use the following general formula, that works * in a rather Javascript friendly way. I'm glad we don't support this kind of * weird numbering scheme in the kernel. * * (BIT-MAX - (unsigned)val + 1) * -1 * * The astute observer, may think that this doesn't make sense for 8-bit numbers * (really it isn't necessary for them). However, when you get 16-bit numbers, * you do. Let's go back to our prior example and see how this will look: * * (0xffff - 0xff80 + 1) * -1 * (0x007f + 1) * -1 * (0x0080) * -1 */ Buffer.prototype.readInt8 = function(offset, noAssert) { var buffer = this; var neg; if (!noAssert) { assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset < buffer.length, 'Trying to read beyond buffer length'); } neg = buffer.parent[buffer.offset + offset] & 0x80; if (!neg) { return (buffer.parent[buffer.offset + offset]); } return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1); }; function readInt16(buffer, offset, isBigEndian, noAssert) { var neg, val; if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 1 < buffer.length, 'Trying to read beyond buffer length'); } val = readUInt16(buffer, offset, isBigEndian, noAssert); neg = val & 0x8000; if (!neg) { return val; } return (0xffff - val + 1) * -1; } Buffer.prototype.readInt16LE = function(offset, noAssert) { return readInt16(this, offset, false, noAssert); }; Buffer.prototype.readInt16BE = function(offset, noAssert) { return readInt16(this, offset, true, noAssert); }; function readInt32(buffer, offset, isBigEndian, noAssert) { var neg, val; if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 3 < buffer.length, 'Trying to read beyond buffer length'); } val = readUInt32(buffer, offset, isBigEndian, noAssert); neg = val & 0x80000000; if (!neg) { return (val); } return (0xffffffff - val + 1) * -1; } Buffer.prototype.readInt32LE = function(offset, noAssert) { return readInt32(this, offset, false, noAssert); }; Buffer.prototype.readInt32BE = function(offset, noAssert) { return readInt32(this, offset, true, noAssert); }; function readFloat(buffer, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset + 3 < buffer.length, 'Trying to read beyond buffer length'); } return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, 23, 4); } Buffer.prototype.readFloatLE = function(offset, noAssert) { return readFloat(this, offset, false, noAssert); }; Buffer.prototype.readFloatBE = function(offset, noAssert) { return readFloat(this, offset, true, noAssert); }; function readDouble(buffer, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset + 7 < buffer.length, 'Trying to read beyond buffer length'); } return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, 52, 8); } Buffer.prototype.readDoubleLE = function(offset, noAssert) { return readDouble(this, offset, false, noAssert); }; Buffer.prototype.readDoubleBE = function(offset, noAssert) { return readDouble(this, offset, true, noAssert); }; /* * We have to make sure that the value is a valid integer. This means that it is * non-negative. It has no fractional component and that it does not exceed the * maximum allowed value. * * value The number to check for validity * * max The maximum value */ function verifuint(value, max) { assert.ok(typeof (value) == 'number', 'cannot write a non-number as a number'); assert.ok(value >= 0, 'specified a negative value for writing an unsigned value'); assert.ok(value <= max, 'value is larger than maximum value for type'); assert.ok(Math.floor(value) === value, 'value has a fractional component'); } Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { var buffer = this; if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset < buffer.length, 'trying to write beyond buffer length'); verifuint(value, 0xff); } buffer.parent[buffer.offset + offset] = value; }; function writeUInt16(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 1 < buffer.length, 'trying to write beyond buffer length'); verifuint(value, 0xffff); } if (isBigEndian) { buffer.parent[buffer.offset + offset] = (value & 0xff00) >>> 8; buffer.parent[buffer.offset + offset + 1] = value & 0x00ff; } else { buffer.parent[buffer.offset + offset + 1] = (value & 0xff00) >>> 8; buffer.parent[buffer.offset + offset] = value & 0x00ff; } } Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { writeUInt16(this, value, offset, false, noAssert); }; Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { writeUInt16(this, value, offset, true, noAssert); }; function writeUInt32(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 3 < buffer.length, 'trying to write beyond buffer length'); verifuint(value, 0xffffffff); } if (isBigEndian) { buffer.parent[buffer.offset + offset] = (value >>> 24) & 0xff; buffer.parent[buffer.offset + offset + 1] = (value >>> 16) & 0xff; buffer.parent[buffer.offset + offset + 2] = (value >>> 8) & 0xff; buffer.parent[buffer.offset + offset + 3] = value & 0xff; } else { buffer.parent[buffer.offset + offset + 3] = (value >>> 24) & 0xff; buffer.parent[buffer.offset + offset + 2] = (value >>> 16) & 0xff; buffer.parent[buffer.offset + offset + 1] = (value >>> 8) & 0xff; buffer.parent[buffer.offset + offset] = value & 0xff; } } Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { writeUInt32(this, value, offset, false, noAssert); }; Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { writeUInt32(this, value, offset, true, noAssert); }; /* * We now move onto our friends in the signed number category. Unlike unsigned * numbers, we're going to have to worry a bit more about how we put values into * arrays. Since we are only worrying about signed 32-bit values, we're in * slightly better shape. Unfortunately, we really can't do our favorite binary * & in this system. It really seems to do the wrong thing. For example: * * > -32 & 0xff * 224 * * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of * this aren't treated as a signed number. Ultimately a bad thing. * * What we're going to want to do is basically create the unsigned equivalent of * our representation and pass that off to the wuint* functions. To do that * we're going to do the following: * * - if the value is positive * we can pass it directly off to the equivalent wuint * - if the value is negative * we do the following computation: * mb + val + 1, where * mb is the maximum unsigned value in that byte size * val is the Javascript negative integer * * * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If * you do out the computations: * * 0xffff - 128 + 1 * 0xffff - 127 * 0xff80 * * You can then encode this value as the signed version. This is really rather * hacky, but it should work and get the job done which is our goal here. */ /* * A series of checks to make sure we actually have a signed 32-bit number */ function verifsint(value, max, min) { assert.ok(typeof (value) == 'number', 'cannot write a non-number as a number'); assert.ok(value <= max, 'value larger than maximum allowed value'); assert.ok(value >= min, 'value smaller than minimum allowed value'); assert.ok(Math.floor(value) === value, 'value has a fractional component'); } function verifIEEE754(value, max, min) { assert.ok(typeof (value) == 'number', 'cannot write a non-number as a number'); assert.ok(value <= max, 'value larger than maximum allowed value'); assert.ok(value >= min, 'value smaller than minimum allowed value'); } Buffer.prototype.writeInt8 = function(value, offset, noAssert) { var buffer = this; if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset < buffer.length, 'Trying to write beyond buffer length'); verifsint(value, 0x7f, -0x80); } if (value >= 0) { buffer.writeUInt8(value, offset, noAssert); } else { buffer.writeUInt8(0xff + value + 1, offset, noAssert); } }; function writeInt16(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 1 < buffer.length, 'Trying to write beyond buffer length'); verifsint(value, 0x7fff, -0x8000); } if (value >= 0) { writeUInt16(buffer, value, offset, isBigEndian, noAssert); } else { writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert); } } Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { writeInt16(this, value, offset, false, noAssert); }; Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { writeInt16(this, value, offset, true, noAssert); }; function writeInt32(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 3 < buffer.length, 'Trying to write beyond buffer length'); verifsint(value, 0x7fffffff, -0x80000000); } if (value >= 0) { writeUInt32(buffer, value, offset, isBigEndian, noAssert); } else { writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert); } } Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { writeInt32(this, value, offset, false, noAssert); }; Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { writeInt32(this, value, offset, true, noAssert); }; function writeFloat(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 3 < buffer.length, 'Trying to write beyond buffer length'); verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38); } require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, 23, 4); } Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { writeFloat(this, value, offset, false, noAssert); }; Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { writeFloat(this, value, offset, true, noAssert); }; function writeDouble(buffer, value, offset, isBigEndian, noAssert) { if (!noAssert) { assert.ok(value !== undefined && value !== null, 'missing value'); assert.ok(typeof (isBigEndian) === 'boolean', 'missing or invalid endian'); assert.ok(offset !== undefined && offset !== null, 'missing offset'); assert.ok(offset + 7 < buffer.length, 'Trying to write beyond buffer length'); verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308); } require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, 52, 8); } Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { writeDouble(this, value, offset, false, noAssert); }; Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { writeDouble(this, value, offset, true, noAssert); }; SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8; SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE; SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE; SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE; SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE; SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8; SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE; SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE; SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE; SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE; SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE; SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE; SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE; SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE; SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8; SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE; SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE; SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE; SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE; SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8; SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE; SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE; SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE; SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE; SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE; SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE; SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE; SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE; }); require.define("/node_modules/buffer-browserify/node_modules/base64-js/package.json",function(require,module,exports,__dirname,__filename,process,global){module.exports = {"main":"lib/b64.js"} }); require.define("/node_modules/buffer-browserify/node_modules/base64-js/lib/b64.js",function(require,module,exports,__dirname,__filename,process,global){(function (exports) { 'use strict'; var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; function b64ToByteArray(b64) { var i, j, l, tmp, placeHolders, arr; if (b64.length % 4 > 0) { throw 'Invalid string. Length must be a multiple of 4'; } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice placeHolders = b64.indexOf('='); placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0; // base64 is 4/3 + up to two characters of the original data arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? b64.length - 4 : b64.length; for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); arr.push((tmp & 0xFF0000) >> 16); arr.push((tmp & 0xFF00) >> 8); arr.push(tmp & 0xFF); } if (placeHolders === 2) { tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4); arr.push(tmp & 0xFF); } else if (placeHolders === 1) { tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2); arr.push((tmp >> 8) & 0xFF); arr.push(tmp & 0xFF); } return arr; } function uint8ToBase64(uint8) { var i, extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes output = "", temp, length; function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; }; // go through the array every three bytes, we'll deal with trailing stuff later for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); output += tripletToBase64(temp); } // pad the end with zeros, but make sure to not forget the extra bytes switch (extraBytes) { case 1: temp = uint8[uint8.length - 1]; output += lookup[temp >> 2]; output += lookup[(temp << 4) & 0x3F]; output += '=='; break; case 2: temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); output += lookup[temp >> 10]; output += lookup[(temp >> 4) & 0x3F]; output += lookup[(temp << 2) & 0x3F]; output += '='; break; } return output; } module.exports.toByteArray = b64ToByteArray; module.exports.fromByteArray = uint8ToBase64; }()); }); require.define("/node_modules/buffer-browserify/buffer_ieee754.js",function(require,module,exports,__dirname,__filename,process,global){exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, nBits = -7, i = isBE ? 0 : (nBytes - 1), d = isBE ? 1 : -1, s = buffer[offset + i]; i += d; e = s & ((1 << (-nBits)) - 1); s >>= (-nBits); nBits += eLen; for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); m = e & ((1 << (-nBits)) - 1); e >>= (-nBits); nBits += mLen; for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); if (e === 0) { e = 1 - eBias; } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity); } else { m = m + Math.pow(2, mLen); e = e - eBias; } return (s ? -1 : 1) * m * Math.pow(2, e - mLen); }; exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) { var e, m, c, eLen = nBytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), i = isBE ? (nBytes - 1) : 0, d = isBE ? -1 : 1, s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; value = Math.abs(value); if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0; e = eMax; } else { e = Math.floor(Math.log(value) / Math.LN2); if (value * (c = Math.pow(2, -e)) < 1) { e--; c *= 2; } if (e + eBias >= 1) { value += rt / c; } else { value += rt * Math.pow(2, 1 - eBias); } if (value * c >= 2) { e++; c /= 2; } if (e + eBias >= eMax) { m = 0; e = eMax; } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen); e = e + eBias; } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); e = 0; } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); e = (e << mLen) | m; eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); buffer[offset + i - d] |= s * 128; }; }); require.define("/node_modules/trimesh/src/heap.js",function(require,module,exports,__dirname,__filename,process,global){// Binary Heap // By: Marjin Haverbeke // Web: http://eloquentjavascript.net/appendix2.html function BinaryHeap(scoreFunction){ this.content = []; this.scoreFunction = scoreFunction; } BinaryHeap.prototype = { push: function(element) { // Add the new element to the end of the array. this.content.push(element); // Allow it to bubble up. this.bubbleUp(this.content.length - 1); }, pop: function() { // Store the first element so we can return it later. var result = this.content[0]; // Get the element at the end of the array. var end = this.content.pop(); // If there are any elements left, put the end element at the // start, and let it sink down. if (this.content.length > 0) { this.content[0] = end; this.sinkDown(0); } return result; }, remove: function(node) { var len = this.content.length; // To remove a value, we must search through the array to find // it. for (var i = 0; i < len; i++) { if (this.content[i] == node) { // When it is found, the process seen in 'pop' is repeated // to fill up the hole. var end = this.content.pop(); if (i != len - 1) { this.content[i] = end; if (this.scoreFunction(end) < this.scoreFunction(node)) this.bubbleUp(i); else this.sinkDown(i); } return; } } }, size: function() { return this.content.length; }, bubbleUp: function(n) { // Fetch the element that has to be moved. var element = this.content[n]; // When at 0, an element can not go up any further. while (n > 0) { // Compute the parent element's index, and fetch it. var parentN = Math.floor((n + 1) / 2) - 1, parent = this.content[parentN]; // Swap the elements if the parent is greater. if (this.scoreFunction(element) < this.scoreFunction(parent)) { this.content[parentN] = element; this.content[n] = parent; // Update 'n' to continue at the new position. n = parentN; } // Found a parent that is less, no need to move it further. else { break; } } }, sinkDown: function(n) { // Look up the target element and its score. var length = this.content.length, element = this.content[n], elemScore = this.scoreFunction(element); while(true) { // Compute the indices of the child elements. var child2N = (n + 1) * 2, child1N = child2N - 1; // This is used to store the new position of the element, // if any. var swap = null; // If the first child exists (is inside the array)... if (child1N < length) { // Look it up and compute its score. var child1 = this.content[child1N], child1Score = this.scoreFunction(child1); // If the score is less than our element's, we need to swap. if (child1Score < elemScore) swap = child1N; } // Do the same checks for the other child. if (child2N < length) { var child2 = this.content[child2N], child2Score = this.scoreFunction(child2); if (child2Score < (swap == null ? elemScore : child1Score)) swap = child2N; } // If the element needs to be moved, swap it, and continue. if (swap != null) { this.content[n] = this.content[swap]; this.content[swap] = element; n = swap; } // Otherwise, we are done. else { break; } } } }; if(typeof(exports) !== "undefined") { exports.BinaryHeap = BinaryHeap; } }); require.define("/node_modules/trimesh/src/shapes.js",function(require,module,exports,__dirname,__filename,process,global){"use strict"; var repair = require('./repair.js'); //Creates a grid mesh function grid_mesh(args) { var nx = args.width || 10; var ny = args.height || 10; var positions = new Array((nx+1) * (ny+1)); for(var j=0; j<=ny; ++j) { for(var i=0; i<=nx; ++i) { positions[i + (nx+1)*j] = [i, j, 0]; } } function p(x,y) { return x + (nx+1)*y; }; var faces = []; for(var j=0; j> 1; var side_len = 2*radius + 1; function p(x,y,s) { return x + side_len * (y + side_len * s); } var positions = new Array(6 * side_len * side_len); var faces = []; for(var d=0; d<3; ++d) { var u = (d+1)%3; var v = (d+2)%3; for(var s=0; s<2; ++s) { var f = 2*d + s; var x = new Array(3); x[u] = -radius; x[v] = -radius; x[d] = (1 - 2*s) * radius; for(var j=0; j EPSILON) { row_inner.push(new ColumnEntry(j, wi)); inner_weight += wi; } if(wo - wi > EPSILON) { row_outer.push(new ColumnEntry(j, wo - wi)); outer_weight += wo - wi; } } //Rescale inner matrix var s = 1.0 / inner_weight; for(var j=0; j EPSILON) { la = 1.0 / Math.sqrt(la); } if(lb > EPSILON) { lb = 1.0 / Math.sqrt(lb); } var na = new Array(3); var nb = new Array(3); for(var i=0; i<3; ++i) { na[i] = a[i] * la; nb[i] = b[i] * lb; } //Compute quaternion cross of a and b var r = new Array(4); var s = 0.0; for(var i=0; i<3; ++i) { var u = (i+1)%3; var v = (i+2)%3; r[i+1] = na[u]*nb[v] - na[v]*nb[u]; s += Math.pow(r[i+1], 2); } r[0] = Math.sqrt(1.0 - s); return r; } function qnormalize(q) { var s = 0.0; for(var i=0; i<4; ++i) { s += q[i] * q[i]; } if(s < EPSILON) { return [1.0, 0.0, 0.0, 0.0]; } s = 1.0 / Math.sqrt(s); var r = new Array(4); for(var i=0; i<4; ++i) { r[i] = q[i] * s; } return r; } //Assumes z-direction is view axis function ArcballCamera() { this.rotation = [1.0, 0.0, 0.0, 0.0]; this.translation = [0.0, 0.0, 0.0]; this.zoom_factor = 0.0; this.z_plane = 0.5; this.pan_speed = 20.0; this.zoom_speed = 1.0; this.last_x = 0.0; this.last_y = 0.0; } //Call this whenever the mouse moves ArcballCamera.prototype.update = function(mx, my, flags) { if(flags.rotate) { var v0 = [this.last_x, -this.last_y, this.z_plane]; var v1 = [mx, -my, this.z_plane]; this.rotation = qnormalize(qmult(qcross(v0, v1), this.rotation)); } if(flags.pan || flags.zoom) { var rmatrix = qmatrix(this.rotation); var dx = mx - this.last_x; var dy = this.last_y - my; var pan_speed = flags.pan ? this.pan_speed : 0.0; var zoom_speed = flags.zoom ? this.zoom_speed : 0.0; for(var i=0; i<3; ++i) { this.translation[i] += pan_speed * (dx * rmatrix[0][i] + dy * rmatrix[1][i]); } this.zoom_factor += zoom_speed * dy; } this.last_x = mx; this.last_y = my; } //Returns the camera matrix ArcballCamera.prototype.matrix = function() { var rmatrix = qmatrix(this.rotation); var result = new Array(4); var scale = Math.exp(this.zoom_factor); for(var i=0; i<4; ++i) { if(i < 3) { result[i] = new Array(4); result[i][3] = 0.0; for(var j=0; j<3; ++j) { result[i][j] = rmatrix[i][j] * scale; result[i][3] += rmatrix[i][j] * this.translation[j] * scale; } } else { result[i] = [0.0, 0.0, 0.0, 1.0]; } } return result; } exports.ArcballCamera = ArcballCamera; }); require.define("/shapes.js",function(require,module,exports,__dirname,__filename,process,global){var meshdata = require('meshdata'); var trimesh = require('trimesh'); function createMoebius(u_res, v_res) { var faces = []; var vertices = []; var stripes = []; for(var j=0; j 0) { var s0 = stripes[stripes.length-2]; var s1 = stripe; for(var i=1; i>16)/255.0, ((hex>>8)&0xff)/255.0, (hex&0xff)/255.0 ] } var color_scheme = { bg_color: hex2rgb(0x64aad0), light_color: hex2rgb(0x3914af), dark_color: hex2rgb(0x41db00), cell_color: hex2rgb(0xff8b00) }; //Context and mesh shader variables var context; var meshShader; var simulation; var paused = false; var camera = new ArcballCamera(); var old_params = { mesh: "", inner_radius: 0, outer_radius: 0 }; var buttons = { rotate: false, zoom: false, pan: false }; function printVec3(vec) { return "vec3(" + vec[0] + "," + vec[1] + "," + vec[2] + ")"; } //Flattens an array function flatten(arr) { var flat = []; for(var i=0; i MeshLife

Simulation Parameters:


Mesh:
Subdivisions:
Outer Radius:
Inner Radius:
Birth Min:
Birth Max:
Survive Min:
Survive Max:
Alpha N:
Alpha M:
Timestep:
Delta t:
Initial Sites:

================================================ FILE: MeshLife/main.css ================================================ #container { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; } #controls { position: absolute; top: 10px; left: 10px; z-index: 1; font-family: Sans-Serif; } ================================================ FILE: MeshSimplify/MIT-LICENSE.txt ================================================ Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MeshSimplify/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: MeshSimplify/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: MeshSimplify/experiment.txt ================================================ Method: tested each algorithm on 65^3 grid. Plotted the function sin(omega * x) + sin(omega * y) + sin(omega * z) in the range [-pi/2, pi/2] x [-pi/2, pi/2] x [-pi/2, pi/2] To control for garbage collection and other unpredictable run time events, each run was repeated 100x to get an averaged measurement. Also, since v8 has a JIT, we ran each method on a grid initialized with omega = 5 for 100 iterations in an attempt to trigger v8's optimizer. Measurements were taken on my laptop: node.js version: 0.6.14 Linux Mint 12 CPU: Intel Core2 Duo P8700 @ 2.53GHz RAM: 4 GB First column is omega, second column is time taken. All measurements are in milliseconds (ms) mc: 0, 29.93 1, 43.62 2, 61.48 3, 93.31 4, 138.2 5, 145.8 6, 186.0 7, 213.2 8, 255.9 9, 272.1 10, 274.6 sn (no precalc): 0, 26.79 1, 33.95 2, 44.87 3, 54.74 4, 59.81 5, 86.61 6, 98.45 7, 114.5 8, 131.2 9, 131.0 10, 147.7 sn (w/ edge precalculation): 0, 24.06 1, 29.42 2, 37.78 3, 47.72 4, 51.36 5, 74.54 6, 83.99 7, 97.34 8, 112.4 9, 109.2 10, 124.3 mt (NOTE: Number of iterations was reduced to 20 in order to get benchmark to complete in a reasonable time): 0, 57 1, 171 2, 250 3, 392 4, 510 5, 620 6, 784 7, 922 8, 1070 9, 1220 10, 1420 Mesh sizes: vertices/faces: sn: 0, 0 7759, 7569 15261, 14513 23247, 22695 30590, 29132 38627, 37749 45957, 43861 53899, 52755 60978, 58304 68991, 67665 76193, 73133 mc: 0, 0 31038, 15520 61034, 30512 93042, 46548 122378, 61204 154758, 77504 184138, 92224 216282, 108484 244514, 122576 277422, 139440 306554, 154168 mt: 0, 0 139770, 42701 214610, 65071 338766, 102805 431466, 130840 553458, 167781 652046, 197603 769878, 233265 869174, 263474 986538, 298725 1087086, 329083 ================================================ FILE: MeshSimplify/index.html ================================================ Volume Sampling Toolbox
Volume Resampling
- p for screenshot

Input Data:

Filter:

Scale:

Show facets:

Show edges:

Volume Resolution:

Vertex count:

Face count:

================================================ FILE: MeshSimplify/js/marchingcubes.js ================================================ /** * Javascript Marching Cubes * * Based on Paul Bourke's classic implementation: * http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ * * JS port by Mikola Lysenko */ var MarchingCubes = (function() { var edgeTable= new Uint32Array([ 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ]) , triTable = [ [], [0, 8, 3], [0, 1, 9], [1, 8, 3, 9, 8, 1], [1, 2, 10], [0, 8, 3, 1, 2, 10], [9, 2, 10, 0, 2, 9], [2, 8, 3, 2, 10, 8, 10, 9, 8], [3, 11, 2], [0, 11, 2, 8, 11, 0], [1, 9, 0, 2, 3, 11], [1, 11, 2, 1, 9, 11, 9, 8, 11], [3, 10, 1, 11, 10, 3], [0, 10, 1, 0, 8, 10, 8, 11, 10], [3, 9, 0, 3, 11, 9, 11, 10, 9], [9, 8, 10, 10, 8, 11], [4, 7, 8], [4, 3, 0, 7, 3, 4], [0, 1, 9, 8, 4, 7], [4, 1, 9, 4, 7, 1, 7, 3, 1], [1, 2, 10, 8, 4, 7], [3, 4, 7, 3, 0, 4, 1, 2, 10], [9, 2, 10, 9, 0, 2, 8, 4, 7], [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4], [8, 4, 7, 3, 11, 2], [11, 4, 7, 11, 2, 4, 2, 0, 4], [9, 0, 1, 8, 4, 7, 2, 3, 11], [4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1], [3, 10, 1, 3, 11, 10, 7, 8, 4], [1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4], [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3], [4, 7, 11, 4, 11, 9, 9, 11, 10], [9, 5, 4], [9, 5, 4, 0, 8, 3], [0, 5, 4, 1, 5, 0], [8, 5, 4, 8, 3, 5, 3, 1, 5], [1, 2, 10, 9, 5, 4], [3, 0, 8, 1, 2, 10, 4, 9, 5], [5, 2, 10, 5, 4, 2, 4, 0, 2], [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8], [9, 5, 4, 2, 3, 11], [0, 11, 2, 0, 8, 11, 4, 9, 5], [0, 5, 4, 0, 1, 5, 2, 3, 11], [2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5], [10, 3, 11, 10, 1, 3, 9, 5, 4], [4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10], [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3], [5, 4, 8, 5, 8, 10, 10, 8, 11], [9, 7, 8, 5, 7, 9], [9, 3, 0, 9, 5, 3, 5, 7, 3], [0, 7, 8, 0, 1, 7, 1, 5, 7], [1, 5, 3, 3, 5, 7], [9, 7, 8, 9, 5, 7, 10, 1, 2], [10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3], [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2], [2, 10, 5, 2, 5, 3, 3, 5, 7], [7, 9, 5, 7, 8, 9, 3, 11, 2], [9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11], [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7], [11, 2, 1, 11, 1, 7, 7, 1, 5], [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11], [5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0], [11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0], [11, 10, 5, 7, 11, 5], [10, 6, 5], [0, 8, 3, 5, 10, 6], [9, 0, 1, 5, 10, 6], [1, 8, 3, 1, 9, 8, 5, 10, 6], [1, 6, 5, 2, 6, 1], [1, 6, 5, 1, 2, 6, 3, 0, 8], [9, 6, 5, 9, 0, 6, 0, 2, 6], [5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8], [2, 3, 11, 10, 6, 5], [11, 0, 8, 11, 2, 0, 10, 6, 5], [0, 1, 9, 2, 3, 11, 5, 10, 6], [5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11], [6, 3, 11, 6, 5, 3, 5, 1, 3], [0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6], [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9], [6, 5, 9, 6, 9, 11, 11, 9, 8], [5, 10, 6, 4, 7, 8], [4, 3, 0, 4, 7, 3, 6, 5, 10], [1, 9, 0, 5, 10, 6, 8, 4, 7], [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4], [6, 1, 2, 6, 5, 1, 4, 7, 8], [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7], [8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6], [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9], [3, 11, 2, 7, 8, 4, 10, 6, 5], [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11], [0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6], [9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6], [8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6], [5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11], [0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7], [6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9], [10, 4, 9, 6, 4, 10], [4, 10, 6, 4, 9, 10, 0, 8, 3], [10, 0, 1, 10, 6, 0, 6, 4, 0], [8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10], [1, 4, 9, 1, 2, 4, 2, 6, 4], [3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4], [0, 2, 4, 4, 2, 6], [8, 3, 2, 8, 2, 4, 4, 2, 6], [10, 4, 9, 10, 6, 4, 11, 2, 3], [0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6], [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10], [6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1], [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3], [8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1], [3, 11, 6, 3, 6, 0, 0, 6, 4], [6, 4, 8, 11, 6, 8], [7, 10, 6, 7, 8, 10, 8, 9, 10], [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10], [10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0], [10, 6, 7, 10, 7, 1, 1, 7, 3], [1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7], [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9], [7, 8, 0, 7, 0, 6, 6, 0, 2], [7, 3, 2, 6, 7, 2], [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7], [2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7], [1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11], [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1], [8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6], [0, 9, 1, 11, 6, 7], [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0], [7, 11, 6], [7, 6, 11], [3, 0, 8, 11, 7, 6], [0, 1, 9, 11, 7, 6], [8, 1, 9, 8, 3, 1, 11, 7, 6], [10, 1, 2, 6, 11, 7], [1, 2, 10, 3, 0, 8, 6, 11, 7], [2, 9, 0, 2, 10, 9, 6, 11, 7], [6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8], [7, 2, 3, 6, 2, 7], [7, 0, 8, 7, 6, 0, 6, 2, 0], [2, 7, 6, 2, 3, 7, 0, 1, 9], [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6], [10, 7, 6, 10, 1, 7, 1, 3, 7], [10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8], [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7], [7, 6, 10, 7, 10, 8, 8, 10, 9], [6, 8, 4, 11, 8, 6], [3, 6, 11, 3, 0, 6, 0, 4, 6], [8, 6, 11, 8, 4, 6, 9, 0, 1], [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6], [6, 8, 4, 6, 11, 8, 2, 10, 1], [1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6], [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9], [10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3], [8, 2, 3, 8, 4, 2, 4, 6, 2], [0, 4, 2, 4, 6, 2], [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8], [1, 9, 4, 1, 4, 2, 2, 4, 6], [8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1], [10, 1, 0, 10, 0, 6, 6, 0, 4], [4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3], [10, 9, 4, 6, 10, 4], [4, 9, 5, 7, 6, 11], [0, 8, 3, 4, 9, 5, 11, 7, 6], [5, 0, 1, 5, 4, 0, 7, 6, 11], [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5], [9, 5, 4, 10, 1, 2, 7, 6, 11], [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5], [7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2], [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6], [7, 2, 3, 7, 6, 2, 5, 4, 9], [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7], [3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0], [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8], [9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7], [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4], [4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10], [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10], [6, 9, 5, 6, 11, 9, 11, 8, 9], [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5], [0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11], [6, 11, 3, 6, 3, 5, 5, 3, 1], [1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6], [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10], [11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5], [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3], [5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2], [9, 5, 6, 9, 6, 0, 0, 6, 2], [1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8], [1, 5, 6, 2, 1, 6], [1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6], [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0], [0, 3, 8, 5, 6, 10], [10, 5, 6], [11, 5, 10, 7, 5, 11], [11, 5, 10, 11, 7, 5, 8, 3, 0], [5, 11, 7, 5, 10, 11, 1, 9, 0], [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1], [11, 1, 2, 11, 7, 1, 7, 5, 1], [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11], [9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7], [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2], [2, 5, 10, 2, 3, 5, 3, 7, 5], [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5], [9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2], [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2], [1, 3, 5, 3, 7, 5], [0, 8, 7, 0, 7, 1, 1, 7, 5], [9, 0, 3, 9, 3, 5, 5, 3, 7], [9, 8, 7, 5, 9, 7], [5, 8, 4, 5, 10, 8, 10, 11, 8], [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0], [0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5], [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4], [2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8], [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11], [0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5], [9, 4, 5, 2, 11, 3], [2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4], [5, 10, 2, 5, 2, 4, 4, 2, 0], [3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9], [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2], [8, 4, 5, 8, 5, 3, 3, 5, 1], [0, 4, 5, 1, 0, 5], [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5], [9, 4, 5], [4, 11, 7, 4, 9, 11, 9, 10, 11], [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11], [1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11], [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4], [4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2], [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3], [11, 7, 4, 11, 4, 2, 2, 4, 0], [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4], [2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9], [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7], [3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10], [1, 10, 2, 8, 7, 4], [4, 9, 1, 4, 1, 7, 7, 1, 3], [4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1], [4, 0, 3, 7, 4, 3], [4, 8, 7], [9, 10, 8, 10, 11, 8], [3, 0, 9, 3, 9, 11, 11, 9, 10], [0, 1, 10, 0, 10, 8, 8, 10, 11], [3, 1, 10, 11, 3, 10], [1, 2, 11, 1, 11, 9, 9, 11, 8], [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9], [0, 2, 11, 8, 0, 11], [3, 2, 11], [2, 3, 8, 2, 8, 10, 10, 8, 9], [9, 10, 2, 0, 9, 2], [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8], [1, 10, 2], [1, 3, 8, 9, 1, 8], [0, 9, 1], [0, 3, 8], []] , cubeVerts = [ [0,0,0] ,[1,0,0] ,[1,1,0] ,[0,1,0] ,[0,0,1] ,[1,0,1] ,[1,1,1] ,[0,1,1]] , edgeIndex = [ [0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7] ]; return function(data, dims) { var vertices = [] , faces = [] , n = 0 , grid = new Float32Array(8) , edges = new Int32Array(12) , x = new Int32Array(3); //March over the volume for(x[2]=0; x[2] 0) ? 1 << i : 0; } //Compute vertices var edge_mask = edgeTable[cube_index]; if(edge_mask === 0) { continue; } for(var i=0; i<12; ++i) { if((edge_mask & (1< 1e-6) { t = a / d; } for(var j=0; j<3; ++j) { nv[j] = (x[j] + p0[j]) + t * (p1[j] - p0[j]); } vertices.push(nv); } //Add faces var f = triTable[cube_index]; for(var i=0; i 1e-6) { t = g0 / t; } for(var i=0; i<3; ++i) { v[i] += p0[i] + t * (p1[i] - p0[i]); } vertices.push(v); return vertices.length - 1; } //March over the volume for(x[2]=0; x[2] 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Int32Array(4096); return function(data, dims) { var vertices = [] , faces = [] , n = 0 , x = new Int32Array(3) , R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[0]+1)]) , grid = new Float32Array(8) , buf_no = 1; //Resize buffer if necessary if(R[2] * 2 > buffer.length) { buffer = new Int32Array(R[2] * 2); } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1< 54 ) { t = Math.max(t, x - 54); } if( y > 54 ) { t = Math.max(t, y - 54); } if( z > 54 ) { t = Math.max(t, z - 54); } return t; } ); result['Sphere'] = makeVolume( [[-1.55, 1.55, 0.05], [-1.55, 1.55, 0.05], [-1.55, 1.55, 0.05]], function(x,y,z) { var r = Math.sqrt(x*x + y*y + z*z); return r - 0.64; } ) result['Torus'] = makeVolume( [[-2.2, 2.2, 4.4 / 62.0], [-2.2, 2.2, 4.4 / 62.0], [-1.4, 1.4, 4.4 / 62.0]], function(x,y,z) { return Math.pow(1.0 - Math.sqrt(x*x + y*y), 2) + z*z - 0.25; } ); result['Hyperelliptic'] = makeVolume( [[-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0]], function(x,y,z) { return Math.pow( Math.pow(x, 6) + Math.pow(y, 6) + Math.pow(z, 6), 1.0/6.0 ) - 1.0; } ); result["Goursat's Surface"] = makeVolume( [[-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0], [-3.0, 3.0, 6.0/62.0]], function(x,y,z) { return Math.pow(x,4) + Math.pow(y,4) + Math.pow(z,4) - 1.5 * (x*x + y*y + z*z) + 1; } ); result["Heart"] = makeVolume( [[-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0], [-2.0, 2.0, 4.0/62.0]], function(x,y,z) { y *= 1.5; z *= 1.5; return Math.pow(2*x*x+y*y+2*z*z-1, 3) - 0.1 * z*z*y*y*y - y*y*y*x*x; } ); result['Noise (Slow)'] = makeVolume( [[-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0], [-2.0, 2.0, 4.0/126.0]], function(x,y,z) { if(x < -1.0 || x > 1.0 || y < -1.0 || y > 1.0 || z < -1.0 || z > 1.0 ) { return 0.6; } return 0.6 - PerlinNoise.noise(4.0 * x, 4.0 * y, 4.0 * z); } ); result['Asteroid (Slow)'] = makeVolume( [[-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0], [-1.5, 1.5, 3.0/94.0]], function(x,y,z) { return (x*x + y*y + z*z) - PerlinNoise.noise(x*2,y*2,z*2); } ); result['Terrain (Slow)'] = makeVolume( [[-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0], [-1, 1, 1.0/62.0]], function(x,y,z) { return y + PerlinNoise.noise(x*2+5,y*2+3,z*2+0.6); } ); result['Empty'] = function(){ return { volume: new Float32Array(32*32*32), dims:[32,32,32] } }; return result; } ================================================ FILE: MeshSimplify/js/triangle_index.js ================================================ function TriangleIndex(mesh) { } ================================================ FILE: MeshSimplify/vendor/dsp.js ================================================ /* * DSP.js - a comprehensive digital signal processing library for javascript * * Created by Corban Brook on 2010-01-01. * Copyright 2010 Corban Brook. All rights reserved. * */ //////////////////////////////////////////////////////////////////////////////// // CONSTANTS // //////////////////////////////////////////////////////////////////////////////// /** * DSP is an object which contains general purpose utility functions and constants */ var DSP = { // Channels LEFT: 0, RIGHT: 1, MIX: 2, // Waveforms SINE: 1, TRIANGLE: 2, SAW: 3, SQUARE: 4, // Filters LOWPASS: 0, HIGHPASS: 1, BANDPASS: 2, NOTCH: 3, // Window functions BARTLETT: 1, BARTLETTHANN: 2, BLACKMAN: 3, COSINE: 4, GAUSS: 5, HAMMING: 6, HANN: 7, LANCZOS: 8, RECTANGULAR: 9, TRIANGULAR: 10, // Loop modes OFF: 0, FW: 1, BW: 2, FWBW: 3, // Math TWO_PI: 2*Math.PI }; // Setup arrays for platforms which do not support byte arrays function setupTypedArray(name, fallback) { // check if TypedArray exists // typeof on Minefield and Chrome return function, typeof on Webkit returns object. if (typeof this[name] !== "function" && typeof this[name] !== "object") { // nope.. check if WebGLArray exists if (typeof this[fallback] === "function" && typeof this[fallback] !== "object") { this[name] = this[fallback]; } else { // nope.. set as Native JS array this[name] = function(obj) { if (obj instanceof Array) { return obj; } else if (typeof obj === "number") { return new Array(obj); } }; } } } setupTypedArray("Float32Array", "WebGLFloatArray"); setupTypedArray("Int32Array", "WebGLIntArray"); setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"); setupTypedArray("Uint8Array", "WebGLUnsignedByteArray"); //////////////////////////////////////////////////////////////////////////////// // DSP UTILITY FUNCTIONS // //////////////////////////////////////////////////////////////////////////////// /** * Inverts the phase of a signal * * @param {Array} buffer A sample buffer * * @returns The inverted sample buffer */ DSP.invert = function(buffer) { for (var i = 0, len = buffer.length; i < len; i++) { buffer[i] *= -1; } return buffer; }; /** * Converts split-stereo (dual mono) sample buffers into a stereo interleaved sample buffer * * @param {Array} left A sample buffer * @param {Array} right A sample buffer * * @returns The stereo interleaved buffer */ DSP.interleave = function(left, right) { if (left.length !== right.length) { throw "Can not interleave. Channel lengths differ."; } var stereoInterleaved = new Float32Array(left.length * 2); for (var i = 0, len = left.length; i < len; i++) { stereoInterleaved[2*i] = left[i]; stereoInterleaved[2*i+1] = right[i]; } return stereoInterleaved; }; /** * Converts a stereo-interleaved sample buffer into split-stereo (dual mono) sample buffers * * @param {Array} buffer A stereo-interleaved sample buffer * * @returns an Array containing left and right channels */ DSP.deinterleave = (function() { var left, right, mix, deinterleaveChannel = []; deinterleaveChannel[DSP.MIX] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { mix[i] = (buffer[2*i] + buffer[2*i+1]) / 2; } return mix; }; deinterleaveChannel[DSP.LEFT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { left[i] = buffer[2*i]; } return left; }; deinterleaveChannel[DSP.RIGHT] = function(buffer) { for (var i = 0, len = buffer.length/2; i < len; i++) { right[i] = buffer[2*i+1]; } return right; }; return function(channel, buffer) { left = left || new Float32Array(buffer.length/2); right = right || new Float32Array(buffer.length/2); mix = mix || new Float32Array(buffer.length/2); if (buffer.length/2 !== left.length) { left = new Float32Array(buffer.length/2); right = new Float32Array(buffer.length/2); mix = new Float32Array(buffer.length/2); } return deinterleaveChannel[channel](buffer); }; }()); /** * Separates a channel from a stereo-interleaved sample buffer * * @param {Array} buffer A stereo-interleaved sample buffer * @param {Number} channel A channel constant (LEFT, RIGHT, MIX) * * @returns an Array containing a signal mono sample buffer */ DSP.getChannel = DSP.deinterleave; /** * Helper method (for Reverb) to mix two (interleaved) samplebuffers. It's possible * to negate the second buffer while mixing and to perform a volume correction * on the final signal. * * @param {Array} sampleBuffer1 Array containing Float values or a Float32Array * @param {Array} sampleBuffer2 Array containing Float values or a Float32Array * @param {Boolean} negate When true inverts/flips the audio signal * @param {Number} volumeCorrection When you add multiple sample buffers, use this to tame your signal ;) * * @returns A new Float32Array interleaved buffer. */ DSP.mixSampleBuffers = function(sampleBuffer1, sampleBuffer2, negate, volumeCorrection){ var outputSamples = new Float32Array(sampleBuffer1); for(var i = 0; i peak) ? Math.abs(buffer[i]) : peak; } return peak; }; // Fourier Transform Module used by DFT, FFT, RFFT function FourierTransform(bufferSize, sampleRate) { this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.bandwidth = 2 / bufferSize * sampleRate / 2; this.spectrum = new Float32Array(bufferSize/2); this.real = new Float32Array(bufferSize); this.imag = new Float32Array(bufferSize); this.peakBand = 0; this.peak = 0; /** * Calculates the *middle* frequency of an FFT band. * * @param {Number} index The index of the FFT band. * * @returns The middle frequency in Hz. */ this.getBandFrequency = function(index) { return this.bandwidth * index + this.bandwidth / 2; }; this.calculateSpectrum = function() { var spectrum = this.spectrum, real = this.real, imag = this.imag, bSi = 2 / this.bufferSize, sqrt = Math.sqrt, rval, ival, mag; for (var i = 0, N = bufferSize/2; i < N; i++) { rval = real[i]; ival = imag[i]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } }; } /** * DFT is a class for calculating the Discrete Fourier Transform of a signal. * * @param {Number} bufferSize The size of the sample buffer to be computed * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function DFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); var N = bufferSize/2 * bufferSize; var TWO_PI = 2 * Math.PI; this.sinTable = new Float32Array(N); this.cosTable = new Float32Array(N); for (var i = 0; i < N; i++) { this.sinTable[i] = Math.sin(i * TWO_PI / bufferSize); this.cosTable[i] = Math.cos(i * TWO_PI / bufferSize); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer * * @returns The frequency spectrum array */ DFT.prototype.forward = function(buffer) { var real = this.real, imag = this.imag, rval, ival; for (var k = 0; k < this.bufferSize/2; k++) { rval = 0.0; ival = 0.0; for (var n = 0; n < buffer.length; n++) { rval += this.cosTable[k*n] * buffer[n]; ival += this.sinTable[k*n] * buffer[n]; } real[k] = rval; imag[k] = ival; } return this.calculateSpectrum(); }; /** * FFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ function FFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.reverseTable = new Uint32Array(bufferSize); var limit = 1; var bit = bufferSize >> 1; var i; while (limit < bufferSize) { for (i = 0; i < limit; i++) { this.reverseTable[i + limit] = this.reverseTable[i] + bit; } limit = limit << 1; bit = bit >> 1; } this.sinTable = new Float32Array(bufferSize); this.cosTable = new Float32Array(bufferSize); for (i = 0; i < bufferSize; i++) { this.sinTable[i] = Math.sin(-Math.PI/i); this.cosTable[i] = Math.cos(-Math.PI/i); } } /** * Performs a forward transform on the sample buffer. * Converts a time domain signal to frequency domain spectra. * * @param {Array} buffer The sample buffer. Buffer Length must be power of 2 * * @returns The frequency spectrum array */ FFT.prototype.forward = function(buffer) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, real = this.real, imag = this.imag, spectrum = this.spectrum; var k = Math.floor(Math.log(bufferSize) / Math.LN2); if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; } if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; } var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { real[i] = buffer[reverseTable[i]]; imag[i] = 0; } while (halfSize < bufferSize) { //phaseShiftStepReal = Math.cos(-Math.PI/halfSize); //phaseShiftStepImag = Math.sin(-Math.PI/halfSize); phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } return this.calculateSpectrum(); }; FFT.prototype.inverse = function(real, imag) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, spectrum = this.spectrum; real = real || this.real; imag = imag || this.imag; var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal, i; for (i = 0; i < bufferSize; i++) { imag[i] *= -1; } var revReal = new Float32Array(bufferSize); var revImag = new Float32Array(bufferSize); for (i = 0; i < real.length; i++) { revReal[i] = real[reverseTable[i]]; revImag[i] = imag[reverseTable[i]]; } real = revReal; imag = revImag; while (halfSize < bufferSize) { phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } var buffer = new Float32Array(bufferSize); // this should be reused instead for (i = 0; i < bufferSize; i++) { buffer[i] = real[i] / bufferSize; } return buffer; }; /** * RFFT is a class for calculating the Discrete Fourier Transform of a signal * with the Fast Fourier Transform algorithm. * * This method currently only contains a forward transform but is highly optimized. * * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) * * @constructor */ // lookup tables don't really gain us any speed, but they do increase // cache footprint, so don't use them in here // also we don't use sepearate arrays for real/imaginary parts // this one a little more than twice as fast as the one in FFT // however I only did the forward transform // the rest of this was translated from C, see http://www.jjj.de/fxt/ // this is the real split radix FFT function RFFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.trans = new Float32Array(bufferSize); this.reverseTable = new Uint32Array(bufferSize); // don't use a lookup table to do the permute, use this instead this.reverseBinPermute = function (dest, source) { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; dest[0] = source[0]; do { r += halfSize; dest[i] = source[r]; dest[r] = source[i]; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { dest[i] = source[r]; dest[r] = source[i]; dest[nm1-i] = source[nm1-r]; dest[nm1-r] = source[nm1-i]; } i++; } while (i < halfSize); dest[nm1] = source[nm1]; }; this.generateReverseTable = function () { var bufferSize = this.bufferSize, halfSize = bufferSize >>> 1, nm1 = bufferSize - 1, i = 1, r = 0, h; this.reverseTable[0] = 0; do { r += halfSize; this.reverseTable[i] = r; this.reverseTable[r] = i; i++; h = halfSize << 1; while (h = h >> 1, !((r ^= h) & h)); if (r >= i) { this.reverseTable[i] = r; this.reverseTable[r] = i; this.reverseTable[nm1-i] = nm1-r; this.reverseTable[nm1-r] = nm1-i; } i++; } while (i < halfSize); this.reverseTable[nm1] = nm1; }; this.generateReverseTable(); } // Ordering of output: // // trans[0] = re[0] (==zero frequency, purely real) // trans[1] = re[1] // ... // trans[n/2-1] = re[n/2-1] // trans[n/2] = re[n/2] (==nyquist frequency, purely real) // // trans[n/2+1] = im[n/2-1] // trans[n/2+2] = im[n/2-2] // ... // trans[n-1] = im[1] RFFT.prototype.forward = function(buffer) { var n = this.bufferSize, spectrum = this.spectrum, x = this.trans, TWO_PI = 2*Math.PI, sqrt = Math.sqrt, i = n >>> 1, bSi = 2 / n, n2, n4, n8, nn, t1, t2, t3, t4, i1, i2, i3, i4, i5, i6, i7, i8, st1, cc1, ss1, cc3, ss3, e, a, rval, ival, mag; this.reverseBinPermute(x, buffer); /* var reverseTable = this.reverseTable; for (var k = 0, len = reverseTable.length; k < len; k++) { x[k] = buffer[reverseTable[k]]; } */ for (var ix = 0, id = 4; ix < n; id *= 4) { for (var i0 = ix; i0 < n; i0 += id) { //sumdiff(x[i0], x[i0+1]); // {a, b} <--| {a+b, a-b} st1 = x[i0] - x[i0+1]; x[i0] += x[i0+1]; x[i0+1] = st1; } ix = 2*(id-1); } n2 = 2; nn = n >>> 1; while((nn = nn >>> 1)) { ix = 0; n2 = n2 << 1; id = n2 << 1; n4 = n2 >>> 2; n8 = n2 >>> 3; do { if(n4 !== 1) { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; i1 += n8; i2 += n8; i3 += n8; i4 += n8; //sumdiff(x[i3], x[i4], t1, t2); // {s, d} <--| {a+b, a-b} t1 = x[i3] + x[i4]; t2 = x[i3] - x[i4]; t1 = -t1 * Math.SQRT1_2; t2 *= Math.SQRT1_2; // sumdiff(t1, x[i2], x[i4], x[i3]); // {s, d} <--| {a+b, a-b} st1 = x[i2]; x[i4] = t1 + st1; x[i3] = t1 - st1; //sumdiff3(x[i1], t2, x[i2]); // {a, b, d} <--| {a+b, b, a-b} x[i2] = x[i1] - t2; x[i1] += t2; } } else { for(i0 = ix; i0 < n; i0 += id) { i1 = i0; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; //diffsum3_r(x[i3], x[i4], t1); // {a, b, s} <--| {a, b-a, a+b} t1 = x[i3] + x[i4]; x[i4] -= x[i3]; //sumdiff3(x[i1], t1, x[i3]); // {a, b, d} <--| {a+b, b, a-b} x[i3] = x[i1] - t1; x[i1] += t1; } } ix = (id << 1) - n2; id = id << 2; } while (ix < n); e = TWO_PI / n2; for (var j = 1; j < n8; j++) { a = j * e; ss1 = Math.sin(a); cc1 = Math.cos(a); //ss3 = sin(3*a); cc3 = cos(3*a); cc3 = 4*cc1*(cc1*cc1-0.75); ss3 = 4*ss1*(0.75-ss1*ss1); ix = 0; id = n2 << 1; do { for (i0 = ix; i0 < n; i0 += id) { i1 = i0 + j; i2 = i1 + n4; i3 = i2 + n4; i4 = i3 + n4; i5 = i0 + n4 - j; i6 = i5 + n4; i7 = i6 + n4; i8 = i7 + n4; //cmult(c, s, x, y, &u, &v) //cmult(cc1, ss1, x[i7], x[i3], t2, t1); // {u,v} <--| {x*c-y*s, x*s+y*c} t2 = x[i7]*cc1 - x[i3]*ss1; t1 = x[i7]*ss1 + x[i3]*cc1; //cmult(cc3, ss3, x[i8], x[i4], t4, t3); t4 = x[i8]*cc3 - x[i4]*ss3; t3 = x[i8]*ss3 + x[i4]*cc3; //sumdiff(t2, t4); // {a, b} <--| {a+b, a-b} st1 = t2 - t4; t2 += t4; t4 = st1; //sumdiff(t2, x[i6], x[i8], x[i3]); // {s, d} <--| {a+b, a-b} //st1 = x[i6]; x[i8] = t2 + st1; x[i3] = t2 - st1; x[i8] = t2 + x[i6]; x[i3] = t2 - x[i6]; //sumdiff_r(t1, t3); // {a, b} <--| {a+b, b-a} st1 = t3 - t1; t1 += t3; t3 = st1; //sumdiff(t3, x[i2], x[i4], x[i7]); // {s, d} <--| {a+b, a-b} //st1 = x[i2]; x[i4] = t3 + st1; x[i7] = t3 - st1; x[i4] = t3 + x[i2]; x[i7] = t3 - x[i2]; //sumdiff3(x[i1], t1, x[i6]); // {a, b, d} <--| {a+b, b, a-b} x[i6] = x[i1] - t1; x[i1] += t1; //diffsum3_r(t4, x[i5], x[i2]); // {a, b, s} <--| {a, b-a, a+b} x[i2] = t4 + x[i5]; x[i5] -= t4; } ix = (id << 1) - n2; id = id << 2; } while (ix < n); } } while (--i) { rval = x[i]; ival = x[n-i-1]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } spectrum[0] = bSi * x[0]; return spectrum; }; function Sampler(file, bufferSize, sampleRate, playStart, playEnd, loopStart, loopEnd, loopMode) { this.file = file; this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.playStart = playStart || 0; // 0% this.playEnd = playEnd || 1; // 100% this.loopStart = loopStart || 0; this.loopEnd = loopEnd || 1; this.loopMode = loopMode || DSP.OFF; this.loaded = false; this.samples = []; this.signal = new Float32Array(bufferSize); this.frameCount = 0; this.envelope = null; this.amplitude = 1; this.rootFrequency = 110; // A2 110 this.frequency = 550; this.step = this.frequency / this.rootFrequency; this.duration = 0; this.samplesProcessed = 0; this.playhead = 0; var audio = /* new Audio();*/ document.createElement("AUDIO"); var self = this; this.loadSamples = function(event) { var buffer = DSP.getChannel(DSP.MIX, event.frameBuffer); for ( var i = 0; i < buffer.length; i++) { self.samples.push(buffer[i]); } }; this.loadComplete = function() { // convert flexible js array into a fast typed array self.samples = new Float32Array(self.samples); self.loaded = true; }; this.loadMetaData = function() { self.duration = audio.duration; }; audio.addEventListener("MozAudioAvailable", this.loadSamples, false); audio.addEventListener("loadedmetadata", this.loadMetaData, false); audio.addEventListener("ended", this.loadComplete, false); audio.muted = true; audio.src = file; audio.play(); } Sampler.prototype.applyEnvelope = function() { this.envelope.process(this.signal); return this.signal; }; Sampler.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var loopWidth = this.playEnd * this.samples.length - this.playStart * this.samples.length; var playStartSamples = this.playStart * this.samples.length; // ie 0.5 -> 50% of the length var playEndSamples = this.playEnd * this.samples.length; // ie 0.5 -> 50% of the length var offset; for ( var i = 0; i < this.bufferSize; i++ ) { switch (this.loopMode) { case DSP.OFF: this.playhead = Math.round(this.samplesProcessed * this.step + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } else { this.signal[i] = 0; } break; case DSP.FW: this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.BW: this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; case DSP.FWBW: if ( Math.floor(this.samplesProcessed * this.step / loopWidth) % 2 === 0 ) { this.playhead = Math.round((this.samplesProcessed * this.step) % loopWidth + playStartSamples); } else { this.playhead = playEndSamples - Math.round((this.samplesProcessed * this.step) % loopWidth); } if (this.playhead < (this.playEnd * this.samples.length) ) { this.signal[i] = this.samples[this.playhead] * this.amplitude; } break; } this.samplesProcessed++; } this.frameCount++; return this.signal; }; Sampler.prototype.setFreq = function(frequency) { var totalProcessed = this.samplesProcessed * this.step; this.frequency = frequency; this.step = this.frequency / this.rootFrequency; this.samplesProcessed = Math.round(totalProcessed/this.step); }; Sampler.prototype.reset = function() { this.samplesProcessed = 0; this.playhead = 0; }; /** * Oscillator class for generating and modifying signals * * @param {Number} type A waveform constant (eg. DSP.SINE) * @param {Number} frequency Initial frequency of the signal * @param {Number} amplitude Initial amplitude of the signal * @param {Number} bufferSize Size of the sample buffer to generate * @param {Number} sampleRate The sample rate of the signal * * @contructor */ function Oscillator(type, frequency, amplitude, bufferSize, sampleRate) { this.frequency = frequency; this.amplitude = amplitude; this.bufferSize = bufferSize; this.sampleRate = sampleRate; //this.pulseWidth = pulseWidth; this.frameCount = 0; this.waveTableLength = 2048; this.cyclesPerSample = frequency / sampleRate; this.signal = new Float32Array(bufferSize); this.envelope = null; switch(parseInt(type, 10)) { case DSP.TRIANGLE: this.func = Oscillator.Triangle; break; case DSP.SAW: this.func = Oscillator.Saw; break; case DSP.SQUARE: this.func = Oscillator.Square; break; default: case DSP.SINE: this.func = Oscillator.Sine; break; } this.generateWaveTable = function() { Oscillator.waveTable[this.func] = new Float32Array(2048); var waveTableTime = this.waveTableLength / this.sampleRate; var waveTableHz = 1 / waveTableTime; for (var i = 0; i < this.waveTableLength; i++) { Oscillator.waveTable[this.func][i] = this.func(i * waveTableHz/this.sampleRate); } }; if ( typeof Oscillator.waveTable === 'undefined' ) { Oscillator.waveTable = {}; } if ( typeof Oscillator.waveTable[this.func] === 'undefined' ) { this.generateWaveTable(); } this.waveTable = Oscillator.waveTable[this.func]; } /** * Set the amplitude of the signal * * @param {Number} amplitude The amplitude of the signal (between 0 and 1) */ Oscillator.prototype.setAmp = function(amplitude) { if (amplitude >= 0 && amplitude <= 1) { this.amplitude = amplitude; } else { throw "Amplitude out of range (0..1)."; } }; /** * Set the frequency of the signal * * @param {Number} frequency The frequency of the signal */ Oscillator.prototype.setFreq = function(frequency) { this.frequency = frequency; this.cyclesPerSample = frequency / this.sampleRate; }; // Add an oscillator Oscillator.prototype.add = function(oscillator) { for ( var i = 0; i < this.bufferSize; i++ ) { //this.signal[i] += oscillator.valueAt(i); this.signal[i] += oscillator.signal[i]; } return this.signal; }; // Add a signal to the current generated osc signal Oscillator.prototype.addSignal = function(signal) { for ( var i = 0; i < signal.length; i++ ) { if ( i >= this.bufferSize ) { break; } this.signal[i] += signal[i]; /* // Constrain amplitude if ( this.signal[i] > 1 ) { this.signal[i] = 1; } else if ( this.signal[i] < -1 ) { this.signal[i] = -1; } */ } return this.signal; }; // Add an envelope to the oscillator Oscillator.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; Oscillator.prototype.applyEnvelope = function() { this.envelope.process(this.signal); }; Oscillator.prototype.valueAt = function(offset) { return this.waveTable[offset % this.waveTableLength]; }; Oscillator.prototype.generate = function() { var frameOffset = this.frameCount * this.bufferSize; var step = this.waveTableLength * this.frequency / this.sampleRate; var offset; for ( var i = 0; i < this.bufferSize; i++ ) { //var step = (frameOffset + i) * this.cyclesPerSample % 1; //this.signal[i] = this.func(step) * this.amplitude; //this.signal[i] = this.valueAt(Math.round((frameOffset + i) * step)) * this.amplitude; offset = Math.round((frameOffset + i) * step); this.signal[i] = this.waveTable[offset % this.waveTableLength] * this.amplitude; } this.frameCount++; return this.signal; }; Oscillator.Sine = function(step) { return Math.sin(DSP.TWO_PI * step); }; Oscillator.Square = function(step) { return step < 0.5 ? 1 : -1; }; Oscillator.Saw = function(step) { return 2 * (step - Math.round(step)); }; Oscillator.Triangle = function(step) { return 1 - 4 * Math.abs(Math.round(step) - step); }; Oscillator.Pulse = function(step) { // stub }; function ADSR(attackLength, decayLength, sustainLevel, sustainLength, releaseLength, sampleRate) { this.sampleRate = sampleRate; // Length in seconds this.attackLength = attackLength; this.decayLength = decayLength; this.sustainLevel = sustainLevel; this.sustainLength = sustainLength; this.releaseLength = releaseLength; this.sampleRate = sampleRate; // Length in samples this.attackSamples = attackLength * sampleRate; this.decaySamples = decayLength * sampleRate; this.sustainSamples = sustainLength * sampleRate; this.releaseSamples = releaseLength * sampleRate; // Updates the envelope sample positions this.update = function() { this.attack = this.attackSamples; this.decay = this.attack + this.decaySamples; this.sustain = this.decay + this.sustainSamples; this.release = this.sustain + this.releaseSamples; }; this.update(); this.samplesProcessed = 0; } ADSR.prototype.noteOn = function() { this.samplesProcessed = 0; this.sustainSamples = this.sustainLength * this.sampleRate; this.update(); }; // Send a note off when using a sustain of infinity to let the envelope enter the release phase ADSR.prototype.noteOff = function() { this.sustainSamples = this.samplesProcessed - this.decaySamples; this.update(); }; ADSR.prototype.processSample = function(sample) { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return sample * amplitude; }; ADSR.prototype.value = function() { var amplitude = 0; if ( this.samplesProcessed <= this.attack ) { amplitude = 0 + (1 - 0) * ((this.samplesProcessed - 0) / (this.attack - 0)); } else if ( this.samplesProcessed > this.attack && this.samplesProcessed <= this.decay ) { amplitude = 1 + (this.sustainLevel - 1) * ((this.samplesProcessed - this.attack) / (this.decay - this.attack)); } else if ( this.samplesProcessed > this.decay && this.samplesProcessed <= this.sustain ) { amplitude = this.sustainLevel; } else if ( this.samplesProcessed > this.sustain && this.samplesProcessed <= this.release ) { amplitude = this.sustainLevel + (0 - this.sustainLevel) * ((this.samplesProcessed - this.sustain) / (this.release - this.sustain)); } return amplitude; }; ADSR.prototype.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { buffer[i] *= this.value(); this.samplesProcessed++; } return buffer; }; ADSR.prototype.isActive = function() { if ( this.samplesProcessed > this.release || this.samplesProcessed === -1 ) { return false; } else { return true; } }; ADSR.prototype.disable = function() { this.samplesProcessed = -1; }; function IIRFilter(type, cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; switch(type) { case DSP.LOWPASS: case DSP.LP12: this.func = new IIRFilter.LP12(cutoff, resonance, sampleRate); break; } } IIRFilter.prototype.__defineGetter__('cutoff', function() { return this.func.cutoff; } ); IIRFilter.prototype.__defineGetter__('resonance', function() { return this.func.resonance; } ); IIRFilter.prototype.set = function(cutoff, resonance) { this.func.calcCoeff(cutoff, resonance); }; IIRFilter.prototype.process = function(buffer) { this.func.process(buffer); }; // Add an envelope to the filter IIRFilter.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.func.addEnvelope(envelope); } else { throw "Not an envelope."; } }; IIRFilter.LP12 = function(cutoff, resonance, sampleRate) { this.sampleRate = sampleRate; this.vibraPos = 0; this.vibraSpeed = 0; this.envelope = false; this.calcCoeff = function(cutoff, resonance) { this.w = 2.0 * Math.PI * cutoff / this.sampleRate; this.q = 1.0 - this.w / (2.0 * (resonance + 0.5 / (1.0 + this.w)) + this.w - 2.0); this.r = this.q * this.q; this.c = this.r + 1.0 - 2.0 * Math.cos(this.w) * this.q; this.cutoff = cutoff; this.resonance = resonance; }; this.calcCoeff(cutoff, resonance); this.process = function(buffer) { for ( var i = 0; i < buffer.length; i++ ) { this.vibraSpeed += (buffer[i] - this.vibraPos) * this.c; this.vibraPos += this.vibraSpeed; this.vibraSpeed *= this.r; /* var temp = this.vibraPos; if ( temp > 1.0 ) { temp = 1.0; } else if ( temp < -1.0 ) { temp = -1.0; } else if ( temp != temp ) { temp = 1; } buffer[i] = temp; */ if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (this.vibraPos * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = this.vibraPos; } } }; }; IIRFilter.LP12.prototype.addEnvelope = function(envelope) { this.envelope = envelope; }; function IIRFilter2(type, cutoff, resonance, sampleRate) { this.type = type; this.cutoff = cutoff; this.resonance = resonance; this.sampleRate = sampleRate; this.f = Float32Array(4); this.f[0] = 0.0; // lp this.f[1] = 0.0; // hp this.f[2] = 0.0; // bp this.f[3] = 0.0; // br this.calcCoeff = function(cutoff, resonance) { this.freq = 2 * Math.sin(Math.PI * Math.min(0.25, cutoff/(this.sampleRate*2))); this.damp = Math.min(2 * (1 - Math.pow(resonance, 0.25)), Math.min(2, 2/this.freq - this.freq * 0.5)); }; this.calcCoeff(cutoff, resonance); } IIRFilter2.prototype.process = function(buffer) { var input, output; var f = this.f; for ( var i = 0; i < buffer.length; i++ ) { input = buffer[i]; // first pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output = 0.5 * f[this.type]; // second pass f[3] = input - this.damp * f[2]; f[0] = f[0] + this.freq * f[2]; f[1] = f[3] - f[0]; f[2] = this.freq * f[1] + f[2]; output += 0.5 * f[this.type]; if (this.envelope) { buffer[i] = (buffer[i] * (1 - this.envelope.value())) + (output * this.envelope.value()); this.envelope.samplesProcessed++; } else { buffer[i] = output; } } }; IIRFilter2.prototype.addEnvelope = function(envelope) { if ( envelope instanceof ADSR ) { this.envelope = envelope; } else { throw "This is not an envelope."; } }; IIRFilter2.prototype.set = function(cutoff, resonance) { this.calcCoeff(cutoff, resonance); }; function WindowFunction(type, alpha) { this.alpha = alpha; switch(type) { case DSP.BARTLETT: this.func = WindowFunction.Bartlett; break; case DSP.BARTLETTHANN: this.func = WindowFunction.BartlettHann; break; case DSP.BLACKMAN: this.func = WindowFunction.Blackman; this.alpha = this.alpha || 0.16; break; case DSP.COSINE: this.func = WindowFunction.Cosine; break; case DSP.GAUSS: this.func = WindowFunction.Gauss; this.alpha = this.alpha || 0.25; break; case DSP.HAMMING: this.func = WindowFunction.Hamming; break; case DSP.HANN: this.func = WindowFunction.Hann; break; case DSP.LANCZOS: this.func = WindowFunction.Lanczoz; break; case DSP.RECTANGULAR: this.func = WindowFunction.Rectangular; break; case DSP.TRIANGULAR: this.func = WindowFunction.Triangular; break; } } WindowFunction.prototype.process = function(buffer) { var length = buffer.length; for ( var i = 0; i < length; i++ ) { buffer[i] *= this.func(length, i, this.alpha); } return buffer; }; WindowFunction.Bartlett = function(length, index) { return 2 / (length - 1) * ((length - 1) / 2 - Math.abs(index - (length - 1) / 2)); }; WindowFunction.BartlettHann = function(length, index) { return 0.62 - 0.48 * Math.abs(index / (length - 1) - 0.5) - 0.38 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Blackman = function(length, index, alpha) { var a0 = (1 - alpha) / 2; var a1 = 0.5; var a2 = alpha / 2; return a0 - a1 * Math.cos(DSP.TWO_PI * index / (length - 1)) + a2 * Math.cos(4 * Math.PI * index / (length - 1)); }; WindowFunction.Cosine = function(length, index) { return Math.cos(Math.PI * index / (length - 1) - Math.PI / 2); }; WindowFunction.Gauss = function(length, index, alpha) { return Math.pow(Math.E, -0.5 * Math.pow((index - (length - 1) / 2) / (alpha * (length - 1) / 2), 2)); }; WindowFunction.Hamming = function(length, index) { return 0.54 - 0.46 * Math.cos(DSP.TWO_PI * index / (length - 1)); }; WindowFunction.Hann = function(length, index) { return 0.5 * (1 - Math.cos(DSP.TWO_PI * index / (length - 1))); }; WindowFunction.Lanczos = function(length, index) { var x = 2 * index / (length - 1) - 1; return Math.sin(Math.PI * x) / (Math.PI * x); }; WindowFunction.Rectangular = function(length, index) { return 1; }; WindowFunction.Triangular = function(length, index) { return 2 / length * (length / 2 - Math.abs(index - (length - 1) / 2)); }; function sinh (arg) { // Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 // // version: 1004.2314 // discuss at: http://phpjs.org/functions/sinh // + original by: Onno Marsman // * example 1: sinh(-0.9834330348825909); // * returns 1: -1.1497971402636502 return (Math.exp(arg) - Math.exp(-arg))/2; } /* * Biquad filter * * Created by Ricard Marxer on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ // Implementation based on: // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt function Biquad(type, sampleRate) { this.Fs = sampleRate; this.type = type; // type of the filter this.parameterType = DSP.Q; // type of the parameter this.x_1_l = 0; this.x_2_l = 0; this.y_1_l = 0; this.y_2_l = 0; this.x_1_r = 0; this.x_2_r = 0; this.y_1_r = 0; this.y_2_r = 0; this.b0 = 1; this.a0 = 1; this.b1 = 0; this.a1 = 0; this.b2 = 0; this.a2 = 0; this.b0a0 = this.b0 / this.a0; this.b1a0 = this.b1 / this.a0; this.b2a0 = this.b2 / this.a0; this.a1a0 = this.a1 / this.a0; this.a2a0 = this.a2 / this.a0; this.f0 = 3000; // "wherever it's happenin', man." Center Frequency or // Corner Frequency, or shelf midpoint frequency, depending // on which filter type. The "significant frequency". this.dBgain = 12; // used only for peaking and shelving filters this.Q = 1; // the EE kind of definition, except for peakingEQ in which A*Q is // the classic EE Q. That adjustment in definition was made so that // a boost of N dB followed by a cut of N dB for identical Q and // f0/Fs results in a precisely flat unity gain filter or "wire". this.BW = -3; // the bandwidth in octaves (between -3 dB frequencies for BPF // and notch or between midpoint (dBgain/2) gain frequencies for // peaking EQ this.S = 1; // a "shelf slope" parameter (for shelving EQ only). When S = 1, // the shelf slope is as steep as it can be and remain monotonically // increasing or decreasing gain with frequency. The shelf slope, in // dB/octave, remains proportional to S for all other values for a // fixed f0/Fs and dBgain. this.coefficients = function() { var b = [this.b0, this.b1, this.b2]; var a = [this.a0, this.a1, this.a2]; return {b: b, a:a}; }; this.setFilterType = function(type) { this.type = type; this.recalculateCoefficients(); }; this.setSampleRate = function(rate) { this.Fs = rate; this.recalculateCoefficients(); }; this.setQ = function(q) { this.parameterType = DSP.Q; this.Q = Math.max(Math.min(q, 115.0), 0.001); this.recalculateCoefficients(); }; this.setBW = function(bw) { this.parameterType = DSP.BW; this.BW = bw; this.recalculateCoefficients(); }; this.setS = function(s) { this.parameterType = DSP.S; this.S = Math.max(Math.min(s, 5.0), 0.0001); this.recalculateCoefficients(); }; this.setF0 = function(freq) { this.f0 = freq; this.recalculateCoefficients(); }; this.setDbGain = function(g) { this.dBgain = g; this.recalculateCoefficients(); }; this.recalculateCoefficients = function() { var A; if (type === DSP.PEAKING_EQ || type === DSP.LOW_SHELF || type === DSP.HIGH_SHELF ) { A = Math.pow(10, (this.dBgain/40)); // for peaking and shelving EQ filters only } else { A = Math.sqrt( Math.pow(10, (this.dBgain/20)) ); } var w0 = DSP.TWO_PI * this.f0 / this.Fs; var cosw0 = Math.cos(w0); var sinw0 = Math.sin(w0); var alpha = 0; switch (this.parameterType) { case DSP.Q: alpha = sinw0/(2*this.Q); break; case DSP.BW: alpha = sinw0 * sinh( Math.LN2/2 * this.BW * w0/sinw0 ); break; case DSP.S: alpha = sinw0/2 * Math.sqrt( (A + 1/A)*(1/this.S - 1) + 2 ); break; } /** FYI: The relationship between bandwidth and Q is 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT) or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype) The relationship between shelf slope and Q is 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2) */ var coeff; switch (this.type) { case DSP.LPF: // H(s) = 1 / (s^2 + s/Q + 1) this.b0 = (1 - cosw0)/2; this.b1 = 1 - cosw0; this.b2 = (1 - cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.HPF: // H(s) = s^2 / (s^2 + s/Q + 1) this.b0 = (1 + cosw0)/2; this.b1 = -(1 + cosw0); this.b2 = (1 + cosw0)/2; this.a0 = 1 + alpha; this.a1 = -2 * cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_SKIRT: // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) this.b0 = sinw0/2; this.b1 = 0; this.b2 = -sinw0/2; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.BPF_CONSTANT_PEAK: // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) this.b0 = alpha; this.b1 = 0; this.b2 = -alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.NOTCH: // H(s) = (s^2 + 1) / (s^2 + s/Q + 1) this.b0 = 1; this.b1 = -2*cosw0; this.b2 = 1; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.APF: // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) this.b0 = 1 - alpha; this.b1 = -2*cosw0; this.b2 = 1 + alpha; this.a0 = 1 + alpha; this.a1 = -2*cosw0; this.a2 = 1 - alpha; break; case DSP.PEAKING_EQ: // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) this.b0 = 1 + alpha*A; this.b1 = -2*cosw0; this.b2 = 1 - alpha*A; this.a0 = 1 + alpha/A; this.a1 = -2*cosw0; this.a2 = 1 - alpha/A; break; case DSP.LOW_SHELF: // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) - (A-1)*cosw0 + coeff); this.b1 = 2*A*((A-1) - (A+1)*cosw0); this.b2 = A*((A+1) - (A-1)*cosw0 - coeff); this.a0 = (A+1) + (A-1)*cosw0 + coeff; this.a1 = -2*((A-1) + (A+1)*cosw0); this.a2 = (A+1) + (A-1)*cosw0 - coeff; break; case DSP.HIGH_SHELF: // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) coeff = sinw0 * Math.sqrt( (A^2 + 1)*(1/this.S - 1) + 2*A ); this.b0 = A*((A+1) + (A-1)*cosw0 + coeff); this.b1 = -2*A*((A-1) + (A+1)*cosw0); this.b2 = A*((A+1) + (A-1)*cosw0 - coeff); this.a0 = (A+1) - (A-1)*cosw0 + coeff; this.a1 = 2*((A-1) - (A+1)*cosw0); this.a2 = (A+1) - (A-1)*cosw0 - coeff; break; } this.b0a0 = this.b0/this.a0; this.b1a0 = this.b1/this.a0; this.b2a0 = this.b2/this.a0; this.a1a0 = this.a1/this.a0; this.a2a0 = this.a2/this.a0; }; this.process = function(buffer) { //y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] // - (a1/a0)*y[n-1] - (a2/a0)*y[n-2] var len = buffer.length; var output = new Float32Array(len); for ( var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * @buffer array of magnitudes to convert to decibels * * @returns the array in decibels * */ DSP.mag2db = function(buffer) { var minDb = -120; var minMag = Math.pow(10.0, minDb / 20.0); var log = Math.log; var max = Math.max; var result = Float32Array(buffer.length); for (var i=0; i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * * Calculates the frequency response at the given points. * * @b b coefficients of the filter * @a a coefficients of the filter * @w w points (normally between -PI and PI) where to calculate the frequency response * * @returns the frequency response in magnitude * */ DSP.freqz = function(b, a, w) { var i, j; if (!w) { w = Float32Array(200); for (i=0;i on 2010-05-23. * Copyright 2010 Ricard Marxer. All rights reserved. * */ function GraphicalEq(sampleRate) { this.FS = sampleRate; this.minFreq = 40.0; this.maxFreq = 16000.0; this.bandsPerOctave = 1.0; this.filters = []; this.freqzs = []; this.calculateFreqzs = true; this.recalculateFilters = function() { var bandCount = Math.round(Math.log(this.maxFreq/this.minFreq) * this.bandsPerOctave/ Math.LN2); this.filters = []; for (var i=0; i (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds."; } if (!gain) { throw "A gain must be passed."; } this.filters[bandIndex].setDbGain(gain); this.recalculateFreqz(bandIndex); }; this.recalculateFreqz = function(bandIndex) { if (!this.calculateFreqzs) { return; } if (bandIndex < 0 || bandIndex > (this.filters.length-1)) { throw "The band index of the graphical equalizer is out of bounds. " + bandIndex + " is out of [" + 0 + ", " + this.filters.length-1 + "]"; } if (!this.w) { this.w = Float32Array(400); for (var i=0; i1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function MultiDelay(maxDelayInSamplesSize, delayInSamples, masterVolume, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ MultiDelay.prototype.setDelayInSamples = function (delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setMasterVolume = function(masterVolume) { this.masterVolume = masterVolume; }; /** * Change the delay feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ MultiDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and adds the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ MultiDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * SingleDelay effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: See usage in Reverb class * * This is a delay that does NOT feeds it's own delayed signal back into its * circular buffer, neither does it return the original signal. Also known as * an AllPassFilter(?). * * Compatible with interleaved stereo (or more channel) buffers and * non-interleaved mono buffers. * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffer) * @param {Number} delayInSamples Initial delay in samples * @param {Number} delayVolume Initial feedback delay volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * * @constructor */ function SingleDelay(maxDelayInSamplesSize, delayInSamples, delayVolume) { this.delayBufferSamples = new Float32Array(maxDelayInSamplesSize); // The maximum size of delay this.delayInputPointer = delayInSamples; this.delayOutputPointer = 0; this.delayInSamples = delayInSamples; this.delayVolume = delayVolume; } /** * Change the delay time in samples. * * @param {Number} delayInSamples Delay in samples */ SingleDelay.prototype.setDelayInSamples = function(delayInSamples) { this.delayInSamples = delayInSamples; this.delayInputPointer = this.delayOutputPointer + delayInSamples; if (this.delayInputPointer >= this.delayBufferSamples.length-1) { this.delayInputPointer = this.delayInputPointer - this.delayBufferSamples.length; } }; /** * Change the return signal volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ SingleDelay.prototype.setDelayVolume = function(delayVolume) { this.delayVolume = delayVolume; }; /** * Process a given interleaved or mono non-interleaved float value Array and * returns the delayed audio. * * @param {Array} samples Array containing Float values or a Float32Array * * @returns A new Float32Array interleaved or mono non-interleaved as was fed to this function. */ SingleDelay.prototype.process = function(samples) { // NB. Make a copy to put in the output samples to return. var outputSamples = new Float32Array(samples.length); for (var i=0; i= this.delayBufferSamples.length-1) { this.delayInputPointer = 0; } this.delayOutputPointer++; if (this.delayOutputPointer >= this.delayBufferSamples.length-1) { this.delayOutputPointer = 0; } } return outputSamples; }; /** * Reverb effect by Almer Thie (http://code.almeros.com). * Copyright 2010 Almer Thie. All rights reserved. * Example: http://code.almeros.com/code-examples/reverb-firefox-audio-api/ * * This reverb consists of 6 SingleDelays, 6 MultiDelays and an IIRFilter2 * for each of the two stereo channels. * * Compatible with interleaved stereo buffers only! * * @param {Number} maxDelayInSamplesSize Maximum possible delay in samples (size of circular buffers) * @param {Number} delayInSamples Initial delay in samples for internal (Single/Multi)delays * @param {Number} masterVolume Initial master volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} mixVolume Initial reverb signal mix volume. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} delayVolume Initial feedback delay volume for internal (Single/Multi)delays. Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) * @param {Number} dampFrequency Initial low pass filter frequency. 0 to 44100 (depending on your maximum sampling frequency) * * @constructor */ function Reverb(maxDelayInSamplesSize, delayInSamples, masterVolume, mixVolume, delayVolume, dampFrequency) { this.delayInSamples = delayInSamples; this.masterVolume = masterVolume; this.mixVolume = mixVolume; this.delayVolume = delayVolume; this.dampFrequency = dampFrequency; this.NR_OF_MULTIDELAYS = 6; this.NR_OF_SINGLEDELAYS = 6; this.LOWPASSL = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.LOWPASSR = new IIRFilter2(DSP.LOWPASS, dampFrequency, 0, 44100); this.singleDelays = []; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i] = new SingleDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.delayVolume); } this.multiDelays = []; for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i] = new MultiDelay(maxDelayInSamplesSize, Math.round(this.delayInSamples * delayMultiply), this.masterVolume, this.delayVolume); } } /** * Change the delay time in samples as a base for all delays. * * @param {Number} delayInSamples Delay in samples */ Reverb.prototype.setDelayInSamples = function (delayInSamples){ this.delayInSamples = delayInSamples; var i, delayMultiply; for (i = 0; i < this.NR_OF_SINGLEDELAYS; i++) { delayMultiply = 1.0 + (i/7.0); // 1.0, 1.1, 1.2... this.singleDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } for (i = 0; i < this.NR_OF_MULTIDELAYS; i++) { delayMultiply = 1.0 + (i/10.0); // 1.0, 1.1, 1.2... this.multiDelays[i].setDelayInSamples( Math.round(this.delayInSamples * delayMultiply) ); } }; /** * Change the master volume. * * @param {Number} masterVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMasterVolume = function (masterVolume){ this.masterVolume = masterVolume; }; /** * Change the reverb signal mix level. * * @param {Number} mixVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setMixVolume = function (mixVolume){ this.mixVolume = mixVolume; }; /** * Change all delays feedback volume. * * @param {Number} delayVolume Float value: 0.0 (silence), 1.0 (normal), >1.0 (amplify) */ Reverb.prototype.setDelayVolume = function (delayVolume){ this.delayVolume = delayVolume; var i; for (i = 0; iWebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: MeshSimplify/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: MeshSimplify/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: MeshSimplify/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: MeshSimplify/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: MeshSimplify/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: MeshSimplify/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: MeshSimplify/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: MeshSimplify/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MeshSimplify/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: MeshSimplify/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MeshSimplify/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: MeshSimplify/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: MeshSimplify/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: MeshSimplify/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: MeshSimplify/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: MeshSimplify/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: MeshSimplify/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: MinecraftMeshes/MIT-LICENSE.txt ================================================ Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MinecraftMeshes/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: MinecraftMeshes/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: MinecraftMeshes/index.html ================================================ Minecraft Mesh Toolbox
Minecraft Mesh Algorithm Tester
- p for screenshot

Data source:

Mesher:

Show facets:

Show edges:

Quad count:

================================================ FILE: MinecraftMeshes/js/culled.js ================================================ // The MIT License (MIT) // // Copyright (c) 2012-2013 Mikola Lysenko // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //Naive meshing (with face culling) function CulledMesh(volume, dims) { //Precalculate direction vectors for convenience var dir = new Array(3); for(var i=0; i<3; ++i) { dir[i] = [[0,0,0], [0,0,0]]; dir[i][0][(i+1)%3] = 1; dir[i][1][(i+2)%3] = 1; } //March over the volume var quads = [] , x = [0,0,0] , B = [[false,true] //Incrementally update bounds (this is a bit ugly) ,[false,true] ,[false,true]] , n = -dims[0]*dims[1]; for( B[2]=[false,true],x[2]=-1; x[2] 3 || Math.abs(j-7) > 3; }); result['Boss'] = makeVoxels([0,0,0], [16,16,4], function(i,j,k) { return (k == 0) || (Math.abs(i-4) < 2 && Math.abs(j-5) < 2 && k< 2) || (10 <= i && i < 14 && 2 <= j && j < 15); }); result['T-Shape'] = makeVoxels([0,0,0], [16,16,3], function(i,j,k) { return (( 6 <= i && i < 10 && 2 <= j && j < 13) || ( 2 <= i && i < 14 && 8 <= j && j < 13)); }); result['Clover'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { if(i == 0 && Math.abs(j-8) <= 2) { return false; } else if(i == 16 && Math.abs(j-8) <= 2) { return false; } else if(j == 0 && Math.abs(i-8) <= 2) { return false; } else if(j == 16 && Math.abs(i-8) <= 2) { return false; } else { return true; } }); result['Triangle'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { return (i < j); }); result['Saw'] = makeVoxels([0,0,0], [17,3,1], function(i,j,k) { if( j > 0) { return true; } return !!(i & 1); }); result['4Holes'] = makeVoxels([0,0,0], [7,7,1], function(i,j,k) { if( (i == 2 && j == 1) || (i == 5 && j == 2) || (i == 1 && j == 4) || (i == 4 && j == 5) ) { return false; } return true; }); result["Matt's Example"] = makeVoxels([0,0,0], [4,5,1], function(i,j,k) { if( (i == 1 && j == 1) || (i == 2 && j == 3) ) { return false; } return true; }); result['Checker'] = makeVoxels([0,0,0], [8,8,8], function(i,j,k) { return !!((i+j+k)&1); }); result['Noise'] = makeVoxels([0,0,0], [16,16,16], function(i,j,k) { return Math.random() < 0.1; }); result['HollowCube'] = makeVoxels([0,0,0], [16,16,16], function(i,j,k) { return ( i < 1 || i >= 15 || j < 1 || j >= 15 || k < 1 || k >= 15 ); }); result['Sphere'] = makeVoxels([-16,-16,-16], [16,16,16], function(i,j,k) { return i*i+j*j+k*k <= 16*16 }); result['Hill'] = makeVoxels([-16, 0, -16], [16,16,16], function(i,j,k) { return j <= 16 * Math.exp(-(i*i + k*k) / 64); }); result['Valley'] = makeVoxels([0,0,0], [32,32,32], function(i,j,k) { return j <= (i*i + k*k) * 31 / (32*32*2) + 1; }); result['SineTerrain'] = makeVoxels([0,0,0], [32, 8, 32], function(i,j,k) { return j <= 3.0 * Math.sin(Math.PI * i / 12.0 - Math.PI * k * 0.1) + 4.0; }); result['Empty'] = { voxels : [], dims : [0,0,0] }; return result; } ================================================ FILE: MinecraftMeshes/vendor/three.js/Detector.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author mr.doob / http://mrdoob.com/ */ Detector = { canvas : !! window.CanvasRenderingContext2D, webgl : ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), workers : !! window.Worker, fileapi : window.File && window.FileReader && window.FileList && window.Blob, getWebGLErrorMessage : function () { var domElement = document.createElement( 'div' ); domElement.style.fontFamily = 'monospace'; domElement.style.fontSize = '13px'; domElement.style.textAlign = 'center'; domElement.style.background = '#eee'; domElement.style.color = '#000'; domElement.style.padding = '1em'; domElement.style.width = '475px'; domElement.style.margin = '5em auto 0'; if ( ! this.webgl ) { domElement.innerHTML = window.WebGLRenderingContext ? [ 'Your graphics card does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: MinecraftMeshes/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: MinecraftMeshes/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: MinecraftMeshes/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: MinecraftMeshes/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: MinecraftMeshes/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: MinecraftMeshes/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: MinecraftMeshes/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: MinecraftMeshes/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MinecraftMeshes/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: MinecraftMeshes/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MinecraftMeshes/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: MinecraftMeshes/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: MinecraftMeshes/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: MinecraftMeshes/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: MinecraftMeshes/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: MinecraftMeshes/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: MinecraftMeshes/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: MinecraftMeshes2/MIT-LICENSE.txt ================================================ THIS LICENSE IS FOR THE FRAMEWORK, NOT THE FILES IN JS/* Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MinecraftMeshes2/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: MinecraftMeshes2/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: MinecraftMeshes2/experiments.txt ================================================ node benchmark.js ./stupid.js 32 10 20 0 6.95 0 0 1 2733.65 3293184 823296 2 2848.05 3292128 823032 3 2727.35 3293184 823296 4 2673.4 3289032 822258 5 2729.5 3293184 823296 6 2741.1 3293088 823272 7 2687.75 3293184 823296 8 2729.2 3286512 821628 9 2682.4 3293184 823296 10 2772.95 3293136 823284 node benchmark.js ./culled.js 32 10 20 0, 81.8, 0, 0 1, 129.05, 82488, 20622 2, 147.85, 114696, 28674 3, 166.5, 146016, 36504 4, 180.8, 178792, 44698 5, 206.1, 209256, 52314 6, 208.45, 243672, 60918 7, 258.85, 272304, 68076 8, 267.6, 306640, 76660 9, 278.45, 334968, 83742 10, 297.15, 371496, 92874 node benchmark.js ./greedy.js 32 10 20 0, 92.4, 0, 0 1, 99.1, 20712, 5178 2, 103.1, 44068, 11017 3, 110.35, 61644, 15411 4, 126, 87984, 21996 5, 134.25, 102024, 25506 6, 151.4, 129344, 32336 7, 153.6, 142416, 35604 8, 167.85, 172140, 43035 9, 164.9, 182256, 45564 10, 198.3, 213452, 53363 node benchmark.js ./monotone.js 32 10 20 0, 203.8, 0, 0 1, 221.55, 25372, 19563 2, 234.6, 45462, 28410 3, 261.3, 67574, 43233 4, 283.85, 88570, 55712 5, 302.6, 110558, 69507 6, 332.2, 134578, 84174 7, 355.4, 155760, 97736 8, 373.3, 174672, 111557 9, 400.75, 199214, 125565 10, 437.5, 226628, 143088 ================================================ FILE: MinecraftMeshes2/index.html ================================================ Minecraft Mesh Toolbox (with colors)
Minecraft Mesh Algorithm Tester (version 2)
- p for screenshot

Data source:

Mesher:

Show faces:

Show edges:

Vertex count:

Face count:

================================================ FILE: MinecraftMeshes2/js/benchmark.js ================================================ var mesher = require(process.argv[2]).mesher , res = parseInt(process.argv[3]) , max_freq = parseInt(process.argv[4]) , iter_count = parseInt(process.argv[5]); var nr = 2*res + 1 , volume = new Int32Array(nr * nr * nr) , dims = new Int32Array([nr, nr, nr]); function init_volume(freq) { var n = 0, s = 0.5 * freq * Math.PI / res; for(var z=-res; z<=res; ++z) for(var y=-res; y<=res; ++y) for(var x=-res; x<=res; ++x, ++n) { volume[n] = Math.sin(s * x) + Math.sin(s * y) + Math.sin(s * z) < 0 ? 1 : 0; } } //Warm up run on noisy volume, try to get JIT to compile meser init_volume(res / 4.0); for(var i=0; i 0) { dv[v] = h; du[u] = w; } else { c = -c; du[v] = h; dv[u] = w; } var vertex_count = vertices.length; vertices.push([x[0], x[1], x[2] ]); vertices.push([x[0]+du[0], x[1]+du[1], x[2]+du[2] ]); vertices.push([x[0]+du[0]+dv[0], x[1]+du[1]+dv[1], x[2]+du[2]+dv[2]]); vertices.push([x[0] +dv[0], x[1] +dv[1], x[2] +dv[2]]); faces.push([vertex_count, vertex_count+1, vertex_count+2, vertex_count+3, c]); //Zero-out mask for(l=0; l 0) { dv[v] = h; du[u] = w; } else { c = -c; du[v] = h; dv[u] = w; } var vertex_count = vertices.length; vertices.push([x[0], x[1], x[2] ]); vertices.push([x[0]+du[0], x[1]+du[1], x[2]+du[2] ]); vertices.push([x[0]+du[0]+dv[0], x[1]+du[1]+dv[1], x[2]+du[2]+dv[2]]); vertices.push([x[0] +dv[0], x[1] +dv[1], x[2] +dv[2]]); faces.push([vertex_count, vertex_count+1, vertex_count+2, c]); faces.push([vertex_count, vertex_count+2, vertex_count+3, c]); //Zero-out mask for(l=0; l p_l && p_r > r_l && r_c === p_c) { //Merge run p.merge_run(x[v], r_l, r_r); //Insert polygon into frontier next_frontier[fp++] = frontier[i]; ++i; j += 2; } else { //Check if we need to advance the run pointer if(r_r <= p_r) { if(!!r_c) { var n_poly = new MonotonePolygon(r_c, x[v], r_l, r_r); next_frontier[fp++] = polygons.length; polygons.push(n_poly); } j += 2; } //Check if we need to advance the frontier pointer if(p_r <= r_r) { p.close_off(x[v]); ++i; } } } //Close off any residual polygons for(; i r[1]; } var idx = n_side ? right_index[r_i] : left_index[l_i] , vert = n_side ? p.right[r_i] : p.left[l_i]; if(n_side !== side) { //Opposite side while(bottom+3 < top) { if(flipped === n_side) { faces.push([ stack[bottom], stack[bottom+3], idx, c]); } else { faces.push([ stack[bottom+3], stack[bottom], idx, c]); } bottom += 3; } } else { //Same side while(bottom+3 < top) { //Compute convexity for(var j=0; j<2; ++j) for(var k=0; k<2; ++k) { delta[j][k] = stack[top-3*(j+1)+k+1] - vert[k]; } var det = delta[0][0] * delta[1][1] - delta[1][0] * delta[0][1]; if(n_side === (det > 0)) { break; } if(det !== 0) { if(flipped === n_side) { faces.push([ stack[top-3], stack[top-6], idx, c ]); } else { faces.push([ stack[top-6], stack[top-3], idx, c ]); } } top -= 3; } } //Push vertex stack[top++] = idx; stack[top++] = vert[0]; stack[top++] = vert[1]; //Update loop index if(n_side) { ++r_i; } else { ++l_i; } side = n_side; } } } } return { vertices:vertices, faces:faces }; } })(); if(exports) { exports.mesher = MonotoneMesh; } ================================================ FILE: MinecraftMeshes2/js/stupid.js ================================================ // The MIT License (MIT) // // Copyright (c) 2012-2013 Mikola Lysenko // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //The stupidest possible way to generate a Minecraft mesh (I think) function StupidMesh(volume, dims) { var vertices = [], faces = [], x = [0,0,0], n = 0; for(x[2]=0; x[2] 3 || Math.abs(j-7) > 3 ? 1 : 0; }); result['Boss'] = makeVoxels([0,0,0], [16,16,4], function(i,j,k) { if(k === 0) { return 0x0000ff; } else if(Math.abs(i-4) < 2 && Math.abs(j-5) < 2 && k< 2) { return 0x00ff00; } else if(10 <= i && i < 14 && 2 <= j && j < 15) { return 0xff0000; } return 0; }); result['T-Shape'] = makeVoxels([0,0,0], [16,16,3], function(i,j,k) { return (( 6 <= i && i < 10 && 2 <= j && j < 13) || ( 2 <= i && i < 14 && 8 <= j && j < 13)) ? 0xcc00dd : 0; }); result['HollowCube'] = makeVoxels([0,0,0], [16,16,16], function(i,j,k) { if(i < 1) { return 0xff0000; } else if(i >= 15) { return 0x00ffff; } else if(j < 1) { return 0x00ff00; } else if(j >= 15) { return 0xff00ff; } else if(k < 1) { return 0x0000ff; } else if(k >= 15) { return 0xffff00; } else { return 0; } }); result['Clover'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { if(i == 0 && Math.abs(j-8) <= 2) { return 0; } else if(i == 16 && Math.abs(j-8) <= 2) { return 0; } else if(j == 0 && Math.abs(i-8) <= 2) { return 0; } else if(j == 16 && Math.abs(i-8) <= 2) { return 0; } else { return 0x10de60; } }); result['Triangle'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { return (i < j) ? 0xff00ff : 0; }); result['Saw'] = makeVoxels([0,0,0], [17,3,1], function(i,j,k) { if( j > 0 || !!(i & 1) ) { return 0x00ffff; } return 0; }); result['4Dots'] = makeVoxels([0,0,0], [7,7,1], function(i,j,k) { if( (i == 2 && j == 1) || (i == 5 && j == 2) || (i == 1 && j == 4) || (i == 4 && j == 5) ) { return 0x00ff; } return 0xeedd00; }); result['Checker'] = makeVoxels([0,0,0], [8,8,8], function(i,j,k) { return !!((i+j+k)&1) ? (((i^j^k)&2) ? 1 : 0xffffff) : 0; }); result["Matt's Example"] = makeVoxels([0,0,0], [4,5,1], function(i,j,k) { if( (i == 1 && j == 1) || (i == 2 && j == 3) ) { return 0xee5533; } return 0x128844; }); result['Benchmark (SLOW!)'] = makeVoxels([-32, -32, -32], [33, 33, 33], function(x, y, z) { var s = 2.0 * Math.PI / 32.0; return Math.sin(s * x) + Math.sin(s * y) + Math.sin(s * z) < 0 ? 1 : 0; }); result['Hill'] = makeVoxels([-16, 0, -16], [16,16,16], function(i,j,k) { return j <= 16 * Math.exp(-(i*i + k*k) / 64) ? 0x118822 : 0; }); result['Valley'] = makeVoxels([0,0,0], [32,32,32], function(i,j,k) { return j <= (i*i + k*k) * 31 / (32*32*2) + 1 ? 0x118822 : 0; }); result['Hilly Terrain'] = makeVoxels([0, 0, 0], [32,32,32], function(i,j,k) { var h0 = 3.0 * Math.sin(Math.PI * i / 12.0 - Math.PI * k * 0.1) + 27; if(j > h0+1) { return 0; } if(h0 <= j) { return 0x23dd31; } var h1 = 2.0 * Math.sin(Math.PI * i * 0.25 - Math.PI * k * 0.3) + 20; if(h1 <= j) { return 0x964B00; } if(2 < j) { return Math.random() < 0.1 ? 0x222222 : 0xaaaaaa; } return 0xff0000; }); result['Empty'] = { voxels : [], dims : [0,0,0] }; return result; } ================================================ FILE: MinecraftMeshes2/vendor/three.js/Detector.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author mr.doob / http://mrdoob.com/ */ Detector = { canvas : !! window.CanvasRenderingContext2D, webgl : ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), workers : !! window.Worker, fileapi : window.File && window.FileReader && window.FileList && window.Blob, getWebGLErrorMessage : function () { var domElement = document.createElement( 'div' ); domElement.style.fontFamily = 'monospace'; domElement.style.fontSize = '13px'; domElement.style.textAlign = 'center'; domElement.style.background = '#eee'; domElement.style.color = '#000'; domElement.style.padding = '1em'; domElement.style.width = '475px'; domElement.style.margin = '5em auto 0'; if ( ! this.webgl ) { domElement.innerHTML = window.WebGLRenderingContext ? [ 'Your graphics card does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: MinecraftMeshes2/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: MinecraftMeshes2/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: MinecraftMeshes2/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: MinecraftMeshes2/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: MinecraftMeshes2/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: MinecraftMeshes2/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: MinecraftMeshes2/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MinecraftMeshes2/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: MinecraftMeshes2/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: MinecraftMeshes2/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: MinecraftMeshes2/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: MinecraftMeshes2/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: MinecraftMeshes2/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: MinecraftMeshes2/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: MinecraftMeshes2/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: MinecraftMeshes2/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: Pictures/test_smooth.py ================================================ import scipy as sp import scipy.ndimage as ndi import pylab x0 = 0.25 mu = 5.0 def sigmoid(t): return 1.0 / (1.0 + sp.exp(-mu * t)) def shallow(t): return sigmoid(t) - sigmoid(x0) def steep(t): return sigmoid(t - 2.0*x0) - sigmoid(-x0) def zero(t): return 0.0 * t def downsample(f): for sigma in range(1, 10): pylab.plot(ndi.gaussian_filter1d(f, 2.0 ** sigma)) def make_gif(): t = sp.arange(-5.0, 5.0, 0.01) for sigma in range(1, 10): pylab.clf() pylab.figtext(0,0,"sigma={0}".format(2**sigma)) pylab.axis([-6.0, 6.0, -1.1, 1.1]) A = ndi.gaussian_filter(shallow(t), 2.0**sigma) B = ndi.gaussian_filter(steep(t), 2.0**sigma) pylab.plot(t, A, 'b') pylab.plot(t, B, 'r') #pylab.plot(t, -1.0 * (A > 0), 'b') #pylab.plot(t, (B > 0), 'r') pylab.plot(t, zero(t), 'k') pylab.draw() pylab.savefig('frame{0}'.format(sigma)) def make_gif2(): t = sp.arange(-5.0, 5.0, 0.01) for sigma in range(1, 10): pylab.clf() pylab.figtext(0,0,"sigma={0}".format(2**sigma)) pylab.axis([-6.0, 6.0, -1.1, 1.1]) A = ndi.median_filter(shallow(t), 2.0**sigma) B = ndi.median_filter(steep(t), 2.0**sigma) pylab.plot(t, A, 'b') pylab.plot(t, B, 'r') pylab.plot(t, -1.0 * (A > 0), 'b') pylab.plot(t, (B > 0), 'r') pylab.plot(t, zero(t), 'k') pylab.draw() pylab.savefig('frame{0}'.format(sigma)) ================================================ FILE: Resources/brep.js ================================================ //Javascript Tools for BREPS // Author: Mikola Lysenko // License: MIT // Copyright 2012 var BREP = {}; (function(exports) { "use strict"; var EPSILON = 1e-6; //Compute the star of each vertex in the mesh function compute_stars(mesh) { var stars = new Array(mesh.positions.length); for(var i=0; i0; --i) { if(compare_uopair(result[i], result[i-1]) === 0) { result.splice(i, 1); } } return result; } //Extract face loop function face_loop(f) { var loop = []; var p = f[f.length-1]; for(var j=0; j EPSILON) { var norm = normals[c]; var w = 1.0 / Math.sqrt(m01 * m21); for(var k=0; k<3; ++k) { var u = (k+1)%3; var v = (k+2)%3; norm[k] += w * (d01[u] * d21[v] - d01[v] * d21[u]); } } } } //Scale all normals to unit length for(var i=0; i EPSILON) { var w = 1.0 / Math.sqrt(m); for(var k=0; k<3; ++k) { norm[k] *= w; } } else { for(var k=0; k<3; ++k) { norm[k] = 0.0; } } } //Return the resulting set of patches return normals; } //Set up exports exports.compute_stars = compute_stars; exports.compute_links = compute_links; exports.estimate_normals = estimate_normals; })(typeof(exports) !== "undefined" ? exports : BREP); ================================================ FILE: Resources/glow_shell.js ================================================ // GLOW PingPong shell // Author: Mikola Lysenko (http://0fps.net) // License: BSD //Simulation parameters var parameters = { WIDTH: 256, HEIGHT: 256, STEPS_PER_FRAME: 1 }; // create a context and set white background var context; try { context = new GLOW.Context(); } catch(e) { alert("WebGL not supported :-("); return; } //Make sure we have floating point textures if( !context.enableExtension( "OES_texture_float" )) { alert( "No support for float textures!" ); return; } //Set up basic parameters context.setupClear( { red: 1, green: 1, blue: 1 } ); // attach the context's DOM element var container = document.getElementById("container"); container.appendChild( context.domElement ); //Allocate ping pong buffers var buffer_dims = [ parameters.WIDTH, parameters.HEIGHT ]; var buffers = new Array(2); var current_buffer = 0; (function() { //Create initial conditions var initial_state = new Float32Array(buffer_dims[0] * buffer_dims[1] * 4); var ptr = 0; for(var j=0; j255){GLOW.warn("GLOW.Compiler.interleaveAttributes: Stride owerflow, moving attributes to new interleave index. Please check your interleave setup!");l=j.length;for(j[l]=[];g0)for(;g<=e;g++)GL.enableVertexAttribArray(g);else for(g--;g>e;g--)GL.disableVertexAttribArray(g)}}f=a.attributeArray;for(e=f.length;e--;)f[e].interleaved===!1&&(b.attributeCached(f[e])||f[e].bind());f=a.interleavedAttributeArray; for(e=f.length;e--;)b.interleavedAttributeCached(f[e])||f[e].bind();f=a.uniformArray;for(e=f.length;e--;)b.uniformCached(f[e])||f[e].load();a.elements.draw()};b.prototype.clone=function(a){return new GLOW.Shader({use:this.compiledData,except:a})};b.prototype.dispose=function(a,b){var f,e,g;for(f in this.compiledData.uniforms)delete this[f];for(e in this.compiledData.attributes)delete this[e];for(g in this.compiledData.interleavedAttributes)delete this[g];delete this.program;delete this.elements;delete this.uniforms; delete this.attributes;delete this.interleavedAttributes;this.compiledData.dispose(a,b);delete this.compiledData};return b}(); GLOW.Elements=function(){function b(a,b,f,e){this.id=GLOW.uniqueId();this.type=b!==void 0?b:GL.TRIANGLES;this.offset=e!==void 0?e:0;typeof a==="number"||a===void 0?this.length=a:(a instanceof Uint16Array||(a=new Uint16Array(a)),this.length=a.length,this.elements=GL.createBuffer(),GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER,this.elements),GL.bufferData(GL.ELEMENT_ARRAY_BUFFER,a,f?f:GL.STATIC_DRAW))}b.prototype.draw=function(){this.elements!==void 0?(GLOW.currentContext.cache.elementsCached(this)||GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, this.elements),GL.drawElements(this.type,this.length,GL.UNSIGNED_SHORT,this.offset)):GL.drawArrays(this.type,this.offset,this.length)};b.prototype.clone=function(a){a=a||{};return new GLOW.Elements(a.data||this.data,a.type||this.type,a.usage,a.offset||this.offset)};b.prototype.dispose=function(){this.elements!==void 0&&(GL.deleteBuffer(this.elements),delete this.elements)};return b}(); GLOW.Uniform=function(){function b(){f[GL.INT]=function(){GL.uniform1iv(this.location,this.getNativeValue())};f[GL.FLOAT]=function(){GL.uniform1fv(this.location,this.getNativeValue())};f[GL.INT_VEC2]=function(){GL.uniform2iv(this.location,this.getNativeValue())};f[GL.INT_VEC3]=function(){GL.uniform3iv(this.location,this.getNativeValue())};f[GL.INT_VEC4]=function(){GL.uniform4iv(this.location,this.getNativeValue())};f[GL.BOOL]=function(){GL.uniform1iv(this.location,this.getNativeValue())};f[GL.BOOL_VEC2]= function(){GL.uniform2iv(this.location,this.getNativeValue())};f[GL.BOOL_VEC3]=function(){GL.uniform3iv(this.location,this.getNativeValue())};f[GL.BOOL_VEC4]=function(){GL.uniform4iv(this.location,this.getNativeValue())};f[GL.FLOAT_VEC2]=function(){GL.uniform2fv(this.location,this.getNativeValue())};f[GL.FLOAT_VEC3]=function(){GL.uniform3fv(this.location,this.getNativeValue())};f[GL.FLOAT_VEC4]=function(){GL.uniform4fv(this.location,this.getNativeValue())};f[GL.FLOAT_MAT2]=function(){GL.uniformMatrix2fv(this.location, !1,this.getNativeValue())};f[GL.FLOAT_MAT3]=function(){GL.uniformMatrix3fv(this.location,!1,this.getNativeValue())};f[GL.FLOAT_MAT4]=function(){GL.uniformMatrix4fv(this.location,!1,this.getNativeValue())};f[GL.SAMPLER_2D]=function(){this.data.texture!==void 0&&this.textureUnit!==-1&&!GLOW.currentContext.cache.textureCached(this.textureUnit,this.data)&&(GL.uniform1i(this.location,this.textureUnit),GL.activeTexture(GL.TEXTURE0+this.textureUnit),GL.bindTexture(GL.TEXTURE_2D,this.data.texture),this.data.autoUpdate&& this.data.updateTexture(this.data.autoUpdate))};f[GL.SAMPLER_CUBE]=function(){this.data.texture!==void 0&&this.textureUnit!==-1&&!GLOW.currentContext.cache.textureCached(this.textureUnit,this.data)&&(GL.uniform1i(this.location,this.textureUnit),GL.activeTexture(GL.TEXTURE0+this.textureUnit),GL.bindTexture(GL.TEXTURE_CUBE_MAP,this.data.texture),this.data.autoUpdate&&this.data.updateTexture(this.data.autoUpdate))}}function a(a,g){c||(c=!0,b());this.id=GLOW.uniqueId();this.data=g;this.name=a.name;this.length= a.length;this.type=a.type;this.location=a.location;this.locationNumber=a.locationNumber;this.textureUnit=-1;this.load=a.loadFunction||f[this.type]}var c=!1,f=[];a.prototype.getNativeValue=function(){return this.data.value};a.prototype.clone=function(a){return new GLOW.Uniform(this,a||this.data)};a.prototype.dispose=function(){delete this.data;delete this.load;delete this.location};return a}(); GLOW.Attribute=function(){function b(b,e,g,h){a||(a=!0,c[GL.INT]=1,c[GL.INT_VEC2]=2,c[GL.INT_VEC3]=3,c[GL.INT_VEC4]=4,c[GL.BOOL]=1,c[GL.BOOL_VEC2]=2,c[GL.BOOL_VEC3]=3,c[GL.BOOL_VEC4]=4,c[GL.FLOAT]=1,c[GL.FLOAT_VEC2]=2,c[GL.FLOAT_VEC3]=3,c[GL.FLOAT_VEC4]=4,c[GL.FLOAT_MAT2]=4,c[GL.FLOAT_MAT3]=9,c[GL.FLOAT_MAT4]=16);this.id=GLOW.uniqueId();this.data=e;this.location=b.location;this.locationNumber=b.locationNumber;this.offset=this.stride=0;this.usage=g!==void 0?g:GL.STATIC_DRAW;this.interleaved=h!==void 0? h:!1;this.size=c[b.type];this.name=b.name;this.type=b.type;this.data&&(this.data.length/this.size>65536&&GLOW.warn("GLOW.Attribute.constructor: Unreachable attribute? Please activate GL.drawArrays or split into multiple shaders. Indexed elements cannot reach attribute data beyond 65535."),this.interleaved===!1&&this.bufferData(this.data,this.usage))}var a=!1,c=[];b.prototype.setupInterleave=function(a,b){this.interleaved=!0;this.offset=a;this.stride=b};b.prototype.bufferData=function(a,b){if(a!== void 0&&this.data!==a)this.data=a;if(b!==void 0&&this.usage!==b)this.usage=b;if(this.buffer===void 0)this.buffer=GL.createBuffer();if(this.data.constructor.toString().indexOf(" Array()")!==-1)this.data=new Float32Array(this.data);GL.bindBuffer(GL.ARRAY_BUFFER,this.buffer);GL.bufferData(GL.ARRAY_BUFFER,this.data,this.usage)};b.prototype.bind=function(){this.interleaved===!1&&GL.bindBuffer(GL.ARRAY_BUFFER,this.buffer);GL.vertexAttribPointer(this.location,this.size,GL.FLOAT,!1,this.stride,this.offset)}; b.prototype.clone=function(a){if(this.interleaved)GLOW.error("GLOW.Attribute.clone: Cannot clone interleaved attribute. Please check your interleave setup.");else return a=a||{},new GLOW.Attribute(this,a.data||this.data,a.usage||this.usage,a.interleaved||this.interleaved)};b.prototype.dispose=function(){this.buffer&&(GL.deleteBuffer(this.buffer),delete this.buffer);delete this.data};return b}(); GLOW.InterleavedAttributes=function(){function b(a){this.id=GLOW.uniqueId();this.attributes=a;var b,f=a[0].data.length/a[0].size,e,g=a.length,h,i,j,k=[],l,m=[];for(e=0;e0?this.multiplyScalar(1/a):this.set(0,0,0);return this};b.prototype.setPositionFromMatrix=function(a){a=a.value;this.value[0]=a[12];this.value[1]=a[13];this.value[2]=a[14]};b.prototype.setLength=function(a){return this.normalize().multiplyScalar(a)};b.prototype.isZero=function(){return Math.abs(this.value[0])< 1.0E-4&&Math.abs(this.value[1])<1.0E-4&&Math.abs(this.value[2])<1.0E-4};b.prototype.clone=function(){return GLOW.Vector3(this.value[0],this.value[1],this.value[2])};return b}(); GLOW.Vector4=function(){function b(a,b,f,e){this.value=new Float32Array(4);this.value[0]=a!==void 0?a:0;this.value[1]=b!==void 0?b:0;this.value[2]=f!==void 0?f:0;this.value[3]=e!==void 0?e:0}b.prototype.set=function(a,b,f,e){this.value[0]=a;this.value[1]=b;this.value[2]=f;this.value[3]=e;return this};b.prototype.copy=function(a){this.value[0]=a.value[0];this.value[1]=a.value[1];this.value[2]=a.value[2];this.value[3]=a.value[3];return this};b.prototype.add=function(a,b){this.value[0]=a.value[0]+b.value[0]; this.value[1]=a.value[1]+b.value[1];this.value[2]=a.value[2]+b.value[2];this.value[3]=a.value[3]+b.value[3];return this};b.prototype.addSelf=function(a){this.value[0]+=a.value[0];this.value[1]+=a.value[1];this.value[2]+=a.value[2];this.value[3]+=a.value[3];return this};b.prototype.sub=function(a,b){this.value[0]=a.value[0]-b.value[0];this.value[1]=a.value[1]-b.value[1];this.value[2]=a.value[2]-b.value[2];this.value[3]=a.value[3]-b.value[3];return this};b.prototype.subSelf=function(a){this.value[0]-= a.value[0];this.value[1]-=a.value[1];this.value[2]-=a.value[2];this.value[3]-=a.value[3];return this};b.prototype.multiplyScalar=function(a){this.value[0]*=a;this.value[1]*=a;this.value[2]*=a;this.value[3]*=a;return this};b.prototype.divideScalar=function(a){this.value[0]/=a;this.value[1]/=a;this.value[2]/=a;this.value[3]/=a;return this};b.prototype.lerpSelf=function(a,b){this.value[0]+=(a.x-this.value[0])*b;this.value[1]+=(a.y-this.value[1])*b;this.value[2]+=(a.z-this.value[2])*b;this.value[3]+= (a.w-this.value[3])*b;return this};b.prototype.lengthOfXYZ=function(){return Math.sqrt(this.value[0]*this.value[0]+this.value[1]*this.value[1]+this.value[2]*this.value[2])};b.prototype.clone=function(){return new GLOW.Vector4(this.value[0],this.value[1],this.value[2],this.value[3])};return b}(); GLOW.Matrix3=function(){function b(){this.value=new Float32Array(9);this.identity()}b.prototype.set=function(a,b,f,e,g,h,i,j,k){this.value[0]=a;this.value[3]=b;this.value[6]=f;this.value[1]=e;this.value[4]=g;this.value[7]=h;this.value[2]=i;this.value[5]=j;this.value[8]=k;return this};b.prototype.identity=function(){this.set(1,0,0,0,1,0,0,0,1);return this};b.prototype.extractFromMatrix4=function(a){this.set(a.value[0],a.value[4],a.value[8],a.value[1],a.value[5],a.value[9],a.value[2],a.value[6],a.value[10]); return this};b.prototype.multiplyVector3=function(a){var b=a.value[0],f=a.value[1],e=a.value[2];a.value[0]=this.value[0]*b+this.value[3]*f+this.value[6]*e;a.value[1]=this.value[1]*b+this.value[4]*f+this.value[7]*e;a.value[2]=this.value[2]*b+this.value[5]*f+this.value[8]*e;return a};return b}(); GLOW.Matrix4=function(){function b(){this.value=new Float32Array(16);this.rotation=new GLOW.Vector3;this.position=new GLOW.Vector3;this.columnX=new GLOW.Vector3;this.columnY=new GLOW.Vector3;this.columnZ=new GLOW.Vector3;this.identity()}b.prototype.set=function(a,b,f,e,g,h,i,j,k,l,m,o,n,r,p,q){this.value[0]=a;this.value[4]=b;this.value[8]=f;this.value[12]=e;this.value[1]=g;this.value[5]=h;this.value[9]=i;this.value[13]=j;this.value[2]=k;this.value[6]=l;this.value[10]=m;this.value[14]=o;this.value[3]= n;this.value[7]=r;this.value[11]=p;this.value[15]=q;return this};b.prototype.identity=function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this};b.prototype.copy=function(a){a=a.value;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this};b.prototype.lookAt=function(a,b){var f=GLOW.Matrix4.tempVector3A,e=GLOW.Matrix4.tempVector3B,g=GLOW.Matrix4.tempVector3C,h=this.getPosition();h.value[0]=this.value[12];h.value[1]=this.value[13];h.value[2]= this.value[14];g.sub(h,a).normalize();g.length()===0&&(g.value[3]=1);f.cross(b,g).normalize();f.length()===0&&(g.value[0]+=1.0E-4,f.cross(b,g).normalize());e.cross(g,f).normalize();f=f.value;e=e.value;g=g.value;this.value[0]=f[0];this.value[4]=e[0];this.value[8]=g[0];this.value[1]=f[1];this.value[5]=e[1];this.value[9]=g[1];this.value[2]=f[2];this.value[6]=e[2];this.value[10]=g[2];return this};b.prototype.multiplyVector3=function(a){var b=a.value[0],f=a.value[1],e=a.value[2],g=1/(this.value[3]*b+this.value[7]* f+this.value[11]*e+this.value[15]);a.value[0]=(this.value[0]*b+this.value[4]*f+this.value[8]*e+this.value[12])*g;a.value[1]=(this.value[1]*b+this.value[5]*f+this.value[9]*e+this.value[13])*g;a.value[2]=(this.value[2]*b+this.value[6]*f+this.value[10]*e+this.value[14])*g;return a};b.prototype.multiplyVector4=function(a){var b=a.value[0],f=a.value[1],e=a.value[2],g=a.value[3];a.value[0]=this.value[0]*b+this.value[4]*f+this.value[8]*e+this.value[12]*g;a.value[1]=this.value[1]*b+this.value[5]*f+this.value[9]* e+this.value[13]*g;a.value[2]=this.value[2]*b+this.value[6]*f+this.value[10]*e+this.value[14]*g;a.value[3]=this.value[3]*b+this.value[7]*f+this.value[11]*e+this.value[15]*g;return a};b.prototype.rotateAxis=function(a){var b=a.value[0],f=a.value[1],e=a.value[2];a.value[0]=b*this.value[0]+f*this.value[4]+e*this.value[8];a.value[1]=b*this.value[1]+f*this.value[5]+e*this.value[9];a.value[2]=b*this.value[2]+f*this.value[6]+e*this.value[10];a.normalize();return a};b.prototype.crossVector=function(a){var b= GLOW.Vector4(),f=a.value[0],e=a.value[1],g=a.value[2],a=a.value[3];b.value[0]=this.value[0]*f+this.value[4]*e+this.value[8]*g+this.value[12]*a;b.value[1]=this.value[1]*f+this.value[5]*e+this.value[9]*g+this.value[13]*a;b.value[2]=this.value[2]*f+this.value[6]*e+this.value[10]*g+this.value[14]*a;b.value[3]=a?this.value[3]*f+this.value[7]*e+this.value[11]*g+this.value[15]*a:1;return b};b.prototype.multiply=function(a,b){var a=a.value,b=b.value,f=a[0],e=a[4],g=a[8],h=a[12],i=a[1],j=a[5],k=a[9],l=a[13], m=a[2],o=a[6],n=a[10],r=a[14],p=a[3],q=a[7],s=a[11],t=a[15],u=b[0],v=b[4],x=b[8],w=b[12],y=b[1],z=b[5],A=b[9],B=b[13],C=b[2],D=b[6],E=b[10],F=b[14];this.value[0]=f*u+e*y+g*C;this.value[4]=f*v+e*z+g*D;this.value[8]=f*x+e*A+g*E;this.value[12]=f*w+e*B+g*F+h;this.value[1]=i*u+j*y+k*C;this.value[5]=i*v+j*z+k*D;this.value[9]=i*x+j*A+k*E;this.value[13]=i*w+j*B+k*F+l;this.value[2]=m*u+o*y+n*C;this.value[6]=m*v+o*z+n*D;this.value[10]=m*x+o*A+n*E;this.value[14]=m*w+o*B+n*F+r;this.value[3]=p*u+q*y+s*C;this.value[7]= p*v+q*z+s*D;this.value[11]=p*x+q*A+s*E;this.value[15]=p*w+q*B+s*F+t;return this};b.prototype.multiplySelf=function(a){this.multiply(this,a);return this};b.prototype.multiplyScalar=function(a){this.value[0]*=a;this.value[4]*=a;this.value[8]*=a;this.value[12]*=a;this.value[1]*=a;this.value[5]*=a;this.value[9]*=a;this.value[13]*=a;this.value[2]*=a;this.value[6]*=a;this.value[10]*=a;this.value[14]*=a;this.value[3]*=a;this.value[7]*=a;this.value[11]*=a;this.value[15]*=a;return this};b.prototype.determinant= function(){var a=this.value[0],b=this.value[4],f=this.value[8],e=this.value[12],g=this.value[1],h=this.value[5],i=this.value[9],j=this.value[13],k=this.value[2],l=this.value[6],m=this.value[10],o=this.value[14],n=this.value[3],r=this.value[7],p=this.value[11],q=this.value[15];return e*i*l*n-f*j*l*n-e*h*m*n+b*j*m*n+f*h*o*n-b*i*o*n-e*i*k*r+f*j*k*r+e*g*m*r-a*j*m*r-f*g*o*r+a*i*o*r+e*h*k*p-b*j*k*p-e*g*l*p+a*j*l*p+b*g*o*p-a*h*o*p-f*h*k*q+b*i*k*q+f*g*l*q-a*i*l*q-b*g*m*q+a*h*m*q};b.prototype.transpose=function(){var a; a=this.value[1];this.value[1]=this.value[4];this.value[4]=a;a=this.value[2];this.value[2]=this.value[8];this.value[8]=a;a=this.value[6];this.value[6]=this.value[9];this.value[9]=a;a=this.value[3];this.value[3]=this.value[12];this.value[12]=a;a=this.value[7];this.value[7]=this.value[13];this.value[13]=a;a=this.value[11];this.value[11]=this.value[14];this.value[11]=a;return this};b.prototype.clone=function(){var a=new GLOW.Matrix4;a.value=new Float32Array(this.value);return a};b.prototype.setPosition= function(a,b,f){var e;b!==void 0&&f!==void 0?e=a:(e=a.value[0],b=a.value[1],f=a.value[2]);this.value[12]=e;this.value[13]=b;this.value[14]=f;return this};b.prototype.addPosition=function(a,b,f){var e;b!==void 0&&f!==void 0?e=a:(e=a.value[0],b=a.value[1],f=a.value[2]);this.value[12]+=e;this.value[13]+=b;this.value[14]+=f};b.prototype.setRotation=function(a,b,f){var e;b!==void 0&&f!==void 0?e=a:(e=a.value[0],b=a.value[1],f=a.value[2]);var a=Math.cos(b),b=Math.sin(b),g=Math.cos(f),f=Math.sin(f),h=Math.cos(e); e=Math.sin(e);this.value[0]=a*g;this.value[4]=b*e-a*f*h;this.value[8]=a*f*e+b*h;this.value[1]=f;this.value[5]=g*h;this.value[9]=-g*e;this.value[2]=-b*g;this.value[6]=b*f*h+a*e;this.value[10]=-b*f*e+a*h;return this};b.prototype.addRotation=function(a,b,f){var e;b!==void 0&&f!==void 0?e=a:(e=a.value[0],b=a.value[1],f=a.value[2]);this.rotation.value[0]+=e;this.rotation.value[1]+=b;this.rotation.value[2]+=f;this.setRotation(this.rotation.value[0],this.rotation.value[1],this.rotation.value[2])};b.prototype.getPosition= function(){this.position.set(this.value[12],this.value[13],this.value[14]);return this.position};b.prototype.getColumnX=function(){this.columnX.set(this.value[0],this.value[1],this.value[2]);return this.columnX};b.prototype.getColumnY=function(){this.columnY.set(this.value[4],this.value[5],this.value[6]);return this.columnY};b.prototype.getColumnZ=function(){this.columnZ.set(this.value[8],this.value[9],this.value[10]);return this.columnZ};b.prototype.scale=function(a,b,f){var e;b!==void 0&&f!==void 0? e=a:(e=a.value[0],b=a.value[1],f=a.value[2]);this.value[0]*=e;this.value[4]*=b;this.value[8]*=f;this.value[1]*=e;this.value[5]*=b;this.value[9]*=f;this.value[2]*=e;this.value[6]*=b;this.value[10]*=f;this.value[3]*=e;this.value[7]*=b;this.value[11]*=f;return this};b.prototype.invert=function(){GLOW.Matrix4.makeInverse(this,this);return this};return b}(); GLOW.Matrix4.makeInverse=function(b,a){a===void 0&&(a=new GLOW.Matrix4);var c=b.value,f=a.value,e=c[0],g=c[4],h=c[8],i=c[12],j=c[1],k=c[5],l=c[9],m=c[13],o=c[2],n=c[6],r=c[10],p=c[14],q=c[3],s=c[7],t=c[11],c=c[15];f[0]=l*p*s-m*r*s+m*n*t-k*p*t-l*n*c+k*r*c;f[1]=m*r*q-l*p*q-m*o*t+j*p*t+l*o*c-j*r*c;f[2]=k*p*q-m*n*q+m*o*s-j*p*s-k*o*c+j*n*c;f[3]=l*n*q-k*r*q-l*o*s+j*r*s+k*o*t-j*n*t;f[4]=i*r*s-h*p*s-i*n*t+g*p*t+h*n*c-g*r*c;f[5]=h*p*q-i*r*q+i*o*t-e*p*t-h*o*c+e*r*c;f[6]=i*n*q-g*p*q-i*o*s+e*p*s+g*o*c-e*n*c; f[7]=g*r*q-h*n*q+h*o*s-e*r*s-g*o*t+e*n*t;f[8]=h*m*s-i*l*s+i*k*t-g*m*t-h*k*c+g*l*c;f[9]=i*l*q-h*m*q-i*j*t+e*m*t+h*j*c-e*l*c;f[10]=h*m*q-i*k*q+i*j*s-e*m*s-g*j*c+e*k*c;f[11]=h*k*q-g*l*q-h*j*s+e*l*s+g*j*t-e*k*t;f[12]=i*l*n-h*m*n-i*k*r+g*m*r+h*k*p-g*l*p;f[13]=h*m*o-i*l*o+i*j*r-e*m*r-h*j*p+e*l*p;f[14]=i*k*o-g*m*o-i*j*n+e*m*n+g*j*p-e*k*p;f[15]=g*l*o-h*k*o+h*j*n-e*l*n-g*j*r+e*k*r;a.multiplyScalar(1/b.determinant());return a}; GLOW.Matrix4.makeFrustum=function(b,a,c,f,e,g,h){var i,h=h||new GLOW.Matrix4;i=h.value;i[0]=2*e/(a-b);i[4]=0;i[8]=(a+b)/(a-b);i[12]=0;i[1]=0;i[5]=2*e/(f-c);i[9]=(f+c)/(f-c);i[13]=0;i[2]=0;i[6]=0;i[10]=-(g+e)/(g-e);i[14]=-2*g*e/(g-e);i[3]=0;i[7]=0;i[11]=-1;i[15]=0;return h};GLOW.Matrix4.makeProjection=function(b,a,c,f,e){var g,b=c*Math.tan(b*Math.PI/360);g=-b;return GLOW.Matrix4.makeFrustum(g*a,b*a,g,b,c,f,e)}; GLOW.Matrix4.makeOrtho=function(b,a,c,f,e,g,h){var i,j,k,l,h=h||new GLOW.Matrix4;j=Math.abs(a-b);k=Math.abs(c-f);l=Math.abs(g-e);i=h.value;i[0]=2/j;i[4]=0;i[8]=0;i[12]=-((a+b)/j);i[1]=0;i[5]=2/k;i[9]=0;i[13]=-((c+f)/k);i[2]=0;i[6]=0;i[10]=-2/l;i[14]=-((g+e)/l);i[3]=0;i[7]=0;i[11]=0;i[15]=1;return h};GLOW.Matrix4.tempVector3A=new GLOW.Vector3;GLOW.Matrix4.tempVector3B=new GLOW.Vector3;GLOW.Matrix4.tempVector3C=new GLOW.Vector3;GLOW.Matrix4.tempVector3D=new GLOW.Vector3; GLOW.Color=function(){function b(a,b,f){this.value=new Float32Array(3);b===void 0&&f===void 0?this.setHex(a||0):this.setRGB(a,b,f)}b.prototype.setRGB=function(a,b,f){this.value[0]=a!==void 0?a/255:1;this.value[1]=b!==void 0?b/255:1;this.value[2]=f!==void 0?f/255:1;return this};b.prototype.setHex=function(a){this.value[0]=((a&16711680)>>16)/255;this.value[1]=((a&65280)>>8)/255;this.value[2]=(a&255)/255;return this};b.prototype.multiplyScalar=function(a){this.value[0]*=a;this.value[1]*=a;this.value[2]*= a;return this};b.prototype.mix=function(a,b){var f=1-b;this.value[0]=this.value[0]*f+a.value[0]*b;this.value[1]=this.value[1]*f+a.value[1]*b;this.value[2]=this.value[2]*f+a.value[2]*b;return this};b.prototype.copy=function(a){this.value[0]=a.value[0];this.value[1]=a.value[1];this.value[2]=a.value[2];return this};b.prototype.setHSV=function(a,b,f){var e,g,h,i,j,k;if(f==0)e=g=h=0;else switch(i=Math.floor(a*6),j=a*6-i,a=f*(1-b),k=f*(1-b*j),b=f*(1-b*(1-j)),i){case 1:e=k;g=f;h=a;break;case 2:e=a;g=f;h= b;break;case 3:e=a;g=k;h=f;break;case 4:e=b;g=a;h=f;break;case 5:e=f;g=a;h=k;break;case 6:case 0:e=f,g=b,h=a}this.value[0]=e;this.value[1]=g;this.value[2]=h;return this};return b}(); GLOW.Geometry={randomVector3Array:function(b,a){var a=a!==void 0?a:1,c,f=[],e=a*2;for(c=0;c-1)b[e].indexOf("Fragment")>-1&&(a=f, f="");else{var g=b[e];g.indexOf("//")>-1&&(g=g.substring(0,g.indexOf("//")));g.indexOf(";")===-1&&(g+="\n");f+=g}this.scope.parameters[this.parametersProperty]={fragmentShader:"#ifdef GL_ES\nprecision highp float;\n#endif\n"+f,vertexShader:a};this.scope.handleLoadedItem()}};b.prototype.onLoadError=function(a){GLOW.error("GLOW.Load.onLoadError: Error "+a.target.status)};b.prototype.parseThreeJS=function(a){var b={},f=a.scale!==void 0?1/a.scale:1;(function(e){if(a.version===void 0||a.version!=2)GLOW.error("Deprecated file format."); else{var f,h,i,j,k,l,m,o,n,r,p,q,s,t,u=a.faces;l=a.vertices;var v=a.normals,x=a.colors,w=0;for(f=0;f65533){n-=3; break}c[j]=j++;c[j]=j++;c[j]=j++;for(k in a){i=e[k];size=a[k];for(o=0;o<3;o++){l=0;for(m=size;l 2^(edge configuration) map // There is one entry for each possible cube configuration, and the output is a 12-bit vector enumerating all edges crossing the 0-level. for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer, this may get resized at run time var buffer = new Array(4096); (function() { for(var i=0; i buffer.length) { var ol = buffer.length; buffer.length = R[2] * 2; while(ol < buffer.length) { buffer[ol++] = 0; } } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } //Interpolate vertices and add up intersections (this can be done without multiplying) for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k , b = e1 & k; if(a !== b) { v[j] += a ? 1.0 - t : t; } else { v[j] += a ? 1.0 : 0; } } } //Now we just average the edge intersections and add them to coordinate var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } //Add vertex to buffer, store pointer to vertex index in buffer buffer[m] = vertices.length; vertices.push(v); //Now we need to add faces together, to do this we just loop over 3 basis components for(var i=0; i<3; ++i) { //The first three entries of the edge_mask count the crossings along the edge if(!(edge_mask & (1< Shape Carving Editor
Shape Carving Editor
- p for screenshot
Front: Back:
Top: Bottom:
Left: Right:

Paint:

Show Guides:

================================================ FILE: ShapeCarving/js/benchmark.js ================================================ var mesher = require(process.argv[2]).mesher , res = parseInt(process.argv[3]) , max_freq = parseInt(process.argv[4]) , iter_count = parseInt(process.argv[5]); var nr = 2*res + 1 , volume = new Int32Array(nr * nr * nr) , dims = new Int32Array([nr, nr, nr]); function init_volume(freq) { var n = 0, s = 0.5 * freq * Math.PI / res; for(var z=-res; z<=res; ++z) for(var y=-res; y<=res; ++y) for(var x=-res; x<=res; ++x, ++n) { volume[n] = Math.sin(s * x) + Math.sin(s * y) + Math.sin(s * z) < 0 ? 1 : 0; } } //Warm up run on noisy volume, try to get JIT to compile meser init_volume(res / 4.0); for(var i=0; i 0) { dv[v] = h; du[u] = w; } else { c = -c; du[v] = h; dv[u] = w; } var vertex_count = vertices.length; vertices.push([x[0], x[1], x[2] ]); vertices.push([x[0]+du[0], x[1]+du[1], x[2]+du[2] ]); vertices.push([x[0]+du[0]+dv[0], x[1]+du[1]+dv[1], x[2]+du[2]+dv[2]]); vertices.push([x[0] +dv[0], x[1] +dv[1], x[2] +dv[2]]); faces.push([vertex_count, vertex_count+1, vertex_count+2, vertex_count+3, c]); //Zero-out mask for(l=0; l 0) { dv[v] = h; du[u] = w; } else { c = -c; du[v] = h; dv[u] = w; } var vertex_count = vertices.length; vertices.push([x[0], x[1], x[2] ]); vertices.push([x[0]+du[0], x[1]+du[1], x[2]+du[2] ]); vertices.push([x[0]+du[0]+dv[0], x[1]+du[1]+dv[1], x[2]+du[2]+dv[2]]); vertices.push([x[0] +dv[0], x[1] +dv[1], x[2] +dv[2]]); faces.push([vertex_count, vertex_count+1, vertex_count+2, c]); faces.push([vertex_count, vertex_count+2, vertex_count+3, c]); //Zero-out mask for(l=0; l p_l && p_r > r_l && r_c === p_c) { //Merge run p.merge_run(x[v], r_l, r_r); //Insert polygon into frontier next_frontier[fp++] = frontier[i]; ++i; j += 2; } else { //Check if we need to advance the run pointer if(r_r <= p_r) { if(!!r_c) { var n_poly = new MonotonePolygon(r_c, x[v], r_l, r_r); next_frontier[fp++] = polygons.length; polygons.push(n_poly); } j += 2; } //Check if we need to advance the frontier pointer if(p_r <= r_r) { p.close_off(x[v]); ++i; } } } //Close off any residual polygons for(; i r[1]; } var idx = n_side ? right_index[r_i] : left_index[l_i] , vert = n_side ? p.right[r_i] : p.left[l_i]; if(n_side !== side) { //Opposite side while(bottom+3 < top) { if(flipped === n_side) { faces.push([ stack[bottom], stack[bottom+3], idx, c]); } else { faces.push([ stack[bottom+3], stack[bottom], idx, c]); } bottom += 3; } } else { //Same side while(bottom+3 < top) { //Compute convexity for(var j=0; j<2; ++j) for(var k=0; k<2; ++k) { delta[j][k] = stack[top-3*(j+1)+k+1] - vert[k]; } var det = delta[0][0] * delta[1][1] - delta[1][0] * delta[0][1]; if(n_side === (det > 0)) { break; } if(det !== 0) { if(flipped === n_side) { faces.push([ stack[top-3], stack[top-6], idx, c ]); } else { faces.push([ stack[top-6], stack[top-3], idx, c ]); } } top -= 3; } } //Push vertex stack[top++] = idx; stack[top++] = vert[0]; stack[top++] = vert[1]; //Update loop index if(n_side) { ++r_i; } else { ++l_i; } side = n_side; } } } } return { vertices:vertices, faces:faces }; } })(); if(exports) { exports.mesher = MonotoneMesh; } ================================================ FILE: ShapeCarving/js/shapecarve.js ================================================ "use strict"; function ShapeCarve(dims, views, mask_color, skip) { var x = new Int32Array(3) , volume = new Int32Array(dims[0] * dims[1] * dims[2]) , depth = []; //Initialize volume for(var i=0; i 0) { removed = 0; for(var d=0; d<3; ++d) { var u = (d+1)%3 , v = (d+2)%3; //Do front/back sweep for(s=-1; s<=1; s+=2) { var v_num = 2*d + ((s<0) ? 1 : 0); if(skip[v_num]) { continue; } var aview = views[v_num] , adepth = depth[v_num]; for(x[v]=0; x[v] 3 || Math.abs(j-7) > 3 ? 1 : 0; }); result['Boss'] = makeVoxels([0,0,0], [16,16,4], function(i,j,k) { if(k === 0) { return 0x0000ff; } else if(Math.abs(i-4) < 2 && Math.abs(j-5) < 2 && k< 2) { return 0x00ff00; } else if(10 <= i && i < 14 && 2 <= j && j < 15) { return 0xff0000; } return 0; }); result['T-Shape'] = makeVoxels([0,0,0], [16,16,3], function(i,j,k) { return (( 6 <= i && i < 10 && 2 <= j && j < 13) || ( 2 <= i && i < 14 && 8 <= j && j < 13)) ? 0xcc00dd : 0; }); result['HollowCube'] = makeVoxels([0,0,0], [16,16,16], function(i,j,k) { if(i < 1) { return 0xff0000; } else if(i >= 15) { return 0x00ffff; } else if(j < 1) { return 0x00ff00; } else if(j >= 15) { return 0xff00ff; } else if(k < 1) { return 0x0000ff; } else if(k >= 15) { return 0xffff00; } else { return 0; } }); result['Clover'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { if(i == 0 && Math.abs(j-8) <= 2) { return 0; } else if(i == 16 && Math.abs(j-8) <= 2) { return 0; } else if(j == 0 && Math.abs(i-8) <= 2) { return 0; } else if(j == 16 && Math.abs(i-8) <= 2) { return 0; } else { return 0x10de60; } }); result['Triangle'] = makeVoxels([0,0,0], [17,17,1], function(i,j,k) { return (i < j) ? 0xff00ff : 0; }); result['Saw'] = makeVoxels([0,0,0], [17,3,1], function(i,j,k) { if( j > 0 || !!(i & 1) ) { return 0x00ffff; } return 0; }); result['4Dots'] = makeVoxels([0,0,0], [7,7,1], function(i,j,k) { if( (i == 2 && j == 1) || (i == 5 && j == 2) || (i == 1 && j == 4) || (i == 4 && j == 5) ) { return 0x00ff; } return 0xeedd00; }); result['Checker'] = makeVoxels([0,0,0], [8,8,8], function(i,j,k) { return !!((i+j+k)&1) ? (((i^j^k)&2) ? 1 : 0xffffff) : 0; }); result["Matt's Example"] = makeVoxels([0,0,0], [4,5,1], function(i,j,k) { if( (i == 1 && j == 1) || (i == 2 && j == 3) ) { return 0xee5533; } return 0x128844; }); result['Benchmark (SLOW!)'] = makeVoxels([-32, -32, -32], [33, 33, 33], function(x, y, z) { var s = 2.0 * Math.PI / 32.0; return Math.sin(s * x) + Math.sin(s * y) + Math.sin(s * z) < 0 ? 1 : 0; }); result['Hill'] = makeVoxels([-16, 0, -16], [16,16,16], function(i,j,k) { return j <= 16 * Math.exp(-(i*i + k*k) / 64) ? 0x118822 : 0; }); result['Valley'] = makeVoxels([0,0,0], [32,32,32], function(i,j,k) { return j <= (i*i + k*k) * 31 / (32*32*2) + 1 ? 0x118822 : 0; }); result['Hilly Terrain'] = makeVoxels([0, 0, 0], [32,32,32], function(i,j,k) { var h0 = 3.0 * Math.sin(Math.PI * i / 12.0 - Math.PI * k * 0.1) + 27; if(j > h0+1) { return 0; } if(h0 <= j) { return 0x23dd31; } var h1 = 2.0 * Math.sin(Math.PI * i * 0.25 - Math.PI * k * 0.3) + 20; if(h1 <= j) { return 0x964B00; } if(2 < j) { return Math.random() < 0.1 ? 0x222222 : 0xaaaaaa; } return 0xff0000; }); result['Empty'] = { voxels : [], dims : [0,0,0] }; return result; } ================================================ FILE: ShapeCarving/jscolor/demo.html ================================================ jscolor demo Click here: ================================================ FILE: ShapeCarving/jscolor/jscolor.js ================================================ /** * jscolor, JavaScript Color Picker * * @version 1.4.0 * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html * @author Jan Odvarko, http://odvarko.cz * @created 2008-06-15 * @updated 2012-07-06 * @link http://jscolor.com */ var jscolor = { dir : '', // location of jscolor directory (leave empty to autodetect) bindClass : 'color', // class name binding : true, // automatic binding via preloading : true, // use image preloading? install : function() { jscolor.addEvent(window, 'load', jscolor.init); }, init : function() { if(jscolor.binding) { jscolor.bind(); } if(jscolor.preloading) { jscolor.preload(); } }, getDir : function() { if(!jscolor.dir) { var detected = jscolor.detectDir(); jscolor.dir = detected!==false ? detected : 'jscolor/'; } return jscolor.dir; }, detectDir : function() { var base = location.href; var e = document.getElementsByTagName('base'); for(var i=0; i vs[a] ? (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : tp[a], -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ? (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) : (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c) ]; } drawPicker(pp[a], pp[b]); } }; this.importColor = function() { if(!valueElement) { this.exportColor(); } else { if(!this.adjust) { if(!this.fromString(valueElement.value, leaveValue)) { styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage; styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor; styleElement.style.color = styleElement.jscStyle.color; this.exportColor(leaveValue | leaveStyle); } } else if(!this.required && /^\s*$/.test(valueElement.value)) { valueElement.value = ''; styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage; styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor; styleElement.style.color = styleElement.jscStyle.color; this.exportColor(leaveValue | leaveStyle); } else if(this.fromString(valueElement.value)) { // OK } else { this.exportColor(); } } }; this.exportColor = function(flags) { if(!(flags & leaveValue) && valueElement) { var value = this.toString(); if(this.caps) { value = value.toUpperCase(); } if(this.hash) { value = '#'+value; } valueElement.value = value; } if(!(flags & leaveStyle) && styleElement) { styleElement.style.backgroundImage = "none"; styleElement.style.backgroundColor = '#'+this.toString(); styleElement.style.color = 0.213 * this.rgb[0] + 0.715 * this.rgb[1] + 0.072 * this.rgb[2] < 0.5 ? '#FFF' : '#000'; } if(!(flags & leavePad) && isPickerOwner()) { redrawPad(); } if(!(flags & leaveSld) && isPickerOwner()) { redrawSld(); } }; this.fromHSV = function(h, s, v, flags) { // null = don't change if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); } if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); } if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); } this.rgb = HSV_RGB( h===null ? this.hsv[0] : (this.hsv[0]=h), s===null ? this.hsv[1] : (this.hsv[1]=s), v===null ? this.hsv[2] : (this.hsv[2]=v) ); this.exportColor(flags); }; this.fromRGB = function(r, g, b, flags) { // null = don't change if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); } if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); } if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); } var hsv = RGB_HSV( r===null ? this.rgb[0] : r, g===null ? this.rgb[1] : g, b===null ? this.rgb[2] : b ); if(hsv[0] !== null) { this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0])); } if(hsv[2] !== 0) { this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1])); } this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2])); // update RGB according to final HSV, as some values might be trimmed var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]); this.rgb[0] = rgb[0]; this.rgb[1] = rgb[1]; this.rgb[2] = rgb[2]; this.exportColor(flags); }; this.fromString = function(hex, flags) { var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i); if(!m) { return false; } else { if(m[1].length === 6) { // 6-char notation this.fromRGB( parseInt(m[1].substr(0,2),16) / 255, parseInt(m[1].substr(2,2),16) / 255, parseInt(m[1].substr(4,2),16) / 255, flags ); } else { // 3-char notation this.fromRGB( parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255, parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255, parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255, flags ); } return true; } }; this.toString = function() { return ( (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) + (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) + (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1) ); }; function RGB_HSV(r, g, b) { var n = Math.min(Math.min(r,g),b); var v = Math.max(Math.max(r,g),b); var m = v - n; if(m === 0) { return [ null, 0, v ]; } var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m); return [ h===6?0:h, m/v, v ]; } function HSV_RGB(h, s, v) { if(h === null) { return [ v, v, v ]; } var i = Math.floor(h); var f = i%2 ? h-i : 1-(h-i); var m = v * (1 - s); var n = v * (1 - s*f); switch(i) { case 6: case 0: return [v,n,m]; case 1: return [n,v,m]; case 2: return [m,v,n]; case 3: return [m,n,v]; case 4: return [n,m,v]; case 5: return [v,m,n]; } } function removePicker() { delete jscolor.picker.owner; document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB); } function drawPicker(x, y) { if(!jscolor.picker) { jscolor.picker = { box : document.createElement('div'), boxB : document.createElement('div'), pad : document.createElement('div'), padB : document.createElement('div'), padM : document.createElement('div'), sld : document.createElement('div'), sldB : document.createElement('div'), sldM : document.createElement('div'), btn : document.createElement('div'), btnS : document.createElement('span'), btnT : document.createTextNode(THIS.pickerCloseText) }; for(var i=0,segSize=4; iWebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: ShapeCarving/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: ShapeCarving/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: ShapeCarving/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: ShapeCarving/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: ShapeCarving/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: ShapeCarving/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: ShapeCarving/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: ShapeCarving/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: ShapeCarving/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: ShapeCarving/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: ShapeCarving/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: ShapeCarving/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: ShapeCarving/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: ShapeCarving/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: ShapeCarving/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: ShapeCarving/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: ShapeCarving/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: TJunctions/MIT-LICENSE.txt ================================================ THIS IS FOR THE FRAMEWORK CODE, NOT ACTUAL JS CODE Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: TJunctions/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: TJunctions/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: TJunctions/index.html ================================================ T-Junction Tester
T-Junction Experiment
- p for screenshot

Top Subdivisions:

Bottom Subdivisions:

Mesh Scale:

Show edges:

================================================ FILE: TJunctions/vendor/three.js/Detector.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author mr.doob / http://mrdoob.com/ */ Detector = { canvas : !! window.CanvasRenderingContext2D, webgl : ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), workers : !! window.Worker, fileapi : window.File && window.FileReader && window.FileList && window.Blob, getWebGLErrorMessage : function () { var domElement = document.createElement( 'div' ); domElement.style.fontFamily = 'monospace'; domElement.style.fontSize = '13px'; domElement.style.textAlign = 'center'; domElement.style.background = '#eee'; domElement.style.color = '#000'; domElement.style.padding = '1em'; domElement.style.width = '475px'; domElement.style.margin = '5em auto 0'; if ( ! this.webgl ) { domElement.innerHTML = window.WebGLRenderingContext ? [ 'Your graphics card does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ) : [ 'Your browser does not seem to support WebGL.
', 'Find out how to get it here.' ].join( '\n' ); } return domElement; }, addGetWebGLMessage : function ( parameters ) { var parent, id, domElement; parameters = parameters || {}; parent = parameters.parent !== undefined ? parameters.parent : document.body; id = parameters.id !== undefined ? parameters.id : 'oldie'; domElement = Detector.getWebGLErrorMessage(); domElement.id = id; parent.appendChild( domElement ); } }; ================================================ FILE: TJunctions/vendor/three.js/ShaderExtras.js ================================================ /** * @author alteredq / http://alteredqualia.com/ * @author zz85 / http://www.lab4games.net/zz85/blog * * ShaderExtras currently contains: * * screen * convolution * film * bokeh * sepia * dotscreen * vignette * bleachbypass * basic * dofmipmap * focus * triangleBlur * horizontalBlur + verticalBlur * horizontalTiltShift + verticalTiltShift * blend * fxaa * luminosity * colorCorrection * normalmap * ssao * colorify * unpackDepthRGBA */ THREE.ShaderExtras = { /* ------------------------------------------------------------------------- // Full-screen textured quad shader ------------------------------------------------------------------------- */ 'screen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "gl_FragColor = opacity * texel;", "}" ].join("\n") }, /* ------------------------------------------------------------------------ // Convolution shader // - ported from o3d sample to WebGL / GLSL // http://o3d.googlecode.com/svn/trunk/samples/convolution.html ------------------------------------------------------------------------ */ 'convolution': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, "cKernel" : { type: "fv1", value: [] } }, vertexShader: [ //"#define KERNEL_SIZE 25.0", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vUv = uv - ( ( KERNEL_SIZE - 1.0 ) / 2.0 ) * uImageIncrement;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ //"#define KERNEL_SIZE 25", "uniform float cKernel[ KERNEL_SIZE ];", "uniform sampler2D tDiffuse;", "uniform vec2 uImageIncrement;", "varying vec2 vUv;", "void main() {", "vec2 imageCoord = vUv;", "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", "for( int i = 0; i < KERNEL_SIZE; i ++ ) {", "sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];", "imageCoord += uImageIncrement;", "}", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Film grain & scanlines shader // - ported from HLSL to WebGL / GLSL // http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html // Screen Space Static Postprocessor // // Produces an analogue noise overlay similar to a film grain / TV static // // Original implementation and noise algorithm // Pat 'Hawthorne' Shearon // // Optimized scanlines + noise version with intensity scaling // Georg 'Leviathan' Steinrohder // This version is provided under a Creative Commons Attribution 3.0 License // http://creativecommons.org/licenses/by/3.0/ ------------------------------------------------------------------------- */ 'film': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, time: { type: "f", value: 0.0 }, nIntensity: { type: "f", value: 0.5 }, sIntensity: { type: "f", value: 0.05 }, sCount: { type: "f", value: 4096 }, grayscale: { type: "i", value: 1 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ // control parameter "uniform float time;", "uniform bool grayscale;", // noise effect intensity value (0 = no effect, 1 = full effect) "uniform float nIntensity;", // scanlines effect intensity value (0 = no effect, 1 = full effect) "uniform float sIntensity;", // scanlines effect count value (0 = no effect, 4096 = full effect) "uniform float sCount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // sample the source "vec4 cTextureScreen = texture2D( tDiffuse, vUv );", // make some noise "float x = vUv.x * vUv.y * time * 1000.0;", "x = mod( x, 13.0 ) * mod( x, 123.0 );", "float dx = mod( x, 0.01 );", // add noise "vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx * 100.0, 0.0, 1.0 );", // get us a sine and cosine "vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );", // add scanlines "cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;", // interpolate between source and result by intensity "cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", // convert to grayscale if desired "if( grayscale ) {", "cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );", "}", "gl_FragColor = vec4( cResult, cTextureScreen.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader with bokeh // ported from GLSL shader by Martins Upitis // http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html ------------------------------------------------------------------------- */ 'bokeh' : { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, aspect: { type: "f", value: 1.0 }, aperture: { type: "f", value: 0.025 }, maxblur: { type: "f", value: 1.0 }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "varying vec2 vUv;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "uniform float maxblur;", // max blur amount "uniform float aperture;", // aperture - bigger values for shallower depth of field "uniform float focus;", "uniform float aspect;", "void main() {", "vec2 aspectcorrect = vec2( 1.0, aspect );", "vec4 depth1 = texture2D( tDepth, vUv );", "float factor = depth1.x - focus;", "vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );", "vec2 dofblur9 = dofblur * 0.9;", "vec2 dofblur7 = dofblur * 0.7;", "vec2 dofblur4 = dofblur * 0.4;", "vec4 col = vec4( 0.0 );", "col += texture2D( tColor, vUv.xy );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );", "col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );", "gl_FragColor = col / 41.0;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Depth-of-field shader using mipmaps // - from Matt Handley @applmak // - requires power-of-2 sized render target with enabled mipmaps ------------------------------------------------------------------------- */ 'dofmipmap': { uniforms: { tColor: { type: "t", value: 0, texture: null }, tDepth: { type: "t", value: 1, texture: null }, focus: { type: "f", value: 1.0 }, maxblur: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float focus;", "uniform float maxblur;", "uniform sampler2D tColor;", "uniform sampler2D tDepth;", "varying vec2 vUv;", "void main() {", "vec4 depth = texture2D( tDepth, vUv );", "float factor = depth.x - focus;", "vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );", "gl_FragColor = col;", "gl_FragColor.a = 1.0;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Sepia tone shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'sepia': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, amount: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float amount;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "vec3 c = color.rgb;", "color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );", "color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );", "color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );", "gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Dot screen shader // - based on glfx.js sepia shader // https://github.com/evanw/glfx.js ------------------------------------------------------------------------- */ 'dotscreen': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, tSize: { type: "v2", value: new THREE.Vector2( 256, 256 ) }, center: { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) }, angle: { type: "f", value: 1.57 }, scale: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec2 center;", "uniform float angle;", "uniform float scale;", "uniform vec2 tSize;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "float pattern() {", "float s = sin( angle ), c = cos( angle );", "vec2 tex = vUv * tSize - center;", "vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;", "return ( sin( point.x ) * sin( point.y ) ) * 4.0;", "}", "void main() {", "vec4 color = texture2D( tDiffuse, vUv );", "float average = ( color.r + color.g + color.b ) / 3.0;", "gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );", "}" ].join("\n") }, /* ------------------------------------------------------------------------------------------------ // Vignette shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js ------------------------------------------------------------------------------------------------ */ 'vignette': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, offset: { type: "f", value: 1.0 }, darkness: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float offset;", "uniform float darkness;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", // Eskil's vignette "vec4 texel = texture2D( tDiffuse, vUv );", "vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );", "gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );", /* // alternative version from glfx.js // this one makes more "dusty" look (as opposed to "burned") "vec4 color = texture2D( tDiffuse, vUv );", "float dist = distance( vUv, vec2( 0.5 ) );", "color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", "gl_FragColor = color;", */ "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] // - based on Nvidia example // http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass ------------------------------------------------------------------------- */ 'bleachbypass': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 base = texture2D( tDiffuse, vUv );", "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", "float lum = dot( lumCoeff, base.rgb );", "vec3 blend = vec3( lum );", "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", "vec3 result1 = 2.0 * base.rgb * blend;", "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", "vec3 newColor = mix( result1, result2, L );", "float A2 = opacity * base.a;", "vec3 mixRGB = A2 * newColor.rgb;", "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", "gl_FragColor = vec4( mixRGB, base.a );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Focus shader // - based on PaintEffect postprocess from ro.me // http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js -------------------------------------------------------------------------------------------------- */ 'focus': { uniforms : { "tDiffuse": { type: "t", value: 0, texture: null }, "screenWidth": { type: "f", value: 1024 }, "screenHeight": { type: "f", value: 1024 }, "sampleDistance": { type: "f", value: 0.94 }, "waveFactor": { type: "f", value: 0.00125 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float screenWidth;", "uniform float screenHeight;", "uniform float sampleDistance;", "uniform float waveFactor;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 color, org, tmp, add;", "float sample_dist, f;", "vec2 vin;", "vec2 uv = vUv;", "add += color = org = texture2D( tDiffuse, uv );", "vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );", "sample_dist = dot( vin, vin ) * 2.0;", "f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;", "vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );", "if( tmp.b < color.b ) color = tmp;", "color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );", "color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );", "gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Triangle blur shader // - based on glfx.js triangle blur shader // https://github.com/evanw/glfx.js // A basic blur filter, which convolves the image with a // pyramid filter. The pyramid filter is separable and is applied as two // perpendicular triangle filters. ------------------------------------------------------------------------- */ 'triangleBlur': { uniforms : { "texture": { type: "t", value: 0, texture: null }, "delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "#define ITERATIONS 10.0", "uniform sampler2D texture;", "uniform vec2 delta;", "varying vec2 vUv;", "float random( vec3 scale, float seed ) {", // use the fragment position for a different seed per-pixel "return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );", "}", "void main() {", "vec4 color = vec4( 0.0 );", "float total = 0.0;", // randomize the lookup values to hide the fixed number of samples "float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );", "for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {", "float percent = ( t + offset - 0.5 ) / ITERATIONS;", "float weight = 1.0 - abs( percent );", "color += texture2D( texture, vUv + delta * percent ) * weight;", "total += weight;", "}", "gl_FragColor = color / total;", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Simple test shader ------------------------------------------------------------------------- */ 'basic': { uniforms: {}, vertexShader: [ "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "void main() {", "gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Two pass Gaussian blur filter (horizontal and vertical blur shaders) // - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/ // and used in http://www.cake23.de/traveling-wavefronts-lit-up.html // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" -------------------------------------------------------------------------------------------------- */ 'horizontalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalBlur': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* -------------------------------------------------------------------------------------------------- // Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position // // - 9 samples per pass // - standard deviation 2.7 // - "h" and "v" parameters should be set to "1 / width" and "1 / height" // - "r" parameter control where "focused" horizontal line lies -------------------------------------------------------------------------------------------------- */ 'horizontalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "h": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float h;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float hh = h * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, 'verticalTiltShift': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "v": { type: "f", value: 1.0 / 512.0 }, "r": { type: "f", value: 0.35 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform float v;", "uniform float r;", "varying vec2 vUv;", "void main() {", "vec4 sum = vec4( 0.0 );", "float vv = v * abs( r - vUv.y );", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;", "sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;", "gl_FragColor = sum;", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Blend two textures ------------------------------------------------------------------------- */ 'blend': { uniforms: { tDiffuse1: { type: "t", value: 0, texture: null }, tDiffuse2: { type: "t", value: 1, texture: null }, mixRatio: { type: "f", value: 0.5 }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform float mixRatio;", "uniform sampler2D tDiffuse1;", "uniform sampler2D tDiffuse2;", "varying vec2 vUv;", "void main() {", "vec4 texel1 = texture2D( tDiffuse1, vUv );", "vec4 texel2 = texture2D( tDiffuse2, vUv );", "gl_FragColor = opacity * mix( texel1, texel2, mixRatio );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // NVIDIA FXAA by Timothy Lottes // http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html // - WebGL port by @supereggbert // http://www.glge.org/demos/fxaa/ ------------------------------------------------------------------------- */ 'fxaa': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec2 resolution;", "varying vec2 vUv;", "#define FXAA_REDUCE_MIN (1.0/128.0)", "#define FXAA_REDUCE_MUL (1.0/8.0)", "#define FXAA_SPAN_MAX 8.0", "void main() {", "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", "vec3 rgbM = texture2D( tDiffuse, gl_FragCoord.xy * resolution ).xyz;", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float lumaNW = dot( rgbNW, luma );", "float lumaNE = dot( rgbNE, luma );", "float lumaSW = dot( rgbSW, luma );", "float lumaSE = dot( rgbSE, luma );", "float lumaM = dot( rgbM, luma );", "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", "vec2 dir;", "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", "dir * rcpDirMin)) * resolution;", "vec3 rgbA = 0.5 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );", "vec3 rgbB = rgbA * 0.5 + 0.25 * (", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +", "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );", "float lumaB = dot( rgbB, luma );", "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", "gl_FragColor = vec4( rgbA, 1.0 );", "} else {", "gl_FragColor = vec4( rgbB, 1.0 );", "}", "}", ].join("\n"), }, /* ------------------------------------------------------------------------- // Luminosity // http://en.wikipedia.org/wiki/Luminosity ------------------------------------------------------------------------- */ 'luminosity': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v, v, v, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Color correction ------------------------------------------------------------------------- */ 'colorCorrection': { uniforms: { "tDiffuse" : { type: "t", value: 0, texture: null }, "powRGB" : { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, "mulRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Normal map shader // - compute normals from heightmap ------------------------------------------------------------------------- */ 'normalmap': { uniforms: { "heightMap" : { type: "t", value: 0, texture: null }, "resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "scale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, "height" : { type: "f", value: 0.05 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float height;", "uniform vec2 resolution;", "uniform sampler2D heightMap;", "varying vec2 vUv;", "void main() {", "float val = texture2D( heightMap, vUv ).x;", "float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;", "float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;", "gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );", "}", ].join("\n") }, /* ------------------------------------------------------------------------- // Screen-space ambient occlusion shader // - ported from // SSAO GLSL shader v1.2 // assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com) // original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/) // - modifications // - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass) // - made fog more compatible with three.js linear fog // - refactoring and optimizations ------------------------------------------------------------------------- */ 'ssao': { uniforms: { "tDiffuse": { type: "t", value: 0, texture: null }, "tDepth": { type: "t", value: 1, texture: null }, "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, "cameraNear": { type: "f", value: 1 }, "cameraFar": { type: "f", value: 100 }, "fogNear": { type: "f", value: 5 }, "fogFar": { type: "f", value: 100 }, "fogEnabled": { type: "i", value: 0 }, "aoClamp": { type: "f", value: 0.3 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float cameraNear;", "uniform float cameraFar;", "uniform float fogNear;", "uniform float fogFar;", "uniform bool fogEnabled;", "uniform vec2 size;", // texture width, height "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges "uniform sampler2D tDiffuse;", "uniform sampler2D tDepth;", "varying vec2 vUv;", //"#define PI 3.14159265", "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) ) "#define EULER 2.718281828459045", // helpers "float width = size.x;", // texture width "float height = size.y;", // texture height "float cameraFarPlusNear = cameraFar + cameraNear;", "float cameraFarMinusNear = cameraFar - cameraNear;", "float cameraCoef = 2.0 * cameraNear;", // user variables "const int samples = 8;", // ao sample count "const float radius = 5.0;", // ao radius "const bool useNoise = false;", // use noise instead of pattern for sample dithering "const float noiseAmount = 0.0002;", // dithering amount "const float diffArea = 0.4;", // self-shadowing reduction "const float gDisplace = 0.4;", // gauss bell center "const bool onlyAO = false;", // use only ambient occlusion pass? "const float lumInfluence = 0.3;", // how much luminance affects occlusion // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", // generating noise / pattern texture for dithering "vec2 rand( const vec2 coord ) {", "vec2 noise;", "if ( useNoise ) {", "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );", "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );", "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );", "} else {", "float ff = fract( 1.0 - coord.s * ( width / 2.0 ) );", "float gg = fract( coord.t * ( height / 2.0 ) );", "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;", "}", "return ( noise * 2.0 - 1.0 ) * noiseAmount;", "}", "float doFog() {", "float zdepth = unpackDepth( texture2D( tDepth, vUv ) );", "float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );", "return smoothstep( fogNear, fogFar, depth );", "}", "float readDepth( const in vec2 coord ) {", //"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );", "return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );", "}", "float compareDepths( const in float depth1, const in float depth2, inout int far ) {", "float garea = 2.0;", // gauss bell width "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100) // reduce left bell width to avoid self-shadowing "if ( diff < gDisplace ) {", "garea = diffArea;", "} else {", "far = 1;", "}", "float dd = diff - gDisplace;", "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );", "return gauss;", "}", "float calcAO( float depth, float dw, float dh ) {", "float dd = radius - depth * radius;", "vec2 vv = vec2( dw, dh );", "vec2 coord1 = vUv + dd * vv;", "vec2 coord2 = vUv - dd * vv;", "float temp1 = 0.0;", "float temp2 = 0.0;", "int far = 0;", "temp1 = compareDepths( depth, readDepth( coord1 ), far );", // DEPTH EXTRAPOLATION "if ( far > 0 ) {", "temp2 = compareDepths( readDepth( coord2 ), depth, far );", "temp1 += ( 1.0 - temp1 ) * temp2;", "}", "return temp1;", "}", "void main() {", "vec2 noise = rand( vUv );", "float depth = readDepth( vUv );", "float tt = clamp( depth, aoClamp, 1.0 );", "float w = ( 1.0 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );", "float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );", "float pw;", "float ph;", "float ao;", "float dz = 1.0 / float( samples );", "float z = 1.0 - dz / 2.0;", "float l = 0.0;", "for ( int i = 0; i <= samples; i ++ ) {", "float r = sqrt( 1.0 - z );", "pw = cos( l ) * r;", "ph = sin( l ) * r;", "ao += calcAO( depth, pw * w, ph * h );", "z = z - dz;", "l = l + DL;", "}", "ao /= float( samples );", "ao = 1.0 - ao;", "if ( fogEnabled ) {", "ao = mix( ao, 1.0, doFog() );", "}", "vec3 color = texture2D( tDiffuse, vUv ).rgb;", "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );", "float lum = dot( color.rgb, lumcoeff );", "vec3 luminance = vec3( lum );", "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance ) "if ( onlyAO ) {", "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only "}", "gl_FragColor = vec4( final, 1.0 );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Colorify shader ------------------------------------------------------------------------- */ 'colorify': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, color: { type: "c", value: new THREE.Color( 0xffffff ) } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform vec3 color;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );", "vec3 luma = vec3( 0.299, 0.587, 0.114 );", "float v = dot( texel.xyz, luma );", "gl_FragColor = vec4( v * color, texel.w );", "}" ].join("\n") }, /* ------------------------------------------------------------------------- // Unpack RGBA depth shader // - show RGBA encoded depth as monochrome color ------------------------------------------------------------------------- */ 'unpackDepthRGBA': { uniforms: { tDiffuse: { type: "t", value: 0, texture: null }, opacity: { type: "f", value: 1.0 } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, 1.0 - uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join("\n"), fragmentShader: [ "uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", // RGBA depth "float unpackDepth( const in vec4 rgba_depth ) {", "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );", "float depth = dot( rgba_depth, bit_shift );", "return depth;", "}", "void main() {", "float depth = 1.0 - unpackDepth( texture2D( tDiffuse, vUv ) );", "gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );", "}" ].join("\n") }, // METHODS buildKernel: function( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. function gauss( x, sigma ) { return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); } var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; halfWidth = ( kernelSize - 1 ) * 0.5 values = new Array( kernelSize ); sum = 0.0; for ( i = 0; i < kernelSize; ++i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; } // normalize the kernel for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; return values; } }; ================================================ FILE: TJunctions/vendor/three.js/Stats.js ================================================ // stats.js r8 - http://github.com/mrdoob/stats.js var Stats=function(){var h,a,n=0,o=0,i=Date.now(),u=i,p=i,l=0,q=1E3,r=0,e,j,f,b=[[16,16,48],[0,255,255]],m=0,s=1E3,t=0,d,k,g,c=[[16,48,16],[0,255,0]];h=document.createElement("div");h.style.cursor="pointer";h.style.width="80px";h.style.opacity="0.9";h.style.zIndex="10001";h.addEventListener("mousedown",function(a){a.preventDefault();n=(n+1)%2;n==0?(e.style.display="block",d.style.display="none"):(e.style.display="none",d.style.display="block")},!1);e=document.createElement("div");e.style.textAlign= "left";e.style.lineHeight="1.2em";e.style.backgroundColor="rgb("+Math.floor(b[0][0]/2)+","+Math.floor(b[0][1]/2)+","+Math.floor(b[0][2]/2)+")";e.style.padding="0 0 3px 3px";h.appendChild(e);j=document.createElement("div");j.style.fontFamily="Helvetica, Arial, sans-serif";j.style.fontSize="9px";j.style.color="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";j.style.fontWeight="bold";j.innerHTML="FPS";e.appendChild(j);f=document.createElement("div");f.style.position="relative";f.style.width="74px";f.style.height= "30px";f.style.backgroundColor="rgb("+b[1][0]+","+b[1][1]+","+b[1][2]+")";for(e.appendChild(f);f.children.length<74;)a=document.createElement("span"),a.style.width="1px",a.style.height="30px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+b[0][0]+","+b[0][1]+","+b[0][2]+")",f.appendChild(a);d=document.createElement("div");d.style.textAlign="left";d.style.lineHeight="1.2em";d.style.backgroundColor="rgb("+Math.floor(c[0][0]/2)+","+Math.floor(c[0][1]/2)+","+Math.floor(c[0][2]/2)+")";d.style.padding= "0 0 3px 3px";d.style.display="none";h.appendChild(d);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.fontSize="9px";k.style.color="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";k.style.fontWeight="bold";k.innerHTML="MS";d.appendChild(k);g=document.createElement("div");g.style.position="relative";g.style.width="74px";g.style.height="30px";g.style.backgroundColor="rgb("+c[1][0]+","+c[1][1]+","+c[1][2]+")";for(d.appendChild(g);g.children.length<74;)a=document.createElement("span"), a.style.width="1px",a.style.height=Math.random()*30+"px",a.style.cssFloat="left",a.style.backgroundColor="rgb("+c[0][0]+","+c[0][1]+","+c[0][2]+")",g.appendChild(a);return{domElement:h,update:function(){i=Date.now();m=i-u;s=Math.min(s,m);t=Math.max(t,m);k.textContent=m+" MS ("+s+"-"+t+")";var a=Math.min(30,30-m/200*30);g.appendChild(g.firstChild).style.height=a+"px";u=i;o++;if(i>p+1E3)l=Math.round(o*1E3/(i-p)),q=Math.min(q,l),r=Math.max(r,l),j.textContent=l+" FPS ("+q+"-"+r+")",a=Math.min(30,30-l/ 100*30),f.appendChild(f.firstChild).style.height=a+"px",p=i,o=0}}}; ================================================ FILE: TJunctions/vendor/three.js/Three.js ================================================ // Three.js - http://github.com/mrdoob/three.js 'use strict';var THREE=THREE||{REVISION:"49"};self.Int32Array||(self.Int32Array=Array,self.Float32Array=Array); (function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},lerpSelf:function(a,b){this.r=this.r+(a.r-this.r)*b;this.g=this.g+(a.g-this.g)*b;this.b=this.b+(a.b-this.b)*b;return this},getHex:function(){return Math.floor(this.r*255)<<16^Math.floor(this.g*255)<<8^Math.floor(this.b*255)},getContextStyle:function(){return"rgb("+Math.floor(this.r*255)+","+Math.floor(this.g*255)+","+Math.floor(this.b*255)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}}; THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;return this},divideScalar:function(a){if(a){this.x= this.x/a;this.y=this.y/a}else this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;return this},addScalar:function(a){this.x=this.x+a;this.y=this.y+ a;this.z=this.z+a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x=this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x=this.x*a.x;this.y=this.y*a.y;this.z=this.z*a.z;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;return this},divideSelf:function(a){this.x=this.x/a.x;this.y= this.y/a.y;this.z=this.z/a.z;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a}else this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())}, setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this, a).lengthSq()},getPositionFromMatrix:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,e=b?b.z:1,f=a.elements[0]/c,g=a.elements[4]/d,c=a.elements[1]/c,d=a.elements[5]/d,h=a.elements[9]/e,j=a.elements[10]/e;this.y=Math.asin(a.elements[8]/e);e=Math.cos(this.y);if(Math.abs(e)>1.0E-5){this.x=Math.atan2(-h/e,j/e);this.z=Math.atan2(-g/e,f/e)}else{this.x=0;this.z=Math.atan2(c,d)}return this},getScaleFromMatrix:function(a){var b= this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},isZero:function(){return this.lengthSq()<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w!==void 0?a.w:1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x=this.x+a.x;this.y=this.y+a.y;this.z=this.z+a.z;this.w=this.w+a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x= this.x-a.x;this.y=this.y-a.y;this.z=this.z-a.z;this.w=this.w-a.w;return this},multiplyScalar:function(a){this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a;return this},divideScalar:function(a){if(a){this.x=this.x/a;this.y=this.y/a;this.z=this.z/a;this.w=this.w/a}else{this.z=this.y=this.x=0;this.w=1}return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x=this.x+(a.x-this.x)*b;this.y=this.y+(a.y-this.y)*b;this.z=this.z+(a.z-this.z)*b;this.w=this.w+(a.w-this.w)*b;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes,d=a.elements,a=d[0];b=d[1];var e=d[2],f=d[3],g=d[4],h=d[5],j=d[6],l=d[7],k=d[8],p=d[9],m=d[10],o=d[11],q=d[12],n=d[13],r=d[14],d=d[15];c[0].set(f-a,l-g,o-k,d-q);c[1].set(f+a,l+g,o+k,d+q);c[2].set(f+b,l+h,o+p,d+n);c[3].set(f-b,l-h,o-p,d-n);c[4].set(f-e,l-j,o-m,d-r);c[5].set(f+e,l+j,o+m,d+r);for(a=0;a<6;a++){b=c[a];b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}}; THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=c.elements,c=-a.geometry.boundingSphere.radius*c.getMaxScaleOnAxis(),e=0;e<6;e++){a=b[e].x*d[12]+b[e].y*d[13]+b[e].z*d[14]+b[e].w;if(a<=c)return false}return true};THREE.Frustum.__v1=new THREE.Vector3; THREE.Ray=function(a,b){function c(a,b,c){q.sub(c,a);u=q.dot(b);t=n.add(a,r.copy(b).multiplyScalar(u));return y=c.distanceTo(t)}function d(a,b,c,d){q.sub(d,b);n.sub(c,b);r.sub(a,b);s=q.dot(q);w=q.dot(n);H=q.dot(r);E=n.dot(n);z=n.dot(r);v=1/(s*E-w*w);A=(E*H-w*z)*v;J=(s*z-w*H)*v;return A>=0&&J>=0&&A+J<1}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;var e=1.0E-4;this.setPrecision=function(a){e=a};var f=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3,j=new THREE.Vector3, l=new THREE.Vector3,k=new THREE.Vector3,p=new THREE.Vector3,m=new THREE.Vector3,o=new THREE.Vector3;this.intersectObject=function(a){var b,n=[];if(a instanceof THREE.Particle){var q=c(this.origin,this.direction,a.matrixWorld.getPosition());if(q>a.scale.x)return[];b={distance:q,point:a.position,face:null,object:a};n.push(b)}else if(a instanceof THREE.Mesh){var q=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(), a.matrixWorld.getColumnZ().length());if(q>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,i,t=a.geometry,u=t.vertices,C;a.matrixRotationWorld.extractRotation(a.matrixWorld);q=0;for(r=t.faces.length;q0:s<0))){o.add(l,k.multiplyScalar(i));if(b instanceof THREE.Face3){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));if(d(o,f,g,h)){b={distance:l.distanceTo(o),point:o.clone(),face:b,object:a};n.push(b)}}else if(b instanceof THREE.Face4){f=C.multiplyVector3(f.copy(u[b.a]));g=C.multiplyVector3(g.copy(u[b.b]));h=C.multiplyVector3(h.copy(u[b.c]));j=C.multiplyVector3(j.copy(u[b.d]));if(d(o,f,g,j)||d(o,g,h,j)){b={distance:l.distanceTo(o),point:o.clone(), face:b,object:a};n.push(b)}}}}}}return n};this.intersectObjects=function(a){for(var b=[],c=0,d=a.length;cf?d:f;e=e>g? e:g}a()};this.add3Points=function(f,g,k,p,m,o){if(h){h=false;b=fk?f>m?f:m:k>m?k:m;e=g>p?g>o?g:o:p>o?p:o}else{b=fk?f>m?f>d?f:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d;e=g>p?g>o?g>e?g:e:o>e?o:e:p>o?p>e?p:e:o>e?o:e}a()};this.addRectangle=function(f){if(h){h=false;b=f.getLeft();c=f.getTop();d=f.getRight();e=f.getBottom()}else{b=bf.getRight()?d:f.getRight();e=e>f.getBottom()?e:f.getBottom()}a()};this.inflate=function(f){b=b-f;c=c-f;d=d+f;e=e+f;a()};this.minSelf=function(f){b=b>f.getLeft()?b:f.getLeft();c=c>f.getTop()?c:f.getTop();d=da.getRight()||ea.getBottom()?false:true};this.empty=function(){h=true;e=d=c=b=0;a()};this.isEmpty=function(){return h}}; THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a0?1:0}};THREE.Matrix3=function(){this.elements=new Float32Array(9)}; THREE.Matrix3.prototype={constructor:THREE.Matrix3,getInverse:function(a){var b=a.elements,a=b[10]*b[5]-b[6]*b[9],c=-b[10]*b[1]+b[2]*b[9],d=b[6]*b[1]-b[2]*b[5],e=-b[10]*b[4]+b[6]*b[8],f=b[10]*b[0]-b[2]*b[8],g=-b[6]*b[0]+b[2]*b[4],h=b[9]*b[4]-b[5]*b[8],j=-b[9]*b[0]+b[1]*b[8],l=b[5]*b[0]-b[1]*b[4],b=b[0]*a+b[1]*e+b[2]*h;b===0&&console.warn("Matrix3.getInverse(): determinant == 0");var b=1/b,k=this.elements;k[0]=b*a;k[1]=b*c;k[2]=b*d;k[3]=b*e;k[4]=b*f;k[5]=b*g;k[6]=b*h;k[7]=b*j;k[8]=b*l;return this}, transpose:function(){var a,b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},transposeIntoArray:function(a){var b=this.m;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this}};THREE.Matrix4=function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){this.elements=new Float32Array(16);this.set(a!==void 0?a:1,b||0,c||0,d||0,e||0,f!==void 0?f:1,g||0,h||0,j||0,l||0,k!==void 0?k:1,p||0,m||0,o||0,q||0,n!==void 0?n:1)}; THREE.Matrix4.prototype={constructor:THREE.Matrix4,set:function(a,b,c,d,e,f,g,h,j,l,k,p,m,o,q,n){var r=this.elements;r[0]=a;r[4]=b;r[8]=c;r[12]=d;r[1]=e;r[5]=f;r[9]=g;r[13]=h;r[2]=j;r[6]=l;r[10]=k;r[14]=p;r[3]=m;r[7]=o;r[11]=q;r[15]=n;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},lookAt:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(a,b).normalize();if(g.length()===0)g.z=1;e.cross(c,g).normalize();if(e.length()===0){g.x=g.x+1.0E-4;e.cross(c,g).normalize()}f.cross(g,e);d[0]=e.x;d[4]=f.x;d[8]=g.x;d[1]=e.y;d[5]=f.y;d[9]=g.y;d[2]=e.z;d[6]=f.z;d[10]=g.z;return this},multiply:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],j=c[12],l=c[1],k=c[5],p=c[9],m=c[13],o=c[2],q=c[6],n=c[10],r=c[14],u=c[3],t=c[7],y=c[11],c=c[15],s=d[0],w=d[4], H=d[8],E=d[12],z=d[1],v=d[5],A=d[9],J=d[13],K=d[2],R=d[6],P=d[10],D=d[14],M=d[3],G=d[7],i=d[11],d=d[15];e[0]=f*s+g*z+h*K+j*M;e[4]=f*w+g*v+h*R+j*G;e[8]=f*H+g*A+h*P+j*i;e[12]=f*E+g*J+h*D+j*d;e[1]=l*s+k*z+p*K+m*M;e[5]=l*w+k*v+p*R+m*G;e[9]=l*H+k*A+p*P+m*i;e[13]=l*E+k*J+p*D+m*d;e[2]=o*s+q*z+n*K+r*M;e[6]=o*w+q*v+n*R+r*G;e[10]=o*H+q*A+n*P+r*i;e[14]=o*E+q*J+n*D+r*d;e[3]=u*s+t*z+y*K+c*M;e[7]=u*w+t*v+y*R+c*G;e[11]=u*H+t*A+y*P+c*i;e[15]=u*E+t*J+y*D+c*d;return this},multiplySelf:function(a){return this.multiply(this, a)},multiplyToArray:function(a,b,c){var d=this.elements;this.multiply(a,b);c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]=b[0]*a;b[4]=b[4]*a;b[8]=b[8]*a;b[12]=b[12]*a;b[1]=b[1]*a;b[5]=b[5]*a;b[9]=b[9]*a;b[13]=b[13]*a;b[2]=b[2]*a;b[6]=b[6]*a;b[10]=b[10]*a;b[14]=b[14]*a;b[3]=b[3]*a;b[7]=b[7]*a;b[11]=b[11]*a;b[15]= b[15]*a;return this},multiplyVector3:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=1/(b[3]*c+b[7]*d+b[11]*e+b[15]);a.x=(b[0]*c+b[4]*d+b[8]*e+b[12])*f;a.y=(b[1]*c+b[5]*d+b[9]*e+b[13])*f;a.z=(b[2]*c+b[6]*d+b[10]*e+b[14])*f;return a},multiplyVector4:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w;a.x=b[0]*c+b[4]*d+b[8]*e+b[12]*f;a.y=b[1]*c+b[5]*d+b[9]*e+b[13]*f;a.z=b[2]*c+b[6]*d+b[10]*e+b[14]*f;a.w=b[3]*c+b[7]*d+b[11]*e+b[15]*f;return a},rotateAxis:function(a){var b=this.elements,c=a.x, d=a.y,e=a.z;a.x=c*b[0]+d*b[4]+e*b[8];a.y=c*b[1]+d*b[5]+e*b[9];a.z=c*b[2]+d*b[6]+e*b[10];a.normalize();return a},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],j=a[13],l=a[2],k=a[6],p=a[10],m=a[14],o=a[3],q=a[7], n=a[11],a=a[15];return e*h*k*o-d*j*k*o-e*g*p*o+c*j*p*o+d*g*m*o-c*h*m*o-e*h*l*q+d*j*l*q+e*f*p*q-b*j*p*q-d*f*m*q+b*h*m*q+e*g*l*n-c*j*l*n-e*f*k*n+b*j*k*n+c*f*m*n-b*g*m*n-d*g*l*a+c*h*l*a+d*f*k*a-b*h*k*a-c*f*p*a+b*g*p*a},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2]; a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[12],a[13], a[14])},setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getColumnX:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[0],a[1],a[2])},getColumnY:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[4],a[5],a[6])},getColumnZ:function(){var a=this.elements;return THREE.Matrix4.__v1.set(a[8],a[9],a[10])},getInverse:function(a){var b=this.elements,c=a.elements,d=c[0],e=c[4],f=c[8],g=c[12],h=c[1],j=c[5],l=c[9],k=c[13],p=c[2],m=c[6],o=c[10],q= c[14],n=c[3],r=c[7],u=c[11],c=c[15];b[0]=l*q*r-k*o*r+k*m*u-j*q*u-l*m*c+j*o*c;b[4]=g*o*r-f*q*r-g*m*u+e*q*u+f*m*c-e*o*c;b[8]=f*k*r-g*l*r+g*j*u-e*k*u-f*j*c+e*l*c;b[12]=g*l*m-f*k*m-g*j*o+e*k*o+f*j*q-e*l*q;b[1]=k*o*n-l*q*n-k*p*u+h*q*u+l*p*c-h*o*c;b[5]=f*q*n-g*o*n+g*p*u-d*q*u-f*p*c+d*o*c;b[9]=g*l*n-f*k*n-g*h*u+d*k*u+f*h*c-d*l*c;b[13]=f*k*p-g*l*p+g*h*o-d*k*o-f*h*q+d*l*q;b[2]=j*q*n-k*m*n+k*p*r-h*q*r-j*p*c+h*m*c;b[6]=g*m*n-e*q*n-g*p*r+d*q*r+e*p*c-d*m*c;b[10]=e*k*n-g*j*n+g*h*r-d*k*r-e*h*c+d*j*c;b[14]=g*j*p- e*k*p-g*h*m+d*k*m+e*h*q-d*j*q;b[3]=l*m*n-j*o*n-l*p*r+h*o*r+j*p*u-h*m*u;b[7]=e*o*n-f*m*n+f*p*r-d*o*r-e*p*u+d*m*u;b[11]=f*j*n-e*l*n-f*h*r+d*l*r+e*h*u-d*j*u;b[15]=e*l*p-f*j*p+f*h*m-d*l*m-e*h*o+d*j*o;this.multiplyScalar(1/a.determinant());return this},setRotationFromEuler:function(a,b){var c=this.elements,d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),j=Math.cos(f),f=Math.sin(f);switch(b){case "YXZ":var l=h*j,k=h*f,p=e*j,m=e*f;c[0]=l+m*d;c[4]=p*d-k;c[8]=g*e;c[1]=g*f;c[5]=g* j;c[9]=-d;c[2]=k*d-p;c[6]=m+l*d;c[10]=g*h;break;case "ZXY":l=h*j;k=h*f;p=e*j;m=e*f;c[0]=l-m*d;c[4]=-g*f;c[8]=p+k*d;c[1]=k+p*d;c[5]=g*j;c[9]=m-l*d;c[2]=-g*e;c[6]=d;c[10]=g*h;break;case "ZYX":l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=p*e-k;c[8]=l*e+m;c[1]=h*f;c[5]=m*e+l;c[9]=k*e-p;c[2]=-e;c[6]=d*h;c[10]=g*h;break;case "YZX":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=m-l*f;c[8]=p*f+k;c[1]=f;c[5]=g*j;c[9]=-d*j;c[2]=-e*j;c[6]=k*f+p;c[10]=l-m*f;break;case "XZY":l=g*h;k=g*e;p=d*h;m=d*e;c[0]=h*j;c[4]=-f;c[8]=e*j; c[1]=l*f+m;c[5]=g*j;c[9]=k*f-p;c[2]=p*f-k;c[6]=d*j;c[10]=m*f+l;break;default:l=g*j;k=g*f;p=d*j;m=d*f;c[0]=h*j;c[4]=-h*f;c[8]=e;c[1]=k+p*e;c[5]=l-m*e;c[9]=-d*h;c[2]=m-l*e;c[6]=p+k*e;c[10]=g*h}return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,j=e+e,a=c*g,l=c*h,c=c*j,k=d*h,d=d*j,e=e*j,g=f*g,h=f*h,f=f*j;b[0]=1-(k+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+k);return this},compose:function(a,b,c){var d=this.elements, e=THREE.Matrix4.__m1,f=THREE.Matrix4.__m2;e.identity();e.setRotationFromQuaternion(b);f.makeScale(c.x,c.y,c.z);this.multiply(e,f);d[12]=a.x;d[13]=a.y;d[14]=a.z;return this},decompose:function(a,b,c){var d=this.elements,e=THREE.Matrix4.__v1,f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;e.set(d[0],d[1],d[2]);f.set(d[4],d[5],d[6]);g.set(d[8],d[9],d[10]);a=a instanceof THREE.Vector3?a:new THREE.Vector3;b=b instanceof THREE.Quaternion?b:new THREE.Quaternion;c=c instanceof THREE.Vector3?c:new THREE.Vector3; c.x=e.length();c.y=f.length();c.z=g.length();a.x=d[12];a.y=d[13];a.z=d[14];d=THREE.Matrix4.__m1;d.copy(this);d.elements[0]=d.elements[0]/c.x;d.elements[1]=d.elements[1]/c.x;d.elements[2]=d.elements[2]/c.x;d.elements[4]=d.elements[4]/c.y;d.elements[5]=d.elements[5]/c.y;d.elements[6]=d.elements[6]/c.y;d.elements[8]=d.elements[8]/c.z;d.elements[9]=d.elements[9]/c.z;d.elements[10]=d.elements[10]/c.z;b.setFromRotationMatrix(d);return[a,b,c]},extractPosition:function(a){var b=this.elements,a=a.elements; b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(a){var b=this.elements,a=a.elements,c=THREE.Matrix4.__v1,d=1/c.set(a[0],a[1],a[2]).length(),e=1/c.set(a[4],a[5],a[6]).length(),c=1/c.set(a[8],a[9],a[10]).length();b[0]=a[0]*d;b[1]=a[1]*d;b[2]=a[2]*d;b[4]=a[4]*e;b[5]=a[5]*e;b[6]=a[6]*e;b[8]=a[8]*c;b[9]=a[9]*c;b[10]=a[10]*c;return this},translate:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]* d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[4]=k*c+a*g;b[5]=k*d+a*h;b[6]=k*e+a*j;b[7]=k*f+a*l;b[8]=k*g-a*c;b[9]=k*h-a*d;b[10]=k*j-a*e;b[11]=k*l-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=b[9],j=b[10],l=b[11],k=Math.cos(a),a=Math.sin(a);b[0]=k*c-a*g;b[1]=k*d-a*h;b[2]=k*e-a*j;b[3]=k*f-a*l;b[8]=k*g+a*c;b[9]= k*h+a*d;b[10]=k*j+a*e;b[11]=k*l+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],j=b[6],l=b[7],k=Math.cos(a),a=Math.sin(a);b[0]=k*c+a*g;b[1]=k*d+a*h;b[2]=k*e+a*j;b[3]=k*f+a*l;b[4]=k*g-a*c;b[5]=k*h-a*d;b[6]=k*j-a*e;b[7]=k*l-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(a.x===1&&a.y===0&&a.z===0)return this.rotateX(b);if(a.x===0&&a.y===1&&a.z===0)return this.rotateY(b);if(a.x===0&&a.y===0&&a.z===1)return this.rotateZ(b);var d=a.x, e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,j=f*f,l=Math.cos(b),k=Math.sin(b),p=1-l,m=d*e*p,o=d*f*p,p=e*f*p,d=d*k,q=e*k,k=f*k,f=g+(1-g)*l,g=m+k,e=o-q,m=m-k,h=h+(1-h)*l,k=p+d,o=o+q,p=p-d,j=j+(1-j)*l,l=c[0],d=c[1],q=c[2],n=c[3],r=c[4],u=c[5],t=c[6],y=c[7],s=c[8],w=c[9],H=c[10],E=c[11];c[0]=f*l+g*r+e*s;c[1]=f*d+g*u+e*w;c[2]=f*q+g*t+e*H;c[3]=f*n+g*y+e*E;c[4]=m*l+h*r+k*s;c[5]=m*d+h*u+k*w;c[6]=m*q+h*t+k*H;c[7]=m*n+h*y+k*E;c[8]=o*l+p*r+j*s;c[9]=o*d+p*u+j*w;c[10]=o*q+p*t+j*H;c[11]= o*n+p*y+j*E;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]=b[0]*c;b[4]=b[4]*d;b[8]=b[8]*a;b[1]=b[1]*c;b[5]=b[5]*d;b[9]=b[9]*a;b[2]=b[2]*c;b[6]=b[6]*d;b[10]=b[10]*a;b[3]=b[3]*c;b[7]=b[7]*d;b[11]=b[11]*a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this}, makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,j=e*f,l=e*g;this.set(j*f+c,j*g-d*h,j*h+d*g,0,j*g+d*h,l*g+c,l*h-d*f,0,j*h- d*g,l*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(a*Math.PI/360),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a, b,c,d,e,f){var g=this.elements,h=b-a,j=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/j;g[9]=0;g[13]=-((c+d)/j);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;THREE.Matrix4.__m1=new THREE.Matrix4; THREE.Matrix4.__m2=new THREE.Matrix4; THREE.Object3D=function(){this.id=THREE.Object3DCount++;this.name="";this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=false;this.renderDepth=null;this.rotationAutoUpdate=true;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate= true;this.quaternion=new THREE.Quaternion;this.useQuaternion=false;this.boundRadius=0;this.boundRadiusScale=1;this.visible=true;this.receiveShadow=this.castShadow=false;this.frustumCulled=true;this._vector=new THREE.Vector3}; THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(a){this.matrix.multiply(a,this.matrix);this.scale.getScaleFromMatrix(this.matrix);this.rotation.getRotationFromMatrix(this.matrix,this.scale);this.position.getPositionFromMatrix(this.matrix)},translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a, this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.getRotationFromMatrix(this.matrix)},add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){a.parent!==void 0&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b= this.children.indexOf(a);if(b!==-1){a.parent=void 0;this.children.splice(b,1);for(b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.__removeObject(a)}},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c=0&&f>=0&&g>=0&&h>=0)return true;if(e<0&&f<0||g<0&&h<0)return false;e<0?c=Math.max(c,e/(e-f)):f<0&&(d=Math.min(d,e/(e-f)));g<0?c=Math.max(c,g/(g-h)):h<0&&(d=Math.min(d,g/(g-h)));if(dg&&h.positionScreen.z0)){ea=l[j-2];J.copy(F.positionScreen);K.copy(ea.positionScreen);if(d(J,K)){J.multiplyScalar(1/J.w);K.multiplyScalar(1/K.w);$=u[r]=u[r]||new THREE.RenderableLine;r++;n=$;n.v1.positionScreen.copy(J); n.v2.positionScreen.copy(K);n.z=Math.max(J.z,K.z);n.material=O.material;w.elements.push(n)}}}}}a=0;for(H=w.sprites.length;a0&&E.z<1){g=s[y]=s[y]||new THREE.RenderableParticle;y++;t=g;t.x=E.x/E.w;t.y=E.y/E.w;t.z=E.z;t.rotation=O.rotation.z;t.scale.x=O.scale.x*Math.abs(t.x-(E.x+e.projectionMatrix.elements[0])/(E.w+e.projectionMatrix.elements[12])); t.scale.y=O.scale.y*Math.abs(t.y-(E.y+e.projectionMatrix.elements[5])/(E.w+e.projectionMatrix.elements[13]));t.material=O.material;w.elements.push(t)}}}f&&w.elements.sort(c);return w}};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=d!==void 0?d:1}; THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,e=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-e),e=Math.sin(-e),f=Math.cos(c),c=Math.sin(c),g=a*b,h=d*e;this.w=g*f-h*c;this.x=g*c+h*f;this.y=d*b*f+a*e*c;this.z=a*e*f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c); this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.elements[0]+a.elements[5]+a.elements[10]))/2;this.x=Math.sqrt(Math.max(0,b+a.elements[0]-a.elements[5]-a.elements[10]))/2;this.y=Math.sqrt(Math.max(0,b-a.elements[0]+a.elements[5]-a.elements[10]))/2;this.z=Math.sqrt(Math.max(0,b-a.elements[0]-a.elements[5]+a.elements[10]))/2;this.x=a.elements[6]-a.elements[9]<0?-Math.abs(this.x): Math.abs(this.x);this.y=a.elements[8]-a.elements[2]<0?-Math.abs(this.y):Math.abs(this.y);this.z=a.elements[1]-a.elements[4]<0?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x=this.x*-1;this.y=this.y*-1;this.z=this.z*-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a= Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);if(a===0)this.w=this.z=this.y=this.x=0;else{a=1/a;this.x=this.x*a;this.y=this.y*a;this.z=this.z*a;this.w=this.w*a}return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y= c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiplyVector3:function(a,b){b||(b=a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,l=j*c+g*e-h*d,k=j*d+h*c-f*e,p=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=l*j+c*-f+k*-h-p*-g;b.y=k*j+c*-g+p*-f-l*-h;b.z=p*j+c*-h+l*-g-k*-f;return b},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}}; THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;if(e<0){c.w=-b.w;c.x=-b.x;c.y=-b.y;c.z=-b.z;e=-e}else c.copy(b);if(Math.abs(e)>=1){c.w=a.w;c.x=a.x;c.y=a.y;c.z=a.z;return c}var f=Math.acos(e),e=Math.sqrt(1-e*e);if(Math.abs(e)<0.001){c.w=0.5*(a.w+b.w);c.x=0.5*(a.x+b.x);c.y=0.5*(a.y+b.y);c.z=0.5*(a.z+b.z);return c}b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.")}; THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3}; THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b0){var a;a=this.vertices[0];this.boundingBox.min.copy(a);this.boundingBox.max.copy(a);for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;dc.x)c.x= a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else{this.boundingBox.min.set(0,0,0);this.boundingBox.max.set(0,0,0)}},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a)}this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h;f=0;for(g=this.vertices.length;f0;a--)if(d.indexOf(e["abcd"[a]])!=a){d.splice(a,1);this.faces[f]=new THREE.Face3(d[0],d[1],d[2]);e=0;for(d=this.faceVertexUvs.length;ethis.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: f+2;l=this.points[c[0]];k=this.points[c[1]];p=this.points[c[2]];m=this.points[c[3]];h=g*g;j=g*h;d.x=b(l.x,k.x,p.x,m.x,g,h,j);d.y=b(l.y,k.y,p.y,m.y,g,h,j);d.z=b(l.z,k.z,p.z,m.z,g,h,j);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a1&&(K=new THREE.MeshFaceMaterial); a=new THREE.Mesh(J,K);a.name=m;if(t){a.matrixAutoUpdate=false;a.matrix.set(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}else{a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2])}a.visible=u.visible;a.doubleSided=u.doubleSided;a.castShadow=u.castShadow;a.receiveShadow=u.receiveShadow;C.scene.add(a);C.objects[m]=a}}else{w=u.position;H=u.rotation;E=u.quaternion; z=u.scale;E=0;a=new THREE.Object3D;a.name=m;a.position.set(w[0],w[1],w[2]);if(E){a.quaternion.set(E[0],E[1],E[2],E[3]);a.useQuaternion=true}else a.rotation.set(H[0],H[1],H[2]);a.scale.set(z[0],z[1],z[2]);a.visible=u.visible!==void 0?u.visible:false;C.scene.add(a);C.objects[m]=a;C.empties[m]=a}}}function f(a){return function(b){C.geometries[a]=b;e();G=G-1;j.onLoadComplete();h()}}function g(a){return function(b){C.geometries[a]=b}}function h(){j.callbackProgress({totalModels:T,totalTextures:U,loadedModels:T- G,loadedTextures:U-i},C);j.onLoadProgress();G==0&&i==0&&b(C)}var j=this,l=THREE.Loader.prototype.extractUrlBase(c),k,p,m,o,q,n,r,u,t,y,s,w,H,E,z,v,A,J,K,R,P,D,M,G,i,T,U,C;D=a;c=new THREE.BinaryLoader;M=new THREE.JSONLoader;i=G=0;C={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{}};if(D.transform){a=D.transform.position;y=D.transform.rotation;v=D.transform.scale;a&&C.scene.position.set(a[0],a[1],a[2]);y&&C.scene.rotation.set(y[0],y[1], y[2]);v&&C.scene.scale.set(v[0],v[1],v[2]);if(a||y||v){C.scene.updateMatrix();C.scene.updateMatrixWorld()}}a=function(){i=i-1;h();j.onLoadComplete()};for(q in D.cameras){v=D.cameras[q];v.type=="perspective"?R=new THREE.PerspectiveCamera(v.fov,v.aspect,v.near,v.far):v.type=="ortho"&&(R=new THREE.OrthographicCamera(v.left,v.right,v.top,v.bottom,v.near,v.far));w=v.position;y=v.target;v=v.up;R.position.set(w[0],w[1],w[2]);R.target=new THREE.Vector3(y[0],y[1],y[2]);v&&R.up.set(v[0],v[1],v[2]);C.cameras[q]= R}for(o in D.lights){y=D.lights[o];q=y.color!==void 0?y.color:16777215;R=y.intensity!==void 0?y.intensity:1;if(y.type=="directional"){w=y.direction;s=new THREE.DirectionalLight(q,R);s.position.set(w[0],w[1],w[2]);s.position.normalize()}else if(y.type=="point"){w=y.position;s=y.distance;s=new THREE.PointLight(q,R,s);s.position.set(w[0],w[1],w[2])}else y.type=="ambient"&&(s=new THREE.AmbientLight(q));C.scene.add(s);C.lights[o]=s}for(n in D.fogs){o=D.fogs[n];o.type=="linear"?P=new THREE.Fog(0,o.near, o.far):o.type=="exp2"&&(P=new THREE.FogExp2(0,o.density));v=o.color;P.color.setRGB(v[0],v[1],v[2]);C.fogs[n]=P}if(C.cameras&&D.defaults.camera)C.currentCamera=C.cameras[D.defaults.camera];if(C.fogs&&D.defaults.fog)C.scene.fog=C.fogs[D.defaults.fog];v=D.defaults.bgcolor;C.bgColor=new THREE.Color;C.bgColor.setRGB(v[0],v[1],v[2]);C.bgColorAlpha=D.defaults.bgalpha;for(k in D.geometries){n=D.geometries[k];if(n.type=="bin_mesh"||n.type=="ascii_mesh"){G=G+1;j.onLoadStart()}}T=G;for(k in D.geometries){n= D.geometries[k];if(n.type=="cube"){J=new THREE.CubeGeometry(n.width,n.height,n.depth,n.segmentsWidth,n.segmentsHeight,n.segmentsDepth,null,n.flipped,n.sides);C.geometries[k]=J}else if(n.type=="plane"){J=new THREE.PlaneGeometry(n.width,n.height,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="sphere"){J=new THREE.SphereGeometry(n.radius,n.segmentsWidth,n.segmentsHeight);C.geometries[k]=J}else if(n.type=="cylinder"){J=new THREE.CylinderGeometry(n.topRad,n.botRad,n.height,n.radSegs, n.heightSegs);C.geometries[k]=J}else if(n.type=="torus"){J=new THREE.TorusGeometry(n.radius,n.tube,n.segmentsR,n.segmentsT);C.geometries[k]=J}else if(n.type=="icosahedron"){J=new THREE.IcosahedronGeometry(n.radius,n.subdivisions);C.geometries[k]=J}else if(n.type=="bin_mesh")c.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="ascii_mesh")M.load(d(n.url,D.urlBaseType),f(k));else if(n.type=="embedded_mesh"){n=D.embeds[n.id];n.metadata=D.metadata;n&&M.createModel(n,g(k),"")}}for(r in D.textures){k=D.textures[r]; if(k.url instanceof Array){i=i+k.url.length;for(n=0;n1){g=g[1];c[g]||(c[g]={start:Infinity,end:-Infinity});var h=c[g];if(eh.end)h.end=e;b||(b=g)}}a.firstAnimation=b}; THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];if(c){this.setFrameRange(c.start,c.end);this.duration=1E3*((c.end-c.start)/b);this.time=0}else console.warn("animation["+a+"] undefined")}; THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time=this.time+this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||this.time<0){this.direction=this.direction*-1;if(this.time>this.duration){this.time=this.duration;this.directionBackwards=true}if(this.time<0){this.time=0;this.directionBackwards=false}}}else{this.time=this.time%this.duration;if(this.time<0)this.time=this.time+this.duration}a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/ b),0,this.length-1);if(a!==this.currentKeyframe){this.morphTargetInfluences[this.lastKeyframe]=0;this.morphTargetInfluences[this.currentKeyframe]=1;this.morphTargetInfluences[a]=0;this.lastKeyframe=this.currentKeyframe;this.currentKeyframe=a}b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b}; THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon;THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){b===void 0&&(b=0);for(var b=Math.abs(b),c=0;c1){a.matrixWorldInverse.getInverse(a.matrixWorld);a=a.matrixWorldInverse;a=-(a.elements[2]*this.matrixWorld.elements[12]+a.elements[6]*this.matrixWorld.elements[13]+a.elements[10]*this.matrixWorld.elements[14]+a.elements[14]);this.LODs[0].object3D.visible=true;for(var b=1;b=this.LODs[b].visibleAtDistance){this.LODs[b-1].object3D.visible=false;this.LODs[b].object3D.visible=true}else break;for(;b>1);n=m.y*f+f-(o.offsetHeight>>1);o.style.left=q+"px";o.style.top=n+"px";o.style.zIndex=Math.abs(Math.floor((1-m.z)*d.far/d.near));g&&(o.style[g]="scale("+m.scale.x*e+","+m.scale.y*f+")")}}}}; THREE.CanvasRenderer=function(a){function b(a){if(t!=a)n.globalAlpha=t=a}function c(a){if(y!=a){switch(a){case THREE.NormalBlending:n.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:n.globalCompositeOperation="lighter"}y=a}}function d(a){if(s!=a)n.strokeStyle=s=a}function e(a){if(w!=a)n.fillStyle=w=a}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,j,l=new THREE.Projector,k=a.canvas!==void 0?a.canvas:document.createElement("canvas"),p,m,o,q,n=k.getContext("2d"), r=new THREE.Color(0),u=0,t=1,y=0,s=null,w=null,H=null,E=null,z=null,v,A,J,K,R=new THREE.RenderableVertex,P=new THREE.RenderableVertex,D,M,G,i,T,U,C,Y,F,ea,fa,ia,O=new THREE.Color,Q=new THREE.Color,Z=new THREE.Color,$=new THREE.Color,ha=new THREE.Color,Ma=[],Ka=[],Ra,La,Sa,Na,Kb,lb,gb,Lb,hb,Cb,Wa=new THREE.Rectangle,Ba=new THREE.Rectangle,xa=new THREE.Rectangle,$a=false,aa=new THREE.Color,Ta=new THREE.Color,Qa=new THREE.Color,oa=new THREE.Vector3,ib,Db,Sc,ab,pc,Bc,a=16;ib=document.createElement("canvas"); ib.width=ib.height=2;Db=ib.getContext("2d");Db.fillStyle="rgba(0,0,0,1)";Db.fillRect(0,0,2,2);Sc=Db.getImageData(0,0,2,2);ab=Sc.data;pc=document.createElement("canvas");pc.width=pc.height=a;Bc=pc.getContext("2d");Bc.translate(-a/2,-a/2);Bc.scale(a,a);a--;this.domElement=k;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){p=a;m=b;o=Math.floor(p/2);q=Math.floor(m/2);k.width=p;k.height=m;Wa.set(-o,-q,o,q);Ba.set(-o,-q,o,q);t=1;y= 0;z=E=H=w=s=null};this.setClearColor=function(a,b){r.copy(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.setClearColorHex=function(a,b){r.setHex(a);u=b!==void 0?b:1;Ba.set(-o,-q,o,q)};this.clear=function(){n.setTransform(1,0,0,-1,o,q);if(!Ba.isEmpty()){Ba.minSelf(Wa);Ba.inflate(2);u<1&&n.clearRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()));if(u>0){c(THREE.NormalBlending);b(1);e("rgba("+Math.floor(r.r*255)+","+Math.floor(r.g*255)+","+Math.floor(r.b* 255)+","+u+")");n.fillRect(Math.floor(Ba.getX()),Math.floor(Ba.getY()),Math.floor(Ba.getWidth()),Math.floor(Ba.getHeight()))}Ba.empty()}};this.render=function(a,k){function m(a){var b,c,d,e;aa.setRGB(0,0,0);Ta.setRGB(0,0,0);Qa.setRGB(0,0,0);b=0;for(c=a.length;b>1;m=k.height>>1;g=f.scale.x*o;j=f.scale.y*q;i=g*l;h=j*m;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(g,-j);n.translate(-l,-m);n.drawImage(k,0,0);n.restore()}}}else if(g instanceof THREE.ParticleCanvasMaterial){i=f.scale.x*o;h=f.scale.y*q;xa.set(a.x-i,a.y-h,a.x+i,a.y+h);if(Wa.intersects(xa)){d(g.color.getContextStyle()); e(g.color.getContextStyle());n.save();n.translate(a.x,a.y);n.rotate(-f.rotation);n.scale(i,h);g.program(n);n.restore()}}}function s(a,e,f,g){b(g.opacity);c(g.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(e.positionScreen.x,e.positionScreen.y);n.closePath();if(g instanceof THREE.LineBasicMaterial){a=g.linewidth;if(H!=a)n.lineWidth=H=a;a=g.linecap;if(E!=a)n.lineCap=E=a;a=g.linejoin;if(z!=a)n.lineJoin=z=a;d(g.color.getContextStyle());n.stroke();xa.inflate(g.linewidth* 2)}}function t(a,d,e,g,h,l,m,n){f.info.render.vertices=f.info.render.vertices+3;f.info.render.faces++;b(n.opacity);c(n.blending);D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;w(D,M,G,i,T,U);if(n instanceof THREE.MeshBasicMaterial)if(n.map){if(n.map.mapping instanceof THREE.UVMapping){Na=m.uvs[0];ad(D,M,G,i,T,U,Na[g].u,Na[g].v,Na[h].u,Na[h].v,Na[l].u,Na[l].v,n.map)}}else if(n.envMap){if(n.envMap.mapping instanceof THREE.SphericalReflectionMapping){a= k.matrixWorldInverse;oa.copy(m.vertexNormalsWorld[g]);Kb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[h]);gb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Lb=-(oa.x*a.elements[1]+oa.y*a.elements[5]+oa.z*a.elements[9])*0.5+0.5;oa.copy(m.vertexNormalsWorld[l]);hb=(oa.x*a.elements[0]+oa.y*a.elements[4]+oa.z*a.elements[8])*0.5+0.5;Cb=-(oa.x*a.elements[1]+oa.y* a.elements[5]+oa.z*a.elements[9])*0.5+0.5;ad(D,M,G,i,T,U,Kb,lb,gb,Lb,hb,Cb,n.envMap)}}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshLambertMaterial)if($a)if(!n.wireframe&&n.shading==THREE.SmoothShading&&m.vertexNormalsWorld.length==3){Q.r=Z.r=$.r=aa.r;Q.g=Z.g=$.g=aa.g;Q.b=Z.b=$.b=aa.b;p(j,m.v1.positionWorld,m.vertexNormalsWorld[0],Q);p(j,m.v2.positionWorld,m.vertexNormalsWorld[1],Z);p(j,m.v3.positionWorld,m.vertexNormalsWorld[2], $);Q.r=Math.max(0,Math.min(n.color.r*Q.r,1));Q.g=Math.max(0,Math.min(n.color.g*Q.g,1));Q.b=Math.max(0,Math.min(n.color.b*Q.b,1));Z.r=Math.max(0,Math.min(n.color.r*Z.r,1));Z.g=Math.max(0,Math.min(n.color.g*Z.g,1));Z.b=Math.max(0,Math.min(n.color.b*Z.b,1));$.r=Math.max(0,Math.min(n.color.r*$.r,1));$.g=Math.max(0,Math.min(n.color.g*$.g,1));$.b=Math.max(0,Math.min(n.color.b*$.b,1));ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else{O.r=aa.r;O.g= aa.g;O.b=aa.b;p(j,m.centroidWorld,m.normalWorld,O);O.r=Math.max(0,Math.min(n.color.r*O.r,1));O.g=Math.max(0,Math.min(n.color.g*O.g,1));O.b=Math.max(0,Math.min(n.color.b*O.b,1));n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}else n.wireframe?Mb(n.color,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(n.color);else if(n instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z, Ra,La);$.r=$.g=$.b=1-ac(e.positionScreen.z,Ra,La);ha.r=(Z.r+$.r)*0.5;ha.g=(Z.g+$.g)*0.5;ha.b=(Z.b+$.b)*0.5;Sa=Cc(Q,Z,$,ha);gc(D,M,G,i,T,U,0,0,1,0,0,1,Sa)}else if(n instanceof THREE.MeshNormalMaterial){O.r=hc(m.normalWorld.x);O.g=hc(m.normalWorld.y);O.b=hc(m.normalWorld.z);n.wireframe?Mb(O,n.wireframeLinewidth,n.wireframeLinecap,n.wireframeLinejoin):Eb(O)}}function u(a,d,e,g,h,l,n,m,o){f.info.render.vertices=f.info.render.vertices+4;f.info.render.faces++;b(m.opacity);c(m.blending);if(m.map||m.envMap){t(a, d,g,0,1,3,n,m,o);t(h,e,l,1,2,3,n,m,o)}else{D=a.positionScreen.x;M=a.positionScreen.y;G=d.positionScreen.x;i=d.positionScreen.y;T=e.positionScreen.x;U=e.positionScreen.y;C=g.positionScreen.x;Y=g.positionScreen.y;F=h.positionScreen.x;ea=h.positionScreen.y;fa=l.positionScreen.x;ia=l.positionScreen.y;if(m instanceof THREE.MeshBasicMaterial){y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshLambertMaterial)if($a)if(!m.wireframe&& m.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==4){Q.r=Z.r=$.r=ha.r=aa.r;Q.g=Z.g=$.g=ha.g=aa.g;Q.b=Z.b=$.b=ha.b=aa.b;p(j,n.v1.positionWorld,n.vertexNormalsWorld[0],Q);p(j,n.v2.positionWorld,n.vertexNormalsWorld[1],Z);p(j,n.v4.positionWorld,n.vertexNormalsWorld[3],$);p(j,n.v3.positionWorld,n.vertexNormalsWorld[2],ha);Q.r=Math.max(0,Math.min(m.color.r*Q.r,1));Q.g=Math.max(0,Math.min(m.color.g*Q.g,1));Q.b=Math.max(0,Math.min(m.color.b*Q.b,1));Z.r=Math.max(0,Math.min(m.color.r*Z.r,1));Z.g= Math.max(0,Math.min(m.color.g*Z.g,1));Z.b=Math.max(0,Math.min(m.color.b*Z.b,1));$.r=Math.max(0,Math.min(m.color.r*$.r,1));$.g=Math.max(0,Math.min(m.color.g*$.g,1));$.b=Math.max(0,Math.min(m.color.b*$.b,1));ha.r=Math.max(0,Math.min(m.color.r*ha.r,1));ha.g=Math.max(0,Math.min(m.color.g*ha.g,1));ha.b=Math.max(0,Math.min(m.color.b*ha.b,1));Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}else{O.r=aa.r;O.g=aa.g;O.b=aa.b;p(j,n.centroidWorld, n.normalWorld,O);O.r=Math.max(0,Math.min(m.color.r*O.r,1));O.g=Math.max(0,Math.min(m.color.g*O.g,1));O.b=Math.max(0,Math.min(m.color.b*O.b,1));y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else{y(D,M,G,i,T,U,C,Y);m.wireframe?Mb(m.color,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(m.color)}else if(m instanceof THREE.MeshNormalMaterial){O.r=hc(n.normalWorld.x);O.g=hc(n.normalWorld.y);O.b=hc(n.normalWorld.z);y(D,M,G,i,T,U,C, Y);m.wireframe?Mb(O,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):Eb(O)}else if(m instanceof THREE.MeshDepthMaterial){Ra=k.near;La=k.far;Q.r=Q.g=Q.b=1-ac(a.positionScreen.z,Ra,La);Z.r=Z.g=Z.b=1-ac(d.positionScreen.z,Ra,La);$.r=$.g=$.b=1-ac(g.positionScreen.z,Ra,La);ha.r=ha.g=ha.b=1-ac(e.positionScreen.z,Ra,La);Sa=Cc(Q,Z,$,ha);w(D,M,G,i,C,Y);gc(D,M,G,i,C,Y,0,0,1,0,0,1,Sa);w(F,ea,T,U,fa,ia);gc(F,ea,T,U,fa,ia,1,0,1,1,0,1,Sa)}}}function w(a,b,c,d,e,f){n.beginPath();n.moveTo(a,b);n.lineTo(c, d);n.lineTo(e,f);n.lineTo(a,b);n.closePath()}function y(a,b,c,d,e,f,g,i){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(e,f);n.lineTo(g,i);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,e){if(H!=b)n.lineWidth=H=b;if(E!=c)n.lineCap=E=c;if(z!=e)n.lineJoin=z=e;d(a.getContextStyle());n.stroke();xa.inflate(b*2)}function Eb(a){e(a.getContextStyle());n.fill()}function ad(a,b,c,d,f,g,i,h,j,k,l,m,p){if(p.image.width!=0){if(p.needsUpdate==true||Ma[p.id]==void 0){var o=p.wrapS==THREE.RepeatWrapping,q=p.wrapT== THREE.RepeatWrapping;Ma[p.id]=n.createPattern(p.image,o&&q?"repeat":o&&!q?"repeat-x":!o&&q?"repeat-y":"no-repeat");p.needsUpdate=false}e(Ma[p.id]);var o=p.offset.x/p.repeat.x,q=p.offset.y/p.repeat.y,Db=p.image.width*p.repeat.x,r=p.image.height*p.repeat.y,i=(i+o)*Db,h=(h+q)*r,c=c-a,d=d-b,f=f-a,g=g-b,j=(j+o)*Db-i,k=(k+q)*r-h,l=(l+o)*Db-i,m=(m+q)*r-h,o=j*m-l*k;if(o==0){if(Ka[p.id]===void 0){b=document.createElement("canvas");b.width=p.image.width;b.height=p.image.height;b=b.getContext("2d");b.drawImage(p.image, 0,0);Ka[p.id]=b.getImageData(0,0,p.image.width,p.image.height).data}b=Ka[p.id];i=(Math.floor(i)+Math.floor(h)*p.image.width)*4;O.setRGB(b[i]/255,b[i+1]/255,b[i+2]/255);Eb(O)}else{o=1/o;p=(m*c-k*f)*o;k=(m*d-k*g)*o;c=(j*f-l*c)*o;d=(j*g-l*d)*o;a=a-p*i-c*h;i=b-k*i-d*h;n.save();n.transform(p,k,c,d,a,i);n.fill();n.restore()}}}function gc(a,b,c,d,e,f,g,i,h,j,k,l,m){var p,o;p=m.width-1;o=m.height-1;g=g*p;i=i*o;c=c-a;d=d-b;e=e-a;f=f-b;h=h*p-g;j=j*o-i;k=k*p-g;l=l*o-i;o=1/(h*l-k*j);p=(l*c-j*e)*o;j=(l*d-j*f)* o;c=(h*e-k*c)*o;d=(h*f-k*d)*o;a=a-p*g-c*i;b=b-j*g-d*i;n.save();n.transform(p,j,c,d,a,b);n.clip();n.drawImage(m,0,0);n.restore()}function Cc(a,b,c,d){var e=~~(a.r*255),f=~~(a.g*255),a=~~(a.b*255),g=~~(b.r*255),i=~~(b.g*255),b=~~(b.b*255),h=~~(c.r*255),j=~~(c.g*255),c=~~(c.b*255),k=~~(d.r*255),l=~~(d.g*255),d=~~(d.b*255);ab[0]=e<0?0:e>255?255:e;ab[1]=f<0?0:f>255?255:f;ab[2]=a<0?0:a>255?255:a;ab[4]=g<0?0:g>255?255:g;ab[5]=i<0?0:i>255?255:i;ab[6]=b<0?0:b>255?255:b;ab[8]=h<0?0:h>255?255:h;ab[9]=j<0?0: j>255?255:j;ab[10]=c<0?0:c>255?255:c;ab[12]=k<0?0:k>255?255:k;ab[13]=l<0?0:l>255?255:l;ab[14]=d<0?0:d>255?255:d;Db.putImageData(Sc,0,0);Bc.drawImage(ib,0,0);return pc}function ac(a,b,c){a=(a-b)/(c-b);return a*a*(3-2*a)}function hc(a){a=(a+1)*0.5;return a<0?0:a>1?1:a}function Nb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;if(e!=0){e=1/Math.sqrt(e);c=c*e;d=d*e;b.x=b.x+c;b.y=b.y+d;a.x=a.x-c;a.y=a.y-d}}var Dc,bd,Ha,eb;this.autoClear?this.clear():n.setTransform(1,0,0,-1,o,q);f.info.render.vertices=0;f.info.render.faces= 0;g=l.projectScene(a,k,this.sortElements);h=g.elements;j=g.lights;($a=j.length>0)&&m(j);Dc=0;for(bd=h.length;Dc1?1:a}console.log("THREE.SVGRenderer",THREE.REVISION);var d=this,e,f,g,h=new THREE.Projector,j=document.createElementNS("http://www.w3.org/2000/svg","svg"),l,k,p,m,o,q,n,r,u=new THREE.Rectangle,t=new THREE.Rectangle,y=false,s=new THREE.Color,w=new THREE.Color,H=new THREE.Color,E=new THREE.Color, z,v=new THREE.Vector3,A=[],J=[],K,R,P,D=1;this.domElement=j;this.sortElements=this.sortObjects=this.autoClear=true;this.info={render:{vertices:0,faces:0}};this.setQuality=function(a){switch(a){case "high":D=1;break;case "low":D=0}};this.setSize=function(a,b){l=a;k=b;p=l/2;m=k/2;j.setAttribute("viewBox",-p+" "+-m+" "+l+" "+k);j.setAttribute("width",l);j.setAttribute("height",k);u.set(-p,-m,p,m)};this.clear=function(){for(;j.childNodes.length>0;)j.removeChild(j.childNodes[0])};this.render=function(k, l){var i,v,A,C;this.autoClear&&this.clear();d.info.render.vertices=0;d.info.render.faces=0;e=h.projectScene(k,l,this.sortElements);f=e.elements;g=e.lights;P=R=0;if(y=g.length>0){w.setRGB(0,0,0);H.setRGB(0,0,0);E.setRGB(0,0,0);i=0;for(v=g.length;i 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nlVector = normalize( lVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvarying vec3 vWorldPosition;\n#endif",lights_phong_vertex:"#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvWorldPosition = mPosition.xyz;\n#endif", lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngle[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngle[ i ] ) {\nspotEffect = pow( spotEffect, spotLightExponent[ i ] );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b=0)return a.geometry.materials[b.materialIndex]}function d(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?false:a&&a.shading!==void 0&&a.shading===THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function e(a){return a.map||a.lightMap||a instanceof THREE.ShaderMaterial?true:false}function f(a,b,c){var d,e,f,g,h=a.vertices;g=h.length; var j=a.colors,k=j.length,l=a.__vertexArray,m=a.__colorArray,n=a.__sortArray,p=a.verticesNeedUpdate,o=a.colorsNeedUpdate,q=a.__webglCustomAttributesList;if(c.sortParticles){xa.copy(Ba);xa.multiplySelf(c.matrixWorld);for(d=0;d=0;c--)a[c].object=== b&&a.splice(c,1)}function q(a,b){for(var c=a.length-1;c>=0;c--)a[c]===b&&a.splice(c,1)}function n(a,b,c,d,e){if(!d.program||d.needsUpdate){G.initMaterial(d,b,c,e);d.needsUpdate=false}if(d.morphTargets&&!e.__webglMorphTargetInfluences){e.__webglMorphTargetInfluences=new Float32Array(G.maxMorphTargets);for(var f=0,g=G.maxMorphTargets;f0};this.setSize=function(a,b){E.width=a;E.height=b;this.setViewport(0,0,E.width,E.height)};this.setViewport=function(a,b,c,d){Kb=a;lb=b;gb=c;Lb=d;i.viewport(Kb,lb,gb,Lb)};this.setScissor=function(a,b,c,d){i.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?i.enable(i.SCISSOR_TEST):i.disable(i.SCISSOR_TEST)};this.setClearColorHex=function(a,b){P.setHex(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.setClearColor=function(a, b){P.copy(a);D=b;i.clearColor(P.r,P.g,P.b,D)};this.getClearColor=function(){return P};this.getClearAlpha=function(){return D};this.clear=function(a,b,c){var d=0;if(a===void 0||a)d=d|i.COLOR_BUFFER_BIT;if(b===void 0||b)d=d|i.DEPTH_BUFFER_BIT;if(c===void 0||c)d=d|i.STENCIL_BUFFER_BIT;i.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)}; this.deallocateObject=function(a){if(a.__webglInit){a.__webglInit=false;delete a._modelViewMatrix;delete a._normalMatrix;delete a._normalMatrixArray;delete a._modelViewMatrixArray;delete a._objectMatrixArray;if(a instanceof THREE.Mesh)for(var b in a.geometry.geometryGroups){var c=a.geometry.geometryGroups[b];i.deleteBuffer(c.__webglVertexBuffer);i.deleteBuffer(c.__webglNormalBuffer);i.deleteBuffer(c.__webglTangentBuffer);i.deleteBuffer(c.__webglColorBuffer);i.deleteBuffer(c.__webglUVBuffer);i.deleteBuffer(c.__webglUV2Buffer); i.deleteBuffer(c.__webglSkinVertexABuffer);i.deleteBuffer(c.__webglSkinVertexBBuffer);i.deleteBuffer(c.__webglSkinIndicesBuffer);i.deleteBuffer(c.__webglSkinWeightsBuffer);i.deleteBuffer(c.__webglFaceBuffer);i.deleteBuffer(c.__webglLineBuffer);var d=void 0,e=void 0;if(c.numMorphTargets){d=0;for(e=c.numMorphTargets;d=0&&e.vertexNormalBuffer){i.bindBuffer(i.ARRAY_BUFFER, e.vertexNormalBuffer);i.vertexAttribPointer(a.normal,e.vertexNormalBuffer.itemSize,i.FLOAT,false,0,f[d].index*12)}if(a.uv>=0&&e.vertexUvBuffer)if(e.vertexUvBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexUvBuffer);i.vertexAttribPointer(a.uv,e.vertexUvBuffer.itemSize,i.FLOAT,false,0,f[d].index*8);i.enableVertexAttribArray(a.uv)}else i.disableVertexAttribArray(a.uv);if(a.color>=0&&e.vertexColorBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.vertexColorBuffer);i.vertexAttribPointer(a.color,e.vertexColorBuffer.itemSize, i.FLOAT,false,0,f[d].index*16)}i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.vertexIndexBuffer)}i.drawElements(i.TRIANGLES,f[d].count,i.UNSIGNED_SHORT,f[d].start*2);G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+f[d].count;G.info.render.faces=G.info.render.faces+f[d].count/3}}}};this.renderBuffer=function(a,b,c,d,e,f){if(d.visible!==false){var g,h,c=n(a,b,c,d,f),b=c.attributes,a=false,c=e.id*16777215+c.id*2+(d.wireframe?1:0);if(c!==F){F=c;a=true}if(!d.morphTargets&&b.position>=0){if(a){i.bindBuffer(i.ARRAY_BUFFER, e.__webglVertexBuffer);i.vertexAttribPointer(b.position,3,i.FLOAT,false,0,0)}}else if(f.morphTargetBase){c=d.program.attributes;if(f.morphTargetBase!==-1){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}else if(c.position>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglVertexBuffer);i.vertexAttribPointer(c.position,3,i.FLOAT,false,0,0)}if(f.morphTargetForcedOrder.length){g=0;var j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;g< d.numSupportedMorphTargets&&gk){l=m;k=h[l]}i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[l]);i.vertexAttribPointer(c["morphTarget"+g],3,i.FLOAT,false,0,0);if(d.morphNormals){i.bindBuffer(i.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[l]);i.vertexAttribPointer(c["morphNormal"+g],3,i.FLOAT,false,0,0)}f.__webglMorphTargetInfluences[g]=k;j[l]=1;k=-1;g++}}d.program.uniforms.morphTargetInfluences!==null&&i.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(a){if(e.__webglCustomAttributesList){g= 0;for(h=e.__webglCustomAttributesList.length;g=0){i.bindBuffer(i.ARRAY_BUFFER,c.buffer);i.vertexAttribPointer(b[c.buffer.belongsToAttribute],c.size,i.FLOAT,false,0,0)}}}if(b.color>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglColorBuffer);i.vertexAttribPointer(b.color,3,i.FLOAT,false,0,0)}if(b.normal>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglNormalBuffer);i.vertexAttribPointer(b.normal,3,i.FLOAT,false,0,0)}if(b.tangent>=0){i.bindBuffer(i.ARRAY_BUFFER, e.__webglTangentBuffer);i.vertexAttribPointer(b.tangent,4,i.FLOAT,false,0,0)}if(b.uv>=0)if(e.__webglUVBuffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUVBuffer);i.vertexAttribPointer(b.uv,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv)}else i.disableVertexAttribArray(b.uv);if(b.uv2>=0)if(e.__webglUV2Buffer){i.bindBuffer(i.ARRAY_BUFFER,e.__webglUV2Buffer);i.vertexAttribPointer(b.uv2,2,i.FLOAT,false,0,0);i.enableVertexAttribArray(b.uv2)}else i.disableVertexAttribArray(b.uv2);if(d.skinning&&b.skinVertexA>= 0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0){i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexABuffer);i.vertexAttribPointer(b.skinVertexA,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinVertexBBuffer);i.vertexAttribPointer(b.skinVertexB,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinIndicesBuffer);i.vertexAttribPointer(b.skinIndex,4,i.FLOAT,false,0,0);i.bindBuffer(i.ARRAY_BUFFER,e.__webglSkinWeightsBuffer);i.vertexAttribPointer(b.skinWeight,4,i.FLOAT,false,0,0)}}if(f instanceof THREE.Mesh){if(d.wireframe){d=d.wireframeLinewidth;if(d!==Na){i.lineWidth(d);Na=d}a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer);i.drawElements(i.LINES,e.__webglLineCount,i.UNSIGNED_SHORT,0)}else{a&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer);i.drawElements(i.TRIANGLES,e.__webglFaceCount,i.UNSIGNED_SHORT,0)}G.info.render.calls++;G.info.render.vertices=G.info.render.vertices+e.__webglFaceCount;G.info.render.faces=G.info.render.faces+e.__webglFaceCount/3}else if(f instanceof THREE.Line){f=f.type===THREE.LineStrip?i.LINE_STRIP:i.LINES;d=d.linewidth;if(d!==Na){i.lineWidth(d);Na=d}i.drawArrays(f,0,e.__webglLineCount);G.info.render.calls++}else if(f instanceof THREE.ParticleSystem){i.drawArrays(i.POINTS,0,e.__webglParticleCount);G.info.render.calls++;G.info.render.points=G.info.render.points+e.__webglParticleCount}else if(f instanceof THREE.Ribbon){i.drawArrays(i.TRIANGLE_STRIP,0,e.__webglVertexCount);G.info.render.calls++}}};this.render=function(a,b,c,d){var e,f,k,m,n=a.__lights, p=a.fog;Y=-1;Ta=true;if(b.parent===void 0){console.warn("DEPRECATED: Camera hasn't been added to a Scene. Adding it...");a.add(b)}this.autoUpdateScene&&a.updateMatrixWorld();if(!b._viewMatrixArray)b._viewMatrixArray=new Float32Array(16);if(!b._projectionMatrixArray)b._projectionMatrixArray=new Float32Array(16);b.matrixWorldInverse.getInverse(b.matrixWorld);b.matrixWorldInverse.flattenToArray(b._viewMatrixArray);b.projectionMatrix.flattenToArray(b._projectionMatrixArray);Ba.multiply(b.projectionMatrix, b.matrixWorldInverse);Wa.setFromMatrix(Ba);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);G.info.render.calls=0;G.info.render.vertices=0;G.info.render.faces=0;G.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);m=a.__webglObjects;d=0;for(e=m.length;d=0){t=q.geometry.materials[t];if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}}}else if(t)if(t.transparent){o.transparent=t;o.opaque=null}else{o.opaque=t;o.transparent=null}f.render=true;if(this.sortObjects)if(k.renderDepth)f.z=k.renderDepth;else{$a.copy(k.matrixWorld.getPosition());Ba.multiplyVector3($a);f.z=$a.z}}}this.sortObjects&& m.sort(g);m=a.__webglObjectsImmediate;d=0;for(e=m.length;d65535){A[z].counter=A[z].counter+1;y=A[z].hash+"_"+A[z].counter;r.geometryGroups[y]===void 0&&(r.geometryGroups[y]={faces3:[],faces4:[],materialIndex:v,vertices:0,numMorphTargets:C, numMorphNormals:D})}u instanceof THREE.Face3?r.geometryGroups[y].faces3.push(s):r.geometryGroups[y].faces4.push(s);r.geometryGroups[y].vertices=r.geometryGroups[y].vertices+w}r.geometryGroupsList=[];var E=void 0;for(E in r.geometryGroups){r.geometryGroups[E].id=fa++;r.geometryGroupsList.push(r.geometryGroups[E])}}for(j in l.geometryGroups){n=l.geometryGroups[j];if(!n.__webglVertexBuffer){var F=n;F.__webglVertexBuffer=i.createBuffer();F.__webglNormalBuffer=i.createBuffer();F.__webglTangentBuffer=i.createBuffer(); F.__webglColorBuffer=i.createBuffer();F.__webglUVBuffer=i.createBuffer();F.__webglUV2Buffer=i.createBuffer();F.__webglSkinVertexABuffer=i.createBuffer();F.__webglSkinVertexBBuffer=i.createBuffer();F.__webglSkinIndicesBuffer=i.createBuffer();F.__webglSkinWeightsBuffer=i.createBuffer();F.__webglFaceBuffer=i.createBuffer();F.__webglLineBuffer=i.createBuffer();var H=void 0,K=void 0;if(F.numMorphTargets){F.__webglMorphTargetsBuffers=[];H=0;for(K=F.numMorphTargets;H 0||O.faceVertexUvs.length>0)Q.__uvArray=new Float32Array(P*2);if(O.faceUvs.length>1||O.faceVertexUvs.length>1)Q.__uv2Array=new Float32Array(P*2)}if(J.geometry.skinWeights.length&&J.geometry.skinIndices.length){Q.__skinVertexAArray=new Float32Array(P*4);Q.__skinVertexBArray=new Float32Array(P*4);Q.__skinIndexArray=new Float32Array(P*4);Q.__skinWeightArray=new Float32Array(P*4)}Q.__faceArray=new Uint16Array(Z*3);Q.__lineArray=new Uint16Array(Y*2);var U=void 0,ha=void 0;if(Q.numMorphTargets){Q.__morphTargetsArrays= [];U=0;for(ha=Q.numMorphTargets;U0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexABuffer);i.bufferData(i.ARRAY_BUFFER,ra,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinVertexBBuffer);i.bufferData(i.ARRAY_BUFFER,sa,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinIndicesBuffer);i.bufferData(i.ARRAY_BUFFER,ta,Xa);i.bindBuffer(i.ARRAY_BUFFER,ca.__webglSkinWeightsBuffer);i.bufferData(i.ARRAY_BUFFER,ua,Xa)}}if(td&&Tc){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglColorBuffer);i.bufferData(i.ARRAY_BUFFER,Ga,Xa)}}if(sd&&Pa.hasTangents){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUVBuffer);i.bufferData(i.ARRAY_BUFFER,vc,Xa)}}if(gd&&Yc&&dd){I=0;for(S=ka.length;I0){i.bindBuffer(i.ARRAY_BUFFER,ca.__webglUV2Buffer);i.bufferData(i.ARRAY_BUFFER,wc,Xa)}}if(qd){I=0;for(S=ka.length;I0?"#define VERTEX_TEXTURES":"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+ c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG": "",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinVertexA;\nattribute vec4 skinVertexB;\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); k=["precision "+z+" float;","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",G.gammaInput?"#define GAMMA_INPUT":"",G.gammaOutput?"#define GAMMA_OUTPUT":"",G.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP": "",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); i.attachShader(r,t("fragment",k+n));i.attachShader(r,t("vertex",d+j));i.linkProgram(r);i.getProgramParameter(r,i.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+i.getProgramParameter(r,i.VALIDATE_STATUS)+", gl error ["+i.getError()+"]");r.uniforms={};r.attributes={};var s,d=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition","boneGlobalMatrices","morphTargetInfluences"];for(s in h)d.push(s);s=d;d=0;for(h=s.length;d=0&&i.enableVertexAttribArray(q.position); q.color>=0&&i.enableVertexAttribArray(q.color);q.normal>=0&&i.enableVertexAttribArray(q.normal);q.tangent>=0&&i.enableVertexAttribArray(q.tangent);if(a.skinning&&q.skinVertexA>=0&&q.skinVertexB>=0&&q.skinIndex>=0&&q.skinWeight>=0){i.enableVertexAttribArray(q.skinVertexA);i.enableVertexAttribArray(q.skinVertexB);i.enableVertexAttribArray(q.skinIndex);i.enableVertexAttribArray(q.skinWeight)}if(a.attributes)for(f in a.attributes)q[f]!==void 0&&q[f]>=0&&i.enableVertexAttribArray(q[f]);if(a.morphTargets){a.numSupportedMorphTargets= 0;r="morphTarget";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphTargets++}}}if(a.morphNormals){a.numSupportedMorphNormals=0;r="morphNormal";for(f=0;f=0){i.enableVertexAttribArray(q[s]);a.numSupportedMorphNormals++}}}a.uniformsList=[];for(e in a.uniforms)a.uniformsList.push([a.uniforms[e],e])};this.setFaceCulling=function(a,b){if(a){!b||b==="ccw"?i.frontFace(i.CCW):i.frontFace(i.CW);a==="back"?i.cullFace(i.BACK): a==="front"?i.cullFace(i.FRONT):i.cullFace(i.FRONT_AND_BACK);i.enable(i.CULL_FACE)}else i.disable(i.CULL_FACE)};this.setObjectFaces=function(a){if(ia!==a.doubleSided){a.doubleSided?i.disable(i.CULL_FACE):i.enable(i.CULL_FACE);ia=a.doubleSided}if(O!==a.flipSided){a.flipSided?i.frontFace(i.CW):i.frontFace(i.CCW);O=a.flipSided}};this.setDepthTest=function(a){if(Ma!==a){a?i.enable(i.DEPTH_TEST):i.disable(i.DEPTH_TEST);Ma=a}};this.setDepthWrite=function(a){if(Ka!==a){i.depthMask(a);Ka=a}};this.setBlending= function(a,b,c,d){if(a!==Q){switch(a){case THREE.NoBlending:i.disable(i.BLEND);break;case THREE.AdditiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.SRC_ALPHA,i.ONE);break;case THREE.SubtractiveBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:i.enable(i.BLEND);i.blendEquation(i.FUNC_ADD);i.blendFunc(i.ZERO,i.SRC_COLOR);break;case THREE.CustomBlending:i.enable(i.BLEND);break;default:i.enable(i.BLEND); i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD);i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)}Q=a}if(a===THREE.CustomBlending){if(b!==Z){i.blendEquation(H(b));Z=b}if(c!==$||d!==ha){i.blendFunc(H(c),H(d));$=c;ha=d}}else ha=$=Z=null};this.setTexture=function(a,b){if(a.needsUpdate){if(!a.__webglInit){a.__webglInit=true;a.__webglTexture=i.createTexture();G.info.memory.textures++}i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture);i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha);var c=a.image,d=(c.width&c.width-1)===0&&(c.height&c.height-1)===0,e=H(a.format),f=H(a.type);y(i.TEXTURE_2D,a,d);a instanceof THREE.DataTexture?i.texImage2D(i.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data):i.texImage2D(i.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&i.generateMipmap(i.TEXTURE_2D);a.needsUpdate=false;if(a.onUpdate)a.onUpdate()}else{i.activeTexture(i.TEXTURE0+b);i.bindTexture(i.TEXTURE_2D,a.__webglTexture)}};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){if(a.depthBuffer===void 0)a.depthBuffer=true;if(a.stencilBuffer===void 0)a.stencilBuffer=true;a.__webglTexture=i.createTexture();var c=(a.width&a.width-1)===0&&(a.height&a.height-1)===0,d=H(a.format),e=H(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];i.bindTexture(i.TEXTURE_CUBE_MAP,a.__webglTexture);y(i.TEXTURE_CUBE_MAP,a,c);for(var f=0;f<6;f++){a.__webglFramebuffer[f]=i.createFramebuffer();a.__webglRenderbuffer[f]=i.createRenderbuffer(); i.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=i.TEXTURE_CUBE_MAP_POSITIVE_X+f;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer[f]);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,h,g.__webglTexture,0);s(a.__webglRenderbuffer[f],a)}c&&i.generateMipmap(i.TEXTURE_CUBE_MAP)}else{a.__webglFramebuffer=i.createFramebuffer();a.__webglRenderbuffer=i.createRenderbuffer();i.bindTexture(i.TEXTURE_2D,a.__webglTexture);y(i.TEXTURE_2D,a,c);i.texImage2D(i.TEXTURE_2D, 0,d,a.width,a.height,0,d,e,null);d=i.TEXTURE_2D;i.bindFramebuffer(i.FRAMEBUFFER,a.__webglFramebuffer);i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,d,a.__webglTexture,0);s(a.__webglRenderbuffer,a);c&&i.generateMipmap(i.TEXTURE_2D)}b?i.bindTexture(i.TEXTURE_CUBE_MAP,null):i.bindTexture(i.TEXTURE_2D,null);i.bindRenderbuffer(i.RENDERBUFFER,null);i.bindFramebuffer(i.FRAMEBUFFER,null)}if(a){b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer;c=a.width;a=a.height;e=d=0}else{b=null; c=gb;a=Lb;d=Kb;e=lb}if(b!==C){i.bindFramebuffer(i.FRAMEBUFFER,b);i.viewport(d,e,c,a);C=b}hb=c;Cb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=c.wrapS!==void 0?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=c.wrapT!==void 0?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=c.magFilter!==void 0?c.magFilter:THREE.LinearFilter;this.minFilter=c.minFilter!==void 0?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=c.format!==void 0?c.format:THREE.RGBAFormat;this.type=c.type!==void 0?c.type: THREE.UnsignedByteType;this.depthBuffer=c.depthBuffer!==void 0?c.depthBuffer:true;this.stencilBuffer=c.stencilBuffer!==void 0?c.stencilBuffer:true;this.generateMipmaps=true}; THREE.WebGLRenderTarget.prototype.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.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;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=true};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; THREE.ColorUtils={adjustHSV:function(a,b,c,d){var e=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,e);e.h=THREE.Math.clamp(e.h+b,0,1);e.s=THREE.Math.clamp(e.s+c,0,1);e.v=THREE.Math.clamp(e.v+d,0,1);a.setHSV(e.h,e.s,e.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,e=a.b,f=Math.max(Math.max(c,d),e),g=Math.min(Math.min(c,d),e);if(g===f)g=c=0;else{var h=f-g,g=h/f,c=(c===f?(d-e)/h:d===f?2+(e-c)/h:4+(c-d)/h)/6;c<0&&(c=c+1);c>1&&(c=c-1)}b===void 0&&(b={h:0,s:0,v:0});b.h=c;b.s=g;b.v=f;return b}}; THREE.ColorUtils.__hsv={h:0,s:0,v:0}; THREE.GeometryUtils={merge:function(a,b){for(var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,j=a.faces,l=f.faces,k=a.faceVertexUvs[0],p=f.faceVertexUvs[0],m={},o=0;o1){d=1-d;e=1-e}f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.addSelf(h);h.copy(c);h.multiplyScalar(f);g.addSelf(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];return THREE.GeometryUtils.randomPointInTriangle(d,e,f)}if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;if(c)if(a._area1&&a._area2){c=a._area1;g=a._area2}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b);a._area1=c;a._area2=g}else{c=THREE.GeometryUtils.triangleArea(d,e,b);g=THREE.GeometryUtils.triangleArea(e,f,b)}return THREE.GeometryUtils.random()* (c+g)a?b(c,e-1):l[e] b||q>b||m>b){j=a.vertices.length;y=e.clone();s=e.clone();if(o>=q&&o>=m){l=l.clone();l.lerpSelf(k,0.5);y.a=f;y.b=j;y.c=h;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);y.vertexNormals[1].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);y.vertexColors[1].copy(f);s.vertexColors[0].copy(f)}e=0}else if(q>=o&&q>=m){l=k.clone();l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c= j;s.a=j;s.b=h;s.c=f;if(e.vertexNormals.length===3){f=e.vertexNormals[1].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f);s.vertexNormals[1].copy(e.vertexNormals[2]);s.vertexNormals[2].copy(e.vertexNormals[0])}if(e.vertexColors.length===3){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f);s.vertexColors[1].copy(e.vertexColors[2]);s.vertexColors[2].copy(e.vertexColors[0])}e=1}else{l=l.clone(); l.lerpSelf(p,0.5);y.a=f;y.b=g;y.c=j;s.a=j;s.b=g;s.c=h;if(e.vertexNormals.length===3){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[2],0.5);y.vertexNormals[2].copy(f);s.vertexNormals[0].copy(f)}if(e.vertexColors.length===3){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[2],0.5);y.vertexColors[2].copy(f);s.vertexColors[0].copy(f)}e=2}w.push(y,s);a.vertices.push(l);f=0;for(g=a.faceVertexUvs.length;fb||q>b||n>b||r>b){u=a.vertices.length;t=a.vertices.length+1;y=e.clone();s=e.clone();if(o>=q&&o>=n&&o>=r||n>=q&&n>=o&&n>=r){o=l.clone();o.lerpSelf(k,0.5);k=p.clone();k.lerpSelf(m,0.5);y.a=f;y.b=u;y.c=t;y.d=j;s.a=u;s.b=g;s.c=h;s.d=t;if(e.vertexNormals.length===4){f=e.vertexNormals[0].clone();f.lerpSelf(e.vertexNormals[1],0.5);g=e.vertexNormals[2].clone();g.lerpSelf(e.vertexNormals[3],0.5);y.vertexNormals[1].copy(f); y.vertexNormals[2].copy(g);s.vertexNormals[0].copy(f);s.vertexNormals[3].copy(g)}if(e.vertexColors.length===4){f=e.vertexColors[0].clone();f.lerpSelf(e.vertexColors[1],0.5);g=e.vertexColors[2].clone();g.lerpSelf(e.vertexColors[3],0.5);y.vertexColors[1].copy(f);y.vertexColors[2].copy(g);s.vertexColors[0].copy(f);s.vertexColors[3].copy(g)}e=0}else{o=k.clone();o.lerpSelf(p,0.5);k=m.clone();k.lerpSelf(l,0.5);y.a=f;y.b=g;y.c=u;y.d=t;s.a=t;s.b=u;s.c=h;s.d=j;if(e.vertexNormals.length===4){f=e.vertexNormals[1].clone(); f.lerpSelf(e.vertexNormals[2],0.5);g=e.vertexNormals[3].clone();g.lerpSelf(e.vertexNormals[0],0.5);y.vertexNormals[2].copy(f);y.vertexNormals[3].copy(g);s.vertexNormals[0].copy(g);s.vertexNormals[1].copy(f)}if(e.vertexColors.length===4){f=e.vertexColors[1].clone();f.lerpSelf(e.vertexColors[2],0.5);g=e.vertexColors[3].clone();g.lerpSelf(e.vertexColors[0],0.5);y.vertexColors[2].copy(f);y.vertexColors[3].copy(g);s.vertexColors[0].copy(g);s.vertexColors[1].copy(f)}e=1}w.push(y,s);a.vertices.push(o,k); f=0;for(g=a.faceVertexUvs.length;fe-1?e-1:p+1,q=k-1<0?0:k-1,n=k+1>d-1?d-1:k+1,r=[],u=[0,0,h[(p*d+k)*4]/255*b];r.push([-1,0,h[(p*d+q)*4]/255*b]);r.push([-1,-1,h[(m*d+q)*4]/255*b]);r.push([0, -1,h[(m*d+k)*4]/255*b]);r.push([1,-1,h[(m*d+n)*4]/255*b]);r.push([1,0,h[(p*d+n)*4]/255*b]);r.push([1,1,h[(o*d+n)*4]/255*b]);r.push([0,1,h[(o*d+k)*4]/255*b]);r.push([-1,1,h[(o*d+q)*4]/255*b]);m=[];q=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}); THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=false;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=false;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++){c=this.getPoint(e/a);f=f+c.distanceTo(d);b.push(f);d=c}return this.cacheArcLengths=b}; THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=true;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,j;g<=h;){d=Math.floor(g+(h-g)/2);j=c[d]-f;if(j<0)g=d+1;else if(j>0)h=d-1;else{h=d;break}}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)}; THREE.Curve.prototype.getTangent=function(a){var b=a-1.0E-4,a=a+1.0E-4;b<0&&(b=0);a>1&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().subSelf(b).normalize()};THREE.Curve.prototype.getTangentAt=function(a){return this.getTangent(this.getUtoTmapping(a))};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=new THREE.Curve;THREE.LineCurve.prototype.constructor=THREE.LineCurve; THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().subSelf(this.v1);b.multiplyScalar(a).addSelf(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().subSelf(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=new THREE.Curve;THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)};THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b}; THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=new THREE.Curve;THREE.CubicBezierCurve.prototype.constructor=THREE.CubicBezierCurve;THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)}; THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.SplineCurve=function(a){this.points=a==void 0?[]:a};THREE.SplineCurve.prototype=new THREE.Curve;THREE.SplineCurve.prototype.constructor=THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e=e-a;c[0]=a==0?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; THREE.ArcCurve=function(a,b,c,d,e,f){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=e;this.aClockwise=f};THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,e){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*e},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,e){var a=(c-a)*0.5,d=(d-b)*0.5,f=e*e;return(2*b-2*c+a+d)*e*f+(-3*b+3*c-2*a-d)*f+a*e+b}}; THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e,a=(d.length-1)*a;e=Math.floor(a);a=a-e;c[0]=e==0?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=a==void 0?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e=e-a;a=a+(a>0?0:(Math.floor(Math.abs(a)/d.length)+1)*d.length);c[0]=(a-1)%d.length;c[1]=a%d.length;c[2]=(a+1)%d.length;c[3]=(a+2)%d.length;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=false};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){}; THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b){b=c[a]-b;a=this.curves[a];b=1-b/a.getLength();return a.getPointAt(b)}a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=f.x;else if(f.xc)c=f.y;else if(f.y0){g=c[c.length-1]; o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b2(n,o,p,h);n=THREE.Shape.Utils.b2(n,q,m,j);c.push(new THREE.Vector2(g,n))}break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];j=f[5];p=f[0];m=f[1];l=f[2];k=f[3];if(c.length>0){g=c[c.length-1];o=g.x;q=g.y}else{g=this.actions[d-1].args;o=g[g.length-2];q=g[g.length-1]}for(f=1;f<=a;f++){n=f/a;g=THREE.Shape.Utils.b3(n,o,p,l,h);n=THREE.Shape.Utils.b3(n,q,m,k,j);c.push(new THREE.Vector2(g, n))}break;case THREE.PathActions.CSPLINE_THRU:g=this.actions[d-1].args;n=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;n=n.concat(f[0]);n=new THREE.SplineCurve(n);for(f=1;f<=g;f++)c.push(n.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];j=f[1];l=f[2];p=f[3];m=!!f[5];k=f[4]-p;o=a*2;for(f=1;f<=o;f++){n=f/o;m||(n=1-n);n=p+n*k;g=h+l*Math.cos(n);n=j+l*Math.sin(n);c.push(new THREE.Vector2(g,n))}}}d=c[c.length-1];Math.abs(d.x-c[0].x)<1.0E-10&&Math.abs(d.y-c[0].y)<1.0E-10&&c.splice(c.length- 1,1);b&&c.push(c[0]);return c};THREE.Path.prototype.transform=function(a,b){this.getBoundingBox();return this.getWrapPoints(this.getPoints(b),a)};THREE.Path.prototype.nltransform=function(a,b,c,d,e,f){var g=this.getPoints(),h,j,l,k,p;h=0;for(j=g.length;h=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;var n=[l[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(n);var r=[l[g],l[f],c[h]];m=THREE.FontUtils.Triangulate.area(r);o=h;k=g;h=h+1;g=g+ -1;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1;n=[l[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(n);r=[l[g],l[f],c[h]];r=THREE.FontUtils.Triangulate.area(r);if(p+m>n+r){h=o;g=k;h<0&&(h=h+c.length);h=h%c.length;g<0&&(g=g+l.length);g=g%l.length;e=h-1>=0?h-1:c.length-1;f=g-1>=0?g-1:l.length-1}p=c.slice(0,h);m=c.slice(h);o=l.slice(g);k=l.slice(0,g);f=[l[g],l[f],c[h]];q.push([l[g],c[h],c[e]]);q.push(f);c=p.concat(o).concat(k).concat(m)}return{shape:c, isolatedPts:q,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,false),f,g,h,j,l={};f=0;for(g=d.length;f1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+o);d=d<0?0:1}if(c==="pos"){c=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType=== THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=this.getPrevKeyWith("pos",o,g.index-1).pos;this.points[1]=e;this.points[2]=f;this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);c.x=e[0];c.y=e[1];c.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(c);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x, this.target.z);a.rotation.set(0,d,0)}}}else if(c==="rot")THREE.Quaternion.slerp(e,f,a.quaternion,d);else if(c==="scl"){c=a.scale;c.x=e[0]+(f[0]-e[0])*d;c.y=e[1]+(f[1]-e[1])*d;c.z=e[2]+(f[2]-e[2])*d}}}}if(this.JITCompile&&k[0][l]===void 0){this.hierarchy[0].updateMatrixWorld(true);for(o=0;oa.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];j=a[c[2]];l=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],j[0],l[0],e,c,g);d[1]=this.interpolate(f[1],h[1],j[1],l[1],e,c,g);d[2]=this.interpolate(f[2],h[2],j[2],l[2],e,c,g);return d}; THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=(c-a)*0.5;d=(d-b)*0.5;return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c0?c:0:c>=0?c:c+d.length;c>=0;c--)if(d[c][a]!==void 0)return d[c];return this.data.hierarchy[b].keys[d.length-1]}; THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=false;this.loop=this.isPaused=true;this.JITCompile=c!==void 0?c:true;a=0;for(b=this.hierarchy.length;a=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=true}}if(this.JITCompile&&f[0][e]===void 0){this.hierarchy[0].updateMatrixWorld(true); for(a=0;a=0?c:c+b.length;c>=0;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]}; THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90, 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var j=new THREE.PerspectiveCamera(90,1,a,b);j.up.set(0,-1,0);j.lookAt(new THREE.Vector3(0,0,-1));this.add(j);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=false;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace= 2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.generateMipmaps=m;c.activeCubeFace=5;a.render(b,j,c)}};THREE.CubeCamera.prototype=new THREE.Object3D;THREE.CubeCamera.prototype.constructor=THREE.CubeCamera; THREE.CombinedCamera=function(a,b,c,d,e,f,g){THREE.Camera.call(this);this.fov=c;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2;this.cameraO=new THREE.OrthographicCamera(a/-2,a/2,b/2,b/-2,f,g);this.cameraP=new THREE.PerspectiveCamera(c,a/b,d,e);this.zoom=1;this.toPerspective()};THREE.CombinedCamera.prototype=new THREE.Camera;THREE.CombinedCamera.prototype.constructor=THREE.CombinedCamera; THREE.CombinedCamera.prototype.toPerspective=function(){this.near=this.cameraP.near;this.far=this.cameraP.far;this.cameraP.fov=this.fov/this.zoom;this.cameraP.updateProjectionMatrix();this.projectionMatrix=this.cameraP.projectionMatrix;this.inPersepectiveMode=true;this.inOrthographicMode=false}; THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspect,b=(this.cameraP.near+this.cameraP.far)/2,b=Math.tan(this.fov/2)*b,a=2*b*a/2,b=b/this.zoom,a=a/this.zoom;this.cameraO.left=-a;this.cameraO.right=a;this.cameraO.top=b;this.cameraO.bottom=-b;this.cameraO.updateProjectionMatrix();this.near=this.cameraO.near;this.far=this.cameraO.far;this.projectionMatrix=this.cameraO.projectionMatrix;this.inPersepectiveMode=false;this.inOrthographicMode=true}; THREE.CombinedCamera.prototype.setSize=function(a,b){this.cameraP.aspect=a/b;this.left=-a/2;this.right=a/2;this.top=b/2;this.bottom=-b/2};THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.updateProjectionMatrix=function(){if(this.inPersepectiveMode)this.toPerspective();else{this.toPerspective();this.toOrthographic()}}; THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((b!==void 0?b:24)/(a*2))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=false}; THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=b!==void 0?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=false;this.lookVertical=true;this.autoForward=false;this.activeLook=true;this.heightSpeed=false;this.heightCoef=1;this.heightMin=0;this.constrainVertical=false;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX= this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=false;if(this.domElement===document){this.viewHalfX=window.innerWidth/2;this.viewHalfY=window.innerHeight/2}else{this.viewHalfX=this.domElement.offsetWidth/2;this.viewHalfY=this.domElement.offsetHeight/2;this.domElement.setAttribute("tabindex",-1)}this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward= true;break;case 2:this.moveBackward=true}this.mouseDragOn=true};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=false;break;case 2:this.moveBackward=false}this.mouseDragOn=false};this.onMouseMove=function(a){if(this.domElement===document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}}; this.onKeyDown=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=true;break;case 37:case 65:this.moveLeft=true;break;case 40:case 83:this.moveBackward=true;break;case 39:case 68:this.moveRight=true;break;case 82:this.moveUp=true;break;case 70:this.moveDown=true;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=false;break;case 37:case 65:this.moveLeft=false;break;case 40:case 83:this.moveBackward=false;break;case 39:case 68:this.moveRight= false;break;case 82:this.moveUp=false;break;case 70:this.moveDown=false}};this.update=function(a){var b=0;if(!this.freeze){if(this.heightSpeed){b=THREE.Math.clamp(this.object.position.y,this.heightMin,this.heightMax)-this.heightMin;this.autoSpeedFactor=a*b*this.heightCoef}else this.autoSpeedFactor=0;b=a*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.object.translateZ(-(b+this.autoSpeedFactor));this.moveBackward&&this.object.translateZ(b);this.moveLeft&&this.object.translateX(-b); this.moveRight&&this.object.translateX(b);this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b);a=a*this.lookSpeed;this.activeLook||(a=0);this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target,c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)* Math.sin(this.theta);b=1;this.constrainVertical&&(b=Math.PI/(this.verticalMax-this.verticalMin));this.lon=this.lon+this.mouseX*a;if(this.lookVertical)this.lat=this.lat-this.mouseY*a*b;this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=THREE.Math.mapLinear(this.phi,0,Math.PI,this.verticalMin,this.verticalMax);b=this.target;c=this.object.position;b.x=c.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=c.y+ 100*Math.cos(this.phi);b.z=c.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),false);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),false);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),false);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),false);this.domElement.addEventListener("keyup", c(this,this.onKeyUp),false)}; THREE.PathControls=function(a,b){function c(a){return(a=a*2)<1?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function e(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,u=0;f=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?a:a+g;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange; b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){if(this.domElement=== document){this.mouseX=a.pageX-this.viewHalfX;this.mouseY=a.pageY-this.viewHalfY}else{this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX;this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY}};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}), c=new THREE.CubeGeometry(10,10,20),g=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(g,b);a.position.set(0,10,0);this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else{this.animation=e(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.target);this.animationParent.add(this.object)}if(this.createDebugPath){var a= this.debugPath,b=this.spline,g=f(b,10),c=f(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),g=new THREE.Line(g,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));g.scale.set(1,1,1);a.add(g);c.scale.set(1,1,1);a.add(c);for(var g=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),o=0;o0){var b=this.getContainerDimensions(),c=b.size[0]/2,g=b.size[1]/2;this.moveState.yawLeft=-(a.pageX-b.offset[0]-c)/c;this.moveState.pitchDown=(a.pageY-b.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(a){a.preventDefault();a.stopPropagation();if(this.dragToLook){this.mouseStatus--;this.moveState.yawLeft=this.moveState.pitchDown=0}else switch(a.button){case 0:this.moveForward= false;break;case 2:this.moveBackward=false}this.updateRotationVector()};this.update=function(a){var b=a*this.movementSpeed,a=a*this.rollSpeed;this.object.translateX(this.moveVector.x*b);this.object.translateY(this.moveVector.y*b);this.object.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*a,this.rotationVector.y*a,this.rotationVector.z*a,1).normalize();this.object.quaternion.multiplySelf(this.tmpQuaternion);this.object.matrix.setPosition(this.object.position);this.object.matrix.setRotationFromQuaternion(this.object.quaternion); this.object.matrixWorldNeedsUpdate=true};this.updateMovementVector=function(){var a=this.moveState.forward||this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-a+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z= -this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!=document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),false);this.domElement.addEventListener("mousedown",c(this,this.mousedown),false);this.domElement.addEventListener("mouseup", c(this,this.mouseup),false);this.domElement.addEventListener("keydown",c(this,this.keydown),false);this.domElement.addEventListener("keyup",c(this,this.keyup),false);this.updateMovementVector();this.updateRotationVector()}; THREE.RollControls=function(a,b){this.object=a;this.domElement=b!==void 0?b:document;this.mouseLook=true;this.autoForward=false;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.object.matrixAutoUpdate=false;this.forward=new THREE.Vector3(0,0,1);this.roll=0;var c=new THREE.Vector3,d=new THREE.Vector3,e=new THREE.Vector3,f=new THREE.Matrix4,g=false,h=1,j=0,l=0,k=0,p=0,m=0,o=window.innerWidth/2,q=window.innerHeight/2;this.update=function(a){if(this.mouseLook){var b= a*this.lookSpeed;this.rotateHorizontally(b*p);this.rotateVertically(b*m)}b=a*this.movementSpeed;this.object.translateZ(-b*(j>0||this.autoForward&&!(j<0)?1:j));this.object.translateX(b*l);this.object.translateY(b*k);if(g)this.roll=this.roll+this.rollSpeed*a*h;if(this.forward.y>this.constrainVertical[1]){this.forward.y=this.constrainVertical[1];this.forward.normalize()}else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);g.copy(c.object.position).subSelf(c.target);e=c.object.up.clone().setLength(d.y);e.addSelf(c.object.up.clone().crossSelf(g).setLength(d.x));e.addSelf(g.setLength(d.z));return e};this.rotateCamera=function(){var a=Math.acos(h.dot(j)/h.length()/j.length());if(a){var b=(new THREE.Vector3).cross(h,j).normalize(),d=new THREE.Quaternion,a=a*c.rotateSpeed; d.setFromAxisAngle(b,-a);d.multiplyVector3(g);d.multiplyVector3(c.object.up);d.multiplyVector3(j);if(c.staticMoving)h=j;else{d.setFromAxisAngle(b,a*(c.dynamicDampingFactor-1));d.multiplyVector3(h)}}};this.zoomCamera=function(){var a=1+(k.y-l.y)*c.zoomSpeed;if(a!==1&&a>0){g.multiplyScalar(a);c.staticMoving?l=k:l.y=l.y+(k.y-l.y)*this.dynamicDampingFactor}};this.panCamera=function(){var a=m.clone().subSelf(p);if(a.lengthSq()){a.multiplyScalar(g.length()*c.panSpeed);var b=g.clone().crossSelf(c.object.up).setLength(a.x); b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.target.addSelf(b);c.staticMoving?p=m:p.addSelf(a.sub(m,p).multiplyScalar(c.dynamicDampingFactor))}};this.checkDistances=function(){if(!c.noZoom||!c.noPan){c.object.position.lengthSq()>c.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance);g.lengthSq()0){c.dispatchEvent(o);d.copy(c.object.position)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},false);this.domElement.addEventListener("mousemove",function(a){if(c.enabled){if(e){h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY);l=k=c.getMouseOnScreen(a.clientX,a.clientY);p= m=c.getMouseOnScreen(a.clientX,a.clientY);e=false}f!==-1&&(f===0&&!c.noRotate?j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?k=c.getMouseOnScreen(a.clientX,a.clientY):f===2&&!c.noPan&&(m=c.getMouseOnScreen(a.clientX,a.clientY)))}},false);this.domElement.addEventListener("mousedown",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();if(f===-1){f=a.button;f===0&&!c.noRotate?h=j=c.getMouseProjectionOnBall(a.clientX,a.clientY):f===1&&!c.noZoom?l=k=c.getMouseOnScreen(a.clientX, a.clientY):this.noPan||(p=m=c.getMouseOnScreen(a.clientX,a.clientY))}}},false);this.domElement.addEventListener("mouseup",function(a){if(c.enabled){a.preventDefault();a.stopPropagation();f=-1}},false);window.addEventListener("keydown",function(a){if(c.enabled&&f===-1){a.keyCode===c.keys[0]&&!c.noRotate?f=0:a.keyCode===c.keys[1]&&!c.noZoom?f=1:a.keyCode===c.keys[2]&&!c.noPan&&(f=2);f!==-1&&(e=true)}},false);window.addEventListener("keyup",function(){c.enabled&&f!==-1&&(f=-1)},false)}; THREE.CubeGeometry=function(a,b,c,d,e,f,g,h){function j(a,b,c,g,h,j,k,m){var n,p=d||1,o=e||1,q=h/2,r=j/2,t=l.vertices.length;if(a==="x"&&b==="y"||a==="y"&&b==="x")n="z";else if(a==="x"&&b==="z"||a==="z"&&b==="x"){n="y";o=f||1}else if(a==="z"&&b==="y"||a==="y"&&b==="z"){n="x";p=f||1}var i=p+1,u=o+1,y=h/p,C=j/o,Y=new THREE.Vector3;Y[n]=k>0?1:-1;for(h=0;h0){this.vertices.push(new THREE.Vector3(0, g,0));for(h=0;h0){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;ha&&(a=a+Math.PI*2);c=(b+a)/2;a=-Math.cos(c);c=-Math.sin(c);return new THREE.Vector2(a,c)}return d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function e(c,d){var e,f;for(F=c.length;--F>=0;){e=F;f=F-1;f<0&&(f= c.length-1);for(var g=0,h=m+k*2,g=0;g=0;D--){G=D/k;i=j*(1-G);M=l*Math.sin(G*Math.PI/2);F=0;for(G=P.length;F0)for(l=0;l2;){if(p--<=0){console.log("Warning, unable to triangulate polygon!");break}j=l;e<=j&&(j=0);l=j+1;e<=l&&(l=0);k=l+1;e<=k&&(k=0);var m;a:{m=a;var o=j,q=l,n=k,r=e,u=g,t=void 0,y=void 0,s=void 0,w=void 0,H=void 0, E=void 0,z=void 0,v=void 0,A=void 0,y=m[u[o]].x,s=m[u[o]].y,w=m[u[q]].x,H=m[u[q]].y,E=m[u[n]].x,z=m[u[n]].y;if(1.0E-10>(w-y)*(z-s)-(H-s)*(E-y))m=false;else{for(t=0;t=0&&R>=0&&D>=0){m=false;break a}}m=true}}if(m){f.push([a[g[j]], a[g[l]],a[g[k]]]);h.push([g[j],g[l],g[k]]);j=l;for(k=l+1;k1.0E-4){h.normalize();d=Math.acos(e[l-1].dot(e[l]));j.makeRotationAxis(h,d).multiplyVector3(f[l])}g[l].cross(e[l],f[l])}if(c){d=Math.acos(f[0].dot(f[b-1]));d=d/(b-1);e[0].dot(h.cross(f[0],f[b-1]))>0&&(d=-d);for(l=1;l0;)this.smooth(a)}; THREE.SubdivisionModifier.prototype.smooth=function(a){function b(){m.debug&&console.log.apply(console,arguments)}function c(){console&&console.log.apply(console,arguments)}function d(a,c,d,e,g,h,i){var j=new THREE.Face4(a,c,d,e,null,g.color,g.material);if(m.useOldVertexColors){j.vertexColors=[];for(var l,n,o,q=0;q<4;q++){o=h[q];l=new THREE.Color;l.setRGB(0,0,0);for(var r=0;r=y&&a1){var j=h[1];d[j]||(d[j]={start:Infinity,end:-Infinity});h=d[j];if(fh.end)h.end=f;c||(c=j)}}for(j in d){h=d[j];this.createAnimation(j,h.start,h.end,a)}this.firstAnimation=c}; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a]){a.direction=1;a.directionBackwards=false}};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a]){a.direction=-1;a.directionBackwards=true}};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c){c.fps=b;c.duration=(c.end-c.start)/c.fps}}; THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c){c.duration=b;c.fps=(c.end-c.start)/c.duration}};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];if(b){b.time=0;b.active=true}else console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=false}; THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||d.time<0){d.direction=d.direction*-1;if(d.time>d.duration){d.time=d.duration;d.directionBackwards=true}if(d.time<0){d.time=0;d.directionBackwards=false}}}else{d.time=d.time%d.duration;if(d.time<0)d.time=d.time+d.duration}var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/ e),0,d.length-1),g=d.weight;if(f!==d.currentFrame){this.morphTargetInfluences[d.lastFrame]=0;this.morphTargetInfluences[d.currentFrame]=1*g;this.morphTargetInfluences[f]=0;d.lastFrame=d.currentFrame;d.currentFrame=f}e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,e,f,g,h,j,l,k,p,m,o;this.init=function(q){b=q.context;c=q;d=new Float32Array(16);e=new Uint16Array(6);q=0;d[q++]=-1;d[q++]=-1;d[q++]=0;d[q++]=0;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]= 0;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=1;d[q++]=-1;d[q++]=1;d[q++]=0;d[q++]=1;q=0;e[q++]=0;e[q++]=1;e[q++]=2;e[q++]=0;e[q++]=2;e[q++]=3;f=b.createBuffer();g=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,f);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.bufferData(b.ELEMENT_ARRAY_BUFFER,e,b.STATIC_DRAW);h=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST); b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);if(b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0){l=false;k=a(THREE.ShaderFlares.lensFlare)}else{l=true;k=a(THREE.ShaderFlares.lensFlareVertexTexture)}p={};m={};p.vertex=b.getAttribLocation(k,"position");p.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, "color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=false};this.render=function(a,d,e,u){var a=a.__webglFlares,t=a.length;if(t){var y=new THREE.Vector3,s=u/e,w=e*0.5,H=u*0.5,E=16/u,z=new THREE.Vector2(E*s,E),v=new THREE.Vector3(1,1,0),A=new THREE.Vector2(1,1),J=m,E=p;b.useProgram(k);if(!o){b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);o=true}b.uniform1i(J.occlusionMap,0);b.uniform1i(J.map, 1);b.bindBuffer(b.ARRAY_BUFFER,f);b.vertexAttribPointer(E.vertex,2,b.FLOAT,false,16,0);b.vertexAttribPointer(E.uv,2,b.FLOAT,false,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,g);b.disable(b.CULL_FACE);b.depthMask(false);var K,R,P,D,M;for(K=0;K0&&A.x0&& A.y0.001&&M.scale>0.001){v.x=M.x;v.y=M.y;v.z=M.z;E=M.size*M.scale/u;z.x=E*s;z.y=E;b.uniform3f(J.screenPosition,v.x,v.y,v.z);b.uniform2f(J.scale,z.x,z.y);b.uniform1f(J.rotation,M.rotation);b.uniform1f(J.opacity,M.opacity); b.uniform3f(J.color,M.color.r,M.color.g,M.color.b);c.setBlending(M.blending,M.blendEquation,M.blendSrc,M.blendDst);c.setTexture(M.texture,1);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}}}}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(true)}}}; THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,f=new THREE.Matrix4,g=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:true});c._shadowPass=true;d._shadowPass=true};this.render= function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(j,l){var k,p,m,o,q,n,r,u,t,y=[];o=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);b.shadowMapCullFrontFaces?a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(true);k=0;for(p=j.__lights.length;kh.x)h.x=u.x;if(u.yh.y)h.y=u.y;if(u.zh.z)h.z=u.z}o.left=g.x;o.right=h.x;o.top=h.y;o.bottom=g.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;q=m.shadowCamera;q.position.copy(m.matrixWorld.getPosition());q.lookAt(m.target.matrixWorld.getPosition());q.updateMatrixWorld();q.matrixWorldInverse.getInverse(q.matrixWorld); if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible;m.shadowCameraVisible&&m.cameraHelper.update();n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(q.projectionMatrix);n.multiplySelf(q.matrixWorldInverse);if(!q._viewMatrixArray)q._viewMatrixArray=new Float32Array(16);if(!q._projectionMatrixArray)q._projectionMatrixArray=new Float32Array(16);q.matrixWorldInverse.flattenToArray(q._viewMatrixArray);q.projectionMatrix.flattenToArray(q._projectionMatrixArray);f.multiply(q.projectionMatrix, q.matrixWorldInverse);e.setFromMatrix(f);b.setRenderTarget(o);b.clear();t=j.__webglObjects;m=0;for(o=t.length;m= maxW && ratio <= 1 ){ curW = maxW; curH = maxW * ratio; }else if(curH >= maxH){ curH = maxH; curW = maxH / ratio; } return { width: curW, height: curH }; } // callback once the image is loaded var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onLoad = __bind(function(){ // init the canvas var canvas = document.createElement('canvas'); canvas.width = dstW; canvas.height = dstH; var ctx = canvas.getContext('2d'); // TODO is this needed ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // scale the image while preserving the aspect var scaled = cpuScaleAspect(canvas.width, canvas.height, image.width, image.height); // actually draw the image on canvas var offsetX = (canvas.width - scaled.width )/2; var offsetY = (canvas.height - scaled.height)/2; ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height); // dump the canvas to an URL var mimetype = "image/png"; var newDataUrl = canvas.toDataURL(mimetype); // notify the url to the caller callback && callback(newDataUrl) }, this); // Create new Image object var image = new Image(); image.onload = onLoad; image.src = srcUrl; } // Super cooked function: THREEx.Screenshot.bindKey(renderer) // and you are done to get screenshot on your demo /** * Bind a key to renderer screenshot */ var bindKey = function(renderer, opts){ // handle parameters opts = opts || {}; var charCode = opts.charCode || 'p'.charCodeAt(0); var width = opts.width; var height = opts.height; var callback = opts.callback || function(url){ window.open(url, "name-"+Math.random()); }; // callback to handle keypress var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var onKeyPress = __bind(function(event){ // return now if the KeyPress isnt for the proper charCode if( event.which !== charCode ) return; // get the renderer output var dataUrl = this.toDataURL(renderer); if( width === undefined && height === undefined ){ callback( dataUrl ) }else{ // resize it and notify the callback // * resize == async so if callback is a window open, it triggers the pop blocker _aspectResize(dataUrl, width, height, callback); } }, this); // listen to keypress // NOTE: for firefox it seems mandatory to listen to document directly document.addEventListener('keypress', onKeyPress, false); return { unbind : function(){ document.removeEventListener('keypress', onKeyPress, false); } }; } // export it THREEx.Screenshot = { toDataURL : toDataURL, bindKey : bindKey }; })(); ================================================ FILE: TJunctions/vendor/threex/docs/THREEx.CelShader.html ================================================ THREEx.CelShader.js

THREEx.CelShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

cel shader from ro.me - http://www.ro.me/tech/cel-shader - Apache License 2.0

THREEx.UniformsLib['cel']	= {
      "uDirLightPos"		: { type: "v3", value: new THREE.Vector3(1,0,0) },
      "uDirLightColor"		: { type: "c" , value: new THREE.Color( 0xeeeeee ) },
      "uAmbientLightColor"	: { type: "c" , value: new THREE.Color( 0x050505 ) },
      "uBaseColor"		: { type: "c" , value: new THREE.Color( 0xff0000 ) }
};

THREEx.ShaderLib['cel']	= {
	vertexShader:	[
		"varying vec3 vNormal;",
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
		      
			"vNormal = normalize( normalMatrix * normal );",
		      
			"vec3 I = mPosition.xyz - cameraPosition;",
			"vRefract = refract( normalize( I ), nWorld, 1.02 );",
		      
			"gl_Position = projectionMatrix * mvPosition;",
		
		"}"		
	].join( "\n" ),
	fragmentShader: [
		"uniform vec3 uBaseColor;",
		
		"uniform vec3 uDirLightPos;",
		"uniform vec3 uDirLightColor;",
		
		"uniform vec3 uAmbientLightColor;",
		
		"varying vec3 vNormal;",
		
		"varying vec3 vRefract;",
		
		"void main() {",
		
			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
		      
			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
			"intensity += length(lightWeighting) * 0.2;",
		      
			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
			"intensity = intensity * 0.2 + 0.3;",
		      
			"if ( intensity < 0.50 ) {",
		      
			  "gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
		      
			"} else {",
		      
			  "gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
		      
			"}",
		
		"}"		
	].join( "\n" )
};

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.CubeMap.html ================================================ THREEx.CubeMap.js ================================================ FILE: TJunctions/vendor/threex/docs/THREEx.DeviceOrientationState.html ================================================ THREEx.DeviceOrientationState.js

THREEx.DeviceOrientationState.js

/** @namespace */
var THREEx	= THREEx 		|| {};

THREEx.DeviceOrientationState	= function()
{

to store the current state

	this._state	= { x: 0, y: 0, z: 0 };

	this._$callback	= function(event){ this._onDeviceOrientation(event); }.bind(this);
	

bind events - spec http://dev.w3.org/geo/api/spec-source-orientation.html

	window.addEventListener('deviceorientation', this._$callback);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.DeviceOrientationState.prototype.destroy	= function()
{

unbind events

	window.removeEventListener('deviceorientation', this._$callback);
}

/**
 * to process the keyboard dom event
*/
THREEx.DeviceOrientationState.prototype._onDeviceOrientation	= function(event)
{
	this._state.x	= (!event.alpha ? 0 : event.alpha) * Math.PI / 180;
	this._state.y	= (!event.beta  ? 0 : event.beta ) * Math.PI / 180;
	this._state.z	= (!event.gamma ? 0 : event.gamma) * Math.PI / 180;
}


THREEx.DeviceOrientationState.prototype.angleX	= function()
{
	return this._state.x;
}

THREEx.DeviceOrientationState.prototype.angleY	= function()
{
	return this._state.y;
}

THREEx.DeviceOrientationState.prototype.angleZ	= function()
{
	return this._state.z;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.FullScreen.html ================================================ THREEx.FullScreen.js

THREEx.FullScreen.js

This THREEx helper makes it easy to handle the fullscreen API * it hides the prefix for each browser * it hides the little discrepencies of the various vendor API * at the time of this writing (nov 2011) it is available in firefox nightly, webkit nightly and chrome stable.

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.FullScreen	= THREEx.FullScreen	|| {};

/**
 * test if it is possible to have fullscreen
 * 
 * @returns {Boolean} true if fullscreen API is available, false otherwise
*/
THREEx.FullScreen.available	= function()
{
	return this._hasWebkitFullScreen || this._hasMozFullScreen;
}

/**
 * test if fullscreen is currently activated
 * 
 * @returns {Boolean} true if fullscreen is currently activated, false otherwise
*/
THREEx.FullScreen.activated	= function()
{
	if( this._hasWebkitFullScreen ){
		return document.webkitIsFullScreen;
	}else if( this._hasMozFullScreen ){
		return document.mozFullScreen;
	}else{
		console.assert(false);
	}
}

/**
 * Request fullscreen on a given element
 * @param {DomElement} element to make fullscreen. optional. default to document.body
*/
THREEx.FullScreen.request	= function(element)
{
	element	= element	|| document.body;
	if( this._hasWebkitFullScreen ){
		element.webkitRequestFullScreen();
	}else if( this._hasMozFullScreen ){
		element.mozRequestFullScreen();
	}else{
		console.assert(false);
	}
}

/**
 * Cancel fullscreen
*/
THREEx.FullScreen.cancel	= function()
{
	if( this._hasWebkitFullScreen ){
		document.webkitCancelFullScreen();
	}else if( this._hasMozFullScreen ){
		document.mozCancelFullScreen();
	}else{
		console.assert(false);
	}
}

internal functions to know which fullscreen API implementation is available

THREEx.FullScreen._hasWebkitFullScreen	= 'webkitCancelFullScreen' in document	? true : false;	
THREEx.FullScreen._hasMozFullScreen	= 'mozCancelFullScreen' in document	? true : false;	

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.GeometryUtils.html ================================================ THREEx.GeometryUtils.js

THREEx.GeometryUtils.js

This THREEx helper provide various basic functions for THREE.Geometry. It is able to scale, translate, center a geometry. Other functions may be added soon. The API is chained for convenience.

Scale

To make the geometry twice larger in y

var scale = new THREE.Vector3(1,2,1); THREEx.GeometryUtils.scale(geometry, scale);

Translate

To make the geometry move 100 further in x

var translation = new THREE.Vector3(100,0,0); THREEx.GeometryUtils.translate(geometry, translation);

Center

To center the geometry on its middle point

THREEx.GeometryUtils.center(geometry);

middlePoint

To compute the middle point of a geometry

THREEx.GeometryUtils.middlePoint(geometry);

Code

/** @namespace */
var THREEx		= THREEx 		|| {};
THREEx.GeometryUtils	= THREEx.GeometryUtils	|| {};

TODO - chained API - possibility a matrix to reduce computation ?

/**
 * Change the scale of a geometry
 * 
 * @params {THREE.Geometry} geometry the geometry to compute on
 * @params {THREE.Vector3} scale the middlepoint of the geometry
*/
THREEx.GeometryUtils.scale	= function(geometry, scale)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.multiplySelf(scale); 
	}
	

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

THREEx.GeometryUtils.translate	= function(geometry, delta)
{

change all geometry.vertices

	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		vertex.position.addSelf(delta); 
	}

mark the vertices as dirty

	geometry.__dirtyVertices = true;

return this, to get chained API

	return this;
}

/**
 * Compute the "middlePoint" aka the point at the middle of the boundingBox
 * 
 * @params {THREE.Geometry} the geometry to compute on
 * @returns {THREE.Vector3} the middlepoint of the geometry
*/
THREEx.GeometryUtils.middlePoint	= function(geometry)
{

compute bounding box

	geometry.computeBoundingBox();

compute middle

	var middle	= new THREE.Vector3()
	middle.x	= ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] ) / 2;
	middle.y	= ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] ) / 2;
	middle.z	= ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] ) / 2;

return the just computed middle

	return middle;
}

/**
 * Center the geometry on its middlepoint
*/
THREEx.GeometryUtils.center	= function(geometry, noX, noY, noZ)
{

compute delta

	var delta	= this.middlePoint(geometry).negate();
	if( noX )	delta.x	= 0;
	if( noY )	delta.y	= 0;
	if( noZ )	delta.z	= 0;

	return this.translate(geometry, delta)
}

/**
 * Initial version of attachement
 * - geometry2 is the one which is moved
 * - TODO make something more flexible... especially on the attachement config
*/
THREEx.GeometryUtils.attachRightLeft	= function(geometry1, geometry2, delta)
{
	if( delta === undefined )	delta	= 0;

compute bounding box

	geometry1.computeBoundingBox();
	geometry2.computeBoundingBox();
	
	var maxX1	= geometry1.boundingBox.x[ 1 ]
	var minX2	= geometry2.boundingBox.x[ 0 ];

	var vector	= new THREE.Vector3();
	vector.x	= maxX1+ (-minX2) + delta;

	this.translate(geometry2, vector);
	
	return this;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.GeometryWobble.html ================================================ THREEx.GeometryWobble.js

THREEx.GeometryWobble.js

var THREEx		= THREEx || {};

THREEx.GeometryWobble	= {};

Geometry Wobble based on paul lewis / areotwist - http://lab.aerotwist.com/webgl/undulating-monkey/

THREEx.GeometryWobble.init	= function(geometry)
{
	for(var i = 0; i < geometry.vertices.length; i++){
		var vertex	= geometry.vertices[i];
		vertex.originalPosition	= vertex.position.clone();
		vertex.dirVector	= vertex.position.clone().normalize();
	}
	geometry.dynamic	= true;
	
	this.cpuAxis(geometry, 'y')
}

THREEx.GeometryWobble.cpuAxis	= function(geometry, type, factor)
{
	if( type === undefined )	type	= 'x';
	if( factor === undefined )	factor	= 0.2;
	
	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];

Note: may need more axis ?

		if( type === 'x' )	vertex.axisValue	= vertex.originalPosition.x * factor;
		else if( type === 'y' )	vertex.axisValue	= vertex.originalPosition.y * factor;
		else if( type === 'z' )	vertex.axisValue	= vertex.originalPosition.z * factor;
		else	console.assert(false);
	}
}

THREEx.GeometryWobble.Animate	= function(geometry, phase, magnitude)
{
	if( phase === undefined )	phase		= 0;
	if( magnitude === undefined )	magnitude	= 0.2;
	
	if( typeof magnitude === "number" )	magnitude	= new THREE.Vector3(magnitude, magnitude, magnitude)


	for(var i = 0; i < geometry.vertices.length; i++) {
		var vertex	= geometry.vertices[i];
		var vertexPhase	= Math.cos(phase + vertex.axisValue);
		
		vertex.position.x = vertex.originalPosition.x + vertexPhase * vertex.dirVector.x * magnitude.x;
		vertex.position.y = vertex.originalPosition.y + vertexPhase * vertex.dirVector.y * magnitude.y;
		vertex.position.z = vertex.originalPosition.z + vertexPhase * vertex.dirVector.z * magnitude.z;
	}
	
	geometry.__dirtyVertices = true;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.KeyboardState.html ================================================ THREEx.KeyboardState.js

THREEx.KeyboardState.js

THREEx.KeyboardState.js keep the current state of the keyboard. It is possible to query it at any time. No need of an event. This is particularly convenient in loop driven case, like in 3D demos or games.

Usage

Step 1: Create the object

var keyboard = new THREEx.KeyboardState();

Step 2: Query the keyboard state

This will return true if shift and A are pressed, false otherwise

keyboard.pressed("shift+A")

Step 3: Stop listening to the keyboard

keyboard.destroy()

NOTE: this library may be nice as standaline. independant from three.js - rename it keyboardForGame

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * - NOTE: it would be quite easy to push event-driven too
 *   - microevent.js for events handling
 *   - in this._onkeyChange, generate a string from the DOM event
 *   - use this as event name
*/
THREEx.KeyboardState	= function()
{

to store the current state

	this.keyCodes	= {};
	this.modifiers	= {};
	

create callback to bind/unbind keyboard events

	var self	= this;
	this._onKeyDown	= function(event){ self._onKeyChange(event, true); };
	this._onKeyUp	= function(event){ self._onKeyChange(event, false);};

bind keyEvents

	document.addEventListener("keydown", this._onKeyDown, false);
	document.addEventListener("keyup", this._onKeyUp, false);
}

/**
 * To stop listening of the keyboard events
*/
THREEx.KeyboardState.prototype.destroy	= function()
{

unbind keyEvents

	document.removeEventListener("keydown", this._onKeyDown, false);
	document.removeEventListener("keyup", this._onKeyUp, false);
}

THREEx.KeyboardState.MODIFIERS	= ['shift', 'ctrl', 'alt', 'meta'];
THREEx.KeyboardState.ALIAS	= {
	'left'		: 37,
	'up'		: 38,
	'right'		: 39,
	'down'		: 40,
	'space'		: 32,
	'pageup'	: 33,
	'pagedown'	: 34,
	'tab'		: 9
};

/**
 * to process the keyboard dom event
*/
THREEx.KeyboardState.prototype._onKeyChange	= function(event, pressed)
{

log to debug console.log("onKeyChange", event, pressed, event.keyCode, event.shiftKey, event.ctrlKey, event.altKey, event.metaKey)

update this.keyCodes

	var keyCode		= event.keyCode;
	this.keyCodes[keyCode]	= pressed;

update this.modifiers

	this.modifiers['shift']= event.shiftKey;
	this.modifiers['ctrl']	= event.ctrlKey;
	this.modifiers['alt']	= event.altKey;
	this.modifiers['meta']	= event.metaKey;
}

/**
 * query keyboard state to know if a key is pressed of not
 *
 * @param {String} keyDesc the description of the key. format : modifiers+key e.g shift+A
 * @returns {Boolean} true if the key is pressed, false otherwise
*/
THREEx.KeyboardState.prototype.pressed	= function(keyDesc)
{
	var keys	= keyDesc.split("+");
	for(var i = 0; i < keys.length; i++){
		var key		= keys[i];
		var pressed;
		if( THREEx.KeyboardState.MODIFIERS.indexOf( key ) !== -1 ){
			pressed	= this.modifiers[key];
		}else if( Object.keys(THREEx.KeyboardState.ALIAS).indexOf( key ) != -1 ){
			pressed	= this.keyCodes[ THREEx.KeyboardState.ALIAS[key] ];
		}else {
			pressed	= this.keyCodes[key.toUpperCase().charCodeAt(0)]
		}
		if( !pressed)	return false;
	};
	return true;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.LogoTurtle.html ================================================ THREEx.LogoTurtle.js

THREEx.LogoTurtle.js

/** @namespace */
var THREEx	= THREEx	|| {};

TODO should those relative polar coord function be INSIDE path already ?

THREEx.LogoTurtle	= function()
{
	this._penX	= 0;
	this._penY	= 0;
	this._angle	= 0;
	this._vectors	= [];
}

THREEx.LogoTurtle.create	= function()
{
	return new THREEx.LogoTurtle()
}

THREEx.LogoTurtle.prototype.turn	= function(rotation)
{
	this._angle	+= rotation;
	return this;	
}

THREEx.LogoTurtle.prototype.moveTo	= function(x, y)
{
	this._penX	= x * Math.cos(this._angle) - y * Math.sin(this._angle);
	this._penY	= x * Math.sin(this._angle) + y * Math.cos(this._angle);
	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );
	return this;
}

THREEx.LogoTurtle.prototype.forward	= function(distance)
{
	this._penX	+= Math.cos(this._angle) * distance;
	this._penY	+= Math.sin(this._angle) * distance;

	this._vectors.push( new THREE.Vector2(this._penX, this._penY) );	
	
	return this;
}

THREEx.LogoTurtle.prototype.points	= function()
{
	return this._vectors;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.PlasmaShader.html ================================================ THREEx.PlasmaShader.js

THREEx.PlasmaShader.js

define namespaces

var THREEx		= THREEx || {};
THREEx.ShaderLib	= THREEx.ShaderLib	|| {};
THREEx.UniformsLib	= THREEx.UniformsLib	|| {};

THREEx.UniformsLib['plasma']	= {
	time	: { type : "f", value:  0.0 },
	scale	: { type : "f", value:  1.0 },
	rotation: { type : "f", value:  0.0 },
	opacity	: { type : "f", value:  1.0 },

	c0	: { type : "f", value:  5.0 },
	c1	: { type : "f", value:  3.0 },
	c2	: { type : "f", value: 11.0 },
	c3	: { type : "f", value:  7.0 },
	c4	: { type : "f", value:  9.0 },
	c5	: { type : "f", value:  3.0 }	
};

THREEx.ShaderLib['plasma']	= {
	vertexShader:	[
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		"varying vec2 vUv;",
		"void main(){",
			"vUv	= uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);",
		"}"
	].join( "\n" ),
	fragmentShader: [
		"#ifdef GL_ES",
			"precision highp float;",
		"#endif",
		
		"varying vec2 vUv;",
		"uniform float time;",
		"uniform float scale;",
		"uniform float rotation;",
		"uniform float opacity;",
		"uniform float c0, c1, c2, c3, c4, c5;",

todo zoom and rotation of vec2 point

		"vec2 rotoZoom(const vec2 point, const float scale, const float rotation){",
			"vec2 tmp;",
			"tmp.x		= point.x * cos(rotation) - point.y * sin(rotation);",
			"tmp.y		= point.x * sin(rotation) + point.y * cos(rotation);",
			"tmp		= tmp * scale;",
			"return tmp;",
		"}",
		

based on THREE.Color.setHSV() based on Mads Elvheim / Madsy http://code.google.com/p/opengl3-freenode/wiki/ColorSpaceConversions

		"vec3 HSVtoRGB(const vec3 color){",
			"float h	= color.r;",
			"float s	= color.g;",
			"float v	= color.b;",

			"float i	= floor(h * 6.0);",
			"float f	= (h * 6.0) - i;",
			"float p	= v * (1.0 - s);",
			"float q	= v * (1.0 - f * s);",
			"float t	= v * (1.0 - (1.0 - f) * s);",

			"vec3 result;",
			"if( i < 1.0 )		result = vec3(v,t,p);",
			"else if( i < 2.0 )	result = vec3(q,v,p);",
			"else if( i < 3.0 )	result = vec3(p,v,t);",
			"else if( i < 4.0 )	result = vec3(p,q,v);",
			"else if( i < 5.0 )	result = vec3(t,p,v);",
			"else if( i < 6.0 )	result = vec3(v,p,q);",
			"else 			result = vec3(v,t,p);",

			"return result;",
		"}",

default value

		"#ifndef ROTOZOOM",
			"#define ROTOZOOM 1",
		"#endif",
		"#ifndef USEHSV",
			"#define USEHSV 1",
		"#endif",
		
		"void main(){",
			"vec2 p		= -1.0 + 2.0 * vUv;",
			"#if ROTOZOOM",
				"p 	= rotoZoom(p, scale, rotation);",
			"#endif",

			"float cossin1	= cos(p.x*c0+sin(time*1.3)) - sin(p.y*c3-cos(time)) + sin(time);",
			"float cossin2	= cos(p.y*c1+cos(c1*time/c4)) * sin(p.x*c4*sin(time)) - cos(time);",
			"float cossin3	= cos(p.x*c2+sin(c2*time/c5)) + sin(p.y*c5+cos(time)) + cos(time);",

"vec3 color = vec3(abs(cossin1sin(p.x)), cossin2sin(p.y), cossin3*sin(p.x));",

			"vec3 color	= vec3(abs(cossin1*sin(p.x)), 0.6 - 0.4* abs(cossin2*sin(p.y)), 0.5 - 0.3*(cossin3*sin(p.x)));",

			"#if USEHSV",
				"color	= HSVtoRGB(color);",
			"#endif",

			"gl_FragColor	= vec4(color, opacity);",

"gl_FragColor = vec4(cossin1sin(p.x), cossin2sin(p.y), cossin3*sin(p.x), opacity);",

		"}"
	].join( "\n" )
};

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.SkyMap.html ================================================ THREEx.SkyMap.js

THREEx.SkyMap.js

var THREEx		= THREEx || {};

THREEx.SkyMap	= {};

THREEx.SkyMap.buildMesh	= function(urls, opts)
{

get parameters

	opts		= opts || {}
	var cubeSize	= opts.cubeSize !== undefined ? opts.cubeSize	: 100000;

load the cube textures

	var texture	= THREE.ImageUtils.loadTextureCube( urls );
	

init the cube shadder

	var shader	= THREE.ShaderUtils.lib["cube"];
	var uniforms	= THREE.UniformsUtils.clone( shader.uniforms );
	uniforms['tCube'].texture= textureCube;
	var material = new THREE.MeshShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: uniforms
	});

build the geometry

	var geometry	= new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize, 1, 1, 1, null, true );

build the skybox Mesh

	var mesh	= new THREE.Mesh( geometry, material );
	return mesh;
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPosx	= function(prefix, extension)
{
	return [
		prefix + "posx" + extension,
		prefix + "negx" + extension,
		prefix + "posy" + extension,
		prefix + "negy" + extension,
		prefix + "posz" + extension,
		prefix + "negz" + extension
	];
	return urls;	
}

/**
 * Build the urls array for THREEx.SkyMap.buildMesh()
*/
THREEx.SkyMap.UrlsPx	= function(prefix, extension)
{
	return [
		prefix + "px" + extension,
		prefix + "nx" + extension,
		prefix + "py" + extension,
		prefix + "ny" + extension,
		prefix + "pz" + extension,
		prefix + "nz" + extension
	];
	return urls;	
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.WindowResize.html ================================================ THREEx.WindowResize.js

THREEx.WindowResize.js

This THREEx helper makes it easy to handle window resize. It will update renderer and camera when window is resized.

Usage

Step 1: Start updating renderer and camera

var windowResize = THREEx.WindowResize(aRenderer, aCamera)

Step 2: Start updating renderer and camera

windowResize.stop()

Code

/** @namespace */
var THREEx	= THREEx 		|| {};

/**
 * Update renderer and camera when the window is resized
 * 
 * @param {Object} renderer the renderer to update
 * @param {Object} Camera the camera to update
*/
THREEx.WindowResize	= function(renderer, camera){
	var callback	= function(){

notify the renderer of the size change

		renderer.setSize( window.innerWidth, window.innerHeight );

update the camera

		camera.aspect	= window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	}

bind the resize event

	window.addEventListener('resize', callback, false);

return .stop() the function to stop watching window resize

	return {
		/**
		 * Stop watching window resize
		*/
		stop	: function(){
			window.removeEventListener('resize', callback);
		}
	};
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.glCapability.html ================================================ THREEx.glCapability.js

THREEx.glCapability.js

/**
 * Define namespace
*/
if(typeof THREEx === "undefined")	var THREEx	= {};


/**
 * return the capability of a WebGl context
 *
 * TODO to rewrite
 * - heavily wased on webglreport on sourceforge
 * - is there other/better properties
 * - should i get a more readable output ?
 *   - another function ?
 *
 * @param {WebGLRenderingContext} webgl context
 * @returns {Object} capabilities
*/
THREEx.glCapability	= function(gl)
{

sanity check - gl context MUST BE WebGLRenderingContext

	console.assert(gl instanceof WebGLRenderingContext)

TODO find better names

	var prout	= ['VERSION', 'SHADING_LANGUAGE_VERSION', 'VENDOR', 'RENDERER'];
	var pixDepth	= ['RED_BITS', 'GREEN_BITS', 'BLUE_BITS', 'ALPHA_BITS', 'DEPTH_BITS', 'STENCIL_BITS'];
	var slota	= ['MAX_RENDERBUFFER_SIZE', 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'MAX_CUBE_MAP_TEXTURE_SIZE'
				, 'MAX_FRAGMENT_UNIFORM_VECTORS', 'MAX_TEXTURE_IMAGE_UNITS'
				, 'MAX_TEXTURE_SIZE', 'MAX_VERTEX_ATTRIBS'
				, 'MAX_VERTEX_ATTRIBS', 'MAX_VERTEX_TEXTURE_IMAGE_UNITS'
				, 'MAX_VERTEX_UNIFORM_VECTORS'];	
	var sloti	= ['ALIASED_LINE_WIDTH_RANGE', 'ALIASED_POINT_SIZE_RANGE', 'MAX_VIEWPORT_DIMS'];
	
	var info	= {};
	var collect	= function(arr){
		arr.forEach(function(parameter){

console.log('parameter', parameter)

			info[parameter]	= gl.getParameter(gl[parameter])
		})
	}
	
	collect(prout);
	collect(pixDepth);
	collect(slota);
	collect(sloti)
	

special case to get the extensions

	info['SUPPORTED_EXTENSIONS']	= gl.getSupportedExtensions()
	

console.log("info"); console.dir(info)

	return info;
}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.requestAnimationFrame.html ================================================ THREEx.requestAnimationFrame.js

THREEx.requestAnimationFrame.js

/**
 * Provides requestAnimationFrame/cancelRequestAnimation in a cross browser way.
 * from paul irish + jerome etienne
 * - http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * - http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html
 */

if ( !window.requestAnimationFrame ) {

	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {

			return window.setTimeout( callback, 1000 / 60 );

		};

	} )();

}

if ( !window.cancelRequestAnimationFrame ) {

	window.cancelRequestAnimationFrame = ( function() {

		return window.webkitCancelRequestAnimationFrame ||
		window.mozCancelRequestAnimationFrame ||
		window.oCancelRequestAnimationFrame ||
		window.msCancelRequestAnimationFrame ||
		clearTimeout

	} )();

}

================================================ FILE: TJunctions/vendor/threex/docs/THREEx.screenshot.html ================================================ THREEx.screenshot.js

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();

================================================ FILE: TJunctions/vendor/threex/docs/docco.css ================================================ /*--------------------- Layout and Typography ----------------------------*/ body { font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; font-size: 15px; line-height: 22px; color: #252519; margin: 0; padding: 0; } a { color: #261a3b; } a:visited { color: #261a3b; } p { margin: 0 0 15px 0; } h1, h2, h3, h4, h5, h6 { margin: 0px 0 15px 0; } h1 { margin-top: 40px; } #container { position: relative; } #background { position: fixed; top: 0; left: 525px; right: 0; bottom: 0; background: #f5f5ff; border-left: 1px solid #e5e5ee; z-index: -1; } #jump_to, #jump_page { background: white; -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; font: 10px Arial; text-transform: uppercase; cursor: pointer; text-align: right; } #jump_to, #jump_wrapper { position: fixed; right: 0; top: 0; padding: 5px 10px; } #jump_wrapper { padding: 0; display: none; } #jump_to:hover #jump_wrapper { display: block; } #jump_page { padding: 5px 0 3px; margin: 0 0 25px 25px; } #jump_page .source { display: block; padding: 5px 10px; text-decoration: none; border-top: 1px solid #eee; } #jump_page .source:hover { background: #f5f5ff; } #jump_page .source:first-child { } table td { border: 0; outline: 0; } td.docs, th.docs { max-width: 450px; min-width: 450px; min-height: 5px; padding: 10px 25px 1px 50px; overflow-x: hidden; vertical-align: top; text-align: left; } .docs pre { margin: 15px 0 15px; padding-left: 15px; } .docs p tt, .docs p code { background: #f8f8ff; border: 1px solid #dedede; font-size: 12px; padding: 0 0.2em; } .pilwrap { position: relative; } .pilcrow { font: 12px Arial; text-decoration: none; color: #454545; position: absolute; top: 3px; left: -20px; padding: 1px 2px; opacity: 0; -webkit-transition: opacity 0.2s linear; } td.docs:hover .pilcrow { opacity: 1; } td.code, th.code { padding: 14px 15px 16px 25px; width: 100%; vertical-align: top; background: #f5f5ff; border-left: 1px solid #e5e5ee; } pre, tt, code { font-size: 12px; line-height: 18px; font-family: Monaco, Consolas, "Lucida Console", monospace; margin: 0; padding: 0; } /*---------------------- Syntax Highlighting -----------------------------*/ td.linenos { background-color: #f0f0f0; padding-right: 10px; } span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } body .hll { background-color: #ffffcc } body .c { color: #408080; font-style: italic } /* Comment */ body .err { border: 1px solid #FF0000 } /* Error */ body .k { color: #954121 } /* Keyword */ body .o { color: #666666 } /* Operator */ body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ body .cp { color: #BC7A00 } /* Comment.Preproc */ body .c1 { color: #408080; font-style: italic } /* Comment.Single */ body .cs { color: #408080; font-style: italic } /* Comment.Special */ body .gd { color: #A00000 } /* Generic.Deleted */ body .ge { font-style: italic } /* Generic.Emph */ body .gr { color: #FF0000 } /* Generic.Error */ body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ body .gi { color: #00A000 } /* Generic.Inserted */ body .go { color: #808080 } /* Generic.Output */ body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ body .gs { font-weight: bold } /* Generic.Strong */ body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ body .gt { color: #0040D0 } /* Generic.Traceback */ body .kc { color: #954121 } /* Keyword.Constant */ body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ body .kp { color: #954121 } /* Keyword.Pseudo */ body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ body .kt { color: #B00040 } /* Keyword.Type */ body .m { color: #666666 } /* Literal.Number */ body .s { color: #219161 } /* Literal.String */ body .na { color: #7D9029 } /* Name.Attribute */ body .nb { color: #954121 } /* Name.Builtin */ body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ body .no { color: #880000 } /* Name.Constant */ body .nd { color: #AA22FF } /* Name.Decorator */ body .ni { color: #999999; font-weight: bold } /* Name.Entity */ body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ body .nf { color: #0000FF } /* Name.Function */ body .nl { color: #A0A000 } /* Name.Label */ body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ body .nt { color: #954121; font-weight: bold } /* Name.Tag */ body .nv { color: #19469D } /* Name.Variable */ body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ body .w { color: #bbbbbb } /* Text.Whitespace */ body .mf { color: #666666 } /* Literal.Number.Float */ body .mh { color: #666666 } /* Literal.Number.Hex */ body .mi { color: #666666 } /* Literal.Number.Integer */ body .mo { color: #666666 } /* Literal.Number.Oct */ body .sb { color: #219161 } /* Literal.String.Backtick */ body .sc { color: #219161 } /* Literal.String.Char */ body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ body .s2 { color: #219161 } /* Literal.String.Double */ body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ body .sh { color: #219161 } /* Literal.String.Heredoc */ body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ body .sx { color: #954121 } /* Literal.String.Other */ body .sr { color: #BB6688 } /* Literal.String.Regex */ body .s1 { color: #219161 } /* Literal.String.Single */ body .ss { color: #19469D } /* Literal.String.Symbol */ body .bp { color: #954121 } /* Name.Builtin.Pseudo */ body .vc { color: #19469D } /* Name.Variable.Class */ body .vg { color: #19469D } /* Name.Variable.Global */ body .vi { color: #19469D } /* Name.Variable.Instance */ body .il { color: #666666 } /* Literal.Number.Integer.Long */ ================================================ FILE: TJunctions/vendor/threex/examples/THREEx.DeviceOrientationState.html ================================================ angleX:
angleY:
angleZ:
================================================ FILE: TJunctions/vendor/threex/examples/THREEx.KeyboardState.html ================================================ ================================================ FILE: TJunctions/vendor/threex/examples/threex.embedded/noshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: TJunctions/vendor/threex/examples/threex.embedded/noshield-iframe.html ================================================ WITHOUT shielding events
Click to get focus Got Focus!
Now use arrow UP/DOWN and the host page will scroll as events are not shielded.
================================================ FILE: TJunctions/vendor/threex/examples/threex.embedded/withshield-host.html ================================================
dummy div 1024px height to create a scrollable page
================================================ FILE: TJunctions/vendor/threex/examples/threex.embedded/withshield-iframe.html ================================================ WITH shielding events
Click to get focus Got Focus!
now use arrow UP/DOWN and the host page won't scroll as events are shielded.
================================================ FILE: TJunctions/vendor/threex/examples/threex.fullscreen.html ================================================

threex.fullscreen.js demo

threex.js - helpers for three.js
fullscreen available ?
fullscreen activated ?

================================================ FILE: TJunctions/vendor/threex/threex.chromeWebStoreInstall.js ================================================ // This THREEx helper makes it easy to handle chrome.webstore.install API. // * api description http://code.google.com/chrome/webstore/docs/inline_installation.html // * paul kinlan post on g+ https://plus.google.com/116059998563577101552/posts/c9zYiA9RdC5 // // # Code // /** @namespace */ var THREEx = THREEx || {}; THREEx.ChromeWebStoreInstall = THREEx.ChromeWebStoreInstall || {}; /** * test if the API is available * @returns {Boolean} true if the API is available, false otherwise */ THREEx.ChromeWebStoreInstall.apiAvailable = function() { var available = typeof chrome !== 'undefined' && chrome.webstore && chrome.webstore.install; return available ? true : false; } /** * Test if the application is already installed * * @returns {Boolean} true if the application is installed, false otherwise */ THREEx.ChromeWebStoreInstall.isInstalled = function() { if( !this.apiAvailable() ) return false; return chrome.app.isInstalled ? true : false; } /** * Trigger an installation * @param {String} url of the application (optional) * @param {Function} callback called if installation succeed * @param {Function} callback called if installation failed */ THREEx.ChromeWebStoreInstall.install = function(url, successCallback, failureCallback) { console.assert( this.apiAvailable() ) chrome.webstore.install(url, successCallback, failureCallback); } ================================================ FILE: TJunctions/vendor/threex/threex.embedded.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.Embedded = THREEx.Embedded || {}; /** * @returns {Boolean} return true if we are in a iframe, false otherwise */ THREEx.Embedded.inIFrame = function() { return window != window.top ? true : false; } /** * Prevent Arrows key event from going out of the iframe */ THREEx.Embedded.shieldArrowKeys = function() { document.addEventListener('keydown', function(event){ // if it is keydown on a arrow, prevent default if( event.keyCode >= 37 && event.keyCode <= 40 ){ event.preventDefault(); } }, true); } ================================================ FILE: TJunctions/vendor/threex/threex.sparks.js ================================================ // This THREEx helper makes it even easier to use spark.js with three.js // * FIXME This is currently only with WebGL // // # Code // var THREEx = THREEx || {}; THREEx.Sparks = function(opts) { opts = opts || {}; this._maxParticles = opts.maxParticles || console.assert(false); this._texture = opts.texture || this._buildDefaultTexture(); var counter = opts.counter || console.assert(false); var vertexIndexPool = { __pools: [], // Get a new Vector get: function() { if( this.__pools.length > 0 ) return this.__pools.pop(); console.assert(false, "pool ran out!") return null; }, // Release a vector back into the pool add: function(v){ this.__pools.push(v); } }; var particles = new THREE.Geometry(); var vertices = particles.vertices; for ( i = 0; i < this._maxParticles; i++ ) { var position = new THREE.Vector3(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); vertices.push(new THREE.Vertex(position)); vertexIndexPool.add(i); } // to handle window resize this._$onWindowResize = this._onWindowResize.bind(this); window.addEventListener('resize', this._$onWindowResize, false); var attributes = this._attributes = { size : { type: 'f', value: [] }, aColor : { type: 'c', value: [] } }; var uniforms = this._uniforms = { texture : { type: "t", texture: this._texture }, color : { type: "c", value: new THREE.Color(0xffffff) }, sizeRatio : { type: "f", value: this._computeSizeRatio() } }; // fill attributes array var valuesSize = this._attributes.size.value; var valuesColor = this._attributes.aColor.value; for(var v = 0; v < particles.vertices.length; v++ ){ valuesSize[v] = 99; valuesColor[v] = new THREE.Color( 0x000000 ); } var material = new THREE.ShaderMaterial( { uniforms : this._uniforms, attributes : this._attributes, vertexShader : THREEx.Sparks.vertexShaderText, fragmentShader : THREEx.Sparks.fragmentShaderText, blending : THREE.AdditiveBlending, depthWrite : false, transparent : true }); this._group = new THREE.ParticleSystem( particles, material ); //this._group.dynamic = true; //this._group.sortParticles = true; // TODO is this needed ? //// EMITTER STUFF var setTargetParticle = function() { var vertexIdx = vertexIndexPool.get(); var target = { vertexIdx : vertexIdx, size : function(value){ valuesSize[vertexIdx] = value; }, color : function(){ return valuesColor[vertexIdx]; } }; return target; }; var onParticleCreated = function(particle) { var vertexIdx = particle.target.vertexIdx; // copy particle position into three.js geometry vertices[vertexIdx].position = particle.position; }; var onParticleDead = function(particle) { var vertexIdx = particle.target.vertexIdx; // Hide the particle valuesColor[vertexIdx].setHex( 0x000000 ); vertices[vertexIdx].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); // Mark particle system as available by returning to pool vertexIndexPool.add( vertexIdx ); }; var emitter = this._emitter = new SPARKS.Emitter(counter); emitter.addInitializer(new SPARKS.Target(null, setTargetParticle)); emitter.addCallback("created" , onParticleCreated ); emitter.addCallback("dead" , onParticleDead ); } THREEx.Sparks.prototype.destroy = function() { window.removeEventListener('resize', this._$onWindowResize); if( this._emitter.isRunning() ) this._emitter.stop(); } ////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype.container = function() { return this._group; } THREEx.Sparks.prototype.emitter = function() { return this._emitter; } THREEx.Sparks.prototype.update = function() { this._group.geometry.__dirtyVertices = true; this._group.geometry.__dirtyColors = true; this._attributes.size.needsUpdate = true; this._attributes.aColor.needsUpdate = true; } ////////////////////////////////////////////////////////////////////////////////// // handle window resize // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._onWindowResize = function() { this._uniforms.sizeRatio.value = this._computeSizeRatio(); this._uniforms.sizeRatio.needsUpdate = true; } THREEx.Sparks.prototype._computeSizeRatio = function() { return window.innerHeight / 1024; } ////////////////////////////////////////////////////////////////////////////////// // Shader Text // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.vertexShaderText = [ "attribute float size;", "attribute vec4 aColor;", "uniform float sizeRatio;", "varying vec4 vColor;", "void main() {", "vec4 mvPosition= modelViewMatrix * vec4( position, 1.0 );", "gl_PointSize = size * sizeRatio * ( 150.0 / length( mvPosition.xyz ) );", "gl_Position = projectionMatrix * mvPosition;", "vColor = aColor;", "}" ].join('\n'); THREEx.Sparks.fragmentShaderText = [ "uniform vec3 color;", "uniform sampler2D texture;", "varying vec4 vColor;", "void main() {", "vec4 outColor = texture2D( texture, gl_PointCoord );", "gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );", "}" ].join('\n'); ////////////////////////////////////////////////////////////////////////////////// // Texture // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.prototype._buildDefaultTexture = function(size) { size = size || 128; var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d' ); canvas.width = canvas.height = size; var gradient = context.createRadialGradient( canvas.width/2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 ); gradient.addColorStop( 0 , 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' ); gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' ); gradient.addColorStop( 1 , 'rgba(0,0,0,1)' ); context.beginPath(); context.arc(size/2, size/2, size/2, 0, Math.PI*2, false); context.closePath(); context.fillStyle = gradient; //context.fillStyle = 'rgba(128,128,128,1)'; context.fill(); var texture = new THREE.Texture( canvas ); texture.needsUpdate = true; return texture; } ////////////////////////////////////////////////////////////////////////////////// // Custom initializer TODO put it elsewhere // ////////////////////////////////////////////////////////////////////////////////// THREEx.Sparks.ColorSizeInitializer = function(color, size){ this._color = color; this._size = size; } THREEx.Sparks.ColorSizeInitializer.prototype.initialize = function(emitter, particle) { if( this._color !== undefined ) particle.target.color().copy(this._color); if( this._size !== undefined ) particle.target.size(this._size); } ================================================ FILE: TJunctions/vendor/threex/threex.texturePoolBall.js ================================================ // NOTE: this match THREE namespace on purpose if(typeof THREEx === "undefined") var THREEx = {}; if(typeof THREEx.Texture === "undefined") THREEx.Texture = {}; /** */ THREEx.Texture.PoolBall = { clear : function(canvas){ var w = canvas.width; var ctx = canvas.getContext( '2d' ); clearRect(0, 0, w, w); }, /** * display the shaddow of the smiley in a texture * * @param {canvasElement} the canvas where we draw */ draw : function(canvas, textData, stripped, color){ var ctx = canvas.getContext( '2d' ); var w = canvas.width; var h = canvas.height; // base color is white ctx.save(); ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0, w, h); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var rectH = stripped ? h/2 : h; ctx.fillStyle = color.getContextStyle(); ctx.fillRect(-w/2,-rectH/2, w, rectH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) ctx.fillStyle = "#FFFFFF"; var radiusW = 0.7 * w/4; var radiusH = 1.2 * h/4; ctx.fillEllipse( -radiusW/2, -radiusH/2, radiusW, radiusH); ctx.restore(); ctx.save(); ctx.translate(w/2, h/2) var textH = w/4; ctx.font = "bolder "+textH+"px Arial"; ctx.fillStyle = "#000000"; var textW = ctx.measureText(textData).width; ctx.fillText(textData, -textW/2, 0.8*textH/2); ctx.restore(); }, ////////////////////////////////////////////////////////////////////////////////// // texture helper // ////////////////////////////////////////////////////////////////////////////////// ballTexture: function( textData, stripped, color, canvasW, mapping, callback ) { var canvasDrawer = function(canvas){ THREEx.Texture.PoolBall.draw(canvas, textData, stripped, color); } return THREEx.Texture.PoolBall._buildTexture( canvasW, mapping, callback, canvasDrawer ); }, _buildTexture: function( canvasW, mapping, callback, canvasDrawer ) { canvasW = typeof canvasW !== 'undefined' ? canvasW : 64; var canvas = document.createElement('canvas'); canvas.width = canvas.height = canvasW; var texture = new THREE.Texture(canvas, mapping); canvasDrawer(canvas); texture.needsUpdate = true; if( callback ) callback( this ); return texture; }, } ================================================ FILE: TJunctions/vendor/threex.dragpancontrols.js ================================================ /** @namespace */ var THREEx = THREEx || {}; THREEx.DragPanControls = function(object, domElement) { this._object = object; this._domElement= domElement || document; // parameters that you can change after initialisation this.target = new THREE.Vector3(0, 0, 0); this.speedX = 0.03; this.speedY = 0.03; this.rangeX = -40; this.rangeY = +40; // private variables this._mouseX = 0; this._mouseY = 0; var _this = this; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._domElement.addEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.addEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.addEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.destroy = function() { this._domElement.removeEventListener( 'mousemove', this._$onMouseMove, false ); this._domElement.removeEventListener( 'touchstart', this._$onTouchStart,false ); this._domElement.removeEventListener( 'touchmove', this._$onTouchMove, false ); } THREEx.DragPanControls.prototype.update = function(event) { this._object.position.x += ( this._mouseX * this.rangeX - this._object.position.x ) * this.speedX; this._object.position.y += ( this._mouseY * this.rangeY - this._object.position.y ) * this.speedY; this._object.lookAt( this.target ); } THREEx.DragPanControls.prototype._onMouseMove = function(event) { this._mouseX = ( event.clientX / window.innerWidth ) - 0.5; this._mouseY = ( event.clientY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchStart = function(event) { if( event.touches.length != 1 ) return; // no preventDefault to get click event on ios this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } THREEx.DragPanControls.prototype._onTouchMove = function(event) { if( event.touches.length != 1 ) return; event.preventDefault(); this._mouseX = ( event.touches[ 0 ].pageX / window.innerWidth ) - 0.5; this._mouseY = ( event.touches[ 0 ].pageY / window.innerHeight) - 0.5; } ================================================ FILE: Terrain/MIT-LICENSE.txt ================================================ Copyright (c) 2011 Jerome Etienne, http://jetienne.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Terrain/Makefile ================================================ # makefile to automatize simple operations server: python -m SimpleHTTPServer deploy: # assume there is something to commit # use "git diff --exit-code HEAD" to know if there is something to commit # so two lines: one if no commit, one if something to commit git commit -a -m "New deploy" && git push -f origin HEAD:gh-pages && git reset HEAD~ ================================================ FILE: Terrain/css/main.css ================================================ body { overflow : hidden; padding : 0; margin : 0; color : #222; background-color: #BBB; font-family : arial; font-size : 100%; } #info .top { position : absolute; top : 0px; width : 100%; padding : 5px; text-align : center; } #info a { color : #66F; text-decoration : none; } #info a:hover { text-decoration : underline; } #info .bottom { position : absolute; bottom : 0px; right : 5px; padding : 5px; } #info .controls { position : absolute; top : 10px; left : 10px; padding : 5px; } ================================================ FILE: Terrain/index.html ================================================ WebGL Boilerplate
< /div > ================================================ FILE: Terrain/index.html~ ================================================ WebGL Boilerplate
================================================ FILE: Terrain/js/dualcontour.js ================================================ /** * Dual contouring in javascript * * Written by Mikola Lysenko (C) 2012 * * Free to use, but give credit. */ var DualContouring = (function() { //Precompute edge tables. // This saves a bit of time when computing the centroid of each boundary cell var cube_edges = new Int32Array([ 0, 1 //First 3 edges are used for generating faces , 0, 2 , 0, 4 , 1, 3 //Order for these edges does not matter , 1, 5 , 2, 3 , 2, 6 , 3, 7 , 4, 5 , 4, 6 , 5, 7 , 6, 7 ]) , edge_table = new Int32Array(256); (function() { for(var i=0; i<256; ++i) { var em = 0; for(var j=0; j<24; j+=2) { var a = !!(i & (1<> 1)) : 0; } edge_table[i] = em; } })(); //Internal buffer var buffer = new Int32Array(0); return { meshTransition: function(data0, dims0, bnd0, data1, dims1, bnd1) { return { vertices:[], faces:[] }; }, meshVolume: function(data, dims) { var vertices = [] , faces = [] , n = 0 , x = new Int32Array(3) , R = new Int32Array([1, (dims[0]+1), (dims[0]+1)*(dims[0]+1)]) , grid = new Float32Array(8) , buf_no = 1; //Resize buffer if necessary if(R[2] * 2 > buffer.length) { buffer = new Int32Array(R[2] * 2); } //March over the voxel grid for(x[2]=0; x[2] 1e-6) { t = g0 / t; } else { continue; } for(var j=0, k=1; j<3; ++j, k<<=1) { var a = e0 & k; if(a & (~e1)) { v[j] += !!a ? 1.0 - t : t; } else { v[j] += !!a ? 1.0 : 0; } } } //Average edge intersections to get vertex var s = 1.0 / e_count; for(var i=0; i<3; ++i) { v[i] = x[i] + s * v[i]; } buffer[m] = vertices.length; vertices.push(v); //Connect faces together for(var i=0; i<3; ++i) { if(!(edge_mask & (1< 0 && tree._listeners.length > m) { tree._listeners.warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', tree._listeners.length); console.trace(); } } } return true; } name = type.shift(); } return true; }; // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.delimiter = '.'; EventEmitter.prototype.setMaxListeners = function(n) { this._events || init.call(this); this._events.maxListeners = n; }; EventEmitter.prototype.event = ''; EventEmitter.prototype.once = function(event, fn) { this.many(event, 1, fn); return this; }; EventEmitter.prototype.many = function(event, ttl, fn) { var self = this; if (typeof fn !== 'function') { throw new Error('many only accepts instances of Function'); } function listener() { if (--ttl === 0) { self.off(event, listener); } fn.apply(this, arguments); }; listener._origin = fn; this.on(event, listener); return self; }; EventEmitter.prototype.emit = function() { this._events || init.call(this); var type = arguments[0]; if (type === 'newListener') { if (!this._events.newListener) { return false; } } // Loop through the *_all* functions and invoke them. if (this._all) { var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; for (i = 0, l = this._all.length; i < l; i++) { this.event = type; this._all[i].apply(this, args); } } // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._all && !this._events.error && !(this.wildcard && this.listenerTree.error)) { if (arguments[1] instanceof Error) { throw arguments[1]; // Unhandled 'error' event } else { throw new Error("Uncaught, unspecified 'error' event."); } return false; } } var handler; if(this.wildcard) { handler = []; var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); searchListenerTree.call(this, handler, ns, this.listenerTree, 0); } else { handler = this._events[type]; } if (typeof handler === 'function') { this.event = type; if (arguments.length === 1) { handler.call(this); } else if (arguments.length > 1) switch (arguments.length) { case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } return true; } else if (handler) { var l = arguments.length; var args = new Array(l - 1); for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { this.event = type; listeners[i].apply(this, args); } return (listeners.length > 0) || this._all; } else { return this._all; } }; EventEmitter.prototype.on = function(type, listener) { if (typeof type === 'function') { this.onAny(type); return this; } if (typeof listener !== 'function') { throw new Error('on only accepts instances of Function'); } this._events || init.call(this); // To avoid recursion in the case that type == "newListeners"! Before // adding it to the listeners, first emit "newListeners". this.emit('newListener', type, listener); if(this.wildcard) { growListenerTree.call(this, type, listener); return this; } if (!this._events[type]) { // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; } else if(typeof this._events[type] === 'function') { // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; } else if (isArray(this._events[type])) { // If we've already got an array, just append. this._events[type].push(listener); // Check for listener leak if (!this._events[type].warned) { var m = defaultMaxListeners; if (typeof this._events.maxListeners !== 'undefined') { m = this._events.maxListeners; } if (m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } } return this; }; EventEmitter.prototype.onAny = function(fn) { if(!this._all) { this._all = []; } if (typeof fn !== 'function') { throw new Error('onAny only accepts instances of Function'); } // Add the function to the event listener collection. this._all.push(fn); return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; EventEmitter.prototype.off = function(type, listener) { if (typeof listener !== 'function') { throw new Error('removeListener only takes instances of Function'); } var handlers,leafs=[]; if(this.wildcard) { var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); } else { // does not use listeners(), so no side effect of creating _events[type] if (!this._events[type]) return this; handlers = this._events[type]; leafs.push({_listeners:handlers}); } for (var iLeaf=0; iLeaf 0) { fns = this._all; for(i = 0, l = fns.length; i < l; i++) { if(fn === fns[i]) { fns.splice(i, 1); return this; } } } else { this._all = []; } return this; }; EventEmitter.prototype.removeListener = EventEmitter.prototype.off; EventEmitter.prototype.removeAllListeners = function(type) { if (arguments.length === 0) { !this._events || init.call(this); return this; } if(this.wildcard) { var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); for (var iLeaf=0; iLeaf 1) { --dsti; } else if (isRelative) { ++negatives; } else { dst[0] = ''; } } else if (part !== '.' && (dsti === 0 || keepBlanks || part !== '')) { dst[dsti++] = part; } } if (negatives) { dst[--negatives] = dst[dsti-1]; dsti = negatives + 1; while (negatives--) { dst[negatives] = '..'; } } dst.length = dsti; return dst; } // normalize an id function normalizeId(id, parentId) { id = id.replace(/\/+$/g, ''); return normalizeArray((parentId ? parentId + '/../' + id : id).split('/')) .join('/'); } // normalize a url function normalizeUrl(url, baseLocation) { if (!(/^\w+:/).test(url)) { var u = baseLocation.protocol+'//'+baseLocation.hostname; if (baseLocation.port && baseLocation.port !== 80) { u += ':'+baseLocation.port; } var path = baseLocation.pathname; if (url.charAt(0) === '/') { url = u + normalizeArray(url.split('/')).join('/'); } else { path += ((path.charAt(path.length-1) === '/') ? '' : '/../') + url; url = u + normalizeArray(path.split('/')).join('/'); } } return url; } // define a constant (read-only) value property var defineConstant; if (Object.defineProperty) { defineConstant = function (obj, name, value) { Object.defineProperty(obj, name, {value: value, writable: false, enumerable: true, configurable: false}); } } else { defineConstant = function (obj, name, value) { obj[name] = value; } } // require/load/import a module // require(id[, parentId]) -> [object module-api] // @throws Error /module not found (json-rep-of-id)/ function require (id, parentId) { var originalInputId = id; // for "not found" error message if (id.charAt(0) === '.') { id = normalizeId(id, parentId); } if (!require.modules.hasOwnProperty(id)) { throw new Error('module not found '+JSON.stringify(originalInputId)); } var mod = require.modules[id]; if (mod.exports === undefined) { var _require = function (_id) { //console.log('_require', _id, 'from', id); return require(_id, id); }; defineConstant(_require, 'main', require.main); var block = mod.block; delete mod.block; mod.exports = {}; if (require.initFilter) { block = require.initFilter(block); } block(_require, mod, mod.exports); } return mod.exports; } // define a module // define(String id, [String uri,] block(require, module, exports){...}) function define (id, uri, block) { if (typeof uri === 'function') { block = uri; uri = null; } var mod = {block: block}; defineConstant(mod, 'id', String(id)); if (uri) { defineConstant(mod, 'uri', String(uri)); } require.modules[mod.id] = mod; return mod; } // modules keyed by id require.modules = {}; // search paths -- disabled until we use/need this //require.paths = []; // main module, accessible from require.main var mainModule = define(''); delete mainModule.block; mainModule.exports = parentExports; defineConstant(require, 'main', mainModule); // the define function require.define = define; // export the require function parentExports.require = require; // ------------------------------------------------------- // Optional require.load if (typeof XMLHttpRequest === "undefined") { // we make use of XHR XMLHttpRequest = function () { try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {} throw new Error("This browser does not support XMLHttpRequest."); }; } /** * Load and define a module * load ( spec Object, Function(callback(err Error)) ) * load ( specs Array, Function(callback(err Error)) ) * load ( url String, Function(callback(err Error)) ) */ function load (spec, callback) { if ((spec instanceof Array) || Object.prototype.toString.call(spec) === "[object Array]") { if (callback) { // load multiple and join on callback var countdown = spec.length; for (var i=0;i= 200) || (xhr.status === 0 && !spec.url.match(/^(?:https?|ftp):\/\//i))) { try { evalResponse(); callback(null); } catch (err) { callback(err); } } else { callback(new Error('failed to load remote module with HTTP'+ ' response status '+xhr.status+' '+ xhr.responseText)); } } }; } xhr.send(null); if (!async) { evalResponse(); } } require.load = load; })(this); ================================================ FILE: resume.html ================================================ Online Resume

Mikola Lysenko's Resume

Contact Info:

Selected projects

  • stack.gl: A modular ecosystem for WebGL
  • scijs: A scientific computing environment for JavaScript
  • gl-vis: Modules for data visualization using WebGL
  • voxel.js: Voxel engine in JavaScript
  • box-intersect: A fast library for any dimensional box intersection
  • l1-path-finder: A library for path finding in any dimension
  • orthogami: Orthogami unfolding for polycubes

Papers:

  • M. Lysenko, V. Shapiro. (2015) "Effective Contact Measures" SIAM Symposium on Solid Physical Modeling.
  • J. van de Gronde, M. Lysenko, J. Roerdink. (2014) "Path-based mathematical morphology on tensor fields", Visualization and Processing of Higher Order Descriptors for Multi-Valued Data.
  • M. Lysenko. (2013) "Fourier Collision Detection", International Journal of Robotics Research.
  • B. McCarthy, M. Lysenko, V. Shapiro. (2012) "Configuration Workspaces of Series-Parallel Mechanisms". ASME 2012 International Design and Engineering Technical Conference, IDETC/CIE 2012 Chicago IL
  • M. Lysenko, (2011) "Fourier Collision Detection" Technical Report. University of Wisconsin-Madison
  • S. Nelaturi, M. Lysenko, V. Shapiro (2011) "Rapid Mapping and Exploration of Configuration Space", ASME 2011 International Design and Engineering Technical Conference, IDETC/CIE 2011 Washington DC
  • M. Lysenko, S. Nelaturi, V. Shapiro (2011) "Non-commutative Morphology: Shapes, Filters and Convolutions" Computer Aided Geometric Design.
  • M. Lysenko, S. Nelaturi, V. Shapiro (2010) "Group Morphology With Convolution Algebras" ACM Symposium on Solid Modeling. Haifa, Israel
  • R. D'Souza, M. Lysenko, S. Marion, D. Kirschner (2009) "Data Parallel Algorithms for Agent-Based Model Simulation of Tuberculosis on Graphics Processing Units", Spring Simulation Conference
  • M. Lysenko, R. D'Souza (2009) "Interactive Machinability Analysis for Free-Form Surfaces Using Multiple View Image Space Techniques on the GPU" Journal of Robotics and Computers in Integrated Manufacturing.
  • M. Lysenko, K. Rahmani, R. D'Souza (2008) "Real Time Machinability Analysis of Free Form Surfaces on the GPU" Journal of Computers and Information Science in Engineering
  • M. Lysenko, R. D'Souza, C.K. Shene (2008) "Improved Binary Space Partition Merging", Computer Aided Design.
  • M. Lysenko, R. D'Souza (2008) "A Framework for Megascale Agent Based Modeling on the GPU", Journal of Artificial Societies and Simulations
  • R. Richards, M. Lysenko, G. An, R. D'Souza (2008) "Data-Parallel Techniques for Agent Based Tissue Modeling on Graphics Processing Units", ASME IDETC 2008, New York, NY
  • R. D'Souza, M. Lysenko, K. Rahmani (2007) "SugarScape on Steroids: Simulating over One Million Agents at Interactive Rates" Proceedings of Agent2007 conference. Chicago, IL
  • M. Lysenko, K. Rahmani, R. D'Souza (2007) "Real Time Machinability Analysis of Free Form Surfaces on the GPU" ASME 2007 International Design and Engineering Technical Conference, IDETC/CIE 2007

Selected Talks:

  • Relativistic replication. NodeConfEU, Waterford Ireland. 2014 Slides <
  • Modular multidimensional arrays for JavaScript. Web Rebels, Oslo Norway. 2014 Slides
  • Berlin Mathematical Society Seminar. 2012
  • Cambridge University, United Kingdom. 2012
  • University of Groningen, Netherlands. 2012
  • RWTH Aachen, Germany. 2012
  • Institute of Science and Technology, Austria. 2012
  • Freie Universitat Berlin, Germany. 2012
  • "Piecewise affine function" ACM Symposium on Solid and Physical Modeling 2009
  • "Tolerant Modeling" (joint work with Prem Mansukhani and Vadim Shapiro), ACM Symposium on Solid and Physical Modeling 2009
  • "Get some fibers in your diet!" D Tango Conference. Torun, Poland. 2008
  • U.C. Berkeley, California. 2007
  • "Realtime Constructive Solid Geometry", SIGGRAPH 2007

Teaching:

  • CS 558, Introduction to Computational Geometry (Fall 2014). YouTube lectures
  • WebGL workshop, CampJS 2014.
  • ShaderSchool, NodeConf 2014.
  • CS 558, Introduction to Computational Geometry (Spring 2011)
  • ME 331, Solid Modeling (Fall 2012)
  • CS 558, Introduction to Computational Geometry (Fall 2013)

Awards and Other Activities:

Education:

  • PhD Computer Science/Mechanical Engineering. University of Wisconsin-Madison. ABD
  • Bachelors of Computer Science. Michigan Technological University. 2003-2008

Work History:

  • plot.ly. Consultant. 2013-present
  • 3D Systems. Consultant. 2012-2014.
  • Research Assistant. University of Wisconsin-Madison, Department of Mechanical Engineering. Advisor: Vadim Shapiro. 2009-2014.
  • Research Assistant. Michigan Technological University, Department of Mechanical Engineering. Advisor: Roshan D'Souza. 2006-2008.
  • Oracle DB/Web Programmer. Michigan Technological University, Administrative Department. 2005-2006
  • Programmer. Michigan Molecular Institute. Midland, MI. 2001-2004

Buzzwords/Skills:

  • Languages: C, C++, Python, Java, JavaScript, SML, Lisp, Scheme, VisualBasic, QBasic, MATLAB, Erlang ...
  • Systems (in order of familiarity): Linux, Solaris, OS X, Windows
  • Technologies: HTML5, WebGL, Three.JS, CSS, OpenGL, CUDA, GLSL, HLSL, DirectX, SDL, MongoDB, node.js, redis, CouchDB, Intel TBB, BLAS, MKL, scipy, browserify, npm ...