├── 1 └── index.html ├── 2 └── index.html ├── 3 └── index.html ├── 4 └── index.html ├── 5 └── index.html ├── 6 └── index.html ├── 7 └── index.html ├── 8 └── index.html ├── 9 └── index.html ├── 10 └── index.html ├── 11 ├── index 2.html ├── index 3.html └── index.html ├── 12 ├── all-gpu-test.html ├── index.html └── old.html ├── 13 ├── base-particles.html └── index.html ├── 14 └── index.html ├── 15 └── index.html ├── 16 └── index.html ├── 17 └── index.html ├── 18 └── index.html ├── 19 └── index.html ├── 20 └── index.html ├── 21 └── index.html ├── 22 └── index.html ├── 23 └── index.html ├── 24 └── index.html ├── 25 └── index.html ├── 26 ├── index.html └── original.html ├── 27 ├── index.html └── pointer-line.html ├── 28 ├── index.html └── old.html ├── 29 └── index.html ├── 30 └── index.html ├── LICENSE ├── README.md ├── assets ├── bathymetry_bw_composite.jpg ├── bathymetry_bw_composite_4k.jpg ├── bathymetry_diffuse.jpg ├── bathymetry_diffuse_4k.jpg ├── bathymetry_gloss.jpg ├── bathymetry_gloss_4k.jpg ├── cave.jpg ├── dirt-lens3.jpg ├── lens-flare.jpg ├── map-bump.jpg ├── map-color.jpg ├── map-composite.jpg ├── map.jpg ├── mona-lisa-256x256.jpg ├── numbers.jpg ├── palette.png ├── palette2.png ├── palette3-glow.png ├── palette3.png ├── palette4-glow.png ├── palette4.png ├── pano-pedrera.jpg ├── pattern_09 │ ├── diffus.tga │ ├── diffuse.jpg │ ├── diffuse.png │ ├── height.jpg │ ├── height.png │ ├── normal.jpg │ ├── normal.png │ ├── normal.tga │ ├── preview.jpg │ ├── specular.jpg │ ├── specular.png │ └── specular.tga ├── pumice │ ├── diffuse.png │ ├── height.png │ ├── normal.png │ └── specular.png ├── slate │ ├── ao.png │ ├── diffuse.png │ ├── height.png │ ├── normal.png │ └── specular.png ├── space.jpg ├── space.png ├── st_lucia_beach_2k.jpg ├── world.topo.200412.3x5400x2700.jpg └── xortexture.gif ├── base └── index.html ├── css └── styles.css ├── index.html └── js ├── Boids.js ├── Cloth.js ├── Common.js ├── CurveExtras.js ├── DeviceOrientationControls.js ├── EquirectangularToCubemap.js ├── GeometryUtils.js ├── ImprovedNoise.js ├── Kick.js ├── Maf.js ├── MarchingCubes.js ├── MeshCustomMaterial.js ├── Mirror.js ├── OBJLoader.js ├── Odeo.js ├── OrbitControls.js ├── PanomNom.min.js ├── Sound.js ├── THREE.ConstantSpline.js ├── THREE.FBOHelper.js ├── THREE.MeshLine.js ├── THREE.ShaderTexture.js ├── Walker.js ├── cannon.min.js ├── isMobile.min.js ├── three-drawRange.js ├── three-medusa.js ├── three.js └── three.min.js /10/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Odeo 5 | 6 | 10 | 11 | 17 | 21 | 22 | 23 |
24 |
25 |

Click to start

26 |
27 |
28 |

Previous | Next

29 |

10. Odeo

30 |

31 | Build a media player class that can be easily integrated, supporting 32 | media playback, SoundCloud streaming and getUserMedia streams, using Web 33 | Audio API. 34 |

35 |

36 | It also uses AnalyserNode to perform an FFT, and can upload the spectrum 37 | to a GPU texture. 38 |

39 |

Can work together with kick detection.

40 |

41 | Play | 42 | Use microphone 43 |

44 |

More details...

45 | 77 |

78 | See other experiments for Codevember 2016 81 |

82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 128 | 129 | 143 | 144 | 344 | 345 | 346 | -------------------------------------------------------------------------------- /11/index 3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Skeletal 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

5. Skeletal

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 51 | 52 | 66 | 67 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /12/all-gpu-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GPU-powered Genetic Algorithm 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

5. GPU-powered Genetic Algorithm

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 47 | 48 | 58 | 59 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /12/old.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GPU-powered Genetic Algorithm 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

5. GPU-powered Genetic Algorithm

18 |

More details...

19 | 25 |

See other experiments for Codevember 2016

26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 52 | 53 | 82 | 83 | 100 | 101 | 121 | 122 | 134 | 135 | 370 | 371 | 372 | 373 | -------------------------------------------------------------------------------- /13/base-particles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sphere Impostor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

13. Sphere Impostor

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 63 | 64 | 90 | 91 | 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /14/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Clock flag 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

14. Clock flag

18 |

A flag showing the time

19 |

More details...

20 | 28 |

See other experiments for Codevember 2016

29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 273 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dotty Earth 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

2. Dotty Earth

18 |

An example of building a sphere with dots, making sure there's a uniform density of dots across all the surface. In naive distributions, there's way more points towards the poles than necessary.

19 |

The algorithm accepts different point sizes and differents spacing between points.

20 |

Toggle camera or press Space

21 |

More details...

22 | 32 |

See other experiments for Codevember 2016

33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 70 | 71 | 91 | 92 | 355 | 356 | 357 | 358 | -------------------------------------------------------------------------------- /21/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Numerical renderer 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

21. Numerical renderer

18 |

Like those ASCII renderers, but with less characters: just 10.

19 |

More details...

20 | 27 |

See other experiments for Codevember 2016

28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 55 | 56 | 69 | 70 | 103 | 104 | 133 | 134 | 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /22/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Line thickness 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

22. Line thickness

18 |

Simulating the effect of linocut, or wood engraving.

19 |

Drop an image in the page!

20 |

More details...

21 | 27 |

See other experiments for Codevember 2016

28 |
29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 62 | 63 | 133 | 134 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /26/original.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Cutouts 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

26. Cutouts

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 51 | 52 | 175 | 176 | 272 | 273 | 274 | 275 | -------------------------------------------------------------------------------- /27/pointer-line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Medusa 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

27. Medusa

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /28/old.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Neon sign 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

28. Neon sign

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 45 | 46 | 108 | 109 | 427 | 428 | 429 | 430 | -------------------------------------------------------------------------------- /29/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bands 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

29. Bands

18 |

Recreatign an animated gif.

19 |

More details...

20 | 27 |

See other experiments for Codevember 2016

28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | [Attribution CC BY](https://creativecommons.org/licenses/by/4.0/) 4 | 5 | This license lets others distribute, remix, tweak, and build upon your work, even commercially, as long as they credit you for the original creation. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # codevember-2016 2 | 3 | Experiments for Codevember 2016 4 | 5 | # License 6 | 7 | [Attribution CC BY](https://creativecommons.org/licenses/by/4.0/) 8 | 9 | This license lets others distribute, remix, tweak, and build upon your work, even commercially, as long as they credit you for the original creation. 10 | -------------------------------------------------------------------------------- /assets/bathymetry_bw_composite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_bw_composite.jpg -------------------------------------------------------------------------------- /assets/bathymetry_bw_composite_4k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_bw_composite_4k.jpg -------------------------------------------------------------------------------- /assets/bathymetry_diffuse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_diffuse.jpg -------------------------------------------------------------------------------- /assets/bathymetry_diffuse_4k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_diffuse_4k.jpg -------------------------------------------------------------------------------- /assets/bathymetry_gloss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_gloss.jpg -------------------------------------------------------------------------------- /assets/bathymetry_gloss_4k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/bathymetry_gloss_4k.jpg -------------------------------------------------------------------------------- /assets/cave.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/cave.jpg -------------------------------------------------------------------------------- /assets/dirt-lens3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/dirt-lens3.jpg -------------------------------------------------------------------------------- /assets/lens-flare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/lens-flare.jpg -------------------------------------------------------------------------------- /assets/map-bump.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/map-bump.jpg -------------------------------------------------------------------------------- /assets/map-color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/map-color.jpg -------------------------------------------------------------------------------- /assets/map-composite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/map-composite.jpg -------------------------------------------------------------------------------- /assets/map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/map.jpg -------------------------------------------------------------------------------- /assets/mona-lisa-256x256.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/mona-lisa-256x256.jpg -------------------------------------------------------------------------------- /assets/numbers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/numbers.jpg -------------------------------------------------------------------------------- /assets/palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette.png -------------------------------------------------------------------------------- /assets/palette2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette2.png -------------------------------------------------------------------------------- /assets/palette3-glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette3-glow.png -------------------------------------------------------------------------------- /assets/palette3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette3.png -------------------------------------------------------------------------------- /assets/palette4-glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette4-glow.png -------------------------------------------------------------------------------- /assets/palette4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/palette4.png -------------------------------------------------------------------------------- /assets/pano-pedrera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pano-pedrera.jpg -------------------------------------------------------------------------------- /assets/pattern_09/diffuse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/diffuse.jpg -------------------------------------------------------------------------------- /assets/pattern_09/diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/diffuse.png -------------------------------------------------------------------------------- /assets/pattern_09/height.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/height.jpg -------------------------------------------------------------------------------- /assets/pattern_09/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/height.png -------------------------------------------------------------------------------- /assets/pattern_09/normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/normal.jpg -------------------------------------------------------------------------------- /assets/pattern_09/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/normal.png -------------------------------------------------------------------------------- /assets/pattern_09/normal.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/normal.tga -------------------------------------------------------------------------------- /assets/pattern_09/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/preview.jpg -------------------------------------------------------------------------------- /assets/pattern_09/specular.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/specular.jpg -------------------------------------------------------------------------------- /assets/pattern_09/specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pattern_09/specular.png -------------------------------------------------------------------------------- /assets/pumice/diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pumice/diffuse.png -------------------------------------------------------------------------------- /assets/pumice/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pumice/height.png -------------------------------------------------------------------------------- /assets/pumice/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pumice/normal.png -------------------------------------------------------------------------------- /assets/pumice/specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/pumice/specular.png -------------------------------------------------------------------------------- /assets/slate/ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/slate/ao.png -------------------------------------------------------------------------------- /assets/slate/diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/slate/diffuse.png -------------------------------------------------------------------------------- /assets/slate/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/slate/height.png -------------------------------------------------------------------------------- /assets/slate/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/slate/normal.png -------------------------------------------------------------------------------- /assets/slate/specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/slate/specular.png -------------------------------------------------------------------------------- /assets/space.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/space.jpg -------------------------------------------------------------------------------- /assets/space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/space.png -------------------------------------------------------------------------------- /assets/st_lucia_beach_2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/st_lucia_beach_2k.jpg -------------------------------------------------------------------------------- /assets/world.topo.200412.3x5400x2700.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/world.topo.200412.3x5400x2700.jpg -------------------------------------------------------------------------------- /assets/xortexture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spite/codevember-2016/94d39f7c6036426053d097dc14f11c80c36ec213/assets/xortexture.gif -------------------------------------------------------------------------------- /base/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Trencadís 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Previous | Next

17 |

5. Trencadís texture

18 |

See other experiments for Codevember 2016

19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | html { 7 | height: 100%; 8 | -moz-user-select: none; 9 | -khtml-user-select: none; 10 | -webkit-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | } 14 | body { 15 | margin: 0; 16 | padding: 0; 17 | background-color: #202020; 18 | color: #ffffff; 19 | line-height: 1.4em; 20 | height: 100%; 21 | overflow: hidden; 22 | font-family: "Lato", sans-serif; 23 | font-size: 13px; 24 | font-weight: 100; 25 | text-shadow: 0 1px 0 rgba(0, 0, 0, 1); 26 | } 27 | #container { 28 | position: absolute; 29 | left: 0; 30 | top: 0; 31 | right: 0; 32 | bottom: 0; 33 | width: 100%; 34 | height: 100%; 35 | } 36 | #info { 37 | position: absolute; 38 | left: 20px; 39 | top: 20px; 40 | max-width: 400px; 41 | height: 100%; 42 | overflow: auto; 43 | pointer-events: none; 44 | } 45 | #info h1 { 46 | font-family: "Playfair Display", sans-serif; 47 | font-weight: 700; 48 | font-size: 16px; 49 | margin-bottom: 1em; 50 | text-transform: uppercase; 51 | } 52 | #info p { 53 | margin-bottom: 1em; 54 | hyphens: auto; 55 | } 56 | #info a, 57 | .action { 58 | color: inherit; 59 | cursor: pointer; 60 | text-decoration: none; 61 | opacity: 0.7; 62 | transition: opacity 100ms ease-out; 63 | pointer-events: auto; 64 | font-weight: 700; 65 | } 66 | #info a:hover, 67 | .action:hover { 68 | opacity: 1; 69 | } 70 | b { 71 | font-weight: 700; 72 | } 73 | #details { 74 | background-color: rgba(0, 0, 0, 0.4); 75 | height: auto; 76 | opacity: 1; 77 | transition: opacity 250ms ease-out, height 250ms ease-out; 78 | overflow: hidden; 79 | padding: 20px; 80 | margin-bottom: 1em; 81 | height: calc(100% - 300px); 82 | overflow: auto; 83 | pointer-events: auto; 84 | } 85 | #details.hidden { 86 | opacity: 0; 87 | height: 0; 88 | padding: 0; 89 | margin-bottom: 0; 90 | } 91 | #moreDetails { 92 | cursor: pointer; 93 | pointer-events: auto; 94 | } 95 | .active { 96 | font-weight: bold; 97 | opacity: 1; 98 | } 99 | :-webkit-full-screen, 100 | :fullscreen, 101 | :-ms-fullscreen, 102 | :-moz-full-screen { 103 | position: fixed; 104 | width: 100%; 105 | height: 100%; 106 | top: 0; 107 | background: none; 108 | } 109 | .fullscreen-button { 110 | position: absolute; 111 | right: 20px; 112 | bottom: 20px; 113 | border: 1px solid white; 114 | z-index: 1000; 115 | width: 28px; 116 | height: 28px; 117 | cursor: pointer; 118 | text-align: center; 119 | line-height: 24px; 120 | } 121 | .code { 122 | font-family: "courier new", courier; 123 | color: green; 124 | padding: 5px; 125 | } 126 | 127 | #overlay { 128 | position: absolute; 129 | left: 0; 130 | top: 0; 131 | right: 0; 132 | bottom: 0; 133 | pointer-events: all; 134 | background-color: rgba(0, 0, 0, 0.5); 135 | display: flex; 136 | align-items: center; 137 | justify-content: center; 138 | z-index: 20; 139 | } 140 | 141 | #overlay p { 142 | background-color: black; 143 | padding: 1em; 144 | border-radius: 0.5em; 145 | } 146 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Codevember 2016 5 | 6 | 7 | 8 | 9 | 10 | 11 | 45 | 46 | 47 | 48 | 49 |
50 | 51 |

Codevember 2016

52 |

Jaume Sanchez Elias · @thespite

53 | 54 |
55 | 56 |

This are the projects created for Codevember 2016 -a challenge for developers creating a creative sketch by day during the whole month of November.

57 | 58 |

Initially I wanted to mix very different browsers technologies: CSS, SVG, WebGL, and not limited to just visual effects. In the end i went with WebGL + three.js, creating a basic boilerplate and starting from scratch every project. Of course as I went, the toolbox grew considerably, with things like ShaderTexture, Odeo and a lot of shaders and helper methods.

59 | 60 |

I've tried to make all sites work in as many platforms as possible, but the time constrains don't allow for a lot of beta testing and bug hunting. Wobbly Earth, for instance, doesn't work on my Nexus 5, but works everywhere else I've tried. I have reports that Lines in a Sphere doesn't go well with MacBook Airs. If you find any issue and want to help debug, tweet me.

61 | 62 |

So this is all I've been able to churn out, between work, two kids, broken eyeglasses...
Just don't judge the code too strictly :)

63 | 64 |

Inside info: in all the effects with music (10, 16 and 30) you can open the console and run odeo.playSoundCloud( "whatever_soundcloud_url" ) and you can change the track.

65 |

Even more inside info: in all the effects with FBOS, shadows, etc. you can probably open the console and run helper.show(true) to see the FBOHelper.

66 | 67 |

Source code for all experiments -and discarded ones- is here: codevember-2016

68 | 69 |
70 | 71 | 254 | 255 | 256 | 257 |
258 | 259 | 309 | 310 | 311 | 312 | -------------------------------------------------------------------------------- /js/Boids.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | function Boids( opts ) { 4 | 5 | this.boids = []; 6 | this.opts = opts || {}; 7 | 8 | for( var j = 0; j < this.opts.boids; j++ ) { 9 | 10 | this.boids.push({ 11 | position: new THREE.Vector3( 12 | Maf.randomInRange( -50, 50 ), 13 | 0, 14 | Maf.randomInRange( -50, 50 ) 15 | ), 16 | centerVelocity: new THREE.Vector3(), 17 | alignmentVelocity: new THREE.Vector3(), 18 | velocity: new THREE.Vector3(), 19 | orientation: new THREE.Quaternion( 0, 0, 0, 1 ) 20 | }) 21 | 22 | } 23 | 24 | } 25 | 26 | var tmpVector = new THREE.Vector3(); 27 | 28 | Boids.prototype.update = function() { 29 | 30 | var center = new THREE.Vector3(); 31 | for( var i = 0; i < this.boids.length; i++ ) { 32 | center.add( this.boids[ i ].position ); 33 | } 34 | center.multiplyScalar( 1 / this.boids.length ); 35 | 36 | for( var i = 0; i < this.boids.length; i++ ) { 37 | 38 | tmpVector.copy( center ); 39 | tmpVector.sub( this.boids[ i ].position ); 40 | tmpVector.normalize(); 41 | 42 | this.boids[ i ].centerVelocity.copy( tmpVector ); 43 | 44 | this.boids[ i ].alignmentVelocity.set( 0, 0, 0 ); 45 | 46 | for( var j = 0; j < this.boids.length; j++ ) { 47 | 48 | tmpVector.copy( this.boids[ j ].position ); 49 | var distance = tmpVector.distanceTo( this.boids[ i ].position ); 50 | 51 | if( distance < 10 ) { 52 | 53 | tmpVector.copy( this.boids[ j ].position ); 54 | tmpVector.sub( this.boids[ i ].position ); 55 | this.boids[ i ].alignmentVelocity.add( tmpVector ); 56 | 57 | } 58 | 59 | } 60 | 61 | this.boids[ i ].alignmentVelocity.normalize(); 62 | 63 | this.boids[ i ].velocity.copy( this.boids[ i ].centerVelocity ); 64 | this.boids[ i ].velocity.add( this.boids[ i ].alignmentVelocity ); 65 | this.boids[ i ].velocity.multiplyScalar( .1 ); 66 | 67 | this.boids[ i ].position.add( this.boids[ i ].velocity ); 68 | 69 | } 70 | 71 | } 72 | 73 | window.Boids = Boids; 74 | 75 | })(); 76 | -------------------------------------------------------------------------------- /js/Cloth.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Cloth Simulation using a relaxed constrains solver 3 | */ 4 | 5 | // Suggested Readings 6 | 7 | // Advanced Character Physics by Thomas Jakobsen Character 8 | // http://freespace.virgin.net/hugo.elias/models/m_cloth.htm 9 | // http://en.wikipedia.org/wiki/Cloth_modeling 10 | // http://cg.alexandra.dk/tag/spring-mass-system/ 11 | // Real-time Cloth Animation http://www.darwin3d.com/gamedev/articles/col0599.pdf 12 | 13 | /* 20 x 10 restDist = 30 --> good config 14 | var DAMPING = 0.07; 15 | var DRAG = 1 - DAMPING; 16 | var MASS = .03; 17 | var restDistance = 30; 18 | var GRAVITY = 981 * 1.4; 19 | */ 20 | 21 | var DAMPING = 0.07; 22 | var DRAG = 1 - DAMPING; 23 | var MASS = .05; 24 | var restDistance = 36; 25 | var GRAVITY = 981 * 1.4;; 26 | 27 | var clothProperties = {'damping': DAMPING,'drag': DRAG,'mass': MASS }; 28 | 29 | var xSegs = 50; // 30 | var ySegs = 40; // 31 | 32 | var clothFunction = plane(restDistance * xSegs, restDistance * ySegs); 33 | 34 | var cloth = new Cloth(xSegs, ySegs); 35 | 36 | var gravity = new THREE.Vector3( 0, -GRAVITY, 0 ).multiplyScalar(clothProperties.mass); 37 | 38 | 39 | var TIMESTEP = 18 / 1000; 40 | var TIMESTEP_SQ = TIMESTEP * TIMESTEP; 41 | 42 | var pins = []; 43 | var pinOffset = {x:0,y:0,z:0,'animationVel': 1000,'circularAnimation':false}; 44 | var pinBend = {'amount':1,'periodicity':1000}; 45 | 46 | //var windToggle = true; 47 | var windStrength = 2; 48 | var windForce = new THREE.Vector3(0,0,0); 49 | 50 | var tmpForce = new THREE.Vector3(); 51 | 52 | var lastTime; 53 | 54 | 55 | function plane(width, height) { 56 | 57 | return function(u, v) { 58 | var x = (u-0.5) * width; 59 | var y = (v+0.5) * height; 60 | var z = 0; 61 | 62 | return new THREE.Vector3(x, y, z); 63 | }; 64 | } 65 | 66 | function Particle(x, y, z, mass) { 67 | this.position = clothFunction(x, y); // position 68 | this.previous = clothFunction(x, y); // previous 69 | this.original = clothFunction(x, y); 70 | this.a = new THREE.Vector3(0, 0, 0); // acceleration 71 | this.mass = mass; 72 | this.invMass = 1 / mass; 73 | this.tmp = new THREE.Vector3(); 74 | this.tmp2 = new THREE.Vector3(); 75 | } 76 | 77 | // Force -> Acceleration 78 | Particle.prototype.addForce = function(force) { 79 | this.a.add( 80 | this.tmp2.copy(force).multiplyScalar(this.invMass) 81 | ); 82 | }; 83 | 84 | 85 | // Performs verlet integration 86 | Particle.prototype.integrate = function(timesq) { 87 | var newPos = this.tmp.subVectors(this.position, this.previous); 88 | newPos.multiplyScalar(clothProperties.drag).add(this.position); 89 | newPos.add(this.a.multiplyScalar(timesq)); 90 | 91 | this.tmp = this.previous; 92 | this.previous = this.position; 93 | this.position = newPos; 94 | 95 | this.a.set(0, 0, 0); 96 | } 97 | 98 | 99 | var diff = new THREE.Vector3(); 100 | var tmpP1 = new THREE.Vector3(); 101 | 102 | function satisifyConstrains(p1, p2, distance) { 103 | //Original function.... 104 | diff.subVectors(p2.position, p1.position); 105 | var currentDist = diff.length(); 106 | if (currentDist==0) return; // prevents division by 0 107 | var correction = diff.multiplyScalar(1 - distance/currentDist); 108 | var correctionHalf = correction.multiplyScalar(0.5); 109 | p1.position.add(correctionHalf); 110 | p2.position.sub(correctionHalf); 111 | 112 | 113 | //var diff = new THREE.Vector3(); 114 | /*diff.subVectors(p2.position, p1.position); 115 | var currentDist = diff.length(); 116 | if (currentDist==0) return; // prevents division by 0 117 | if (currentDist<15) return; 118 | diff.normalize(); 119 | 120 | diff.multiplyScalar(distance); 121 | 122 | tmpP1.set(0,0,0); 123 | tmpP1.add(p1.position); 124 | 125 | tmpP1.add(diff); 126 | 127 | p2.position.copy(tmpP1);*/ 128 | } 129 | 130 | 131 | function Cloth(w, h) { 132 | w = w || 10; 133 | h = h || 10; 134 | this.w = w; 135 | this.h = h; 136 | 137 | var particles = []; 138 | var constrains = []; 139 | 140 | var u, v; 141 | 142 | // Create particles 143 | for (v=0;v<=h;v++) { 144 | for (u=0;u<=w;u++) { 145 | //console.log("Create Particles: ",u/w, v/h); 146 | particles.push( 147 | new Particle(u/w, v/h, 0, clothProperties.mass) 148 | ); 149 | } 150 | } 151 | 152 | // Structural 153 | 154 | for (v=0;v 1 ) { 45 | 46 | a = 1 - a; 47 | b = 1 - b; 48 | 49 | } 50 | 51 | var c = 1 - a - b; 52 | 53 | point.copy( vectorA ); 54 | point.multiplyScalar( a ); 55 | 56 | vector.copy( vectorB ); 57 | vector.multiplyScalar( b ); 58 | 59 | point.add( vector ); 60 | 61 | vector.copy( vectorC ); 62 | vector.multiplyScalar( c ); 63 | 64 | point.add( vector ); 65 | 66 | return point; 67 | 68 | }; 69 | 70 | }(), 71 | 72 | // Get random point in face (triangle) 73 | // (uniform distribution) 74 | 75 | randomPointInFace: function ( face, geometry ) { 76 | 77 | var vA, vB, vC; 78 | 79 | vA = geometry.vertices[ face.a ]; 80 | vB = geometry.vertices[ face.b ]; 81 | vC = geometry.vertices[ face.c ]; 82 | 83 | return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); 84 | 85 | }, 86 | 87 | // Get uniformly distributed random points in mesh 88 | // - create array with cumulative sums of face areas 89 | // - pick random number from 0 to total area 90 | // - find corresponding place in area array by binary search 91 | // - get random point in face 92 | 93 | randomPointsInGeometry: function ( geometry, n ) { 94 | 95 | var face, i, 96 | faces = geometry.faces, 97 | vertices = geometry.vertices, 98 | il = faces.length, 99 | totalArea = 0, 100 | cumulativeAreas = [], 101 | vA, vB, vC; 102 | 103 | // precompute face areas 104 | 105 | for ( i = 0; i < il; i ++ ) { 106 | 107 | face = faces[ i ]; 108 | 109 | vA = vertices[ face.a ]; 110 | vB = vertices[ face.b ]; 111 | vC = vertices[ face.c ]; 112 | 113 | face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC ); 114 | 115 | totalArea += face._area; 116 | 117 | cumulativeAreas[ i ] = totalArea; 118 | 119 | } 120 | 121 | // binary search cumulative areas array 122 | 123 | function binarySearchIndices( value ) { 124 | 125 | function binarySearch( start, end ) { 126 | 127 | // return closest larger index 128 | // if exact number is not found 129 | 130 | if ( end < start ) 131 | return start; 132 | 133 | var mid = start + Math.floor( ( end - start ) / 2 ); 134 | 135 | if ( cumulativeAreas[ mid ] > value ) { 136 | 137 | return binarySearch( start, mid - 1 ); 138 | 139 | } else if ( cumulativeAreas[ mid ] < value ) { 140 | 141 | return binarySearch( mid + 1, end ); 142 | 143 | } else { 144 | 145 | return mid; 146 | 147 | } 148 | 149 | } 150 | 151 | var result = binarySearch( 0, cumulativeAreas.length - 1 ); 152 | return result; 153 | 154 | } 155 | 156 | // pick random face weighted by face area 157 | 158 | var r, index, 159 | result = []; 160 | 161 | var stats = {}; 162 | 163 | for ( i = 0; i < n; i ++ ) { 164 | 165 | r = Math.random() * totalArea; 166 | 167 | index = binarySearchIndices( r ); 168 | 169 | result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry ); 170 | 171 | if ( ! stats[ index ] ) { 172 | 173 | stats[ index ] = 1; 174 | 175 | } else { 176 | 177 | stats[ index ] += 1; 178 | 179 | } 180 | 181 | } 182 | 183 | return result; 184 | 185 | }, 186 | 187 | randomPointsInBufferGeometry: function ( geometry, n ) { 188 | 189 | var i, 190 | vertices = geometry.attributes.position.array, 191 | totalArea = 0, 192 | cumulativeAreas = [], 193 | vA, vB, vC; 194 | 195 | // precompute face areas 196 | vA = new THREE.Vector3(); 197 | vB = new THREE.Vector3(); 198 | vC = new THREE.Vector3(); 199 | 200 | // geometry._areas = []; 201 | var il = vertices.length / 9; 202 | 203 | for ( i = 0; i < il; i ++ ) { 204 | 205 | vA.set( vertices[ i * 9 + 0 ], vertices[ i * 9 + 1 ], vertices[ i * 9 + 2 ] ); 206 | vB.set( vertices[ i * 9 + 3 ], vertices[ i * 9 + 4 ], vertices[ i * 9 + 5 ] ); 207 | vC.set( vertices[ i * 9 + 6 ], vertices[ i * 9 + 7 ], vertices[ i * 9 + 8 ] ); 208 | 209 | area = THREE.GeometryUtils.triangleArea( vA, vB, vC ); 210 | totalArea += area; 211 | 212 | cumulativeAreas.push( totalArea ); 213 | 214 | } 215 | 216 | // binary search cumulative areas array 217 | 218 | function binarySearchIndices( value ) { 219 | 220 | function binarySearch( start, end ) { 221 | 222 | // return closest larger index 223 | // if exact number is not found 224 | 225 | if ( end < start ) 226 | return start; 227 | 228 | var mid = start + Math.floor( ( end - start ) / 2 ); 229 | 230 | if ( cumulativeAreas[ mid ] > value ) { 231 | 232 | return binarySearch( start, mid - 1 ); 233 | 234 | } else if ( cumulativeAreas[ mid ] < value ) { 235 | 236 | return binarySearch( mid + 1, end ); 237 | 238 | } else { 239 | 240 | return mid; 241 | 242 | } 243 | 244 | } 245 | 246 | var result = binarySearch( 0, cumulativeAreas.length - 1 ); 247 | return result; 248 | 249 | } 250 | 251 | // pick random face weighted by face area 252 | 253 | var r, index, 254 | result = []; 255 | 256 | for ( i = 0; i < n; i ++ ) { 257 | 258 | r = Math.random() * totalArea; 259 | 260 | index = binarySearchIndices( r ); 261 | 262 | // result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true ); 263 | vA.set( vertices[ index * 9 + 0 ], vertices[ index * 9 + 1 ], vertices[ index * 9 + 2 ] ); 264 | vB.set( vertices[ index * 9 + 3 ], vertices[ index * 9 + 4 ], vertices[ index * 9 + 5 ] ); 265 | vC.set( vertices[ index * 9 + 6 ], vertices[ index * 9 + 7 ], vertices[ index * 9 + 8 ] ); 266 | result[ i ] = THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); 267 | 268 | } 269 | 270 | return result; 271 | 272 | }, 273 | 274 | // Get triangle area (half of parallelogram) 275 | // http://mathworld.wolfram.com/TriangleArea.html 276 | 277 | triangleArea: function () { 278 | 279 | var vector1 = new THREE.Vector3(); 280 | var vector2 = new THREE.Vector3(); 281 | 282 | return function ( vectorA, vectorB, vectorC ) { 283 | 284 | vector1.subVectors( vectorB, vectorA ); 285 | vector2.subVectors( vectorC, vectorA ); 286 | vector1.cross( vector2 ); 287 | 288 | return 0.5 * vector1.length(); 289 | 290 | }; 291 | 292 | }(), 293 | 294 | center: function ( geometry ) { 295 | 296 | console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); 297 | return geometry.center(); 298 | 299 | } 300 | 301 | }; 302 | -------------------------------------------------------------------------------- /js/ImprovedNoise.js: -------------------------------------------------------------------------------- 1 | // http://mrl.nyu.edu/~perlin/noise/ 2 | 3 | var ImprovedNoise = function () { 4 | 5 | var p = [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, 6 | 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, 7 | 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, 8 | 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, 9 | 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, 10 | 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, 11 | 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, 12 | 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, 13 | 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, 14 | 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; 15 | 16 | for (var i=0; i < 256 ; i++) { 17 | 18 | p[256+i] = p[i]; 19 | 20 | } 21 | 22 | function fade(t) { 23 | 24 | return t * t * t * (t * (t * 6 - 15) + 10); 25 | 26 | } 27 | 28 | function lerp(t, a, b) { 29 | 30 | return a + t * (b - a); 31 | 32 | } 33 | 34 | function grad(hash, x, y, z) { 35 | 36 | var h = hash & 15; 37 | var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; 38 | return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); 39 | 40 | } 41 | 42 | return { 43 | 44 | noise: function (x, y, z) { 45 | 46 | var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z); 47 | 48 | var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; 49 | 50 | x -= floorX; 51 | y -= floorY; 52 | z -= floorZ; 53 | 54 | var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1; 55 | 56 | var u = fade(x), v = fade(y), w = fade(z); 57 | 58 | var A = p[X]+Y, AA = p[A]+Z, AB = p[A+1]+Z, B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; 59 | 60 | return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), 61 | grad(p[BA], xMinus1, y, z)), 62 | lerp(u, grad(p[AB], x, yMinus1, z), 63 | grad(p[BB], xMinus1, yMinus1, z))), 64 | lerp(v, lerp(u, grad(p[AA+1], x, y, zMinus1), 65 | grad(p[BA+1], xMinus1, y, z-1)), 66 | lerp(u, grad(p[AB+1], x, yMinus1, zMinus1), 67 | grad(p[BB+1], xMinus1, yMinus1, zMinus1)))); 68 | 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /js/Kick.js: -------------------------------------------------------------------------------- 1 | var Kick = function ( o, data ) { 2 | o = o || {}; 3 | this.frequency = o.frequency !== undefined ? o.frequency : [ 0, 10 ]; 4 | this.threshold = o.threshold !== undefined ? o.threshold : 0.3; 5 | this.decay = o.decay !== undefined ? o.decay : 0.02; 6 | this.onKick = o.onKick; 7 | this.offKick = o.offKick; 8 | this.isOn = false; 9 | this.currentThreshold = this.threshold; 10 | this.value = 0; 11 | this.fftData = data; 12 | }; 13 | 14 | Kick.prototype = { 15 | on : function () { 16 | this.isOn = true; 17 | return this; 18 | }, 19 | off : function () { 20 | this.isOn = false; 21 | return this; 22 | }, 23 | 24 | set : function ( o ) { 25 | o = o || {}; 26 | this.frequency = o.frequency !== undefined ? o.frequency : this.frequency; 27 | this.threshold = o.threshold !== undefined ? o.threshold : this.threshold; 28 | this.decay = o.decay !== undefined ? o.decay : this.decay; 29 | this.onKick = o.onKick || this.onKick; 30 | this.offKick = o.offKick || this.offKick; 31 | }, 32 | 33 | onUpdate : function () { 34 | if ( !this.isOn ) { return; } 35 | var magnitude = this.maxAmplitude( this.frequency, this.fftData ); 36 | this.value = magnitude; 37 | if ( magnitude >= this.currentThreshold && 38 | magnitude >= this.threshold ) { 39 | this.currentThreshold = magnitude; 40 | this.onKick && this.onKick.call( this, magnitude ); 41 | } else { 42 | this.offKick && this.offKick.call( this, magnitude ); 43 | this.currentThreshold -= this.decay; 44 | } 45 | }, 46 | maxAmplitude : function ( frequency, fft ) { 47 | var max = 0; 48 | 49 | // Sloppy array check 50 | if ( !frequency.length ) { 51 | return frequency < fft.length ? 52 | fft[ ~~frequency ] : 53 | null; 54 | } 55 | 56 | for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) { 57 | if ( fft[ i ] > max ) { max = fft[ i ]; } 58 | } 59 | return max; 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /js/Maf.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | // Module code from underscore.js 4 | 5 | // Establish the root object, `window` (`self`) in the browser, `global` 6 | // on the server, or `this` in some virtual machines. We use `self` 7 | // instead of `window` for `WebWorker` support. 8 | var root = typeof self == 'object' && self.self === self && self || 9 | typeof global == 'object' && global.global === global && global || 10 | this; 11 | 12 | var Maf = function(obj) { 13 | if (obj instanceof Maf ) return obj; 14 | if (!(this instanceof Maf )) return new Maf(obj); 15 | this._wrapped = obj; 16 | }; 17 | 18 | // Export the Underscore object for **Node.js**, with 19 | // backwards-compatibility for their old module API. If we're in 20 | // the browser, add `Maf` as a global object. 21 | // (`nodeType` is checked to ensure that `module` 22 | // and `exports` are not HTML elements.) 23 | if (typeof exports != 'undefined' && !exports.nodeType) { 24 | if (typeof module != 'undefined' && !module.nodeType && module.exports) { 25 | exports = module.exports = Maf; 26 | } 27 | exports.Maf = Maf; 28 | } else { 29 | root.Maf = Maf; 30 | } 31 | 32 | // Current version. 33 | Maf.VERSION = '1.0.0'; 34 | 35 | Maf.PI = Math.PI; 36 | 37 | // https://www.opengl.org/sdk/docs/man/html/clamp.xhtml 38 | 39 | Maf.clamp = function( v, minVal, maxVal ) { 40 | return Math.min( maxVal, Math.max( minVal, v ) ); 41 | }; 42 | 43 | // https://www.opengl.org/sdk/docs/man/html/step.xhtml 44 | 45 | Maf.step = function( edge, v ) { 46 | return ( v < edge ) ? 0 : 1; 47 | } 48 | 49 | // https://www.opengl.org/sdk/docs/man/html/smoothstep.xhtml 50 | 51 | Maf.smoothStep = function ( edge0, edge1, v ) { 52 | var t = Maf.clamp( ( v - edge0 ) / ( edge1 - edge0 ), 0.0, 1.0 ); 53 | return t * t * ( 3.0 - 2.0 * t ); 54 | }; 55 | 56 | // http://docs.unity3d.com/ScriptReference/Mathf.html 57 | // http://www.shaderific.com/glsl-functions/ 58 | // https://www.opengl.org/sdk/docs/man4/html/ 59 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ff471376(v=vs.85).aspx 60 | // http://moutjs.com/docs/v0.11/math.html#map 61 | // https://code.google.com/p/kuda/source/browse/public/js/hemi/utils/mathUtils.js?r=8d581c02651077c4ac3f5fc4725323210b6b13cc 62 | 63 | // Converts from degrees to radians. 64 | Maf.deg2Rad = function( degrees ) { 65 |   return degrees * Math.PI / 180; 66 | }; 67 | 68 | Maf.toRadians = Maf.deg2Rad; 69 | 70 | // Converts from radians to degrees. 71 | Maf.rad2Deg = function(radians) { 72 |   return radians * 180 / Math.PI; 73 | }; 74 | 75 | Maf.toDegrees = Maf.rad2Deg; 76 | 77 | Maf.clamp01 = function( v ) { 78 | return Maf.clamp( v, 0, 1 ); 79 | }; 80 | 81 | // https://www.opengl.org/sdk/docs/man/html/mix.xhtml 82 | 83 | Maf.mix = function( x, y, a ) { 84 | if( a <= 0 ) return x; 85 | if( a >= 1 ) return y; 86 | return x + a * (y - x) 87 | }; 88 | 89 | Maf.lerp = Maf.mix; 90 | 91 | Maf.inverseMix = function( a, b, v ) { 92 | return ( v - a ) / ( b - a ); 93 | }; 94 | 95 | Maf.inverseLerp = Maf.inverseMix; 96 | 97 | Maf.mixUnclamped = function( x, y, a ) { 98 | if( a <= 0 ) return x; 99 | if( a >= 1 ) return y; 100 | return x + a * (y - x) 101 | }; 102 | 103 | Maf.lerpUnclamped = Maf.mixUnclamped; 104 | 105 | // https://www.opengl.org/sdk/docs/man/html/fract.xhtml 106 | 107 | Maf.fract = function( v ) { 108 | return v - Math.floor( v ); 109 | }; 110 | 111 | Maf.frac = Maf.fract; 112 | 113 | // http://stackoverflow.com/questions/4965301/finding-if-a-number-is-a-power-of-2 114 | 115 | Maf.isPowerOfTwo = function( v ) { 116 | return ( ( ( v - 1) & v ) == 0 ); 117 | }; 118 | 119 | // https://bocoup.com/weblog/find-the-closest-power-of-2-with-javascript 120 | 121 | Maf.closestPowerOfTwo = function( v ) { 122 | return Math.pow( 2, Math.round( Math.log( v ) / Math.log( 2 ) ) ); 123 | }; 124 | 125 | Maf.nextPowerOfTwo = function( v ) { 126 | return Math.pow( 2, Math.ceil( Math.log( v ) / Math.log( 2 ) ) ); 127 | } 128 | 129 | // http://stackoverflow.com/questions/1878907/the-smallest-difference-between-2-angles 130 | 131 | //function mod(a, n) { return a - Math.floor(a/n) * n; } 132 | Maf.mod = function(a, n) { return (a % n + n) % n; } 133 | 134 | Maf.deltaAngle = function( a, b ) { 135 | var d = Maf.mod( b - a, 360 ); 136 | if( d > 180 ) d = Math.abs( d - 360 ); 137 | return d; 138 | }; 139 | 140 | Maf.deltaAngleDeg = Maf.deltaAngle; 141 | 142 | Maf.deltaAngleRad = function( a, b ) { 143 | return Maf.toRadians( Maf.deltaAngle( Maf.toDegrees( a ), Maf.toDegrees( b ) ) ); 144 | }; 145 | 146 | Maf.lerpAngle = function( a, b, t ) { 147 | var angle = Maf.deltaAngle( a, b ); 148 | return Maf.mod( a + Maf.lerp( 0, angle, t ), 360 ); 149 | }; 150 | 151 | Maf.lerpAngleDeg = Maf.lerpAngle; 152 | 153 | Maf.lerpAngleRad = function( a, b, t ) { 154 | return Maf.toRadians( Maf.lerpAngleDeg( Maf.toDegrees( a ), Maf.toDegrees( b ), t ) ); 155 | }; 156 | 157 | // http://gamedev.stackexchange.com/questions/74324/gamma-space-and-linear-space-with-shader 158 | 159 | Maf.gammaToLinearSpace = function( v ) { 160 | return Math.pow( v, 2.2 ); 161 | }; 162 | 163 | Maf.linearToGammaSpace = function( v ) { 164 | return Math.pow( v, 1 / 2.2 ); 165 | }; 166 | 167 | Maf.map = function( from1, to1, from2, to2, v ) { 168 | return from2 + ( v - from1 ) * ( to2 - from2 ) / ( to1 - from1 ); 169 | } 170 | 171 | Maf.scale = Maf.map; 172 | 173 | // http://www.iquilezles.org/www/articles/functions/functions.htm 174 | 175 | Maf.almostIdentity = function( x, m, n ) { 176 | 177 | if( x > m ) return x; 178 | 179 | var a = 2 * n - m; 180 | var b = 2 * m - 3 * n; 181 | var t = x / m; 182 | 183 | return ( a * t + b) * t * t + n; 184 | } 185 | 186 | Maf.impulse = function( k, x ) { 187 | var h = k * x; 188 | return h * Math.exp( 1 - h ); 189 | }; 190 | 191 | Maf.cubicPulse = function( c, w, x ) { 192 | x = Math.abs( x - c ); 193 | if( x > w ) return 0; 194 | x /= w; 195 | return 1 - x * x * ( 3 - 2 * x ); 196 | } 197 | 198 | Maf.expStep = function( x, k, n ) { 199 | return Math.exp( -k * Math.pow( x, n ) ); 200 | } 201 | 202 | Maf.parabola = function( x, k ) { 203 | return Math.pow( 4 * x * ( 1 - x ), k ); 204 | } 205 | 206 | Maf.powerCurve = function( x, a, b ) { 207 | var k = Math.pow( a + b, a + b ) / ( Math.pow( a, a ) * Math.pow( b, b ) ); 208 | return k * Math.pow( x, a ) * Math.pow( 1 - x, b ); 209 | } 210 | 211 | // http://iquilezles.org/www/articles/smin/smin.htm ? 212 | 213 | Maf.latLonToCartesian = function( lat, lon ) { 214 | 215 | lon += 180; 216 | lat = Maf.clamp( lat, -85, 85 ); 217 | var phi = Maf.toRadians( 90 - lat ); 218 | var theta = Maf.toRadians( 180 - lon ); 219 | var x = Math.sin( phi ) * Math.cos( theta ); 220 | var y = Math.cos( phi ); 221 | var z = Math.sin( phi ) * Math.sin( theta ); 222 | 223 | return { x: x, y: y, z: z } 224 | 225 | } 226 | 227 | Maf.cartesianToLatLon = function( x, y, z ) { 228 | var n = Math.sqrt( x * x + y * y + z * z ); 229 | return{ lat: Math.asin( z / n ), lon: Math.atan2( y, x ) }; 230 | } 231 | 232 | Maf.randomInRange = function( min, max ) { 233 | return min + Math.random() * ( max - min ); 234 | } 235 | 236 | Maf.norm = function( v, minVal, maxVal ) { 237 | return ( v - minVal ) / ( maxVal - minVal ); 238 | } 239 | 240 | Maf.hash = function( n ) { 241 | return Maf.fract( (1.0 + Math.cos(n)) * 415.92653); 242 | } 243 | 244 | Maf.noise2d = function( x, y ) { 245 | var xhash = Maf.hash( x * 37.0 ); 246 | var yhash = Maf.hash( y * 57.0 ); 247 | return Maf.fract( xhash + yhash ); 248 | } 249 | 250 | // http://iquilezles.org/www/articles/smin/smin.htm 251 | 252 | Maf.smoothMin = function( a, b, k ) { 253 | var res = Math.exp( -k*a ) + Math.exp( -k*b ); 254 | return - Math.log( res )/k; 255 | } 256 | 257 | Maf.smoothMax = function( a, b, k ){ 258 | return Math.log( Math.exp(a) + Math.exp(b) )/k; 259 | } 260 | 261 | Maf.almost = function( a, b ) { 262 | return ( Math.abs( a - b ) < .0001 ); 263 | } 264 | 265 | }()); -------------------------------------------------------------------------------- /js/MeshCustomMaterial.js: -------------------------------------------------------------------------------- 1 | function MeshCustomMaterial (parameters) { 2 | THREE.MeshStandardMaterial.call( this ); 3 | this.uniforms = THREE.UniformsUtils.merge([ 4 | THREE.UniformsLib.common, 5 | THREE.UniformsLib.aomap, 6 | THREE.UniformsLib.lightmap, 7 | THREE.UniformsLib.emissivemap, 8 | THREE.UniformsLib.bumpmap, 9 | THREE.UniformsLib.normalmap, 10 | THREE.UniformsLib.displacementmap, 11 | THREE.UniformsLib.roughnessmap, 12 | THREE.UniformsLib.metalnessmap, 13 | THREE.UniformsLib.fog, 14 | THREE.UniformsLib.lights, 15 | parameters.u 16 | ]); 17 | 18 | this.vertexShader = parameters.vertexShader; 19 | this.fragmentShader = parameters.fragmentShader; 20 | this.type = 'MeshCustomMaterial'; 21 | 22 | this.setValues(parameters); 23 | } 24 | 25 | MeshCustomMaterial.prototype = Object.create( THREE.MeshStandardMaterial.prototype ); 26 | MeshCustomMaterial.prototype.constructor = MeshCustomMaterial; 27 | MeshCustomMaterial.prototype.isMeshStandardMaterial = true; 28 | 29 | MeshCustomMaterial.prototype.copy = function ( source ) { 30 | THREE.MeshStandardMaterial.prototype.copy.call( this, source ); 31 | this.uniforms = THREE.UniformsUtils.clone(source.uniforms); 32 | setFlags(this); 33 | return this; 34 | }; 35 | -------------------------------------------------------------------------------- /js/Mirror.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Slayvin / http://slayvin.net 3 | */ 4 | 5 | THREE.ShaderLib[ 'mirror' ] = { 6 | 7 | uniforms: { 8 | "mirrorColor": { value: new THREE.Color( 0x7F7F7F ) }, 9 | "mirrorSampler": { value: null }, 10 | "textureMatrix" : { value: new THREE.Matrix4() } 11 | }, 12 | 13 | vertexShader: [ 14 | 15 | "uniform mat4 textureMatrix;", 16 | 17 | "varying vec4 mirrorCoord;", 18 | 19 | "void main() {", 20 | 21 | "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", 22 | "vec4 worldPosition = modelMatrix * vec4( position, 1.0 );", 23 | "mirrorCoord = textureMatrix * worldPosition;", 24 | 25 | "gl_Position = projectionMatrix * mvPosition;", 26 | 27 | "}" 28 | 29 | ].join( "\n" ), 30 | 31 | fragmentShader: [ 32 | 33 | "uniform vec3 mirrorColor;", 34 | "uniform sampler2D mirrorSampler;", 35 | 36 | "varying vec4 mirrorCoord;", 37 | 38 | "float blendOverlay(float base, float blend) {", 39 | "return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );", 40 | "}", 41 | 42 | "void main() {", 43 | 44 | "vec4 color = texture2DProj(mirrorSampler, mirrorCoord);", 45 | "color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b), 1.0);", 46 | 47 | "gl_FragColor = color;", 48 | 49 | "}" 50 | 51 | ].join( "\n" ) 52 | 53 | }; 54 | 55 | THREE.Mirror = function ( renderer, camera, options ) { 56 | 57 | THREE.Object3D.call( this ); 58 | 59 | this.name = 'mirror_' + this.id; 60 | 61 | options = options || {}; 62 | 63 | this.matrixNeedsUpdate = true; 64 | 65 | var width = options.textureWidth !== undefined ? options.textureWidth : 512; 66 | var height = options.textureHeight !== undefined ? options.textureHeight : 512; 67 | 68 | this.clipBias = options.clipBias !== undefined ? options.clipBias : 0.0; 69 | 70 | var mirrorColor = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F ); 71 | 72 | this.renderer = renderer; 73 | this.mirrorPlane = new THREE.Plane(); 74 | this.normal = new THREE.Vector3( 0, 0, 1 ); 75 | this.mirrorWorldPosition = new THREE.Vector3(); 76 | this.cameraWorldPosition = new THREE.Vector3(); 77 | this.rotationMatrix = new THREE.Matrix4(); 78 | this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 ); 79 | this.clipPlane = new THREE.Vector4(); 80 | 81 | // For debug only, show the normal and plane of the mirror 82 | var debugMode = options.debugMode !== undefined ? options.debugMode : false; 83 | 84 | if ( debugMode ) { 85 | 86 | var arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, 0 ), 10, 0xffff80 ); 87 | var planeGeometry = new THREE.Geometry(); 88 | planeGeometry.vertices.push( new THREE.Vector3( - 10, - 10, 0 ) ); 89 | planeGeometry.vertices.push( new THREE.Vector3( 10, - 10, 0 ) ); 90 | planeGeometry.vertices.push( new THREE.Vector3( 10, 10, 0 ) ); 91 | planeGeometry.vertices.push( new THREE.Vector3( - 10, 10, 0 ) ); 92 | planeGeometry.vertices.push( planeGeometry.vertices[ 0 ] ); 93 | var plane = new THREE.Line( planeGeometry, new THREE.LineBasicMaterial( { color: 0xffff80 } ) ); 94 | 95 | this.add( arrow ); 96 | this.add( plane ); 97 | 98 | } 99 | 100 | if ( camera instanceof THREE.PerspectiveCamera ) { 101 | 102 | this.camera = camera; 103 | 104 | } else { 105 | 106 | this.camera = new THREE.PerspectiveCamera(); 107 | console.log( this.name + ': camera is not a Perspective Camera!' ); 108 | 109 | } 110 | 111 | this.textureMatrix = new THREE.Matrix4(); 112 | 113 | this.mirrorCamera = this.camera.clone(); 114 | this.mirrorCamera.matrixAutoUpdate = true; 115 | 116 | var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; 117 | 118 | this.renderTarget = new THREE.WebGLRenderTarget( width, height, parameters ); 119 | this.renderTarget2 = new THREE.WebGLRenderTarget( width, height, parameters ); 120 | 121 | var mirrorShader = THREE.ShaderLib[ "mirror" ]; 122 | var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms ); 123 | 124 | this.material = new THREE.ShaderMaterial( { 125 | 126 | fragmentShader: mirrorShader.fragmentShader, 127 | vertexShader: mirrorShader.vertexShader, 128 | uniforms: mirrorUniforms 129 | 130 | } ); 131 | 132 | this.material.uniforms.mirrorSampler.value = this.renderTarget.texture; 133 | this.material.uniforms.mirrorColor.value = mirrorColor; 134 | this.material.uniforms.textureMatrix.value = this.textureMatrix; 135 | 136 | if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) { 137 | 138 | this.renderTarget.texture.generateMipmaps = false; 139 | this.renderTarget2.texture.generateMipmaps = false; 140 | 141 | } 142 | 143 | this.updateTextureMatrix(); 144 | this.render(); 145 | 146 | }; 147 | 148 | THREE.Mirror.prototype = Object.create( THREE.Object3D.prototype ); 149 | THREE.Mirror.prototype.constructor = THREE.Mirror; 150 | 151 | THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) { 152 | 153 | // update the mirror matrix to mirror the current view 154 | this.updateTextureMatrix(); 155 | this.matrixNeedsUpdate = false; 156 | 157 | // set the camera of the other mirror so the mirrored view is the reference view 158 | var tempCamera = otherMirror.camera; 159 | otherMirror.camera = this.mirrorCamera; 160 | 161 | // render the other mirror in temp texture 162 | otherMirror.renderTemp(); 163 | otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget2.texture; 164 | 165 | // render the current mirror 166 | this.render(); 167 | this.matrixNeedsUpdate = true; 168 | 169 | // restore material and camera of other mirror 170 | otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget.texture; 171 | otherMirror.camera = tempCamera; 172 | 173 | // restore texture matrix of other mirror 174 | otherMirror.updateTextureMatrix(); 175 | 176 | }; 177 | 178 | THREE.Mirror.prototype.updateTextureMatrix = function () { 179 | 180 | this.updateMatrixWorld(); 181 | this.camera.updateMatrixWorld(); 182 | 183 | this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld ); 184 | this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld ); 185 | 186 | this.rotationMatrix.extractRotation( this.matrixWorld ); 187 | 188 | this.normal.set( 0, 0, 1 ); 189 | this.normal.applyMatrix4( this.rotationMatrix ); 190 | 191 | var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition ); 192 | view.reflect( this.normal ).negate(); 193 | view.add( this.mirrorWorldPosition ); 194 | 195 | this.rotationMatrix.extractRotation( this.camera.matrixWorld ); 196 | 197 | this.lookAtPosition.set( 0, 0, - 1 ); 198 | this.lookAtPosition.applyMatrix4( this.rotationMatrix ); 199 | this.lookAtPosition.add( this.cameraWorldPosition ); 200 | 201 | var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition ); 202 | target.reflect( this.normal ).negate(); 203 | target.add( this.mirrorWorldPosition ); 204 | 205 | this.up.set( 0, - 1, 0 ); 206 | this.up.applyMatrix4( this.rotationMatrix ); 207 | this.up.reflect( this.normal ).negate(); 208 | 209 | this.mirrorCamera.position.copy( view ); 210 | this.mirrorCamera.up = this.up; 211 | this.mirrorCamera.lookAt( target ); 212 | 213 | this.mirrorCamera.updateProjectionMatrix(); 214 | this.mirrorCamera.updateMatrixWorld(); 215 | this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld ); 216 | 217 | // Update the texture matrix 218 | this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 219 | 0.0, 0.5, 0.0, 0.5, 220 | 0.0, 0.0, 0.5, 0.5, 221 | 0.0, 0.0, 0.0, 1.0 ); 222 | this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix ); 223 | this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse ); 224 | 225 | // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html 226 | // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf 227 | this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition ); 228 | this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse ); 229 | 230 | this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant ); 231 | 232 | var q = new THREE.Vector4(); 233 | var projectionMatrix = this.mirrorCamera.projectionMatrix; 234 | 235 | q.x = ( Math.sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; 236 | q.y = ( Math.sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; 237 | q.z = - 1.0; 238 | q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; 239 | 240 | // Calculate the scaled plane vector 241 | var c = new THREE.Vector4(); 242 | c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) ); 243 | 244 | // Replacing the third row of the projection matrix 245 | projectionMatrix.elements[ 2 ] = c.x; 246 | projectionMatrix.elements[ 6 ] = c.y; 247 | projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias; 248 | projectionMatrix.elements[ 14 ] = c.w; 249 | 250 | }; 251 | 252 | THREE.Mirror.prototype.render = function () { 253 | 254 | if ( this.matrixNeedsUpdate ) this.updateTextureMatrix(); 255 | 256 | this.matrixNeedsUpdate = true; 257 | 258 | // Render the mirrored view of the current scene into the target texture 259 | var scene = this; 260 | 261 | while ( scene.parent !== null ) { 262 | 263 | scene = scene.parent; 264 | 265 | } 266 | 267 | if ( scene !== undefined && scene instanceof THREE.Scene ) { 268 | 269 | // We can't render ourself to ourself 270 | var visible = this.material.visible; 271 | this.material.visible = false; 272 | 273 | this.renderer.render( scene, this.mirrorCamera, this.renderTarget, true ); 274 | 275 | this.material.visible = visible; 276 | 277 | } 278 | 279 | }; 280 | 281 | THREE.Mirror.prototype.renderTemp = function () { 282 | 283 | if ( this.matrixNeedsUpdate ) this.updateTextureMatrix(); 284 | 285 | this.matrixNeedsUpdate = true; 286 | 287 | // Render the mirrored view of the current scene into the target texture 288 | var scene = this; 289 | 290 | while ( scene.parent !== null ) { 291 | 292 | scene = scene.parent; 293 | 294 | } 295 | 296 | if ( scene !== undefined && scene instanceof THREE.Scene ) { 297 | 298 | this.renderer.render( scene, this.mirrorCamera, this.renderTarget2, true ); 299 | 300 | } 301 | 302 | }; 303 | -------------------------------------------------------------------------------- /js/Odeo.js: -------------------------------------------------------------------------------- 1 | // /ˈôdēˌō/ 2 | 3 | (function () { 4 | var AudioContext = window.AudioContext || window.webkitAudioContext; 5 | 6 | function OdeoSoundCloudPlayer(id, odeo) { 7 | this.id = id; 8 | this.odeo = odeo; 9 | 10 | SC.initialize({ 11 | client_id: this.id, 12 | }); 13 | 14 | this.audio = document.createElement("audio"); 15 | this.audio.loop = true; 16 | this.audio.autoplay = true; 17 | this.audio.crossOrigin = ""; 18 | 19 | this.songSource = this.odeo.context.createMediaElementSource(this.audio); 20 | this.songSource.connect(this.odeo.analyser); 21 | this.songSource.connect(this.odeo.context.destination); 22 | } 23 | 24 | OdeoSoundCloudPlayer.prototype.getSong = function (songURL) { 25 | SC.resolve(songURL).then( 26 | function (song) { 27 | console.log(song); 28 | //songInfo.innerHTML = '

' + song.title + ' PAUSE
' + song.user.username + '

' 29 | 30 | this.audio.src = song.stream_url + "?client_id=" + this.id; 31 | this.audio.play(); 32 | 33 | this.songSource.connect(this.odeo.analyser); 34 | this.songSource.connect(this.odeo.context.destination); 35 | }.bind(this) 36 | ); 37 | }; 38 | 39 | OdeoSoundCloudPlayer.prototype.stop = function () { 40 | this.audio.pause(); 41 | }; 42 | 43 | function OdeoMediaPlayer() {} 44 | 45 | function OdeoMicrophone(odeo) { 46 | this.microphone = null; 47 | this.odeo = odeo; 48 | } 49 | 50 | OdeoMicrophone.prototype.play = function () { 51 | if (navigator.getUserMedia) { 52 | navigator.getUserMedia( 53 | { audio: true }, 54 | function (stream) { 55 | this.microphone = this.odeo.context.createMediaStreamSource(stream); 56 | this.microphone.connect(this.odeo.analyser); 57 | }.bind(this), 58 | function () {} 59 | ); 60 | } else if (navigator.mediaDevices) { 61 | navigator.mediaDevices 62 | .getUserMedia({ audio: true }) 63 | .then( 64 | function (stream) { 65 | this.microphone = this.odeo.context.createMediaStreamSource(stream); 66 | this.microphone.connect(this.odeo.analyser); 67 | }.bind(this) 68 | ) 69 | .catch(function (err) {}); 70 | } 71 | }; 72 | 73 | OdeoMicrophone.prototype.stop = function () { 74 | this.microphone.disconnect(this.odeo.analyser); 75 | }; 76 | 77 | function Odeo(opts) { 78 | this.options = opts || {}; 79 | 80 | this.context = new AudioContext(); 81 | this.analyser = this.context.createAnalyser(); 82 | this.analyser.fftSize = this.options.fftSize || 256; 83 | this.frequencyData = new Uint8Array(this.analyser.frequencyBinCount); 84 | 85 | this.spectrumTexture = null; 86 | 87 | this.soundCloudPlayer = null; 88 | this.microphone = null; 89 | } 90 | 91 | Odeo.prototype.playMedia = function () {}; 92 | 93 | Odeo.prototype.activate = function () { 94 | this.context.resume(); 95 | }; 96 | 97 | Odeo.prototype.useMicrophone = function () { 98 | if (!this.microphone) this.microphone = new OdeoMicrophone(this); 99 | this.microphone.play(); 100 | }; 101 | 102 | Odeo.prototype.stopUsingMicrophone = function () { 103 | if (!this.microphone) return; 104 | this.microphone.stop(); 105 | }; 106 | 107 | Odeo.prototype.playSoundCloud = function (url) { 108 | if (!this.soundCloudPlayer) 109 | this.soundCloudPlayer = new OdeoSoundCloudPlayer( 110 | this.options.soundCloudId, 111 | this 112 | ); 113 | this.soundCloudPlayer.getSong(url); 114 | }; 115 | 116 | Odeo.prototype.stopSoundCloud = function (url) { 117 | if (!this.soundCloudPlayer) return; 118 | this.soundCloudPlayer.stop(); 119 | }; 120 | 121 | Odeo.prototype.getSpectrumTexture = function () { 122 | this.spectrumTexture = new THREE.DataTexture( 123 | this.frequencyData, 124 | 1 * this.frequencyData.length, 125 | 1, 126 | THREE.LuminanceFormat 127 | ); 128 | this.spectrumTexture.minFilter = THREE.NearestFilter; 129 | this.spectrumTexture.magFilter = THREE.NearestFilter; 130 | this.spectrumTexture.needsUpdate = true; 131 | 132 | return this.spectrumTexture; 133 | }; 134 | 135 | Odeo.prototype.update = function () { 136 | this.analyser.getByteFrequencyData(this.frequencyData); 137 | if (this.spectrumTexture) this.spectrumTexture.needsUpdate = true; 138 | //kick.onUpdate(); 139 | }; 140 | 141 | window.Odeo = Odeo; 142 | })(); 143 | -------------------------------------------------------------------------------- /js/Sound.js: -------------------------------------------------------------------------------- 1 | var id = 'b1275b704badf79d972d51aa4b92ea15'; 2 | 3 | SC.initialize({ 4 | client_id: id 5 | }); 6 | 7 | if( 'webkitAudioContext' in window ) { 8 | var AudioContext = webkitAudioContext; 9 | } 10 | 11 | var raycaster = new THREE.Raycaster(); 12 | var mouse = new THREE.Vector2(); 13 | 14 | var audio = document.createElement( 'audio' ); 15 | audio.loop = true; 16 | audio.autoplay = true; 17 | audio.crossOrigin = ''; 18 | var context = new AudioContext(); 19 | var analyser = context.createAnalyser(); 20 | analyser.fftSize = 256; 21 | var frequencyData = new Uint8Array( analyser.frequencyBinCount ); 22 | 23 | var songSource = context.createMediaElementSource( audio ); 24 | songSource.connect( analyser ); 25 | songSource.connect( context.destination ); 26 | 27 | var kick = new Kick({ 28 | frequency: [ 5, 20 ], 29 | decay: 0.04, 30 | onKick: function() { 31 | lighting = 1; 32 | }, 33 | offKick: function() { 34 | lighting *= .95; 35 | } 36 | }); 37 | kick.on(); 38 | 39 | var spectrumTexture = new THREE.DataTexture( frequencyData, .5 * frequencyData.length, 1, THREE.LuminanceFormat ); 40 | spectrumTexture.minFilter = THREE.NearestFilter; 41 | spectrumTexture.magFilter = THREE.NearestFilter; 42 | spectrumTexture.needsUpdate = true; 43 | 44 | var microphone; 45 | 46 | function resetSound() { 47 | if( microphone ) { 48 | microphone.disconnect(); 49 | } 50 | if( songSource ) { 51 | songSource.disconnect(); 52 | } 53 | } 54 | 55 | var songPanel = document.getElementById( 'songPanel' ); 56 | var songInfo = document.getElementById( 'songInfo' ); 57 | var sharePanel = document.getElementById( 'sharePanel' ); 58 | 59 | function getSong( songURL ) { 60 | SC.resolve( songURL ).then( function(song){ 61 | songInfo.innerHTML = '

' + song.title + ' PAUSE
' + song.user.username + '

' 62 | audio.src = song.stream_url + "?client_id=" + id; 63 | songSource.connect( analyser ); 64 | songSource.connect( context.destination ); 65 | songPanel.classList.remove( 'hidden' ); 66 | 67 | document.getElementById( 'pauseBtn' ).addEventListener( 'click', function( e ) { 68 | if( audio.paused ) { 69 | this.textContent = 'PAUSE'; 70 | audio.play(); 71 | } else { 72 | this.textContent = 'PLAY'; 73 | audio.pause(); 74 | } 75 | e.preventDefault(); 76 | }); 77 | 78 | var baseUrl = 'https://www.clicktorelease.com/code/pumpkin-jam' 79 | var url = baseUrl + '#p=' + PUMPKINS + '&u=' + encodeURIComponent( songURL ); 80 | shareFacebookBtn.onclick = function( e ) { 81 | 82 | window.open( 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent( url ), 'facebook-share-dialog', 'width=626,height=436'); 83 | return false; 84 | } 85 | 86 | shareTwitterBtn.onclick = function( e ) { 87 | 88 | var msg = 'This is my pumpkin jam! ' + url; 89 | window.open( 'https://twitter.com/intent/tweet?original_referer=' + encodeURIComponent( url ) + '&text=' + encodeURIComponent( msg ), 'twitter-share-dialog', 'width=626,height=436'); 90 | return false; 91 | } 92 | 93 | requestAnimationFrame( start ); 94 | }); 95 | } 96 | 97 | function getMicrophone() { 98 | 99 | if( microphone ) { 100 | microphone.connect( analyser ); 101 | return; 102 | } 103 | 104 | navigator.getUserMedia( { audio: true }, function(stream) { 105 | 106 | microphone = context.createMediaStreamSource(stream); 107 | microphone.connect( analyser ); 108 | start(); 109 | 110 | }, 111 | function(err) { 112 | } ); 113 | 114 | } 115 | -------------------------------------------------------------------------------- /js/THREE.ConstantSpline.js: -------------------------------------------------------------------------------- 1 | THREE.ConstantSpline = function() { 2 | 3 | this.p0 = new THREE.Vector3(); 4 | this.p1 = new THREE.Vector3(); 5 | this.p2 = new THREE.Vector3(); 6 | this.p3 = new THREE.Vector3(); 7 | 8 | this.tmp = new THREE.Vector3(); 9 | this.res = new THREE.Vector3(); 10 | this.o = new THREE.Vector3(); 11 | 12 | this.points = []; 13 | this.lPoints = []; 14 | this.steps = []; 15 | 16 | this.inc = .01; 17 | this.d = 0; 18 | 19 | this.distancesNeedUpdate = false; 20 | 21 | }; 22 | 23 | THREE.ConstantSpline.prototype.calculate = function() { 24 | 25 | this.d = 0; 26 | this.points = []; 27 | 28 | this.o.copy( this.p0 ); 29 | 30 | for( var j = 0; j <= 1; j += this.inc ) { 31 | 32 | var i = ( 1 - j ); 33 | var ii = i * i; 34 | var iii = ii * i; 35 | var jj = j * j; 36 | var jjj = jj * j; 37 | 38 | this.res.set( 0, 0, 0 ); 39 | 40 | this.tmp.copy( this.p0 ); 41 | this.tmp.multiplyScalar( iii ); 42 | this.res.add( this.tmp ); 43 | 44 | this.tmp.copy( this.p1 ); 45 | this.tmp.multiplyScalar( 3 * j * ii ); 46 | this.res.add( this.tmp ); 47 | 48 | this.tmp.copy( this.p2 ); 49 | this.tmp.multiplyScalar( 3 * jj * i ); 50 | this.res.add( this.tmp ); 51 | 52 | this.tmp.copy( this.p3 ); 53 | this.tmp.multiplyScalar( jjj ); 54 | this.res.add( this.tmp ); 55 | 56 | this.points.push( this.res.clone() ); 57 | 58 | } 59 | 60 | this.points.push( this.p3.clone() ); 61 | 62 | this.distancesNeedUpdate = true; 63 | 64 | }; 65 | 66 | THREE.ConstantSpline.prototype.calculateDistances = function() { 67 | 68 | this.steps = []; 69 | this.d = 0; 70 | 71 | var from, to, td = 0; 72 | 73 | for( var j = 0; j < this.points.length - 1; j++ ) { 74 | 75 | this.points[ j ].distance = td; 76 | this.points[ j ].ac = this.d; 77 | 78 | from = this.points[ j ], 79 | to = this.points[ j + 1 ], 80 | td = to.distanceTo( from ); 81 | 82 | this.d += td; 83 | 84 | } 85 | 86 | this.points[ this.points.length - 1 ].distance = 0; 87 | this.points[ this.points.length - 1 ].ac = this.d; 88 | 89 | } 90 | 91 | THREE.ConstantSpline.prototype.reticulate = function( settings ) { 92 | 93 | if( this.distancesNeedUpdate ) { 94 | this.calculateDistances(); 95 | this.distancesNeedUpdate = false; 96 | } 97 | 98 | this.lPoints = []; 99 | 100 | var l = []; 101 | 102 | var steps, distancePerStep; 103 | 104 | if( settings.steps) { 105 | steps = settings.steps; 106 | distancePerStep = this.d / steps; 107 | } 108 | 109 | if( settings.distancePerStep ) { 110 | distancePerStep = settings.distancePerStep; 111 | steps = this.d / distancePerStep; 112 | } 113 | 114 | var d = 0, 115 | p = 0; 116 | 117 | this.lPoints = []; 118 | 119 | var current = new THREE.Vector3(); 120 | current.copy( this.points[ 0 ].clone() ); 121 | this.lPoints.push( current.clone() ); 122 | 123 | function splitSegment( a, b, l ) { 124 | 125 | var t = b.clone(); 126 | var d = 0; 127 | t.sub( a ); 128 | var rd = t.length(); 129 | t.normalize(); 130 | t.multiplyScalar( distancePerStep ); 131 | var s = Math.floor( rd / distancePerStep ); 132 | for( var j = 0; j < s; j++ ) { 133 | a.add( t ); 134 | l.push( a.clone() ); 135 | d += distancePerStep; 136 | } 137 | return d; 138 | } 139 | 140 | for( var j = 0; j < this.points.length; j++ ) { 141 | 142 | if( this.points[ j ].ac - d > distancePerStep ) { 143 | 144 | d += splitSegment( current, this.points[ j ], this.lPoints ); 145 | 146 | } 147 | 148 | } 149 | this.lPoints.push( this.points[ this.points.length - 1 ].clone() ); 150 | 151 | 152 | }; 153 | -------------------------------------------------------------------------------- /js/THREE.ShaderTexture.js: -------------------------------------------------------------------------------- 1 | function ShaderTexture( renderer, shader, width, height ) { 2 | 3 | this.renderer = renderer; 4 | this.shader = shader; 5 | this.orthoScene = new THREE.Scene(); 6 | this.fbo = new THREE.WebGLRenderTarget( width, height, { 7 | wrapS: THREE.RepeatWrapping, 8 | wrapT: THREE.RepeatWrapping 9 | } ); 10 | this.orthoCamera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, .00001, 1000 ); 11 | this.orthoQuad = new THREE.Mesh( new THREE.PlaneBufferGeometry( width, height ), this.shader ); 12 | this.orthoScene.add( this.orthoQuad ); 13 | this.texture = this.fbo.texture; 14 | 15 | } 16 | 17 | ShaderTexture.prototype.render = function() { 18 | 19 | this.renderer.render( this.orthoScene, this.orthoCamera, this.fbo ); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /js/isMobile.min.js: -------------------------------------------------------------------------------- 1 | !function(a){var b=/iPhone/i,c=/iPod/i,d=/iPad/i,e=/(?=.*\bAndroid\b)(?=.*\bMobile\b)/i,f=/Android/i,g=/(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i,h=/(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i,i=/Windows Phone/i,j=/(?=.*\bWindows\b)(?=.*\bARM\b)/i,k=/BlackBerry/i,l=/BB10/i,m=/Opera Mini/i,n=/(CriOS|Chrome)(?=.*\bMobile\b)/i,o=/(?=.*\bFirefox\b)(?=.*\bMobile\b)/i,p=new RegExp("(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)","i"),q=function(a,b){return a.test(b)},r=function(a){var r=a||navigator.userAgent,s=r.split("[FBAN");if("undefined"!=typeof s[1]&&(r=s[0]),s=r.split("Twitter"),"undefined"!=typeof s[1]&&(r=s[0]),this.apple={phone:q(b,r),ipod:q(c,r),tablet:!q(b,r)&&q(d,r),device:q(b,r)||q(c,r)||q(d,r)},this.amazon={phone:q(g,r),tablet:!q(g,r)&&q(h,r),device:q(g,r)||q(h,r)},this.android={phone:q(g,r)||q(e,r),tablet:!q(g,r)&&!q(e,r)&&(q(h,r)||q(f,r)),device:q(g,r)||q(h,r)||q(e,r)||q(f,r)},this.windows={phone:q(i,r),tablet:q(j,r),device:q(i,r)||q(j,r)},this.other={blackberry:q(k,r),blackberry10:q(l,r),opera:q(m,r),firefox:q(o,r),chrome:q(n,r),device:q(k,r)||q(l,r)||q(m,r)||q(o,r)||q(n,r)},this.seven_inch=q(p,r),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,"undefined"==typeof window)return this},s=function(){var a=new r;return a.Class=r,a};"undefined"!=typeof module&&module.exports&&"undefined"==typeof window?module.exports=r:"undefined"!=typeof module&&module.exports&&"undefined"!=typeof window?module.exports=s():"function"==typeof define&&define.amd?define("isMobile",[],a.isMobile=s()):a.isMobile=s()}(this); --------------------------------------------------------------------------------