├── .gitignore ├── LICENSE ├── README.md ├── dist ├── .gitkeep ├── aframe-heightgrid-component.js └── aframe-heightgrid-component.min.js ├── examples ├── advanced │ ├── index.html │ ├── index2.html │ ├── index3.html │ └── lib │ │ └── usgsNed.js ├── assets │ ├── gist_earth.png │ ├── gist_earth.xcf │ └── gist_earth10.png ├── basic │ └── index.html ├── index.html └── main.js ├── index.js ├── package.json └── scripts ├── unboil.js └── unboil.js~ /.gitignore: -------------------------------------------------------------------------------- 1 | .sw[ponm] 2 | examples/build.js 3 | examples/node_modules/ 4 | gh-pages 5 | node_modules/ 6 | npm-debug.log 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kevin Ngo 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## aframe-heightgrid-component 2 | 3 | A Height Grid (Terrain) component for [A-Frame](https://aframe.io). The component allows to use a gridded height field for defining a surface. The grid is aligned with the x-z plane, the heights define y coordinates. 4 | 5 | Chrome requires aframe > 0.2.0 for this component to function properly. 6 | 7 | ### Properties 8 | 9 | | Property | Description | Default Value | 10 | | -------- | ----------- | ------------- | 11 | | xdimension | number of grid points in x direction | 2 (the minimum) | 12 | | zdimension | number of grid points in z direction | 2 (the minimum) | 13 | | xspacing | the distance between two grid points in x direction | 1 | 14 | | zspacing | the distance between two grid points in z direction | 1 | 15 | | heights | a list of heights (ordering below) | 0 | 16 | | origin | the location of the first grid point | 0 0 0 | 17 | | uvs | a list of 2d texture coordinates | empty | 18 | 19 | The ordering of heights is from the first grid point to the last. The ordering is such that y(x, z) = heights(x + z * xdimension); eg. first the points along the x direction are assigned heights, then the z position is incremented and those points along the x direction are assigned heights. 20 | 21 | The (local) origin of the grid can be shifted by providing the origin property. This is for special applications only. Usually it is preferrable to wrap in another entity for translation and rotation. 22 | 23 | ### Defaults 24 | 25 | The minimum value x/zdimension is 2. x/zspacing values are unconstrained and can probably be negative. 26 | 27 | If the heights property contains less values than the number of grid points, heights are recycled from the beginning of the list to fill in missing values. By default the heights list only has a single 0 value. Omitting a heights field therefore will produce a horizontal plane. 28 | 29 | The default value for the uvs property is an empty list. An empty list will lead to texture coordinates which correspond directly to the x and z coordinates of the grid points, scaled to vary between 0 and 1. 30 | 31 | The demos have examples of how to use custom uvs. 32 | 33 | ### Usage 34 | 35 | #### Browser Installation 36 | 37 | Install and use by directly including the [browser files](dist): 38 | 39 | ```html 40 | 41 | My A-Frame Scene 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ``` 54 | 55 | #### NPM Installation 56 | 57 | Install via NPM: 58 | 59 | ```bash 60 | npm install aframe-heightgrid-component 61 | ``` 62 | 63 | Then register and use. 64 | 65 | ```js 66 | require('aframe'); 67 | require('aframe-faceset-component'); 68 | require('aframe-heightgrid-component'); 69 | ``` 70 | -------------------------------------------------------------------------------- /dist/.gitkeep: -------------------------------------------------------------------------------- 1 | `npm run dist` to generate browser files. 2 | -------------------------------------------------------------------------------- /dist/aframe-heightgrid-component.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | 29 | 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = ""; 38 | 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ([ 44 | /* 0 */ 45 | /***/ function(module, exports) { 46 | 47 | if (typeof AFRAME === 'undefined') { 48 | throw new Error('Component attempted to register before AFRAME was available.'); 49 | } 50 | 51 | /** 52 | * Height Grid (Terrain) component for A-Frame. 53 | */ 54 | AFRAME.registerComponent('heightgrid', { 55 | schema: { 56 | dependencies: ['faceset'], 57 | origin: { 58 | type: 'vec3', 59 | default: { x: 0, y: 0, z: 0 } }, 60 | xdimension: { 61 | default: 2 }, 62 | zdimension: { 63 | default: 2 }, 64 | xspacing: { 65 | default: 1 }, 66 | zspacing: { 67 | default: 1 }, 68 | heights: { 69 | default: [0], 70 | parse: function (value) { return parseNumbers (value) } , 71 | //stringify: function (value) { return value.toString() } 72 | }, 73 | yscale: { 74 | default: 1.0 }, 75 | uvs: { // texture coordinates as list 76 | default: [], 77 | parse: function (value) { return parseVec2s (value) } , 78 | stringify: function (data) { 79 | return data.map( function stringify (data) { 80 | if (typeof data !== 'object') { return data; } 81 | return [data.x, data.y].join(' '); 82 | }).join(','); 83 | } 84 | }, 85 | }, 86 | 87 | /** 88 | * Called once when component is attached. Generally for initial setup. 89 | */ 90 | init: function () { }, 91 | 92 | /** 93 | * Called when component is attached and when component data changes. 94 | * Generally modifies the entity based on the data. 95 | */ 96 | update: function (oldData) { 97 | var el = this.el; 98 | var data = this.data; 99 | var origin = data.origin; 100 | var xdimension = Math.max(2, data.xdimension); 101 | var zdimension = Math.max(2, data.zdimension); 102 | var xspacing = data.xspacing; 103 | var zspacing = data.zspacing; 104 | var yscale = data.yscale; 105 | var h = data.heights; 106 | var uvs = data.uvs; 107 | //var h = h.length ? h : [0]; 108 | 109 | //vertices 110 | var vts = []; 111 | for (var z = 0; z < zdimension; z++) { 112 | for (var x = 0; x < xdimension; x++) { 113 | vts.push( new THREE.Vector3 ( 114 | origin.x + x * xspacing, 115 | origin.y + yscale * h[(x + z * xdimension)%h.length], 116 | origin.z + z * zspacing ) ); 117 | } 118 | } 119 | //faces 120 | var faces = []; 121 | for (var z = 0; z < zdimension-1; z++) { 122 | for (var x = 0; x < xdimension-1; x++) { 123 | var i = x + z * xdimension; 124 | //alternate diagonal 125 | if ( (x+z)%2 == 0 ) { 126 | faces.push( new THREE.Face3( i, i + 1 + xdimension, i + 1 ) ); 127 | faces.push( new THREE.Face3( i, i + xdimension, i + 1 + xdimension) ); 128 | } 129 | else { 130 | faces.push( new THREE.Face3( i, i + xdimension, i + 1 ) ); 131 | faces.push( new THREE.Face3( i + xdimension, i + 1 + xdimension, i + 1) ); 132 | } 133 | } 134 | } 135 | //uvs 136 | var _uvs = uvs.map(function copy (uv) {return uv}); 137 | if (_uvs.length == 0) { 138 | //default aligned with x,z 139 | for (var z = 0; z < zdimension; z++) { 140 | for (var x = 0; x < xdimension; x++) { 141 | _uvs.push(new THREE.Vector2( x/(xdimension-1), z/(zdimension-1) )); 142 | } 143 | } 144 | } 145 | el.setAttribute('faceset', { triangles: faces, vertices: vts, uvs: _uvs } ); 146 | 147 | }, 148 | 149 | /** 150 | * Called when a component is removed (e.g., via removeAttribute). 151 | * Generally undoes all modifications to the entity. 152 | */ 153 | remove: function () { this.el.removeAttribute('faceset'); } 154 | 155 | }); 156 | 157 | function parseNumbers (value) { 158 | if (typeof value === 'object') {return value} 159 | var mc = value.match(/([+\-0-9eE\.]+)/g); 160 | var numbers = []; 161 | //var vec = {}; 162 | for (var i=0, n=mc?mc.length:0; ir;r++)n.push(parseFloat(t[r],10));return n}function r(e){if("object"==typeof e)return e;for(var t=e.match(/([+\-0-9eE\.]+)/g),n=[],r=0,a=t?t.length:0;a>r;r+=2)n.push(new THREE.Vector2(+t[r+0],+t[r+1]));return n}if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");AFRAME.registerComponent("heightgrid",{schema:{dependencies:["faceset"],origin:{type:"vec3","default":{x:0,y:0,z:0}},xdimension:{"default":2},zdimension:{"default":2},xspacing:{"default":1},zspacing:{"default":1},heights:{"default":[0],parse:function(e){return n(e)}},yscale:{"default":1},uvs:{"default":[],parse:function(e){return r(e)},stringify:function(e){return e.map(function(e){return"object"!=typeof e?e:[e.x,e.y].join(" ")}).join(",")}}},init:function(){},update:function(e){for(var t=this.el,n=this.data,r=n.origin,a=Math.max(2,n.xdimension),i=Math.max(2,n.zdimension),o=n.xspacing,u=n.zspacing,s=n.yscale,f=n.heights,c=n.uvs,p=[],h=0;i>h;h++)for(var d=0;a>d;d++)p.push(new THREE.Vector3(r.x+d*o,r.y+s*f[(d+h*a)%f.length],r.z+h*u));for(var l=[],h=0;i-1>h;h++)for(var d=0;a-1>d;d++){var g=d+h*a;(d+h)%2==0?(l.push(new THREE.Face3(g,g+1+a,g+1)),l.push(new THREE.Face3(g,g+a,g+1+a))):(l.push(new THREE.Face3(g,g+a,g+1)),l.push(new THREE.Face3(g+a,g+1+a,g+1)))}var v=c.map(function(e){return e});if(0==v.length)for(var h=0;i>h;h++)for(var d=0;a>d;d++)v.push(new THREE.Vector2(d/(a-1),h/(i-1)));t.setAttribute("faceset",{triangles:l,vertices:p,uvs:v})},remove:function(){this.el.removeAttribute("faceset")}})}]); -------------------------------------------------------------------------------- /examples/advanced/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A-Frame Height Grid (Terrain) Component - Advanced 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Use keyboard and mouse to fly 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 74 | 75 | -------------------------------------------------------------------------------- /examples/advanced/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A-Frame Height Grid (Terrain) Component - Advanced 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Use keyboard and mouse to fly 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 47 | 281 | 282 | -------------------------------------------------------------------------------- /examples/advanced/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A-Frame Height Grid (Terrain) Component - Advanced 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Use keyboard and mouse to fly 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 47 | 305 | 306 | -------------------------------------------------------------------------------- /examples/advanced/lib/usgsNed.js: -------------------------------------------------------------------------------- 1 | /*global define, module */ 2 | (function (root, factory) { 3 | if (typeof define === 'function' && define.amd) { 4 | // AMD. Register as an anonymous module. 5 | define(function () { 6 | return (root.usgsNed = factory()); 7 | }); 8 | } else if (typeof exports === 'object') { 9 | // Node. Does not work with strict CommonJS, but 10 | // only CommonJS-like enviroments that support module.exports, 11 | // like Node. 12 | module.exports = factory(); 13 | } else { 14 | // Browser globals 15 | root.usgsNed = factory(); 16 | } 17 | }(this, function () { 18 | "use strict"; 19 | 20 | /* 21 | { 22 | "USGS_Elevation_Point_Query_Service": { 23 | "Elevation_Query": { 24 | "x": -122.9009843371, 25 | "y": 46.973556842123, 26 | "Data_Source": "NED 1\/3 arc-second", 27 | "Elevation": 200.480279, 28 | "Units": "Feet" 29 | } 30 | } 31 | } 32 | */ 33 | 34 | /** 35 | * @external {ArcGisFeature} 36 | * @see {@link http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Feature_object/02r3000000n8000000/ Feature} 37 | */ 38 | 39 | /** 40 | * @external {GeoJsonFeature} 41 | * @see {@link http://geojson.org/geojson-spec.html#feature-objects Feature Objects} 42 | */ 43 | 44 | /** 45 | * An object that represents the results of a query to the USGS Elevation service. 46 | * @param {Object} json 47 | * @member {Number} x 48 | * @member {Number} y 49 | * @member {string} dataSource 50 | * @member {Number} elevation 51 | * @member {string} units - Measurement unit of elevation: "Feet" or "Meters". 52 | */ 53 | function ElevationQueryResult(json) { 54 | var resultObj; 55 | if (!json) { 56 | throw new TypeError("The 'json' parameter cannot be null or undefined."); 57 | } 58 | if (json.USGS_Elevation_Point_Query_Service && json.USGS_Elevation_Point_Query_Service.Elevation_Query) { 59 | resultObj = json.USGS_Elevation_Point_Query_Service.Elevation_Query; 60 | } else { 61 | throw new TypeError("The 'json' parameter object did not have expected properties."); 62 | } 63 | this.x = resultObj.x; 64 | this.y = resultObj.y; 65 | this.dataSource = resultObj.Data_Source; 66 | this.elevation = resultObj.Elevation; 67 | this.units = resultObj.Units; 68 | } 69 | 70 | /** 71 | * Returns an {ArcGisFeature} equivalent of this object. 72 | * @returns {ArcGisFeature} 73 | */ 74 | ElevationQueryResult.prototype.toArcGisFeature = function () { 75 | var point, feature; 76 | point = { 77 | x: this.x, 78 | y: this.y, 79 | z: this.elevation, 80 | spatialReference: { 81 | wkid: 4326 82 | } 83 | }; 84 | feature = { 85 | geometry: point, 86 | attributes: { 87 | elevationUnits: this.units, 88 | dataSource: this.dataSource 89 | } 90 | }; 91 | 92 | return feature; 93 | }; 94 | 95 | /** 96 | * Creates a GeoJSON feature equivalent to this object. 97 | * @returns {GeoJsonFeature} 98 | */ 99 | ElevationQueryResult.prototype.toGeoJson = function () { 100 | var geometry, feature; 101 | geometry = { 102 | type: "Point", 103 | coordinates: [this.x, this.y, this.elevation] 104 | }; 105 | feature = { 106 | type: "Feature", 107 | geometry: geometry, 108 | properties: { 109 | elevationUnits: this.units, 110 | dataSource: this.dataSource 111 | } 112 | }; 113 | 114 | return feature; 115 | }; 116 | 117 | var exports = {}; 118 | 119 | /** 120 | * @typedef NedElevationInfo 121 | * @property {number} x 122 | * @property {number} y 123 | * @property {string} Data_Source 124 | * @property {number} Elevation 125 | * @property {string} Units - 'Feet' or 'Meters' 126 | */ 127 | 128 | /** 129 | * Converts an object into a query string 130 | * @returns {string} 131 | */ 132 | function objectToQueryString(/**{Object}*/ o) { 133 | var output = [], v; 134 | for (var name in o) { 135 | if (o.hasOwnProperty(name)) { 136 | v = o[name]; 137 | if (typeof v === "object") { 138 | v = JSON.stringify(v); 139 | } 140 | output.push([name, v].map(encodeURIComponent).join("=")); 141 | } 142 | } 143 | return output.join("&"); 144 | } 145 | 146 | /** 147 | * Creates a request to the USGS NED point service 148 | * @param {number} x 149 | * @param {number} y 150 | * @param {string} [units='Feet'] 151 | * @returns {Promise} 152 | */ 153 | exports.getElevation = function (x, y, units) { 154 | return new Promise(function (resolve, reject) { 155 | var baseUrl = "http://ned.usgs.gov/epqs/pqs.php"; 156 | var params = { 157 | x: x, 158 | y: y, 159 | units: units || "Feet", 160 | output: "json" 161 | }; 162 | var request = new XMLHttpRequest(); 163 | request.open("get", [baseUrl, objectToQueryString(params)].join("?")); 164 | request.onload = function () { 165 | if (request.status === 200) { 166 | /* 167 | { 168 | "USGS_Elevation_Point_Query_Service": { 169 | "Elevation_Query": { 170 | "x": -123, 171 | "y": 45, 172 | "Data_Source": "NED 1/3 arc-second", 173 | "Elevation": 177.965854, 174 | "Units": "Feet" 175 | } 176 | } 177 | } 178 | */ 179 | var response = JSON.parse(this.responseText); 180 | resolve(response.USGS_Elevation_Point_Query_Service.Elevation_Query); 181 | } 182 | else { reject(request.statusText); } 183 | }; 184 | request.onerror = function (e) { 185 | reject(e); 186 | }; 187 | request.send(); 188 | }); 189 | }; 190 | 191 | exports.ElevationQueryResult = ElevationQueryResult; 192 | 193 | return exports; 194 | })); -------------------------------------------------------------------------------- /examples/assets/gist_earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreasplesch/aframe-heightgrid-component/1ddd6801a8326009fc6afe53868c25c3c7ed74f6/examples/assets/gist_earth.png -------------------------------------------------------------------------------- /examples/assets/gist_earth.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreasplesch/aframe-heightgrid-component/1ddd6801a8326009fc6afe53868c25c3c7ed74f6/examples/assets/gist_earth.xcf -------------------------------------------------------------------------------- /examples/assets/gist_earth10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreasplesch/aframe-heightgrid-component/1ddd6801a8326009fc6afe53868c25c3c7ed74f6/examples/assets/gist_earth10.png -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A-Frame Height Grid (Terrain) Component - Basic 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A-Frame Height Grid (Terrain) Component 4 | 5 | 22 | 23 | 24 |

A-Frame Height Grid (Terrain) Component

25 | Basic 26 | Advanced 27 | 28 |
29 |
30 | Fork me on GitHub 31 |
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | require('aframe'); 2 | require('aframe-faceset-component'); 3 | require('../index.js'); 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | if (typeof AFRAME === 'undefined') { 2 | throw new Error('Component attempted to register before AFRAME was available.'); 3 | } 4 | 5 | /** 6 | * Height Grid (Terrain) component for A-Frame. 7 | */ 8 | AFRAME.registerComponent('heightgrid', { 9 | schema: { 10 | dependencies: ['faceset'], 11 | origin: { 12 | type: 'vec3', 13 | default: { x: 0, y: 0, z: 0 } }, 14 | xdimension: { 15 | default: 2 }, 16 | zdimension: { 17 | default: 2 }, 18 | xspacing: { 19 | default: 1 }, 20 | zspacing: { 21 | default: 1 }, 22 | heights: { 23 | default: [0], 24 | parse: function (value) { return parseNumbers (value) } , 25 | //stringify: function (value) { return value.toString() } 26 | }, 27 | yscale: { 28 | default: 1.0 }, 29 | uvs: { // texture coordinates as list 30 | default: [], 31 | parse: function (value) { return parseVec2s (value) } , 32 | stringify: function (data) { 33 | return data.map( function stringify (data) { 34 | if (typeof data !== 'object') { return data; } 35 | return [data.x, data.y].join(' '); 36 | }).join(','); 37 | } 38 | }, 39 | }, 40 | 41 | /** 42 | * Called once when component is attached. Generally for initial setup. 43 | */ 44 | init: function () { }, 45 | 46 | /** 47 | * Called when component is attached and when component data changes. 48 | * Generally modifies the entity based on the data. 49 | */ 50 | update: function (oldData) { 51 | var el = this.el; 52 | var data = this.data; 53 | var origin = data.origin; 54 | var xdimension = Math.max(2, data.xdimension); 55 | var zdimension = Math.max(2, data.zdimension); 56 | var xspacing = data.xspacing; 57 | var zspacing = data.zspacing; 58 | var yscale = data.yscale; 59 | var h = data.heights; 60 | var uvs = data.uvs; 61 | //var h = h.length ? h : [0]; 62 | 63 | //vertices 64 | var vts = []; 65 | for (var z = 0; z < zdimension; z++) { 66 | for (var x = 0; x < xdimension; x++) { 67 | vts.push( new THREE.Vector3 ( 68 | origin.x + x * xspacing, 69 | origin.y + yscale * h[(x + z * xdimension)%h.length], 70 | origin.z + z * zspacing ) ); 71 | } 72 | } 73 | //faces 74 | var faces = []; 75 | for (var z = 0; z < zdimension-1; z++) { 76 | for (var x = 0; x < xdimension-1; x++) { 77 | var i = x + z * xdimension; 78 | //alternate diagonal 79 | if ( (x+z)%2 == 0 ) { 80 | faces.push( new THREE.Face3( i, i + 1 + xdimension, i + 1 ) ); 81 | faces.push( new THREE.Face3( i, i + xdimension, i + 1 + xdimension) ); 82 | } 83 | else { 84 | faces.push( new THREE.Face3( i, i + xdimension, i + 1 ) ); 85 | faces.push( new THREE.Face3( i + xdimension, i + 1 + xdimension, i + 1) ); 86 | } 87 | } 88 | } 89 | //uvs 90 | var _uvs = uvs.map(function copy (uv) {return uv}); 91 | if (_uvs.length == 0) { 92 | //default aligned with x,z 93 | for (var z = 0; z < zdimension; z++) { 94 | for (var x = 0; x < xdimension; x++) { 95 | _uvs.push(new THREE.Vector2( x/(xdimension-1), z/(zdimension-1) )); 96 | } 97 | } 98 | } 99 | el.setAttribute('faceset', { triangles: faces, vertices: vts, uvs: _uvs } ); 100 | 101 | }, 102 | 103 | /** 104 | * Called when a component is removed (e.g., via removeAttribute). 105 | * Generally undoes all modifications to the entity. 106 | */ 107 | remove: function () { this.el.removeAttribute('faceset'); } 108 | 109 | }); 110 | 111 | function parseNumbers (value) { 112 | if (typeof value === 'object') {return value} 113 | var mc = value.match(/([+\-0-9eE\.]+)/g); 114 | var numbers = []; 115 | //var vec = {}; 116 | for (var i=0, n=mc?mc.length:0; i", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/andreasplesch/aframe-heightgrid-component/issues" 31 | }, 32 | "homepage": "https://github.com/andreasplesch/aframe-heightgrid-component#readme", 33 | "devDependencies": { 34 | "aframe": "^0.2.0", 35 | "aframe-faceset-component": "^0.3.1", 36 | "browserify": "^13.0.0", 37 | "browserify-css": "^0.9.1", 38 | "budo": "^8.2.2", 39 | "ghpages": "^0.0.8", 40 | "inquirer": "^1.0.2", 41 | "shelljs": "^0.7.0", 42 | "shx": "^0.1.1", 43 | "webpack": "^1.13.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /scripts/unboil.js: -------------------------------------------------------------------------------- 1 | require('shelljs/global'); 2 | var exec = require('child_process').exec; 3 | var inquirer = require('inquirer'); 4 | 5 | var q1 = { 6 | name: 'shortname', 7 | message: 'What is your component\'s short-name? (e.g., `rick-roll` for aframe-rick-roll-component, ``)', 8 | type: 'input' 9 | }; 10 | 11 | var q2 = { 12 | name: 'longname', 13 | message: 'What is your component\'s long-name? (e.g., `Rick Roll` for A-Frame Rick Roll Component)', 14 | type: 'input' 15 | }; 16 | 17 | var q3 = { 18 | name: 'repo', 19 | message: 'Where is your component on Github? (e.g., yourusername/aframe-rick-roll-component)', 20 | type: 'input' 21 | }; 22 | 23 | var q4 = { 24 | name: 'author', 25 | message: 'Who are you? (e.g., Jane John )', 26 | type: 'input' 27 | }; 28 | 29 | 30 | q1 = 'heightgrid'; 31 | q2 = 'Height Grid (Terrain)' 32 | q3 = 'andreasplesch/aframe-heightgrid-component' 33 | q4 = 'Andreas Plesch ' 34 | 35 | var ans = { 36 | shortname: q1, 37 | longname: q2, 38 | repo: q3, 39 | author: q4 40 | }; 41 | 42 | 43 | //inqu[q1, q2, q3, q4], function (ans) { 44 | ls(['index.js', 'package.json', 'README.md']).forEach(function(file) { 45 | sed('-i', 'aframe-example-component', 'aframe-' + ans.shortname + '-component', file); 46 | sed('-i', 'Example Component', ans.longname + ' Component', file); 47 | sed('-i', 'Example component', ans.longname + ' component', file); 48 | sed('-i', "'example'", "'" + ans.shortname + "'", file); 49 | }); 50 | 51 | ls('README.md').forEach(function (file) { 52 | sed('-i', 'example component', ans.longname + ' component', file); 53 | sed('-i', 'example=', ans.shortname + '=', file); 54 | }); 55 | 56 | find('examples').filter(function (file) { return file.match(/\.html/); }).forEach(function (file) { 57 | sed('-i', 'Example Component', ans.longname + ' Component', file); 58 | sed('-i', 'ngokevin/aframe-component-boilerplate', ans.repo, file); 59 | }); 60 | 61 | ls(['package.json', 'README.md']).forEach(function (file) { 62 | sed('-i', 'aframe-example-component', 'aframe-' + ans.shortname + '-component', file); 63 | sed('-i', 'ngokevin/aframe-component-boilerplate', ans.repo, file); 64 | sed('-i', 'Kevin Ngo ', ans.author, file); 65 | }); 66 | 67 | 68 | exec("sed '1,/--trim--/d' README.md | tee README.md"); 69 | -------------------------------------------------------------------------------- /scripts/unboil.js~: -------------------------------------------------------------------------------- 1 | require('shelljs/global'); 2 | var exec = require('child_process').exec; 3 | var inquirer = require('inquirer'); 4 | 5 | var q1 = { 6 | name: 'shortname', 7 | message: 'What is your component\'s short-name? (e.g., `rick-roll` for aframe-rick-roll-component, ``)', 8 | type: 'input' 9 | }; 10 | 11 | var q2 = { 12 | name: 'longname', 13 | message: 'What is your component\'s long-name? (e.g., `Rick Roll` for A-Frame Rick Roll Component)', 14 | type: 'input' 15 | }; 16 | 17 | var q3 = { 18 | name: 'repo', 19 | message: 'Where is your component on Github? (e.g., yourusername/aframe-rick-roll-component)', 20 | type: 'input' 21 | }; 22 | 23 | var q4 = { 24 | name: 'author', 25 | message: 'Who are you? (e.g., Jane John )', 26 | type: 'input' 27 | }; 28 | 29 | inquirer.prompt([q1, q2, q3, q4], function (ans) { 30 | ls(['index.js', 'package.json', 'README.md']).forEach(function(file) { 31 | sed('-i', 'aframe-example-component', 'aframe-' + ans.shortname + '-component', file); 32 | sed('-i', 'Example Component', ans.longname + ' Component', file); 33 | sed('-i', 'Example component', ans.longname + ' component', file); 34 | sed('-i', "'example'", "'" + ans.shortname + "'", file); 35 | }); 36 | 37 | ls('README.md').forEach(function (file) { 38 | sed('-i', 'example component', ans.longname + ' component', file); 39 | sed('-i', 'example=', ans.shortname + '=', file); 40 | }); 41 | 42 | find('examples').filter(function (file) { return file.match(/\.html/); }).forEach(function (file) { 43 | sed('-i', 'Example Component', ans.longname + ' Component', file); 44 | sed('-i', 'ngokevin/aframe-component-boilerplate', ans.repo, file); 45 | }); 46 | 47 | ls(['package.json', 'README.md']).forEach(function (file) { 48 | sed('-i', 'aframe-example-component', 'aframe-' + ans.shortname + '-component', file); 49 | sed('-i', 'ngokevin/aframe-component-boilerplate', ans.repo, file); 50 | sed('-i', 'Kevin Ngo ', ans.author, file); 51 | }); 52 | }); 53 | 54 | exec("sed '1,/--trim--/d' README.md | tee README.md"); 55 | --------------------------------------------------------------------------------