├── .eslintrc ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── _layouts └── default.html ├── css ├── highlight.css └── style.scss ├── deprecated ├── snapshot.js ├── webgl-ocean-shader.js └── webgl-sky-sun-shader.js ├── dist ├── clapper.js ├── clone.js ├── curve.js ├── fire-item.js ├── follow.js └── ocean-plane.js └── index.md /.eslintrc: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | _site 39 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'github-pages', group: :jekyll_plugins 3 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | RedCloth (4.2.9) 5 | activesupport (4.2.6) 6 | i18n (~> 0.7) 7 | json (~> 1.7, >= 1.7.7) 8 | minitest (~> 5.1) 9 | thread_safe (~> 0.3, >= 0.3.4) 10 | tzinfo (~> 1.1) 11 | addressable (2.4.0) 12 | coffee-script (2.4.1) 13 | coffee-script-source 14 | execjs 15 | coffee-script-source (1.10.0) 16 | colorator (0.1) 17 | ethon (0.8.1) 18 | ffi (>= 1.3.0) 19 | execjs (2.6.0) 20 | faraday (0.9.2) 21 | multipart-post (>= 1.2, < 3) 22 | ffi (1.9.10) 23 | gemoji (2.1.0) 24 | github-pages (69) 25 | RedCloth (= 4.2.9) 26 | github-pages-health-check (= 1.1.0) 27 | jekyll (= 3.0.3) 28 | jekyll-coffeescript (= 1.0.1) 29 | jekyll-feed (= 0.4.0) 30 | jekyll-gist (= 1.4.0) 31 | jekyll-github-metadata (= 1.11.0) 32 | jekyll-mentions (= 1.1.2) 33 | jekyll-paginate (= 1.1.0) 34 | jekyll-redirect-from (= 0.10.0) 35 | jekyll-sass-converter (= 1.3.0) 36 | jekyll-seo-tag (= 1.3.3) 37 | jekyll-sitemap (= 0.10.0) 38 | jekyll-textile-converter (= 0.1.0) 39 | jemoji (= 0.6.2) 40 | kramdown (= 1.10.0) 41 | liquid (= 3.0.6) 42 | mercenary (~> 0.3) 43 | rdiscount (= 2.1.8) 44 | redcarpet (= 3.3.3) 45 | rouge (= 1.10.1) 46 | terminal-table (~> 1.4) 47 | github-pages-health-check (1.1.0) 48 | addressable (~> 2.3) 49 | net-dns (~> 0.8) 50 | octokit (~> 4.0) 51 | public_suffix (~> 1.4) 52 | typhoeus (~> 0.7) 53 | html-pipeline (2.4.0) 54 | activesupport (>= 2, < 5) 55 | nokogiri (>= 1.4) 56 | i18n (0.7.0) 57 | jekyll (3.0.3) 58 | colorator (~> 0.1) 59 | jekyll-sass-converter (~> 1.0) 60 | jekyll-watch (~> 1.1) 61 | kramdown (~> 1.3) 62 | liquid (~> 3.0) 63 | mercenary (~> 0.3.3) 64 | rouge (~> 1.7) 65 | safe_yaml (~> 1.0) 66 | jekyll-coffeescript (1.0.1) 67 | coffee-script (~> 2.2) 68 | jekyll-feed (0.4.0) 69 | jekyll-gist (1.4.0) 70 | octokit (~> 4.2) 71 | jekyll-github-metadata (1.11.0) 72 | octokit (~> 4.0) 73 | jekyll-mentions (1.1.2) 74 | html-pipeline (~> 2.3) 75 | jekyll (~> 3.0) 76 | jekyll-paginate (1.1.0) 77 | jekyll-redirect-from (0.10.0) 78 | jekyll (>= 2.0) 79 | jekyll-sass-converter (1.3.0) 80 | sass (~> 3.2) 81 | jekyll-seo-tag (1.3.3) 82 | jekyll (~> 3.0) 83 | jekyll-sitemap (0.10.0) 84 | jekyll-textile-converter (0.1.0) 85 | RedCloth (~> 4.0) 86 | jekyll-watch (1.3.1) 87 | listen (~> 3.0) 88 | jemoji (0.6.2) 89 | gemoji (~> 2.0) 90 | html-pipeline (~> 2.2) 91 | jekyll (>= 3.0) 92 | json (1.8.3) 93 | kramdown (1.10.0) 94 | liquid (3.0.6) 95 | listen (3.0.6) 96 | rb-fsevent (>= 0.9.3) 97 | rb-inotify (>= 0.9.7) 98 | mercenary (0.3.6) 99 | mini_portile2 (2.0.0) 100 | minitest (5.8.4) 101 | multipart-post (2.0.0) 102 | net-dns (0.8.0) 103 | nokogiri (1.6.7.2) 104 | mini_portile2 (~> 2.0.0.rc2) 105 | octokit (4.3.0) 106 | sawyer (~> 0.7.0, >= 0.5.3) 107 | public_suffix (1.5.3) 108 | rb-fsevent (0.9.7) 109 | rb-inotify (0.9.7) 110 | ffi (>= 0.5.0) 111 | rdiscount (2.1.8) 112 | redcarpet (3.3.3) 113 | rouge (1.10.1) 114 | safe_yaml (1.0.4) 115 | sass (3.4.22) 116 | sawyer (0.7.0) 117 | addressable (>= 2.3.5, < 2.5) 118 | faraday (~> 0.8, < 0.10) 119 | terminal-table (1.5.2) 120 | thread_safe (0.3.5) 121 | typhoeus (0.8.0) 122 | ethon (>= 0.8.0) 123 | tzinfo (1.2.2) 124 | thread_safe (~> 0.1) 125 | 126 | PLATFORMS 127 | ruby 128 | 129 | DEPENDENCIES 130 | github-pages 131 | 132 | BUNDLED WITH 133 | 1.11.2 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Samsung Internet Dev Rel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{ page.title }} 13 | {% if page.image %} 14 | 15 | 16 | {% else %} 17 | 18 | {% endif %} 19 | 20 | 21 | {% if page.title %} 22 | 23 | {% endif %} 24 | {% if page.link %} 25 | 26 | {% endif %} 27 | {% if page.description %} 28 | 29 | 30 | {% endif %} 31 | {% if page.script %} 32 | 33 | {% endif %} 34 | {% if page.scripts %} 35 | {% for item in page.scripts %} 36 | 37 | {% endfor %} 38 | {% endif %} 39 | {% if page.style %} 40 | 41 | {% endif %} 42 | {% if page.styles %} 43 | {% for item in page.styles %} 44 | 45 | {% endfor %} 46 | {% endif %} 47 | 48 | 49 |
50 |

{{ page.title }}

51 | {% if page.author %}

by {{ page.author }}

{% endif %} 52 |
53 |
54 |
55 | {{ content }} 56 |
57 |
58 | Fork me on GitHub 59 | 62 | 63 | -------------------------------------------------------------------------------- /css/highlight.css: -------------------------------------------------------------------------------- 1 | .highlight { 2 | background-color: #333; 3 | color: white; 4 | white-space: pre-wrap; 5 | word-break: break-word; 6 | } 7 | 8 | .highlight .hll { background-color: #49483e } 9 | .highlight .c { color: #75715e } /* Comment */ 10 | .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ 11 | .highlight .k { color: #66d9ef } /* Keyword */ 12 | .highlight .l { color: #ae81ff } /* Literal */ 13 | .highlight .n { color: #f8f8f2 } /* Name */ 14 | .highlight .o { color: #f92672 } /* Operator */ 15 | .highlight .p { color: #f8f8f2 } /* Punctuation */ 16 | .highlight .cm { color: #75715e } /* Comment.Multiline */ 17 | .highlight .cp { color: #75715e } /* Comment.Preproc */ 18 | .highlight .c1 { color: #75715e } /* Comment.Single */ 19 | .highlight .cs { color: #75715e } /* Comment.Special */ 20 | .highlight .ge { font-style: italic } /* Generic.Emph */ 21 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 22 | .highlight .kc { color: #66d9ef } /* Keyword.Constant */ 23 | .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ 24 | .highlight .kn { color: #f92672 } /* Keyword.Namespace */ 25 | .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ 26 | .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ 27 | .highlight .kt { color: #66d9ef } /* Keyword.Type */ 28 | .highlight .ld { color: #e6db74 } /* Literal.Date */ 29 | .highlight .m { color: #ae81ff } /* Literal.Number */ 30 | .highlight .s { color: #e6db74 } /* Literal.String */ 31 | .highlight .na { color: #a6e22e } /* Name.Attribute */ 32 | .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ 33 | .highlight .nc { color: #a6e22e } /* Name.Class */ 34 | .highlight .no { color: #66d9ef } /* Name.Constant */ 35 | .highlight .nd { color: #a6e22e } /* Name.Decorator */ 36 | .highlight .ni { color: #f8f8f2 } /* Name.Entity */ 37 | .highlight .ne { color: #a6e22e } /* Name.Exception */ 38 | .highlight .nf { color: #a6e22e } /* Name.Function */ 39 | .highlight .nl { color: #f8f8f2 } /* Name.Label */ 40 | .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ 41 | .highlight .nx { color: #a6e22e } /* Name.Other */ 42 | .highlight .py { color: #f8f8f2 } /* Name.Property */ 43 | .highlight .nt { color: #f92672 } /* Name.Tag */ 44 | .highlight .nv { color: #f8f8f2 } /* Name.Variable */ 45 | .highlight .ow { color: #f92672 } /* Operator.Word */ 46 | .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ 47 | .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ 48 | .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ 49 | .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ 50 | .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ 51 | .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #e6db74 } /* Literal.String.Char */ 53 | .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ 54 | .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ 55 | .highlight .se { color: #ae81ff } /* Literal.String.Escape */ 56 | .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ 57 | .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ 58 | .highlight .sx { color: #e6db74 } /* Literal.String.Other */ 59 | .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ 60 | .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ 61 | .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ 62 | .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ 63 | .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ 64 | .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ 65 | .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ 66 | .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ 67 | 68 | .highlight .gh { } /* Generic Heading & Diff Header */ 69 | .highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ 70 | .highlight .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ 71 | .highlight .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ -------------------------------------------------------------------------------- /css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | html, body { 5 | font-family: MetricWeb, 'Open Sans', sans-serif; 6 | font-weight: 400; 7 | color: #333; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | h1, h2, h3, h4, h5, h6 { 12 | font-weight: 300; 13 | } 14 | h2, h3 { 15 | &:before { 16 | content: ''; 17 | clear: both; 18 | display: block; 19 | height: 2em; 20 | } 21 | margin: 0 0 1.5em 0; 22 | border-bottom: 1px solid grey; 23 | } 24 | a { 25 | color: #336ACE; 26 | } 27 | h2 a { 28 | text-decoration: none; 29 | } 30 | .title { 31 | margin: 0; 32 | padding: 2em 1em 1em 1em; 33 | position: relative; 34 | border-bottom: 1px solid grey; 35 | color: white; 36 | background: #A25AFF; 37 | 38 | &:after { 39 | content: ''; 40 | position: absolute; 41 | bottom: -1em; 42 | height: 2em; 43 | width: 2em; 44 | background: white; 45 | border: 1px solid grey; 46 | border-width: 1px 0 0 1px; 47 | transform: rotate(45deg); 48 | left: 3em; 49 | font-size: 12px; 50 | } 51 | 52 | h1 { 53 | font-size: 2em; 54 | text-decoration: none; 55 | } 56 | h3 { 57 | border: none; 58 | } 59 | } 60 | 61 | img { 62 | max-width: 100%; 63 | max-height: 66vmin; 64 | float: right; 65 | &+em { 66 | max-width: 100%; 67 | max-height: 66vmin; 68 | float: right; 69 | background: #F9F8BF; 70 | border-bottom: 1px solid grey; 71 | clear: right; 72 | margin: 0 0 0.5em 3em; 73 | } 74 | } 75 | .lifted { 76 | position:relative; 77 | background:#fff; 78 | box-shadow:0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset; 79 | padding: 0.2em 0.5em; 80 | border-radius: 0.5em; 81 | cursor: move; 82 | color: inherit; 83 | text-decoration: none; 84 | 85 | &:active, 86 | &:hover, 87 | &::visited { 88 | color: inherit; 89 | } 90 | 91 | &:before, 92 | &:after { 93 | content: ""; 94 | position: absolute; 95 | z-index: -1; 96 | bottom:15px; 97 | left:3%; 98 | width:50%; 99 | height:20%; 100 | max-width:300px; 101 | box-shadow:0 15px 10px rgba(0, 0, 0, 0.7); 102 | transform:rotate(-3deg); 103 | } 104 | &:after { 105 | right:3%; 106 | left:auto; 107 | transform:rotate(3deg); 108 | } 109 | } 110 | 111 | .code { 112 | font-family: monospace; 113 | display: inline; 114 | white-space: wrap; 115 | } 116 | 117 | pre { 118 | display: block; 119 | border: 1px solid rgba(100, 100, 100, 0.5); 120 | background: 1px solid rgba(100, 100, 100, 0.3); 121 | padding: 0.5em; 122 | margin: 1em; 123 | overflow: auto; 124 | tab-size: 4; 125 | white-space: wrap; 126 | } 127 | 128 | footer { 129 | padding: 1em; 130 | border-top: 1px solid #ccc; 131 | } -------------------------------------------------------------------------------- /deprecated/snapshot.js: -------------------------------------------------------------------------------- 1 | var MAX_DELTA = 0.2; 2 | 3 | var vS = 'void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);}'; 4 | var fS = '\nuniform samplerCube cubemapTexture;\nuniform vec2 resolution;\n\nvoid main( void )\n{\n vec2 texCoord = gl_FragCoord.xy / resolution;\n vec2 thetaphi = ((texCoord * 2.0) - vec2(1.0)) * vec2(3.1415926535897932384626433832795, 1.5707963267948966192313216916398);\n vec3 rayDirection = vec3(cos(thetaphi.y) * cos(thetaphi.x), sin(thetaphi.y), cos(thetaphi.y) * sin(thetaphi.x));\n gl_FragColor = textureCube(cubemapTexture, rayDirection);\n}\n '; 5 | 6 | // Icon by Fabián Alexis 7 | // https://commons.wikimedia.org/wiki/File:Antu_folder-camera.svg 8 | var icon = 'url("data:image/svg+xml,' + encodeURIComponent('') + '")'; 9 | 10 | /** 11 | * WASD component to control entities using WASD keys. 12 | */ 13 | AFRAME.registerComponent('snapshot', { 14 | schema: { 15 | width: {default: 4096}, 16 | height: {default: 2048} 17 | }, 18 | 19 | init: function () { 20 | this.sceneEl = this.el.sceneEl || this.el; 21 | 22 | this.onKeyDown = (function (event) { 23 | if(event.altKey && event.ctrlKey && (event.code === 'keyP' || event.keyCode === 80)) { 24 | this.snapshot(); 25 | } 26 | }.bind(this)); 27 | this.attachKeyEventListeners(); 28 | }, 29 | 30 | tick: function () { 31 | if (!this.button) { 32 | var target = document.querySelector('.a-enter-vr'); 33 | if (target) { 34 | this.button = document.createElement('button'); 35 | this.button.classList.add('a-enter-vr-button'); 36 | this.button.style.backgroundImage = icon; 37 | this.button.style.backgroundSize = '80%'; 38 | this.button.addEventListener('click', this.snapshot.bind(this)); 39 | target.appendChild(this.button); 40 | 41 | Array.from(target.getElementsByClassName('a-enter-vr-button')).forEach(function (el) { 42 | el.style.float = 'right'; 43 | el.style.position = 'relative'; 44 | el.style.marginLeft = '2px'; 45 | }) 46 | } 47 | } 48 | }, 49 | 50 | update: function () { 51 | this.cubeCamera = new AFRAME.THREE.CubeCamera(0.01, 100000, this.data.height); 52 | 53 | // Get sceneEl 54 | this.material = new AFRAME.THREE.ShaderMaterial({ 55 | 56 | uniforms: { 57 | cubemapTexture: this.cubeCamera.renderTarget.texture , 58 | resolution: { value: new AFRAME.THREE.Vector2(this.data.width, -this.data.height) }, 59 | }, 60 | vertexShader: vS, 61 | fragmentShader: fS 62 | }); 63 | }, 64 | 65 | remove: function () { 66 | this.removeKeyEventListeners(); 67 | if (this.button) { 68 | this.button.parentNode.removeChild(this.button); 69 | } 70 | }, 71 | 72 | attachKeyEventListeners: function () { 73 | window.addEventListener('keydown', this.onKeyDown); 74 | }, 75 | 76 | removeKeyEventListeners: function () { 77 | window.removeEventListener('keydown', this.onKeyDown); 78 | }, 79 | 80 | snapshot: function () { 81 | var scene = this.sceneEl.object3D; 82 | var renderer = this.sceneEl.renderer; 83 | var camScale = 0.15; 84 | 85 | if (window.renderOrigin) { 86 | this.cubeCamera.position.copy(window.renderOrigin); 87 | } else { 88 | this.cubeCamera.position.copy(this.sceneEl.camera.getWorldPosition()); 89 | } 90 | scene.add(this.cubeCamera); 91 | this.cubeCamera.updateCubeMap(renderer, scene); 92 | 93 | var orthoCamera = new AFRAME.THREE.OrthographicCamera(0.5 * camScale * this.data.width / -this.data.height, 0.5 * camScale * this.data.width / this.data.height, camScale * 0.5, camScale * -0.5, 0.1, 100); 94 | this.sceneEl.camera.add(orthoCamera); 95 | renderer.render(scene, orthoCamera); 96 | var plane = new AFRAME.THREE.Mesh(new AFRAME.THREE.PlaneGeometry(camScale * this.data.width / this.data.height, camScale * 1), this.material); 97 | orthoCamera.add(plane); 98 | plane.position.set(0, 0, -1); 99 | 100 | // hack to ensure material gets rendered 101 | var chromeMaterial = new AFRAME.THREE.MeshLambertMaterial({ color: 0xffffff, envMap: this.cubeCamera.renderTarget }); 102 | plane.material = chromeMaterial; 103 | 104 | requestAnimationFrame(function () { 105 | 106 | plane.material = this.material; 107 | var old = renderer.getSize(); 108 | 109 | renderer.setSize(this.data.width, this.data.height); 110 | renderer.render(scene, orthoCamera); 111 | window.open(renderer.domElement.toDataURL()); 112 | renderer.setSize(old.width, old.height); 113 | 114 | this.sceneEl.camera.remove(orthoCamera); 115 | 116 | }.bind(this)); 117 | } 118 | 119 | }); 120 | -------------------------------------------------------------------------------- /deprecated/webgl-ocean-shader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Based on https://github.com/mrdoob/three.js/blob/dev/examples/webgl_shaders_ocean.html 3 | * Requires: 4 | * 5 | * 'https://cdn.rawgit.com/mrdoob/three.js/82bd697ef06acf5c4173775abe053d7a499a6722/examples/js/Mirror.js', 6 | * 'https://cdn.rawgit.com/mrdoob/three.js/82bd697ef06acf5c4173775abe053d7a499a6722/examples/js/WaterShader.js' 7 | * 8 | */ 9 | 10 | 11 | // 12 | 13 | function colorParse(str) { 14 | return (new THREE.Color(str)).getHex(); 15 | } 16 | 17 | AFRAME.registerComponent('a-ada-ocean', { 18 | 19 | schema: { 20 | src: { type: 'src' }, 21 | width: { default: 1000 }, 22 | depth: { default: 1000 }, 23 | distortionScale: { default: 15 }, 24 | opacity: { 25 | default: 1.0, 26 | min: 0, max: 1 27 | }, 28 | srcHeight: { default: 512 }, 29 | srcWidth: { default: 512 }, 30 | sunDirection: { 31 | type: 'vec3', 32 | default: { x: 1, y: 1, z: 1 } 33 | }, 34 | sunColor: { 35 | default: 'grey', 36 | parse: colorParse 37 | }, 38 | waterColor: { 39 | default: '#001e0f', 40 | parse: colorParse 41 | }, 42 | light: { 43 | type: 'selector' 44 | } 45 | }, 46 | 47 | init: function () { 48 | this.water = null; 49 | }, 50 | 51 | update: function () { 52 | this.water = undefined; 53 | this.el.setObject3D(null); 54 | }, 55 | 56 | tick: function (time) { 57 | if (this.water) { 58 | this.water.material.uniforms.time.value = time/5000; 59 | this.water.render(); 60 | } else if ( 61 | this.el.sceneEl.renderer && 62 | this.el.sceneEl.camera 63 | ) { 64 | 65 | this.camera = new THREE.PerspectiveCamera(); 66 | this.el.sceneEl.camera.add(this.camera); 67 | 68 | if (this.data.light && this.data.light.object3D) { 69 | var p = this.data.light.object3D.position.normalize(); 70 | this.data.sunDirection = { 71 | x: p.x, 72 | y: p.y, 73 | z: p.z 74 | }; 75 | } 76 | 77 | waterNormals = new THREE.TextureLoader().load( this.data.src ); 78 | waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping; 79 | water = new THREE.Water( this.el.sceneEl.renderer, this.el.sceneEl.camera, this.el.sceneEl.object3D, { 80 | textureWidth: this.data.srcHeight, 81 | textureHeight: this.data.srcWidth, 82 | waterNormals: waterNormals, 83 | alpha: this.data.opacity, 84 | sunDirection: this.data.sunDirection, 85 | sunColor: this.data.sunColor, 86 | waterColor: this.data.waterColor, 87 | distortionScale: this.data.distortionScale, 88 | fog: true 89 | } ); 90 | mirrorMesh = new THREE.Mesh( 91 | new THREE.PlaneBufferGeometry( this.data.width, this.data.depth ), 92 | water.material 93 | ); 94 | mirrorMesh.add( water ); 95 | mirrorMesh.rotation.x = - Math.PI * 0.5; 96 | mirrorMesh.scale.multiplyScalar(10); 97 | 98 | this.water = water; 99 | this.el.setObject3D('mesh', mirrorMesh); 100 | } 101 | }, 102 | 103 | remove: function () { 104 | this.water.remove(); 105 | this.water = undefined; 106 | } 107 | }); 108 | 109 | AFRAME.registerPrimitive('a-ada-ocean', { 110 | defaultComponents: { 111 | 'a-ada-ocean': {} 112 | }, 113 | mappings: { 114 | width: 'a-ada-ocean.width', 115 | depth: 'a-ada-ocean.depth', 116 | color: 'a-ada-ocean.color', 117 | opacity: 'a-ada-ocean.opacity', 118 | light: 'a-ada-ocean.light', 119 | src: 'a-ada-ocean.src', 120 | 'src-height': 'a-ada-ocean.srcWidth', 121 | 'src-width': 'a-ada-ocean.srcHeight' 122 | } 123 | }); -------------------------------------------------------------------------------- /deprecated/webgl-sky-sun-shader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Based on https://github.com/brianchirls/three.js/blob/master/examples/webgl_shaders_sky.html 3 | * Requires: 4 | * 5 | * https://cdn.rawgit.com/mrdoob/three.js/blob/r77/examples/js/SkyShader.js 6 | * 7 | */ 8 | 9 | // 10 | 11 | var distance = 450000; 12 | 13 | AFRAME.registerComponent('webgl-sky', { 14 | 15 | schema: { 16 | turbidity: { default: 10 }, 17 | reileigh: { default: 2 }, 18 | mieCoefficient: { default: 0.005 }, 19 | mieDirectionalG: { default: 0.8 }, 20 | luminance: { default: 1 }, 21 | inclination: { default: 0.49 }, // elevation / inclination 22 | azimuth: { default: 0.25 }, // Facing front, 23 | sun: { default: true }, 24 | control: { type: 'selector' } 25 | }, 26 | 27 | init: function () { 28 | 29 | // Add Sky Mesh 30 | this.sky = new THREE.Sky(); 31 | 32 | // Add Sun Helper 33 | this.sunSphere = new THREE.Mesh( 34 | new THREE.SphereBufferGeometry( 30000, 16, 8 ), 35 | new THREE.MeshBasicMaterial( { color: 0xffffff } ) 36 | ); 37 | 38 | this.sunSphere.visible = false; 39 | 40 | this.sky.mesh.add(this.sunSphere); 41 | this.sky.mesh.scale.multiplyScalar(0.01); 42 | this.el.setObject3D('mesh', this.sky.mesh); 43 | }, 44 | 45 | play: function () { 46 | if (this.data.control && this.data.control.object3D) { 47 | this.data.control.object3D.position.copy(this.sunSphere.position); 48 | } 49 | }, 50 | 51 | getSunSphere: function () { 52 | return this.sunSphere; 53 | }, 54 | 55 | update: function () { 56 | 57 | var uniforms = this.sky.uniforms; 58 | uniforms.turbidity.value = this.data.turbidity; 59 | uniforms.reileigh.value = this.data.reileigh; 60 | uniforms.luminance.value = this.data.luminance; 61 | uniforms.mieCoefficient.value = this.data.mieCoefficient; 62 | uniforms.mieDirectionalG.value = this.data.mieDirectionalG; 63 | 64 | var theta = Math.PI * ( this.data.inclination - 0.5 ); 65 | var phi = 2 * Math.PI * ( this.data.azimuth - 0.5 ); 66 | 67 | this.sunSphere.position.x = distance * Math.cos( phi ); 68 | this.sunSphere.position.y = distance * Math.sin( phi ) * Math.sin( theta ); 69 | this.sunSphere.position.z = distance * Math.sin( phi ) * Math.cos( theta ); 70 | 71 | this.sunSphere.visible = this.data.sun; 72 | 73 | this.sky.uniforms.sunPosition.value.copy(this.sunSphere.position); 74 | 75 | if (this.data.control && this.data.control.object3D) { 76 | this.data.control.object3D.position.copy(this.sunSphere.position); 77 | } 78 | }, 79 | 80 | remove: function () { 81 | this.sky.remove(); 82 | this.sky = undefined; 83 | } 84 | }); 85 | 86 | AFRAME.registerPrimitive('a-webgl-sky', { 87 | defaultComponents: { 88 | 'webgl-sky': {} 89 | }, 90 | mappings: { 91 | turbidity: 'webgl-sky.turbidity', 92 | reileigh: 'webgl-sky.reileigh', 93 | mieCoefficient: 'webgl-sky.mieCoefficient', 94 | mieDirectionalG: 'webgl-sky.mieDirectionalG', 95 | luminance: 'webgl-sky.luminance', 96 | inclination: 'webgl-sky.inclination', 97 | azimuth: 'webgl-sky.azimuth', 98 | sun: 'webgl-sky.sun', 99 | control: 'webgl-sky.control' 100 | } 101 | }); -------------------------------------------------------------------------------- /dist/clapper.js: -------------------------------------------------------------------------------- 1 | AFRAME.registerComponent('clapper', { 2 | schema: { 3 | debounce: { 4 | default: true 5 | }, 6 | trigger: { 7 | default: 0.95 8 | } 9 | }, 10 | Recording: function (cb) { 11 | var recorder = null; 12 | var recording = true; 13 | var audioInput = null; 14 | var volume = null; 15 | var audioContext = null; 16 | var callback = cb; 17 | navigator.getUserMedia = navigator.getUserMedia || 18 | navigator.webkitGetUserMedia || 19 | navigator.mozGetUserMedia || 20 | navigator.msGetUserMedia; 21 | 22 | if(navigator.getUserMedia){ 23 | navigator.getUserMedia({audio:true}, function(e) { 24 | var AudioContext = window.AudioContext || window.webkitAudioContext; 25 | this.audioContext = new AudioContext(); 26 | volume = this.audioContext.createGain(); // creates a gain node 27 | audioInput = this.audioContext.createMediaStreamSource(e); // creates an audio node from the mic stream 28 | recorder = this.audioContext.createScriptProcessor(2048, 1, 1); 29 | recorder.onaudioprocess = function(e){ 30 | if(!recording) return; 31 | var left = e.inputBuffer.getChannelData(0); 32 | callback(new Float32Array(left)); 33 | }; 34 | audioInput.connect(volume); 35 | volume.connect(recorder); 36 | recorder.connect(this.audioContext.destination); 37 | }.bind(this), function(e){ //failure 38 | console.log(e); 39 | }); 40 | } else { 41 | console.log('getUserMedia not supported in this browser.'); 42 | } 43 | }, 44 | detectClap: function detectClap(data){ 45 | var t = (new Date()).getTime(); 46 | if (t - this.lastClap < 100) return false; 47 | var zeroCrossings = 0, highAmp = 0; 48 | for(var i = 1; i < data.length; i++){ 49 | if(Math.abs(data[i]) > this.data.trigger) highAmp++; 50 | if( 51 | data[i] > 0 && data[i-1] < 0 || 52 | data[i] < 0 && data[i-1] > 0 53 | ) { 54 | zeroCrossings++; 55 | } 56 | } 57 | if(highAmp > 20 && zeroCrossings > 30){ 58 | this.lastClap = (new Date()).getTime(); 59 | return true; 60 | } 61 | return false; 62 | }, 63 | init: function () { 64 | 65 | this.lastClap = (new Date()).getTime(); 66 | this.timeout = -1; 67 | 68 | this.Recording.prototype.destroy = function () { 69 | this.audioContext.destination.disconnect(); 70 | this.audioContext = null; 71 | }; 72 | 73 | var clap = (function clap() { 74 | this.el.emit('clap'); 75 | this.timeout = -1; 76 | }).bind(this); 77 | 78 | var clapclap = (function clapclap() { 79 | this.el.emit('clapclap'); 80 | this.timeout = -1; 81 | }).bind(this); 82 | 83 | this.rec = new this.Recording(function(data){ 84 | if(this.detectClap(data)){ 85 | clearTimeout(this.timeout); 86 | if (this.data.debounce) { 87 | if (this.timeout === -1) { 88 | this.timeout = setTimeout(clap, 500); 89 | } else { 90 | this.timeout = setTimeout(clapclap, 500); 91 | } 92 | } else { 93 | clap(); 94 | } 95 | } 96 | }.bind(this)); 97 | }, 98 | remove: function () { 99 | this.rec.destroy(); 100 | this.rec = null; 101 | } 102 | }); 103 | -------------------------------------------------------------------------------- /dist/clone.js: -------------------------------------------------------------------------------- 1 | AFRAME.registerComponent('clone', { 2 | schema: { 3 | type: 'selector' 4 | }, 5 | 6 | init: function () { 7 | var cloneGeom = this.data.object3D.clone(true); 8 | cloneGeom.visible = true; 9 | this.el.setObject3D('clone', cloneGeom); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /dist/curve.js: -------------------------------------------------------------------------------- 1 | 2 | /* For dealing with spline curves */ 3 | 4 | var __tempVector1 = new THREE.Vector3(); 5 | var __tempVector2 = new THREE.Vector3(); 6 | var up = new THREE.Vector3(0, 1, 0); 7 | var zAxis = new THREE.Vector3(0, 0, 1); 8 | var degToRad = THREE.Math.degToRad; 9 | 10 | AFRAME.registerComponent('curve-point', { 11 | 12 | dependencies: ['position'], 13 | 14 | schema: { 15 | position: {type: 'vec3', default: '0 0 0'} 16 | }, 17 | 18 | init: function () { 19 | var el = this.el; 20 | while (el && !el.matches('[curve]')) el = el.parentNode; 21 | this.parentCurve = el; 22 | }, 23 | 24 | update: function () { 25 | this.el.object3D.position.copy(this.data.position); 26 | this.parentCurve.updateComponent('curve'); 27 | }, 28 | 29 | remove: function () { 30 | this.update(); 31 | } 32 | 33 | }); 34 | 35 | AFRAME.registerComponent('curve', { 36 | 37 | schema: { 38 | 39 | // CatmullRom 40 | // Spline 41 | // CubicBezier 42 | // QuadraticBezier 43 | // Line 44 | type: { 45 | default: 'CatmullRom' 46 | } 47 | }, 48 | 49 | update: function () { 50 | this.needsUpdate = true; 51 | }, 52 | 53 | tick: function () { 54 | if (!this.needsUpdate) return; 55 | this.needsUpdate = false; 56 | this.threeConstructor = THREE[this.data.type + 'Curve3']; 57 | 58 | var points = Array.from(this.el.querySelectorAll('a-curve-point')).filter(function (a) { return a.tagName === 'A-CURVE-POINT' }); 59 | 60 | if (points.length <= 1) return; 61 | 62 | this.points = points.map(function (a) { 63 | if (a.x !== undefined && a.y !== undefined && a.z !== undefined) { 64 | return a; 65 | } 66 | 67 | // flush position information to object 3D 68 | 69 | a.updateComponent('position'); 70 | return a.object3D.getWorldPosition() 71 | }); 72 | 73 | // apply the points as ags to the Beziers 74 | if (this.data.type.match(/QuadraticBezier|CubicBezier|Line/)) { 75 | this.curve = (Function.prototype.bind.apply(this.threeConstructor, this.points)); 76 | } else { 77 | if (!this.threeConstructor) { 78 | this.pause(); 79 | throw ('No Three constructor of type (case sensitive): ' + this.data.type + 'Curve3'); 80 | } 81 | this.curve = new this.threeConstructor(this.points); 82 | } 83 | 84 | this.el.emit('curve-updated'); 85 | 86 | this.ready = true; 87 | }, 88 | 89 | remove: function () { 90 | this.curve = null; 91 | this.points = null; 92 | this.ready = false; 93 | }, 94 | 95 | closestPointInLocalSpace: function closestPoint(point, resolution, testPoint, currentRes) { 96 | if (!this.ready) throw Error('Curve not instantiated yet.'); 97 | resolution = resolution || 0.1 / this.curve.getLength(); 98 | currentRes = currentRes || 0.5; 99 | testPoint = testPoint || 0.5; 100 | currentRes /= 2; 101 | var aTest = testPoint + currentRes; 102 | var bTest = testPoint - currentRes; 103 | var a = this.curve.getPointAt(aTest); 104 | var b = this.curve.getPointAt(bTest); 105 | var aDistance = a.distanceTo(point); 106 | var bDistance = b.distanceTo(point); 107 | var aSmaller = aDistance < bDistance; 108 | if (currentRes < resolution) { 109 | 110 | var tangent = this.curve.getTangentAt(aSmaller ? aTest : bTest); 111 | if (currentRes < resolution) return { 112 | result: aSmaller ? aTest : bTest, 113 | location: aSmaller ? a : b, 114 | distance: aSmaller ? aDistance : bDistance, 115 | normal: normalFromTangent(tangent), 116 | tangent: tangent 117 | }; 118 | } 119 | if (aDistance < bDistance) { 120 | return this.closestPointInLocalSpace(point, resolution, aTest, currentRes); 121 | } else { 122 | return this.closestPointInLocalSpace(point, resolution, bTest, currentRes); 123 | } 124 | } 125 | }); 126 | 127 | 128 | var tempQuaternion = new THREE.Quaternion(); 129 | function normalFromTangent(tangent) { 130 | var lineEnd = new THREE.Vector3(0, 1, 0); 131 | tempQuaternion.setFromUnitVectors(zAxis, tangent); 132 | lineEnd.applyQuaternion(tempQuaternion); 133 | return lineEnd; 134 | } 135 | 136 | AFRAME.registerShader('line', { 137 | schema: {}, 138 | 139 | init: function (data) { 140 | this.material = new THREE.LineBasicMaterial(data); 141 | } 142 | }); 143 | 144 | AFRAME.registerComponent('draw-curve', { 145 | 146 | dependencies: ['curve', 'material '], 147 | 148 | schema: { 149 | curve: { type: 'selector' }, 150 | spacing: { default: 1 }, 151 | tangent: { default: false }, 152 | normal: { default: true } 153 | }, 154 | 155 | init: function () { 156 | this.data.curve.addEventListener('curve-updated', this.update.bind(this)); 157 | }, 158 | 159 | update: function () { 160 | if (this.data.curve) { 161 | this.curve = this.data.curve.components.curve; 162 | } else if (this.components.curve.curve) { 163 | this.curve = this.components.curve; 164 | } 165 | 166 | if (this.curve.curve) { 167 | 168 | var length = this.curve.curve.getLength(); 169 | var start = 0; 170 | var end = length; 171 | 172 | var counter = start 173 | var tangent; 174 | var line; 175 | var lineEnd; 176 | var tangentGeometry; 177 | var normalGeometry; 178 | var mesh = this.el.getOrCreateObject3D('mesh', THREE.Line); 179 | var geometry = mesh.geometry = new THREE.Geometry(); 180 | 181 | while (counter < end) { 182 | var p = this.curve.curve.getPointAt(counter / length); 183 | geometry.vertices.push(p); 184 | 185 | if (this.data.tangent) { 186 | tangentGeometry = new THREE.Geometry(); 187 | 188 | lineEnd = new THREE.Vector3(); 189 | lineEnd.copy(p); 190 | lineEnd.add(this.curve.curve.getTangentAt(counter / length).normalize().multiplyScalar(5)); 191 | 192 | tangentGeometry.vertices.push(new THREE.Vector3().copy(p)); 193 | tangentGeometry.vertices.push(lineEnd); 194 | 195 | line = new THREE.Line( 196 | tangentGeometry, 197 | new THREE.LineBasicMaterial({ 198 | color: 'green' 199 | }) 200 | ); 201 | 202 | mesh.add(line); 203 | } 204 | 205 | if (this.data.normal) { 206 | normalGeometry = new THREE.Geometry(); 207 | lineEnd = normalFromTangent(this.curve.curve.getTangentAt(counter / length).normalize()); 208 | lineEnd.add(p); 209 | 210 | normalGeometry.vertices.push(new THREE.Vector3().copy(p)); 211 | normalGeometry.vertices.push(lineEnd); 212 | 213 | line = new THREE.Line( 214 | normalGeometry, 215 | new THREE.LineBasicMaterial({ 216 | color: 'white' 217 | }) 218 | ); 219 | 220 | mesh.add(line); 221 | } 222 | 223 | counter += this.data.spacing; 224 | } 225 | } 226 | }, 227 | 228 | remove: function () { 229 | 230 | this.el.getObject3D('mesh').geometry = new THREE.Geometry(); 231 | } 232 | 233 | }); 234 | 235 | AFRAME.registerComponent('clone-along-curve', { 236 | 237 | dependencies: ['curve'], 238 | 239 | schema: { 240 | curve: { type: 'selector' }, 241 | spacing: { default: 1 }, 242 | rotation: { 243 | type: 'vec3', 244 | default: '0 0 0' 245 | }, 246 | scale: { 247 | type: 'vec3', 248 | default: '1 1 1' 249 | } 250 | }, 251 | 252 | init: function () { 253 | this.el.addEventListener('model-loaded', this.update.bind(this)); 254 | this.data.curve.addEventListener('curve-updated', this.update.bind(this)); 255 | }, 256 | 257 | update: function () { 258 | this.remove(); 259 | if (this.data.curve) { 260 | this.curve = this.data.curve.components.curve; 261 | } else if (this.components.curve.curve) { 262 | this.curve = this.components.curve; 263 | } 264 | }, 265 | 266 | tick: function () { 267 | if (!this.el.getObject3D('clones') && this.curve) { 268 | 269 | var mesh = this.el.getObject3D('mesh'); 270 | 271 | 272 | var length = this.curve.curve.getLength(); 273 | var start = 0; 274 | var end = length; 275 | var counter = start; 276 | 277 | var cloneMesh = this.el.getOrCreateObject3D('clones', THREE.Group); 278 | 279 | var parent = new THREE.Object3D(); 280 | mesh.scale.set(this.data.scale.x, this.data.scale.y, this.data.scale.z); 281 | mesh.rotation.set(degToRad(this.data.rotation.x), degToRad(this.data.rotation.y), degToRad(this.data.rotation.z)); 282 | mesh.rotation.order = 'YXZ'; 283 | 284 | parent.add(mesh); 285 | 286 | while (counter < end) { 287 | 288 | var child = parent.clone(true); 289 | 290 | child.position.copy( this.curve.curve.getPointAt(counter/length) ); 291 | 292 | tangent = this.curve.curve.getTangentAt(counter/length).normalize(); 293 | 294 | child.quaternion.setFromUnitVectors(zAxis, tangent); 295 | 296 | cloneMesh.add(child); 297 | 298 | counter += this.data.spacing; 299 | } 300 | } 301 | }, 302 | 303 | remove: function () { 304 | this.curve = null; 305 | this.el.removeObject3D('clones'); 306 | } 307 | 308 | }); 309 | 310 | AFRAME.registerPrimitive('a-draw-curve', { 311 | defaultComponents: { 312 | 'draw-curve': {}, 313 | 'material': {} 314 | }, 315 | mappings: { 316 | curve: 'draw-curve.curve', 317 | material: 'material' 318 | } 319 | }); 320 | 321 | AFRAME.registerPrimitive('a-curve-point', { 322 | defaultComponents: { 323 | 'curve-point': { 324 | position: '0 0 0' 325 | } 326 | }, 327 | mappings: { 328 | position: 'curve-point.position' 329 | } 330 | }); 331 | 332 | 333 | AFRAME.registerPrimitive('a-curve', { 334 | 335 | defaultComponents: { 336 | 'curve': {} 337 | }, 338 | 339 | mappings: { 340 | curve: 'curve', 341 | } 342 | 343 | }); 344 | -------------------------------------------------------------------------------- /dist/fire-item.js: -------------------------------------------------------------------------------- 1 | AFRAME.registerComponent('fire-item', { 2 | schema: { 3 | el: {type: 'selector'}, 4 | on: {default: 'click'}, 5 | }, 6 | init: function() { 7 | this.events = []; 8 | this.fire = this.fire.bind(this); 9 | }, 10 | update: function (el) { 11 | this.removeEventListeners(); 12 | this.addEventListeners(); 13 | this.data.el.setAttribute('visible', false); 14 | }, 15 | addEventListeners: function () { 16 | this.events.push(this.data.on); 17 | this.el.addEventListener(this.data.on, this.fire); 18 | }, 19 | removeEventListeners: function () { 20 | window.removeEventListener(this.events.pop(), this.fire); 21 | }, 22 | fire: function () { 23 | var newEl = this.data.el.cloneNode(true); 24 | var camera = document.querySelector('a-camera').object3D; 25 | var velocity = new THREE.Vector3(0, 0, -8); 26 | var se = this.el.sceneEl; 27 | velocity.applyEuler(camera.rotation); 28 | newEl.setAttribute('velocity', 29 | velocity.x + ' ' + 30 | (velocity.y + 2) + ' ' + 31 | velocity.z 32 | ); 33 | newEl.setAttribute('position', 34 | camera.position.x + ' ' + 35 | (camera.position.y - 0.5) + ' ' + 36 | camera.position.z 37 | ); 38 | se.appendChild(newEl); 39 | setTimeout(function () { 40 | se.removeChild(newEl); 41 | }, 10000); 42 | } 43 | }); -------------------------------------------------------------------------------- /dist/follow.js: -------------------------------------------------------------------------------- 1 | 2 | /* Follows an object around (don't need to be in same space) */ 3 | 4 | var __tempVector1 = new THREE.Vector3(); 5 | var __tempVector2 = new THREE.Vector3(); 6 | 7 | AFRAME.registerComponent('follow', { 8 | 9 | schema: { 10 | strength: { default: 0.03 }, 11 | target: { type: 'selector' } 12 | }, 13 | 14 | tick: function () { 15 | var usPos = __tempVector1; 16 | this.el.object3D.getWorldPosition(usPos); 17 | var targetPos = __tempVector2; 18 | this.data.target.object3D.getWorldPosition(targetPos); 19 | 20 | targetPos.sub(usPos).multiplyScalar(this.data.strength).add(this.el.object3D.position); 21 | 22 | this.el.setAttribute('position', targetPos); 23 | } 24 | }); -------------------------------------------------------------------------------- /dist/ocean-plane.js: -------------------------------------------------------------------------------- 1 | // Requires a build from the latest a-frame master (August 2016, v0.3) 2 | 3 | AFRAME.registerComponent('wobble-normal', { 4 | schema: {}, 5 | tick: function (t) { 6 | if (!this.el.components.material.material.normalMap) return; 7 | this.el.components.material.material.normalMap.offset.x += 0.0001 * Math.sin(t/10000); 8 | this.el.components.material.material.normalMap.offset.y += 0.0001 * Math.cos(t/8000); 9 | this.el.components.material.material.normalScale.x = 0.5 + 0.5 * Math.cos(t/1000); 10 | this.el.components.material.material.normalScale.x = 0.5 + 0.5 * Math.sin(t/1200); 11 | } 12 | }) 13 | 14 | AFRAME.registerPrimitive('a-ocean-plane', { 15 | defaultComponents: { 16 | geometry: { 17 | primitive: 'plane', 18 | height: 10000, 19 | width: 10000 20 | }, 21 | rotation: '-90 0 0', 22 | material: { 23 | shader: 'standard', 24 | color: '#8ab39f', 25 | metalness: 1, 26 | roughness: 0.2, 27 | normalMap: 'url(https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/waternormals.jpg)', 28 | normalTextureRepeat: '50 50', 29 | normalTextureOffset: '0 0', 30 | normalScale: '0.5 0.5', 31 | opacity: 0.8 32 | }, 33 | 'wobble-normal': {} 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | styles: ['css/style.css', 'css/highlight.css'] 4 | image: https://avatars0.githubusercontent.com/u/21077792?v=3 5 | title: A-Frame Components 6 | repo: https://github.com/SamsungInternet/a-frame-components/ 7 | author: 'Samsung Internet' 8 | date: Monday May 16th 2016 9 | description: Components used in A-Frame projects which can be reused. 10 | --- 11 | 12 | ### dist/clapper.js 13 | 14 | Component for detecting one or multiple claps. 15 | 16 | ```html 17 | 18 | ``` 19 | 20 | * `debounce` - default true - if false will emit `clap` on each clap. Default behaviour is to to emit `clap` after one clap and `clapclap` after two or more. 21 | * `trigger`- default 0.95 - how loud the clap needs to be to trigger. 22 | 23 | ```html 24 | 25 | ``` 26 | 27 | ### dist/fire-item.js 28 | 29 | Component for firing dynamic physics objects on events 30 | 31 | ```html 32 | 33 | 34 | ``` 35 | 36 | ```html 37 | 38 | 39 | ``` 40 | 41 | 58 | 59 | ### dist/clone.js 60 | 61 | Component for cloning another entitiy's object3D into this entity. 62 | 63 | ```html 64 | 65 | ``` 66 | 67 | ```html 68 | 69 | 70 | ``` 71 | 72 | ### dist/curve.js 73 | 74 | Components and Primitives for defining and using curves 75 | 76 | ```html 77 | 78 | ``` 79 | 80 | ```html 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | ``` 113 | 114 | It provides a javascript api for hooking into scripting. 115 | 116 | ```js 117 | // Tries to return the nearest point on the curve. 118 | // Curves which cross over themselves cause this to break down 119 | document.getElementById('track1').components.curve.closestPointInLocalSpace(new THREE.Vector3(1,2,3)); 120 | ``` 121 | 122 | Events: 123 | 124 | * curve-updated - Fired when a curve-point has been changed or added and the curve has been regenerated. 125 | 126 | ### dist/follow.js 127 | 128 | One entity tries to follow another it is damped so if it is close it does not recover as much. 129 | 130 | E.g. in this case the camera should point to and try to be behind the pink box 131 | 132 | ```html 133 | 134 | ``` 135 | 136 | ```html 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | ``` 149 | 150 | ### dist/ocean-plane.js 151 | 152 | Based on the new material options added to A-Frame which are available in a-frame master 153 | 154 | ```html 155 | 156 | ``` 157 | 158 | ```html 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | ``` 168 | 169 | 170 | --------------------------------------------------------------------------------