├── .gitignore ├── css ├── Thumbs.db ├── ajax-loader.gif └── style.css ├── doc ├── Thumbs.db ├── screen1.png └── screen2.png ├── sprites ├── Thumbs.db ├── null.png ├── point1.png ├── point2.png ├── point3.png ├── point4.png ├── point5.png ├── point6.png ├── point7.png ├── marker_1.png ├── marker_10.png ├── marker_2.png ├── marker_3.png ├── marker_4.png ├── marker_5.png ├── marker_6.png ├── marker_7.png ├── marker_8.png └── marker_9.png ├── scripts ├── index.js ├── utils.js ├── CanvasText.js ├── SpriteText2D.js ├── MeshText2D.js ├── PlaneText2D.js └── Text2D.js ├── lib ├── jquery.base64.min.js ├── perspective-transform.min.js ├── transform.js ├── GSVPano.js ├── three-text2d.min.js ├── PanomNom.min.js ├── GSVPanoDepth.js ├── three-text2d.js ├── require.js ├── glfx.js └── dat.gui.min.js ├── index.html ├── README.md └── streetmeasure.js /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | -------------------------------------------------------------------------------- /css/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/css/Thumbs.db -------------------------------------------------------------------------------- /doc/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/doc/Thumbs.db -------------------------------------------------------------------------------- /doc/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/doc/screen1.png -------------------------------------------------------------------------------- /doc/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/doc/screen2.png -------------------------------------------------------------------------------- /sprites/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/Thumbs.db -------------------------------------------------------------------------------- /sprites/null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/null.png -------------------------------------------------------------------------------- /css/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/css/ajax-loader.gif -------------------------------------------------------------------------------- /sprites/point1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point1.png -------------------------------------------------------------------------------- /sprites/point2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point2.png -------------------------------------------------------------------------------- /sprites/point3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point3.png -------------------------------------------------------------------------------- /sprites/point4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point4.png -------------------------------------------------------------------------------- /sprites/point5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point5.png -------------------------------------------------------------------------------- /sprites/point6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point6.png -------------------------------------------------------------------------------- /sprites/point7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/point7.png -------------------------------------------------------------------------------- /sprites/marker_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_1.png -------------------------------------------------------------------------------- /sprites/marker_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_10.png -------------------------------------------------------------------------------- /sprites/marker_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_2.png -------------------------------------------------------------------------------- /sprites/marker_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_3.png -------------------------------------------------------------------------------- /sprites/marker_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_4.png -------------------------------------------------------------------------------- /sprites/marker_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_5.png -------------------------------------------------------------------------------- /sprites/marker_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_6.png -------------------------------------------------------------------------------- /sprites/marker_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_7.png -------------------------------------------------------------------------------- /sprites/marker_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_8.png -------------------------------------------------------------------------------- /sprites/marker_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enricofer/streetmeasure/HEAD/sprites/marker_9.png -------------------------------------------------------------------------------- /scripts/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var SpriteText2D_1 = require("./SpriteText2D"); 3 | exports.SpriteText2D = SpriteText2D_1.SpriteText2D; 4 | var MeshText2D_1 = require("./MeshText2D"); 5 | exports.MeshText2D = MeshText2D_1.MeshText2D; 6 | var utils_1 = require("./utils"); 7 | exports.textAlign = utils_1.textAlign; 8 | -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var three_1 = require("three"); 3 | exports.textAlign = { 4 | center: new three_1.Vector2(0, 0), 5 | left: new three_1.Vector2(1, 0), 6 | topLeft: new three_1.Vector2(1, -1), 7 | topRight: new three_1.Vector2(-1, -1), 8 | right: new three_1.Vector2(-1, 0), 9 | bottomLeft: new three_1.Vector2(1, 1), 10 | bottomRight: new three_1.Vector2(-1, 1), 11 | }; 12 | var fontHeightCache = {}; 13 | function getFontHeight(fontStyle) { 14 | var result = fontHeightCache[fontStyle]; 15 | if (!result) { 16 | var body = document.getElementsByTagName('body')[0]; 17 | var dummy = document.createElement('div'); 18 | var dummyText = document.createTextNode('MÉq'); 19 | dummy.appendChild(dummyText); 20 | dummy.setAttribute('style', "font:" + fontStyle + ";position:absolute;top:0;left:0"); 21 | body.appendChild(dummy); 22 | result = dummy.offsetHeight; 23 | fontHeightCache[fontStyle] = result; 24 | body.removeChild(dummy); 25 | } 26 | return result; 27 | } 28 | exports.getFontHeight = getFontHeight; 29 | -------------------------------------------------------------------------------- /scripts/CanvasText.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var THREE = require("three"); 3 | var utils_1 = require("./utils"); 4 | var CanvasText = (function () { 5 | function CanvasText() { 6 | this.textWidth = null; 7 | this.textHeight = null; 8 | this.canvas = document.createElement('canvas'); 9 | this.ctx = this.canvas.getContext('2d'); 10 | } 11 | Object.defineProperty(CanvasText.prototype, "width", { 12 | get: function () { return this.canvas.width; }, 13 | enumerable: true, 14 | configurable: true 15 | }); 16 | Object.defineProperty(CanvasText.prototype, "height", { 17 | get: function () { return this.canvas.height; }, 18 | enumerable: true, 19 | configurable: true 20 | }); 21 | CanvasText.prototype.drawText = function (text, ctxOptions) { 22 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); 23 | this.ctx.font = ctxOptions.font; 24 | this.textWidth = Math.ceil(this.ctx.measureText(text).width); 25 | this.textHeight = utils_1.getFontHeight(this.ctx.font); 26 | this.canvas.width = THREE.Math.nextPowerOfTwo(this.textWidth); 27 | this.canvas.height = THREE.Math.nextPowerOfTwo(this.textHeight); 28 | this.ctx.font = ctxOptions.font; 29 | this.ctx.fillStyle = ctxOptions.fillStyle; 30 | this.ctx.textAlign = 'left'; 31 | this.ctx.textBaseline = 'top'; 32 | this.ctx.fillText(text, 0, 0); 33 | return this.canvas; 34 | }; 35 | return CanvasText; 36 | }()); 37 | exports.CanvasText = CanvasText; 38 | -------------------------------------------------------------------------------- /lib/jquery.base64.min.js: -------------------------------------------------------------------------------- 1 | "use strict";jQuery.base64=(function($){var _PADCHAR="=",_ALPHA="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",_VERSION="1.0";function _getbyte64(s,i){var idx=_ALPHA.indexOf(s.charAt(i));if(idx===-1){throw"Cannot decode base64"}return idx}function _decode(s){var pads=0,i,b10,imax=s.length,x=[];s=String(s);if(imax===0){return s}if(imax%4!==0){throw"Cannot decode base64"}if(s.charAt(imax-1)===_PADCHAR){pads=1;if(s.charAt(imax-2)===_PADCHAR){pads=2}imax-=4}for(i=0;i>16,(b10>>8)&255,b10&255))}switch(pads){case 1:b10=(_getbyte64(s,i)<<18)|(_getbyte64(s,i+1)<<12)|(_getbyte64(s,i+2)<<6);x.push(String.fromCharCode(b10>>16,(b10>>8)&255));break;case 2:b10=(_getbyte64(s,i)<<18)|(_getbyte64(s,i+1)<<12);x.push(String.fromCharCode(b10>>16));break}return x.join("")}function _getbyte(s,i){var x=s.charCodeAt(i);if(x>255){throw"INVALID_CHARACTER_ERR: DOM Exception 5"}return x}function _encode(s){if(arguments.length!==1){throw"SyntaxError: exactly one argument required"}s=String(s);var i,b10,x=[],imax=s.length-s.length%3;if(s.length===0){return s}for(i=0;i>18));x.push(_ALPHA.charAt((b10>>12)&63));x.push(_ALPHA.charAt((b10>>6)&63));x.push(_ALPHA.charAt(b10&63))}switch(s.length-imax){case 1:b10=_getbyte(s,i)<<16;x.push(_ALPHA.charAt(b10>>18)+_ALPHA.charAt((b10>>12)&63)+_PADCHAR+_PADCHAR);break;case 2:b10=(_getbyte(s,i)<<16)|(_getbyte(s,i+1)<<8);x.push(_ALPHA.charAt(b10>>18)+_ALPHA.charAt((b10>>12)&63)+_ALPHA.charAt((b10>>6)&63)+_PADCHAR);break}return x.join("")}return{decode:_decode,encode:_encode,VERSION:_VERSION}}(jQuery)); -------------------------------------------------------------------------------- /scripts/SpriteText2D.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || function (d, b) { 3 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 4 | function __() { this.constructor = d; } 5 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 6 | }; 7 | var THREE = require("three"); 8 | var Text2D_1 = require("./Text2D"); 9 | var SpriteText2D = (function (_super) { 10 | __extends(SpriteText2D, _super); 11 | function SpriteText2D() { 12 | _super.apply(this, arguments); 13 | } 14 | SpriteText2D.prototype.raycast = function () { 15 | return this.sprite.raycast.apply(this.sprite, arguments); 16 | }; 17 | SpriteText2D.prototype.updateText = function () { 18 | this.canvas.drawText(this._text, { 19 | font: this._font, 20 | fillStyle: this._fillStyle 21 | }); 22 | // cleanup previous texture 23 | this.cleanUp(); 24 | this.texture = new THREE.Texture(this.canvas.canvas); 25 | this.texture.needsUpdate = true; 26 | this.applyAntiAlias(); 27 | if (!this.material) { 28 | this.material = new THREE.SpriteMaterial({ map: this.texture }); 29 | } 30 | else { 31 | this.material.map = this.texture; 32 | } 33 | if (!this.sprite) { 34 | this.sprite = new THREE.Sprite(this.material); 35 | this.geometry = this.sprite.geometry; 36 | this.add(this.sprite); 37 | } 38 | this.sprite.scale.set(this.canvas.width, this.canvas.height, 1); 39 | this.sprite.position.x = ((this.canvas.width / 2) - (this.canvas.textWidth / 2)) + ((this.canvas.textWidth / 2) * this.align.x); 40 | this.sprite.position.y = (-this.canvas.height / 2) + ((this.canvas.textHeight / 2) * this.align.y); 41 | }; 42 | return SpriteText2D; 43 | }(Text2D_1.Text2D)); 44 | exports.SpriteText2D = SpriteText2D; 45 | -------------------------------------------------------------------------------- /scripts/MeshText2D.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || function (d, b) { 3 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 4 | function __() { this.constructor = d; } 5 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 6 | }; 7 | var THREE = require("three"); 8 | var Text2D_1 = require("./Text2D"); 9 | var MeshText2D = (function (_super) { 10 | __extends(MeshText2D, _super); 11 | function MeshText2D(text, options) { 12 | if (text === void 0) { text = ''; } 13 | if (options === void 0) { options = {}; } 14 | _super.call(this, text, options); 15 | } 16 | MeshText2D.prototype.raycast = function () { 17 | this.mesh.raycast.apply(this.mesh, arguments); 18 | }; 19 | MeshText2D.prototype.updateText = function () { 20 | this.cleanUp(); // cleanup previous texture 21 | this.canvas.drawText(this._text, { 22 | font: this._font, 23 | fillStyle: this._fillStyle 24 | }); 25 | this.texture = new THREE.Texture(this.canvas.canvas); 26 | this.texture.needsUpdate = true; 27 | this.applyAntiAlias(); 28 | if (!this.material) { 29 | this.material = new THREE.MeshBasicMaterial({ map: this.texture, side: this.side }); 30 | this.material.transparent = true; 31 | } 32 | else { 33 | this.material.map = this.texture; 34 | } 35 | if (!this.mesh) { 36 | this.geometry = new THREE.PlaneGeometry(this.canvas.width, this.canvas.height); 37 | this.mesh = new THREE.Mesh(this.geometry, this.material); 38 | this.add(this.mesh); 39 | } 40 | this.mesh.position.x = ((this.canvas.width / 2) - (this.canvas.textWidth / 2)) + ((this.canvas.textWidth / 2) * this.align.x); 41 | this.mesh.position.y = (-this.canvas.height / 2) + ((this.canvas.textHeight / 2) * this.align.y); 42 | // manually update geometry vertices 43 | this.geometry.vertices[0].x = this.geometry.vertices[2].x = -this.canvas.width / 2; 44 | this.geometry.vertices[1].x = this.geometry.vertices[3].x = this.canvas.width / 2; 45 | this.geometry.vertices[0].y = this.geometry.vertices[1].y = this.canvas.height / 2; 46 | this.geometry.vertices[2].y = this.geometry.vertices[3].y = -this.canvas.height / 2; 47 | this.geometry.verticesNeedUpdate = true; 48 | }; 49 | return MeshText2D; 50 | }(Text2D_1.Text2D)); 51 | exports.MeshText2D = MeshText2D; 52 | -------------------------------------------------------------------------------- /scripts/PlaneText2D.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || function (d, b) { 3 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 4 | function __() { this.constructor = d; } 5 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 6 | }; 7 | var THREE = require("three"); 8 | var Text2D_1 = require("./Text2D"); 9 | var PlaneText2D = (function (_super) { 10 | __extends(PlaneText2D, _super); 11 | function PlaneText2D(text, options) { 12 | if (text === void 0) { text = ''; } 13 | if (options === void 0) { options = {}; } 14 | _super.call(this, text, options); 15 | } 16 | PlaneText2D.prototype.raycast = function () { 17 | this.mesh.raycast.apply(this.mesh, arguments); 18 | }; 19 | PlaneText2D.prototype.updateText = function () { 20 | this.cleanUp(); // cleanup previous texture 21 | this.canvas.drawText(this._text, { 22 | font: this._font, 23 | fillStyle: this._fillStyle 24 | }); 25 | this.texture = new THREE.Texture(this.canvas.canvas); 26 | this.texture.needsUpdate = true; 27 | this.applyAntiAlias(); 28 | if (!this.material) { 29 | this.material = new THREE.MeshBasicMaterial({ map: this.texture, side: this.side }); 30 | this.material.transparent = true; 31 | } 32 | else { 33 | this.material.map = this.texture; 34 | } 35 | if (!this.mesh) { 36 | this.geometry = new THREE.PlaneGeometry(this.canvas.width, this.canvas.height); 37 | this.mesh = new THREE.Mesh(this.geometry, this.material); 38 | this.add(this.mesh); 39 | } 40 | this.mesh.position.x = ((this.canvas.width / 2) - (this.canvas.textWidth / 2)) + ((this.canvas.textWidth / 2) * this.align.x); 41 | this.mesh.position.y = (-this.canvas.height / 2) + ((this.canvas.textHeight / 2) * this.align.y); 42 | // manually update geometry vertices 43 | this.geometry.vertices[0].x = this.geometry.vertices[2].x = -this.canvas.width / 2; 44 | this.geometry.vertices[1].x = this.geometry.vertices[3].x = this.canvas.width / 2; 45 | this.geometry.vertices[0].y = this.geometry.vertices[1].y = this.canvas.height / 2; 46 | this.geometry.vertices[2].y = this.geometry.vertices[3].y = -this.canvas.height / 2; 47 | this.geometry.verticesNeedUpdate = true; 48 | }; 49 | return PlaneText2D; 50 | }(Text2D_1.Text2D)); 51 | exports.PlaneText2D = PlaneText2D; 52 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 |
26 |
Location not found
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # streetmeasure # 2 | 3 | [streetmeasure](http://enricofer.github.io/streetmeasure) is an experimental javascript app that allows to take measures on google street panoramas and extract and straighten portions of the images. 4 | 5 | ## credits ## 6 | It is built on top of @callumprentice [works](http://callumprentice.github.io/) expecially "Street Cloud Interactive" and relies on the following javascript tools: 7 | 8 | - [THREE.js](https://threejs.org/) for 3d visualization 9 | - [PanomNom.js](https://github.com/spite/PanomNom.js) for panorama fetching 10 | - [GSVPanoDepth.js](https://github.com/proog128/GSVPanoDepth.js) for depth maps fetching 11 | - [glfx.js](https://github.com/evanw/glfx.js) for perspective reprojecting 12 | 13 | 14 | ## usage ## 15 | - start with panoid parameter if known: 16 | `http://enricofer.github.io/streetmeasure/?panoid=cFR_vriBYmaHXq6-SctOxA` 17 | - or lon and lat parameters: 18 | `https://enricofer.github.io/streetmeasure/?lat=45.39245781749395&lon=11.871457844297083` 19 | - and/or optional heading parameter in degrees (default 0): `http://enricofer.github.io/streetmeasure/?panoid=cFR_vriBYmaHXq6-SctOxA&heading=90` 20 | 21 | 22 | If the provided panoid is valid or the requested lon and lat is covered by google street view service, will be loaded the panorama location as equirectangular projection on witch is possible to obtain measures on the panorama. Double clicking on panorama makes a measurement point. With further double clicks distances (meters) between measurements points are obtained. 23 | 24 | Four measurements points shape an extraction polygon assumed to be a rectangle in the reality used as guide for straightening the panorama image. The points for a right image processing must be provided counterclockwise from bottom/left to bottom/right to top/right to top/left. 25 | 26 | Double clicking on tracker map or on arrows on screen to move panorama location without leaving the application. 27 | 28 | ![](doc/screen1.png) 29 | 30 | On the right there is a menu with the following function: 31 | 32 | - *Show* on/off the top left tracker map panel 33 | - *Show* on/off the middle left equirectangular panorama image panel 34 | - *Show* on/off the bottom left equirectangular depth map image panel 35 | - *Show* on/off the depth map image projected over the panorama image (measurements are possible only where there a 3d model covering of the sample point) 36 | - *Pano_quality* to choose between best resolution (5) and performance (1) 37 | - *Border_amount* to determine how much image to be straighten around the four measurements points 38 | - *Clear_measures* to clear measures from screen 39 | - *No measures* to include or not measures on straighten image 40 | - *Straighten* to do the magic 41 | 42 | ![](doc/screen2.png) 43 | 44 | ## Licence ## 45 | The procedures used in the app break almost all Google Streetview service terms of use so I hope no one will use it in production. It's just a game. 46 | -------------------------------------------------------------------------------- /scripts/Text2D.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || function (d, b) { 3 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 4 | function __() { this.constructor = d; } 5 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 6 | }; 7 | var THREE = require("three"); 8 | var utils_1 = require("./utils"); 9 | var CanvasText_1 = require("./CanvasText"); 10 | var Text2D = (function (_super) { 11 | __extends(Text2D, _super); 12 | function Text2D(text, options) { 13 | if (text === void 0) { text = ''; } 14 | if (options === void 0) { options = {}; } 15 | _super.call(this); 16 | this._font = options.font || '30px Arial'; 17 | this._fillStyle = options.fillStyle || '#FFFFFF'; 18 | this.canvas = new CanvasText_1.CanvasText(); 19 | this.align = options.align || utils_1.textAlign.center; 20 | this.side = options.side || THREE.DoubleSide; 21 | // this.anchor = Label.fontAlignAnchor[ this._textAlign ] 22 | this.antialias = (typeof options.antialias === "undefined") ? true : options.antialias; 23 | this.text = text; 24 | } 25 | Object.defineProperty(Text2D.prototype, "width", { 26 | get: function () { return this.canvas.textWidth; }, 27 | enumerable: true, 28 | configurable: true 29 | }); 30 | Object.defineProperty(Text2D.prototype, "height", { 31 | get: function () { return this.canvas.textHeight; }, 32 | enumerable: true, 33 | configurable: true 34 | }); 35 | Object.defineProperty(Text2D.prototype, "text", { 36 | get: function () { return this._text; }, 37 | set: function (value) { 38 | if (this._text !== value) { 39 | this._text = value; 40 | this.updateText(); 41 | } 42 | }, 43 | enumerable: true, 44 | configurable: true 45 | }); 46 | Object.defineProperty(Text2D.prototype, "font", { 47 | get: function () { return this._font; }, 48 | set: function (value) { 49 | if (this._font !== value) { 50 | this._font = value; 51 | this.updateText(); 52 | } 53 | }, 54 | enumerable: true, 55 | configurable: true 56 | }); 57 | Object.defineProperty(Text2D.prototype, "fillStyle", { 58 | get: function () { 59 | return this._fillStyle; 60 | }, 61 | set: function (value) { 62 | if (this._fillStyle !== value) { 63 | this._fillStyle = value; 64 | this.updateText(); 65 | } 66 | }, 67 | enumerable: true, 68 | configurable: true 69 | }); 70 | Text2D.prototype.cleanUp = function () { 71 | if (this.texture) { 72 | this.texture.dispose(); 73 | } 74 | }; 75 | Text2D.prototype.applyAntiAlias = function () { 76 | if (this.antialias === false) { 77 | this.texture.magFilter = THREE.NearestFilter; 78 | this.texture.minFilter = THREE.LinearMipMapLinearFilter; 79 | } 80 | }; 81 | return Text2D; 82 | }(THREE.Object3D)); 83 | exports.Text2D = Text2D; 84 | -------------------------------------------------------------------------------- /lib/perspective-transform.min.js: -------------------------------------------------------------------------------- 1 | /*! perspective-transform - v1.1.0 - 05-05-2015 */ 2 | !function(a){if(!a.numeric){var b={};b.dim=function(a){var c,d;return"object"==typeof a?(c=a[0],"object"==typeof c?(d=c[0],"object"==typeof d?b._dim(a):[a.length,c.length]):[a.length]):[]},b._foreach2=function c(a,b,d,e){if(d===b.length-1)return e(a);var f,g=b[d],h=Array(g);for(f=g-1;f>=0;f--)h[f]=c(a[f],b,d+1,e);return h},b.cloneV=function(a){var b,c=a.length,d=Array(c);for(b=c-1;-1!==b;--b)d[b]=a[b];return d},b.clone=function(a){if("object"!=typeof a)return a;var c=b.cloneV,d=b.dim(a);return b._foreach2(a,d,0,c)},b.diag=function(a){var b,c,d,e,f=a.length,g=Array(f);for(b=f-1;b>=0;b--){for(e=Array(f),c=b+2,d=f-1;d>=c;d-=2)e[d]=0,e[d-1]=0;for(d>b&&(e[d]=0),e[b]=a[b],d=b-1;d>=1;d-=2)e[d]=0,e[d-1]=0;0===d&&(e[0]=0),g[b]=e}return g},b.rep=function(a,c,d){"undefined"==typeof d&&(d=0);var e,f=a[d],g=Array(f);if(d===a.length-1){for(e=f-2;e>=0;e-=2)g[e+1]=c,g[e]=c;return-1===e&&(g[0]=c),g}for(e=f-1;e>=0;e--)g[e]=b.rep(a,c,d+1);return g},b.identity=function(a){return b.diag(b.rep([a],1))},b.inv=function(a){var c,d,e,f,g,h,i,j,k=b.dim(a),l=Math.abs,m=k[0],n=k[1],o=b.clone(a),p=b.identity(m);for(h=0;n>h;++h){var q=-1,r=-1;for(g=h;g!==m;++g)i=l(o[g][h]),i>r&&(q=g,r=i);for(d=o[q],o[q]=o[h],o[h]=d,f=p[q],p[q]=p[h],p[h]=f,j=d[h],i=h;i!==n;++i)d[i]/=j;for(i=n-1;-1!==i;--i)f[i]/=j;for(g=m-1;-1!==g;--g)if(g!==h){for(c=o[g],e=p[g],j=c[h],i=h+1;i!==n;++i)c[i]-=d[i]*j;for(i=n-1;i>0;--i)e[i]-=f[i]*j,--i,e[i]-=f[i]*j;0===i&&(e[0]-=f[0]*j)}}return p},b.dotMMsmall=function(a,b){var c,d,e,f,g,h,i,j,k,l,m;for(f=a.length,g=b.length,h=b[0].length,i=Array(f),c=f-1;c>=0;c--){for(j=Array(h),k=a[c],e=h-1;e>=0;e--){for(l=k[g-1]*b[g-1][e],d=g-2;d>=1;d-=2)m=d-1,l+=k[d]*b[d][e]+k[m]*b[m][e];0===d&&(l+=k[0]*b[0][e]),j[e]=l}i[c]=j}return i},b.dotMV=function(a,c){var d,e=a.length,f=Array(e),g=b.dotVV;for(d=e-1;d>=0;d--)f[d]=g(a[d],c);return f},b.dotVV=function(a,b){var c,d,e=a.length,f=a[e-1]*b[e-1];for(c=e-2;c>=1;c-=2)d=c-1,f+=a[c]*b[c]+a[d]*b[d];return 0===c&&(f+=a[0]*b[0]),f},b.transpose=function(a){var b,c,d,e,f,g=a.length,h=a[0].length,i=Array(h);for(c=0;h>c;c++)i[c]=Array(g);for(b=g-1;b>=1;b-=2){for(e=a[b],d=a[b-1],c=h-1;c>=1;--c)f=i[c],f[b]=e[c],f[b-1]=d[c],--c,f=i[c],f[b]=e[c],f[b-1]=d[c];0===c&&(f=i[0],f[b]=e[0],f[b-1]=d[0])}if(0===b){for(d=a[0],c=h-1;c>=1;--c)i[c][0]=d[c],--c,i[c][0]=d[c];0===c&&(i[0][0]=d[0])}return i},this.numeric=b,a.numeric=b}}(this),function(a,b){"object"==typeof exports&&void 0!==typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PerspT=b()}(this,function(){"use strict";function a(a){return Math.round(1e10*a)/1e10}function b(b,c,d){if(d){var e=c;c=b,b=e}var f,g=[b[0],b[1],1,0,0,0,-1*c[0]*b[0],-1*c[0]*b[1]],h=[0,0,0,b[0],b[1],1,-1*c[1]*b[0],-1*c[1]*b[1]],i=[b[2],b[3],1,0,0,0,-1*c[2]*b[2],-1*c[2]*b[3]],j=[0,0,0,b[2],b[3],1,-1*c[3]*b[2],-1*c[3]*b[3]],k=[b[4],b[5],1,0,0,0,-1*c[4]*b[4],-1*c[4]*b[5]],l=[0,0,0,b[4],b[5],1,-1*c[5]*b[4],-1*c[5]*b[5]],m=[b[6],b[7],1,0,0,0,-1*c[6]*b[6],-1*c[6]*b[7]],n=[0,0,0,b[6],b[7],1,-1*c[7]*b[6],-1*c[7]*b[7]],o=[g,h,i,j,k,l,m,n],p=c;try{f=numeric.inv(numeric.dotMMsmall(numeric.transpose(o),o))}catch(q){return console.log(q),[1,0,0,0,1,0,0,0]}for(var r=numeric.dotMMsmall(f,numeric.transpose(o)),s=numeric.dotMV(r,p),t=0;tres.text()) 22 | .then(res=>JSON.parse(res.substr(4))) 23 | .then(res=>res[1][0][5][0][5][1][2]) 24 | .then(dm => { 25 | var decoded, depthMap; 26 | try { 27 | decoded = self.decode(dm); 28 | depthMap = self.parse(decoded); 29 | } catch(e) { 30 | console.error("Error loading depth map for pano " + panoId + "\n" + e.message + "\nAt " + e.filename + "(" + e.lineNumber + ")"); 31 | depthMap = self.createEmptyDepthMap(); 32 | } 33 | if(self.onDepthLoad) { 34 | self.depthMap = depthMap; 35 | self.onDepthLoad(); 36 | } 37 | }) 38 | .catch(e=>{ 39 | console.error("Request failed: " + url + "\n" + e); 40 | var depthMap = self.createEmptyDepthMap(); 41 | if(self.onDepthLoad) { 42 | self.depthMap = depthMap; 43 | self.onDepthLoad(); 44 | } 45 | }); 46 | } 47 | 48 | this.decode = function(rawDepthMap) { 49 | var self = this, 50 | i, 51 | compressedDepthMapData, 52 | depthMap, 53 | decompressedDepthMap; 54 | 55 | // Append '=' in order to make the length of the array a multiple of 4 56 | while(rawDepthMap.length %4 != 0) 57 | rawDepthMap += '='; 58 | 59 | // Replace '-' by '+' and '_' by '/' 60 | rawDepthMap = rawDepthMap.replace(/-/g,'+'); 61 | rawDepthMap = rawDepthMap.replace(/_/g,'/'); 62 | 63 | // Decode and decompress data 64 | decompressedDepthMap = $.base64.decode(rawDepthMap); 65 | 66 | // Convert output of decompressor to Uint8Array 67 | depthMap = new Uint8Array(decompressedDepthMap.length); 68 | for(i=0; i 0) { 146 | plane = planes[planeIdx]; 147 | 148 | t = Math.abs( plane.d / (v[0]*plane.n[0] + v[1]*plane.n[1] + v[2]*plane.n[2]) ); 149 | depthMap[y*w + (w-x-1)] = t; 150 | } else { 151 | depthMap[y*w + (w-x-1)] = 9999999999999999999.; 152 | } 153 | } 154 | } 155 | 156 | return { 157 | width: w, 158 | height: h, 159 | depthMap: depthMap 160 | }; 161 | } 162 | 163 | this.parse = function(depthMap) { 164 | var self = this, 165 | depthMapData, 166 | header, 167 | data, 168 | depthMap; 169 | 170 | depthMapData = new DataView(depthMap.buffer); 171 | header = self.parseHeader(depthMapData); 172 | data = self.parsePlanes(header, depthMapData); 173 | depthMap = self.computeDepthMap(header, data.indices, data.planes); 174 | 175 | return depthMap; 176 | } 177 | 178 | this.createEmptyDepthMap = function() { 179 | var depthMap = { 180 | width: 512, 181 | height: 256, 182 | depthMap: new Float32Array(512*256) 183 | }; 184 | for(var i=0; i<512*256; ++i) 185 | depthMap.depthMap[i] = 9999999999999999999.; 186 | return depthMap; 187 | } 188 | }; 189 | -------------------------------------------------------------------------------- /lib/three-text2d.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, __webpack_require__) { 46 | 47 | "use strict"; 48 | var SpriteText2D_1 = __webpack_require__(1); 49 | exports.SpriteText2D = SpriteText2D_1.SpriteText2D; 50 | var MeshText2D_1 = __webpack_require__(6); 51 | exports.MeshText2D = MeshText2D_1.MeshText2D; 52 | var utils_1 = __webpack_require__(4); 53 | exports.textAlign = utils_1.textAlign; 54 | 55 | 56 | /***/ }, 57 | /* 1 */ 58 | /***/ function(module, exports, __webpack_require__) { 59 | 60 | "use strict"; 61 | var __extends = (this && this.__extends) || function (d, b) { 62 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 63 | function __() { this.constructor = d; } 64 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 65 | }; 66 | var THREE = __webpack_require__(2); 67 | var Text2D_1 = __webpack_require__(3); 68 | var SpriteText2D = (function (_super) { 69 | __extends(SpriteText2D, _super); 70 | function SpriteText2D() { 71 | _super.apply(this, arguments); 72 | } 73 | SpriteText2D.prototype.raycast = function () { 74 | return this.sprite.raycast.apply(this.sprite, arguments); 75 | }; 76 | SpriteText2D.prototype.updateText = function () { 77 | this.canvas.drawText(this._text, { 78 | font: this._font, 79 | fillStyle: this._fillStyle 80 | }); 81 | // cleanup previous texture 82 | this.cleanUp(); 83 | this.texture = new THREE.Texture(this.canvas.canvas); 84 | this.texture.needsUpdate = true; 85 | this.applyAntiAlias(); 86 | if (!this.material) { 87 | this.material = new THREE.SpriteMaterial({ map: this.texture }); 88 | } 89 | else { 90 | this.material.map = this.texture; 91 | } 92 | if (!this.sprite) { 93 | this.sprite = new THREE.Sprite(this.material); 94 | this.geometry = this.sprite.geometry; 95 | this.add(this.sprite); 96 | } 97 | this.sprite.scale.set(this.canvas.width, this.canvas.height, 1); 98 | this.sprite.position.x = ((this.canvas.width / 2) - (this.canvas.textWidth / 2)) + ((this.canvas.textWidth / 2) * this.align.x); 99 | this.sprite.position.y = (-this.canvas.height / 2) + ((this.canvas.textHeight / 2) * this.align.y); 100 | }; 101 | return SpriteText2D; 102 | }(Text2D_1.Text2D)); 103 | exports.SpriteText2D = SpriteText2D; 104 | 105 | 106 | /***/ }, 107 | /* 2 */ 108 | /***/ function(module, exports) { 109 | 110 | module.exports = THREE; 111 | 112 | /***/ }, 113 | /* 3 */ 114 | /***/ function(module, exports, __webpack_require__) { 115 | 116 | "use strict"; 117 | var __extends = (this && this.__extends) || function (d, b) { 118 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 119 | function __() { this.constructor = d; } 120 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 121 | }; 122 | var THREE = __webpack_require__(2); 123 | var utils_1 = __webpack_require__(4); 124 | var CanvasText_1 = __webpack_require__(5); 125 | var Text2D = (function (_super) { 126 | __extends(Text2D, _super); 127 | function Text2D(text, options) { 128 | if (text === void 0) { text = ''; } 129 | if (options === void 0) { options = {}; } 130 | _super.call(this); 131 | this._font = options.font || '30px Arial'; 132 | this._fillStyle = options.fillStyle || '#FFFFFF'; 133 | this.canvas = new CanvasText_1.CanvasText(); 134 | this.align = options.align || utils_1.textAlign.center; 135 | this.side = options.side || THREE.DoubleSide; 136 | // this.anchor = Label.fontAlignAnchor[ this._textAlign ] 137 | this.antialias = (typeof options.antialias === "undefined") ? true : options.antialias; 138 | this.text = text; 139 | } 140 | Object.defineProperty(Text2D.prototype, "width", { 141 | get: function () { return this.canvas.textWidth; }, 142 | enumerable: true, 143 | configurable: true 144 | }); 145 | Object.defineProperty(Text2D.prototype, "height", { 146 | get: function () { return this.canvas.textHeight; }, 147 | enumerable: true, 148 | configurable: true 149 | }); 150 | Object.defineProperty(Text2D.prototype, "text", { 151 | get: function () { return this._text; }, 152 | set: function (value) { 153 | if (this._text !== value) { 154 | this._text = value; 155 | this.updateText(); 156 | } 157 | }, 158 | enumerable: true, 159 | configurable: true 160 | }); 161 | Object.defineProperty(Text2D.prototype, "font", { 162 | get: function () { return this._font; }, 163 | set: function (value) { 164 | if (this._font !== value) { 165 | this._font = value; 166 | this.updateText(); 167 | } 168 | }, 169 | enumerable: true, 170 | configurable: true 171 | }); 172 | Object.defineProperty(Text2D.prototype, "fillStyle", { 173 | get: function () { 174 | return this._fillStyle; 175 | }, 176 | set: function (value) { 177 | if (this._fillStyle !== value) { 178 | this._fillStyle = value; 179 | this.updateText(); 180 | } 181 | }, 182 | enumerable: true, 183 | configurable: true 184 | }); 185 | Text2D.prototype.cleanUp = function () { 186 | if (this.texture) { 187 | this.texture.dispose(); 188 | } 189 | }; 190 | Text2D.prototype.applyAntiAlias = function () { 191 | if (this.antialias === false) { 192 | this.texture.magFilter = THREE.NearestFilter; 193 | this.texture.minFilter = THREE.LinearMipMapLinearFilter; 194 | } 195 | }; 196 | return Text2D; 197 | }(THREE.Object3D)); 198 | exports.Text2D = Text2D; 199 | 200 | 201 | /***/ }, 202 | /* 4 */ 203 | /***/ function(module, exports, __webpack_require__) { 204 | 205 | "use strict"; 206 | var THREE = __webpack_require__(2); 207 | exports.textAlign = { 208 | center: new THREE.Vector2(0, 0), 209 | left: new THREE.Vector2(1, 0), 210 | topLeft: new THREE.Vector2(1, -1), 211 | topRight: new THREE.Vector2(-1, -1), 212 | right: new THREE.Vector2(-1, 0), 213 | bottomLeft: new THREE.Vector2(1, 1), 214 | bottomRight: new THREE.Vector2(-1, 1), 215 | }; 216 | var fontHeightCache = {}; 217 | function getFontHeight(fontStyle) { 218 | var result = fontHeightCache[fontStyle]; 219 | if (!result) { 220 | var body = document.getElementsByTagName('body')[0]; 221 | var dummy = document.createElement('div'); 222 | var dummyText = document.createTextNode('MÉq'); 223 | dummy.appendChild(dummyText); 224 | dummy.setAttribute('style', "font:" + fontStyle + ";position:absolute;top:0;left:0"); 225 | body.appendChild(dummy); 226 | result = dummy.offsetHeight; 227 | fontHeightCache[fontStyle] = result; 228 | body.removeChild(dummy); 229 | } 230 | return result; 231 | } 232 | exports.getFontHeight = getFontHeight; 233 | 234 | 235 | /***/ }, 236 | /* 5 */ 237 | /***/ function(module, exports, __webpack_require__) { 238 | 239 | "use strict"; 240 | var THREE = __webpack_require__(2); 241 | var utils_1 = __webpack_require__(4); 242 | var CanvasText = (function () { 243 | function CanvasText() { 244 | this.textWidth = null; 245 | this.textHeight = null; 246 | this.canvas = document.createElement('canvas'); 247 | this.ctx = this.canvas.getContext('2d'); 248 | } 249 | Object.defineProperty(CanvasText.prototype, "width", { 250 | get: function () { return this.canvas.width; }, 251 | enumerable: true, 252 | configurable: true 253 | }); 254 | Object.defineProperty(CanvasText.prototype, "height", { 255 | get: function () { return this.canvas.height; }, 256 | enumerable: true, 257 | configurable: true 258 | }); 259 | CanvasText.prototype.drawText = function (text, ctxOptions) { 260 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); 261 | this.ctx.font = ctxOptions.font; 262 | this.textWidth = Math.ceil(this.ctx.measureText(text).width); 263 | this.textHeight = utils_1.getFontHeight(this.ctx.font); 264 | this.canvas.width = THREE.Math.nextPowerOfTwo(this.textWidth); 265 | this.canvas.height = THREE.Math.nextPowerOfTwo(this.textHeight); 266 | this.ctx.font = ctxOptions.font; 267 | this.ctx.fillStyle = ctxOptions.fillStyle; 268 | this.ctx.textAlign = 'left'; 269 | this.ctx.textBaseline = 'top'; 270 | this.ctx.fillText(text, 0, 0); 271 | return this.canvas; 272 | }; 273 | return CanvasText; 274 | }()); 275 | exports.CanvasText = CanvasText; 276 | 277 | 278 | /***/ }, 279 | /* 6 */ 280 | /***/ function(module, exports, __webpack_require__) { 281 | 282 | "use strict"; 283 | var __extends = (this && this.__extends) || function (d, b) { 284 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 285 | function __() { this.constructor = d; } 286 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 287 | }; 288 | var THREE = __webpack_require__(2); 289 | var Text2D_1 = __webpack_require__(3); 290 | var MeshText2D = (function (_super) { 291 | __extends(MeshText2D, _super); 292 | function MeshText2D(text, options) { 293 | if (text === void 0) { text = ''; } 294 | if (options === void 0) { options = {}; } 295 | _super.call(this, text, options); 296 | } 297 | MeshText2D.prototype.raycast = function () { 298 | this.mesh.raycast.apply(this.mesh, arguments); 299 | }; 300 | MeshText2D.prototype.updateText = function () { 301 | this.cleanUp(); // cleanup previous texture 302 | this.canvas.drawText(this._text, { 303 | font: this._font, 304 | fillStyle: this._fillStyle 305 | }); 306 | this.texture = new THREE.Texture(this.canvas.canvas); 307 | this.texture.needsUpdate = true; 308 | this.applyAntiAlias(); 309 | if (!this.material) { 310 | this.material = new THREE.MeshBasicMaterial({ map: this.texture, side: this.side }); 311 | this.material.transparent = true; 312 | } 313 | else { 314 | this.material.map = this.texture; 315 | } 316 | if (!this.mesh) { 317 | this.geometry = new THREE.PlaneGeometry(this.canvas.width, this.canvas.height); 318 | this.mesh = new THREE.Mesh(this.geometry, this.material); 319 | this.add(this.mesh); 320 | } 321 | this.mesh.position.x = ((this.canvas.width / 2) - (this.canvas.textWidth / 2)) + ((this.canvas.textWidth / 2) * this.align.x); 322 | this.mesh.position.y = (-this.canvas.height / 2) + ((this.canvas.textHeight / 2) * this.align.y); 323 | // manually update geometry vertices 324 | this.geometry.vertices[0].x = this.geometry.vertices[2].x = -this.canvas.width / 2; 325 | this.geometry.vertices[1].x = this.geometry.vertices[3].x = this.canvas.width / 2; 326 | this.geometry.vertices[0].y = this.geometry.vertices[1].y = this.canvas.height / 2; 327 | this.geometry.vertices[2].y = this.geometry.vertices[3].y = -this.canvas.height / 2; 328 | this.geometry.verticesNeedUpdate = true; 329 | }; 330 | return MeshText2D; 331 | }(Text2D_1.Text2D)); 332 | exports.MeshText2D = MeshText2D; 333 | 334 | 335 | /***/ } 336 | /******/ ]); -------------------------------------------------------------------------------- /lib/require.js: -------------------------------------------------------------------------------- 1 | /** vim: et:ts=4:sw=4:sts=4 2 | * @license RequireJS 2.3.2 Copyright jQuery Foundation and other contributors. 3 | * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE 4 | */ 5 | var requirejs,require,define;!function(global,setTimeout){function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){if(e){var i;for(i=0;i-1&&(!e[i]||!t(e[i],i,e));i-=1);}}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(e,t,i,r){return t&&eachProp(t,function(t,n){!i&&hasProp(e,n)||(!r||"object"!=typeof t||!t||isArray(t)||isFunction(t)||t instanceof RegExp?e[n]=t:(e[n]||(e[n]={}),mixin(e[n],t,i,r)))}),e}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttp://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}function newContext(e){function t(e){var t,i;for(t=0;t0&&(e.splice(t-1,2),t-=2)}}function i(e,i,r){var n,o,a,s,u,c,d,p,f,l,h,m,g=i&&i.split("/"),v=y.map,x=v&&v["*"];if(e&&(e=e.split("/"),d=e.length-1,y.nodeIdCompat&&jsSuffixRegExp.test(e[d])&&(e[d]=e[d].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&g&&(m=g.slice(0,g.length-1),e=m.concat(e)),t(e),e=e.join("/")),r&&v&&(g||x)){a=e.split("/");e:for(s=a.length;s>0;s-=1){if(c=a.slice(0,s).join("/"),g)for(u=g.length;u>0;u-=1)if(o=getOwn(v,g.slice(0,u).join("/")),o&&(o=getOwn(o,c))){p=o,f=s;break e}!l&&x&&getOwn(x,c)&&(l=getOwn(x,c),h=s)}!p&&l&&(p=l,f=h),p&&(a.splice(0,f,p),e=a.join("/"))}return n=getOwn(y.pkgs,e),n?n:e}function r(e){isBrowser&&each(scripts(),function(t){if(t.getAttribute("data-requiremodule")===e&&t.getAttribute("data-requirecontext")===q.contextName)return t.parentNode.removeChild(t),!0})}function n(e){var t=getOwn(y.paths,e);if(t&&isArray(t)&&t.length>1)return t.shift(),q.require.undef(e),q.makeRequire(null,{skipMap:!0})([e]),!0}function o(e){var t,i=e?e.indexOf("!"):-1;return i>-1&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function a(e,t,r,n){var a,s,u,c,d=null,p=t?t.name:null,f=e,l=!0,h="";return e||(l=!1,e="_@r"+(T+=1)),c=o(e),d=c[0],e=c[1],d&&(d=i(d,p,n),s=getOwn(j,d)),e&&(d?h=s&&s.normalize?s.normalize(e,function(e){return i(e,p,n)}):e.indexOf("!")===-1?i(e,p,n):e:(h=i(e,p,n),c=o(h),d=c[0],h=c[1],r=!0,a=q.nameToUrl(h))),u=!d||s||r?"":"_unnormalized"+(A+=1),{prefix:d,name:h,parentMap:t,unnormalized:!!u,url:a,originalName:f,isDefine:l,id:(d?d+"!"+h:h)+u}}function s(e){var t=e.id,i=getOwn(S,t);return i||(i=S[t]=new q.Module(e)),i}function u(e,t,i){var r=e.id,n=getOwn(S,r);!hasProp(j,r)||n&&!n.defineEmitComplete?(n=s(e),n.error&&"error"===t?i(n.error):n.on(t,i)):"defined"===t&&i(j[r])}function c(e,t){var i=e.requireModules,r=!1;t?t(e):(each(i,function(t){var i=getOwn(S,t);i&&(i.error=e,i.events.error&&(r=!0,i.emit("error",e)))}),r||req.onError(e))}function d(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(q.defQueueMap[t]=!0),O.push(e)}),globalDefQueue=[])}function p(e){delete S[e],delete k[e]}function f(e,t,i){var r=e.map.id;e.error?e.emit("error",e.error):(t[r]=!0,each(e.depMaps,function(r,n){var o=r.id,a=getOwn(S,o);!a||e.depMatched[n]||i[o]||(getOwn(t,o)?(e.defineDep(n,j[o]),e.check()):f(a,t,i))}),i[r]=!0)}function l(){var e,t,i=1e3*y.waitSeconds,o=i&&q.startTime+i<(new Date).getTime(),a=[],s=[],u=!1,d=!0;if(!x){if(x=!0,eachProp(k,function(e){var i=e.map,c=i.id;if(e.enabled&&(i.isDefine||s.push(e),!e.error))if(!e.inited&&o)n(c)?(t=!0,u=!0):(a.push(c),r(c));else if(!e.inited&&e.fetched&&i.isDefine&&(u=!0,!i.prefix))return d=!1}),o&&a.length)return e=makeError("timeout","Load timeout for modules: "+a,null,a),e.contextName=q.contextName,c(e);d&&each(s,function(e){f(e,{},{})}),o&&!t||!u||!isBrowser&&!isWebWorker||w||(w=setTimeout(function(){w=0,l()},50)),x=!1}}function h(e){hasProp(j,e[0])||s(a(e[0],null,!0)).init(e[1],e[2])}function m(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function g(e){var t=e.currentTarget||e.srcElement;return m(t,q.onScriptLoad,"load","onreadystatechange"),m(t,q.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function v(){var e;for(d();O.length;){if(e=O.shift(),null===e[0])return c(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));h(e)}q.defQueueMap={}}var x,b,q,E,w,y={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},S={},k={},M={},O=[],j={},P={},R={},T=1,A=1;return E={require:function(e){return e.require?e.require:e.require=q.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?j[e.map.id]=e.exports:e.exports=j[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(y.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},b=function(e){this.events=getOwn(M,e.id)||{},this.map=e,this.shim=getOwn(y.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0},b.prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,q.startTime=(new Date).getTime();var e=this.map;return this.shim?void q.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()})):e.prefix?this.callPlugin():this.load()}},load:function(){var e=this.map.url;P[e]||(P[e]=!0,q.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var e,t,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=q.execCb(i,o,r,n)}catch(t){e=t}else n=q.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&(t=this.module,t?n=t.exports:this.usingExports&&(n=this.exports)),e)return e.requireMap=this.map,e.requireModules=this.map.isDefine?[this.map.id]:null,e.requireType=this.map.isDefine?"define":"require",c(this.error=e)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(j[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(q,this.map,a)}p(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(q.defQueueMap,i)||this.fetch()}},callPlugin:function(){var e=this.map,t=e.id,r=a(e.prefix);this.depMaps.push(r),u(r,"defined",bind(this,function(r){var n,o,d,f=getOwn(R,this.map.id),l=this.map.name,h=this.map.parentMap?this.map.parentMap.name:null,m=q.makeRequire(e.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(r.normalize&&(l=r.normalize(l,function(e){return i(e,h,!0)})||""),o=a(e.prefix+"!"+l,this.map.parentMap),u(o,"defined",bind(this,function(e){this.map.normalizedMap=o,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),d=getOwn(S,o.id),void(d&&(this.depMaps.push(o),this.events.error&&d.on("error",bind(this,function(e){this.emit("error",e)})),d.enable()))):f?(this.map.url=q.nameToUrl(f),void this.load()):(n=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})}),n.error=bind(this,function(e){this.inited=!0,this.error=e,e.requireModules=[t],eachProp(S,function(e){0===e.map.id.indexOf(t+"_unnormalized")&&p(e.map.id)}),c(e)}),n.fromText=bind(this,function(i,r){var o=e.name,u=a(o),d=useInteractive;r&&(i=r),d&&(useInteractive=!1),s(u),hasProp(y.config,t)&&(y.config[o]=y.config[t]);try{req.exec(i)}catch(e){return c(makeError("fromtexteval","fromText eval for "+t+" failed: "+e,e,[t]))}d&&(useInteractive=!0),this.depMaps.push(u),q.completeLoad(o),m([o],n)}),void r.load(e.name,m,n,y))})),q.enable(r,this),this.pluginMaps[r.id]=r},enable:function(){k[this.map.id]=this,this.enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=a(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(E,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,u(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?u(e,"error",bind(this,this.errback)):this.events.error&&u(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=S[i],hasProp(E,i)||!r||r.enabled||q.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(S,e.id);t&&!t.enabled&&q.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},q={config:y,contextName:e,registry:S,defined:j,urlFetched:P,defQueue:O,defQueueMap:{},Module:b,makeModuleMap:a,nextTick:req.nextTick,onError:c,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var t=e.urlArgs;e.urlArgs=function(e,i){return(i.indexOf("?")===-1?"?":"&")+t}}var i=y.shim,r={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){r[t]?(y[t]||(y[t]={}),mixin(y[t],e,!0,!0)):y[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(R[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=q.makeShimExports(e)),i[t]=e}),y.shim=i),e.packages&&each(e.packages,function(e){var t,i;e="string"==typeof e?{name:e}:e,i=e.name,t=e.location,t&&(y.paths[i]=e.location),y.pkgs[i]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(S,function(e,t){e.inited||e.map.unnormalized||(e.map=a(t,null,!0))}),(e.deps||e.callback)&&q.require(e.deps||[],e.callback)},makeShimExports:function(e){function t(){var t;return e.init&&(t=e.init.apply(global,arguments)),t||e.exports&&getGlobal(e.exports)}return t},makeRequire:function(t,n){function o(i,r,u){var d,p,f;return n.enableBuildCallback&&r&&isFunction(r)&&(r.__requireJsBuild=!0),"string"==typeof i?isFunction(r)?c(makeError("requireargs","Invalid require call"),u):t&&hasProp(E,i)?E[i](S[t.id]):req.get?req.get(q,i,t,o):(p=a(i,t,!1,!0),d=p.id,hasProp(j,d)?j[d]:c(makeError("notloaded",'Module name "'+d+'" has not been loaded yet for context: '+e+(t?"":". Use require([])")))):(v(),q.nextTick(function(){v(),f=s(a(null,t)),f.skipMap=n.skipMap,f.init(i,r,u,{enabled:!0}),l()}),o)}return n=n||{},mixin(o,{isBrowser:isBrowser,toUrl:function(e){var r,n=e.lastIndexOf("."),o=e.split("/")[0],a="."===o||".."===o;return n!==-1&&(!a||n>1)&&(r=e.substring(n,e.length),e=e.substring(0,n)),q.nameToUrl(i(e,t&&t.id,!0),r,!0)},defined:function(e){return hasProp(j,a(e,t,!1,!0).id)},specified:function(e){return e=a(e,t,!1,!0).id,hasProp(j,e)||hasProp(S,e)}}),t||(o.undef=function(e){d();var i=a(e,t,!0),n=getOwn(S,e);n.undefed=!0,r(e),delete j[e],delete P[i.url],delete M[e],eachReverse(O,function(t,i){t[0]===e&&O.splice(i,1)}),delete q.defQueueMap[e],n&&(n.events.defined&&(M[e]=n.events),p(e))}),o},enable:function(e){var t=getOwn(S,e.id);t&&s(e).enable()},completeLoad:function(e){var t,i,r,o=getOwn(y.shim,e)||{},a=o.exports;for(d();O.length;){if(i=O.shift(),null===i[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);h(i)}if(q.defQueueMap={},r=getOwn(S,e),!t&&!hasProp(j,e)&&r&&!r.inited){if(!(!y.enforceDefine||a&&getGlobal(a)))return n(e)?void 0:c(makeError("nodefine","No define call for "+e,null,[e]));h([e,o.deps||[],o.exportsFn])}l()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c,d=getOwn(y.pkgs,e);if(d&&(e=d),c=getOwn(R,e))return q.nameToUrl(c,t,i);if(req.jsExtRegExp.test(e))s=e+(t||"");else{for(r=y.paths,n=e.split("/"),o=n.length;o>0;o-=1)if(a=n.slice(0,o).join("/"),u=getOwn(r,a)){isArray(u)&&(u=u[0]),n.splice(0,o,u);break}s=n.join("/"),s+=t||(/^data\:|^blob\:|\?/.test(s)||i?"":".js"),s=("/"===s.charAt(0)||s.match(/^[\w\+\.\-]+:/)?"":y.baseUrl)+s}return y.urlArgs&&!/^blob\:/.test(s)?s+y.urlArgs(e,s):s},load:function(e,t){req.load(q,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=g(e);q.completeLoad(t.id)}},onScriptError:function(e){var t=g(e);if(!n(t.id)){var i=[];return eachProp(S,function(e,r){0!==r.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===t.id)return i.push(r),!0})}),c(makeError("scripterror",'Script error for "'+t.id+(i.length?'", needed by: '+i.join(", "):'"'),e,[t.id]))}}},q.require=q.makeRequire(),q}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState?interactiveScript:(eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript)}var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.2",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;if("undefined"==typeof define){if("undefined"!=typeof requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}"undefined"==typeof require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),n=getOwn(contexts,a),n||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick="undefined"!=typeof setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(e){req[e]=function(){var t=contexts[defContextName];return t.require[e].apply(t,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],baseElement=document.getElementsByTagName("base")[0],baseElement&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(e,t,i){var r,n=e&&e.config||{};if(isBrowser)return r=req.createNode(n,t,i),r.setAttribute("data-requirecontext",e.contextName),r.setAttribute("data-requiremodule",t),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||isOpera?(r.addEventListener("load",e.onScriptLoad,!1),r.addEventListener("error",e.onScriptError,!1)):(useInteractive=!0,r.attachEvent("onreadystatechange",e.onScriptLoad)),r.src=i,n.onNodeCreated&&n.onNodeCreated(r,n,t,i),currentlyAddingScript=r,baseElement?head.insertBefore(r,baseElement):head.appendChild(r),currentlyAddingScript=null,r;if(isWebWorker)try{setTimeout(function(){},0),importScripts(i),e.completeLoad(t)}catch(r){e.onError(makeError("importscripts","importScripts failed for "+t+" at "+i,r,[t]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||mainScript.indexOf("!")!==-1||(src=mainScript.split("/"),mainScript=src.pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,t,i){var r,n;"string"!=typeof e&&(i=t,t=e,e=null),isArray(t)||(i=t,t=null),!t&&isFunction(i)&&(t=[],i.length&&(i.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,i){t.push(i)}),t=(1===i.length?["require"]:["require","exports","module"]).concat(t))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript(),r&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")])),n?(n.defQueue.push([e,t,i]),n.defQueueMap[e]=!0):globalDefQueue.push([e,t,i])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}}(this,"undefined"==typeof setTimeout?void 0:setTimeout); -------------------------------------------------------------------------------- /lib/glfx.js: -------------------------------------------------------------------------------- 1 | /* 2 | * glfx.js 3 | * http://evanw.github.com/glfx.js/ 4 | * 5 | * Copyright 2011 Evan Wallace 6 | * Released under the MIT license 7 | */ 8 | var fx=function(){function q(a,d,c){return Math.max(a,Math.min(d,c))}function w(b){return{_:b,loadContentsOf:function(b){a=this._.gl;this._.loadContentsOf(b)},destroy:function(){a=this._.gl;this._.destroy()}}}function A(a){return w(r.fromElement(a))}function B(b,d){var c=a.UNSIGNED_BYTE;if(a.getExtension("OES_texture_float")&&a.getExtension("OES_texture_float_linear")){var e=new r(100,100,a.RGBA,a.FLOAT);try{e.drawTo(function(){c=a.FLOAT})}catch(g){}e.destroy()}this._.texture&&this._.texture.destroy(); 9 | this._.spareTexture&&this._.spareTexture.destroy();this.width=b;this.height=d;this._.texture=new r(b,d,a.RGBA,c);this._.spareTexture=new r(b,d,a.RGBA,c);this._.extraTexture=this._.extraTexture||new r(0,0,a.RGBA,c);this._.flippedShader=this._.flippedShader||new h(null,"uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,vec2(texCoord.x,1.0-texCoord.y));}");this._.isInitialized=!0}function C(a,d,c){this._.isInitialized&& 10 | a._.width==this.width&&a._.height==this.height||B.call(this,d?d:a._.width,c?c:a._.height);a._.use();this._.texture.drawTo(function(){h.getDefaultShader().drawRect()});return this}function D(){this._.texture.use();this._.flippedShader.drawRect();return this}function f(a,d,c,e){(c||this._.texture).use();this._.spareTexture.drawTo(function(){a.uniforms(d).drawRect()});this._.spareTexture.swapWith(e||this._.texture)}function E(a){a.parentNode.insertBefore(this,a);a.parentNode.removeChild(a);return this} 11 | function F(){var b=new r(this._.texture.width,this._.texture.height,a.RGBA,a.UNSIGNED_BYTE);this._.texture.use();b.drawTo(function(){h.getDefaultShader().drawRect()});return w(b)}function G(){var b=this._.texture.width,d=this._.texture.height,c=new Uint8Array(4*b*d);this._.texture.drawTo(function(){a.readPixels(0,0,b,d,a.RGBA,a.UNSIGNED_BYTE,c)});return c}function k(b){return function(){a=this._.gl;return b.apply(this,arguments)}}function x(a,d,c,e,g,l,n,p){var m=c-g,h=e-l,f=n-g,k=p-l;g=a-c+g-n;l= 12 | d-e+l-p;var q=m*k-f*h,f=(g*k-f*l)/q,m=(m*l-g*h)/q;return[c-a+f*c,e-d+f*e,f,n-a+m*n,p-d+m*p,m,a,d,1]}function y(a){var d=a[0],c=a[1],e=a[2],g=a[3],l=a[4],n=a[5],p=a[6],m=a[7];a=a[8];var f=d*l*a-d*n*m-c*g*a+c*n*p+e*g*m-e*l*p;return[(l*a-n*m)/f,(e*m-c*a)/f,(c*n-e*l)/f,(n*p-g*a)/f,(d*a-e*p)/f,(e*g-d*n)/f,(g*m-l*p)/f,(c*p-d*m)/f,(d*l-c*g)/f]}function z(a){var d=a.length;this.xa=[];this.ya=[];this.u=[];this.y2=[];a.sort(function(a,b){return a[0]-b[0]});for(var c=0;c0.0){color.rgb=(color.rgb-0.5)/(1.0-contrast)+0.5;}else{color.rgb=(color.rgb-0.5)*(1.0+contrast)+0.5;}gl_FragColor=color;}"); 15 | f.call(this,a.brightnessContrast,{brightness:q(-1,b,1),contrast:q(-1,d,1)});return this}function t(a){a=new z(a);for(var d=[],c=0;256>c;c++)d.push(q(0,Math.floor(256*a.interpolate(c/255)),255));return d}function I(b,d,c){b=t(b);1==arguments.length?d=c=b:(d=t(d),c=t(c));for(var e=[],g=0;256>g;g++)e.splice(e.length,0,b[g],d[g],c[g],255);this._.extraTexture.initFromBytes(256,1,e);this._.extraTexture.use(1);a.curves=a.curves||new h(null,"uniform sampler2D texture;uniform sampler2D map;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color.r=texture2D(map,vec2(color.r)).r;color.g=texture2D(map,vec2(color.g)).g;color.b=texture2D(map,vec2(color.b)).b;gl_FragColor=color;}"); 16 | a.curves.textures({map:1});f.call(this,a.curves,{});return this}function J(b){a.denoise=a.denoise||new h(null,"uniform sampler2D texture;uniform float exponent;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;void main(){vec4 center=texture2D(texture,texCoord);vec4 color=vec4(0.0);float total=0.0;for(float x=-4.0;x<=4.0;x+=1.0){for(float y=-4.0;y<=4.0;y+=1.0){vec4 sample=texture2D(texture,texCoord+vec2(x,y)/texSize);float weight=1.0-abs(dot(sample.rgb-center.rgb,vec3(0.25)));weight=pow(weight,exponent);color+=sample*weight;total+=weight;}}gl_FragColor=color/total;}"); 17 | for(var d=0;2>d;d++)f.call(this,a.denoise,{exponent:Math.max(0,b),texSize:[this.width,this.height]});return this}function K(b,d){a.hueSaturation=a.hueSaturation||new h(null,"uniform sampler2D texture;uniform float hue;uniform float saturation;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float angle=hue*3.14159265;float s=sin(angle),c=cos(angle);vec3 weights=(vec3(2.0*c,-sqrt(3.0)*s-c,sqrt(3.0)*s-c)+1.0)/3.0;float len=length(color.rgb);color.rgb=vec3(dot(color.rgb,weights.xyz),dot(color.rgb,weights.zxy),dot(color.rgb,weights.yzx));float average=(color.r+color.g+color.b)/3.0;if(saturation>0.0){color.rgb+=(average-color.rgb)*(1.0-1.0/(1.001-saturation));}else{color.rgb+=(average-color.rgb)*(-saturation);}gl_FragColor=color;}"); 18 | f.call(this,a.hueSaturation,{hue:q(-1,b,1),saturation:q(-1,d,1)});return this}function L(b){a.noise=a.noise||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;float rand(vec2 co){return fract(sin(dot(co.xy,vec2(12.9898,78.233)))*43758.5453);}void main(){vec4 color=texture2D(texture,texCoord);float diff=(rand(texCoord)-0.5)*amount;color.r+=diff;color.g+=diff;color.b+=diff;gl_FragColor=color;}"); 19 | f.call(this,a.noise,{amount:q(0,b,1)});return this}function M(b){a.sepia=a.sepia||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float r=color.r;float g=color.g;float b=color.b;color.r=min(1.0,(r*(1.0-(0.607*amount)))+(g*(0.769*amount))+(b*(0.189*amount)));color.g=min(1.0,(r*0.349*amount)+(g*(1.0-(0.314*amount)))+(b*0.168*amount));color.b=min(1.0,(r*0.272*amount)+(g*0.534*amount)+(b*(1.0-(0.869*amount))));gl_FragColor=color;}"); 20 | f.call(this,a.sepia,{amount:q(0,b,1)});return this}function N(b,d){a.unsharpMask=a.unsharpMask||new h(null,"uniform sampler2D blurredTexture;uniform sampler2D originalTexture;uniform float strength;uniform float threshold;varying vec2 texCoord;void main(){vec4 blurred=texture2D(blurredTexture,texCoord);vec4 original=texture2D(originalTexture,texCoord);gl_FragColor=mix(blurred,original,1.0+strength);}"); 21 | this._.extraTexture.ensureFormat(this._.texture);this._.texture.use();this._.extraTexture.drawTo(function(){h.getDefaultShader().drawRect()});this._.extraTexture.use(1);this.triangleBlur(b);a.unsharpMask.textures({originalTexture:1});f.call(this,a.unsharpMask,{strength:d});this._.extraTexture.unuse(1);return this}function O(b){a.vibrance=a.vibrance||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float average=(color.r+color.g+color.b)/3.0;float mx=max(color.r,max(color.g,color.b));float amt=(mx-average)*(-amount*3.0);color.rgb=mix(color.rgb,vec3(mx),amt);gl_FragColor=color;}"); 22 | f.call(this,a.vibrance,{amount:q(-1,b,1)});return this}function P(b,d){a.vignette=a.vignette||new h(null,"uniform sampler2D texture;uniform float size;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float dist=distance(texCoord,vec2(0.5,0.5));color.rgb*=smoothstep(0.8,size*0.799,dist*(amount+size));gl_FragColor=color;}"); 23 | f.call(this,a.vignette,{size:q(0,b,1),amount:q(0,d,1)});return this}function Q(b,d,c){a.lensBlurPrePass=a.lensBlurPrePass||new h(null,"uniform sampler2D texture;uniform float power;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color=pow(color,vec4(power));gl_FragColor=vec4(color);}");var e="uniform sampler2D texture0;uniform sampler2D texture1;uniform vec2 delta0;uniform vec2 delta1;uniform float power;varying vec2 texCoord;"+ 24 | s+"vec4 sample(vec2 delta){float offset=random(vec3(delta,151.7182),0.0);vec4 color=vec4(0.0);float total=0.0;for(float t=0.0;t<=30.0;t++){float percent=(t+offset)/30.0;color+=texture2D(texture0,texCoord+delta*percent);total+=1.0;}return color/total;}"; 25 | a.lensBlur0=a.lensBlur0||new h(null,e+"void main(){gl_FragColor=sample(delta0);}");a.lensBlur1=a.lensBlur1||new h(null,e+"void main(){gl_FragColor=(sample(delta0)+sample(delta1))*0.5;}");a.lensBlur2=a.lensBlur2||(new h(null,e+"void main(){vec4 color=(sample(delta0)+2.0*texture2D(texture1,texCoord))/3.0;gl_FragColor=pow(color,vec4(power));}")).textures({texture1:1});for(var e= 26 | [],g=0;3>g;g++){var l=c+2*g*Math.PI/3;e.push([b*Math.sin(l)/this.width,b*Math.cos(l)/this.height])}b=Math.pow(10,q(-1,d,1));f.call(this,a.lensBlurPrePass,{power:b});this._.extraTexture.ensureFormat(this._.texture);f.call(this,a.lensBlur0,{delta0:e[0]},this._.texture,this._.extraTexture);f.call(this,a.lensBlur1,{delta0:e[1],delta1:e[2]},this._.extraTexture,this._.extraTexture);f.call(this,a.lensBlur0,{delta0:e[1]});this._.extraTexture.use(1);f.call(this,a.lensBlur2,{power:1/b,delta0:e[2]});return this} 27 | function R(b,d,c,e,g,l){a.tiltShift=a.tiltShift||new h(null,"uniform sampler2D texture;uniform float blurRadius;uniform float gradientRadius;uniform vec2 start;uniform vec2 end;uniform vec2 delta;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);vec2 normal=normalize(vec2(start.y-end.y,end.x-start.x));float radius=smoothstep(0.0,1.0,abs(dot(texCoord*texSize-start,normal))/gradientRadius)*blurRadius;for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta/texSize*percent*radius);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); 28 | var n=c-b,p=e-d,m=Math.sqrt(n*n+p*p);f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:l,start:[b,d],end:[c,e],delta:[n/m,p/m],texSize:[this.width,this.height]});f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:l,start:[b,d],end:[c,e],delta:[-p/m,n/m],texSize:[this.width,this.height]});return this}function S(b){a.triangleBlur=a.triangleBlur||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta*percent);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); 29 | f.call(this,a.triangleBlur,{delta:[b/this.width,0]});f.call(this,a.triangleBlur,{delta:[0,b/this.height]});return this}function T(b,d,c){a.zoomBlur=a.zoomBlur||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;vec2 toCenter=center-texCoord*texSize;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=0.0;t<=40.0;t++){float percent=(t+offset)/40.0;float weight=4.0*(percent-percent*percent);vec4 sample=texture2D(texture,texCoord+toCenter*percent*strength/texSize);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); 30 | f.call(this,a.zoomBlur,{center:[b,d],strength:c,texSize:[this.width,this.height]});return this}function U(b,d,c,e){a.colorHalftone=a.colorHalftone||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float angle;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;float pattern(float angle){float s=sin(angle),c=cos(angle);vec2 tex=texCoord*texSize-center;vec2 point=vec2(c*tex.x-s*tex.y,s*tex.x+c*tex.y)*scale;return(sin(point.x)*sin(point.y))*4.0;}void main(){vec4 color=texture2D(texture,texCoord);vec3 cmy=1.0-color.rgb;float k=min(cmy.x,min(cmy.y,cmy.z));cmy=(cmy-k)/(1.0-k);cmy=clamp(cmy*10.0-3.0+vec3(pattern(angle+0.26179),pattern(angle+1.30899),pattern(angle)),0.0,1.0);k=clamp(k*10.0-5.0+pattern(angle+0.78539),0.0,1.0);gl_FragColor=vec4(1.0-cmy-k,color.a);}"); 31 | f.call(this,a.colorHalftone,{center:[b,d],angle:c,scale:Math.PI/e,texSize:[this.width,this.height]});return this}function V(b,d,c,e){a.dotScreen=a.dotScreen||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float angle;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;float pattern(){float s=sin(angle),c=cos(angle);vec2 tex=texCoord*texSize-center;vec2 point=vec2(c*tex.x-s*tex.y,s*tex.x+c*tex.y)*scale;return(sin(point.x)*sin(point.y))*4.0;}void main(){vec4 color=texture2D(texture,texCoord);float average=(color.r+color.g+color.b)/3.0;gl_FragColor=vec4(vec3(average*10.0-5.0+pattern()),color.a);}"); 32 | f.call(this,a.dotScreen,{center:[b,d],angle:c,scale:Math.PI/e,texSize:[this.width,this.height]});return this}function W(b){a.edgeWork1=a.edgeWork1||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec3 sample=texture2D(texture,texCoord+delta*percent).rgb;float average=(sample.r+sample.g+sample.b)/3.0;color.x+=average*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=average*weight;total.y+=weight;}}gl_FragColor=vec4(color/total,0.0,1.0);}"); 33 | a.edgeWork2=a.edgeWork2||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec2 sample=texture2D(texture,texCoord+delta*percent).xy;color.x+=sample.x*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=sample.y*weight;total.y+=weight;}}float c=clamp(10000.0*(color.y/total.y-color.x/total.x)+0.5,0.0,1.0);gl_FragColor=vec4(c,c,c,1.0);}"); 34 | f.call(this,a.edgeWork1,{delta:[b/this.width,0]});f.call(this,a.edgeWork2,{delta:[0,b/this.height]});return this}function X(b,d,c){a.hexagonalPixelate=a.hexagonalPixelate||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;void main(){vec2 tex=(texCoord*texSize-center)/scale;tex.y/=0.866025404;tex.x-=tex.y*0.5;vec2 a;if(tex.x+tex.y-floor(tex.x)-floor(tex.y)<1.0)a=vec2(floor(tex.x),floor(tex.y));else a=vec2(ceil(tex.x),ceil(tex.y));vec2 b=vec2(ceil(tex.x),floor(tex.y));vec2 c=vec2(floor(tex.x),ceil(tex.y));vec3 TEX=vec3(tex.x,tex.y,1.0-tex.x-tex.y);vec3 A=vec3(a.x,a.y,1.0-a.x-a.y);vec3 B=vec3(b.x,b.y,1.0-b.x-b.y);vec3 C=vec3(c.x,c.y,1.0-c.x-c.y);float alen=length(TEX-A);float blen=length(TEX-B);float clen=length(TEX-C);vec2 choice;if(alen0.0){coord*=mix(1.0,smoothstep(0.0,radius/distance,percent),strength*0.75);}else{coord*=mix(1.0,pow(percent,1.0+strength*0.75)*radius/distance,1.0-percent);}}coord+=center;"); 37 | f.call(this,a.bulgePinch,{radius:c,strength:q(-1,e,1),center:[b,d],texSize:[this.width,this.height]});return this}function $(b,d,c){a.matrixWarp=a.matrixWarp||u("uniform mat3 matrix;uniform bool useTextureSpace;","if(useTextureSpace)coord=coord/texSize*2.0-1.0;vec3 warp=matrix*vec3(coord,1.0);coord=warp.xy/warp.z;if(useTextureSpace)coord=(coord*0.5+0.5)*texSize;");b=Array.prototype.concat.apply([],b);if(4==b.length)b= 38 | [b[0],b[1],0,b[2],b[3],0,0,0,1];else if(9!=b.length)throw"can only warp with 2x2 or 3x3 matrix";f.call(this,a.matrixWarp,{matrix:d?y(b):b,texSize:[this.width,this.height],useTextureSpace:c|0});return this}function aa(a,d){var c=x.apply(null,d),e=x.apply(null,a),c=y(c);return this.matrixWarp([c[0]*e[0]+c[1]*e[3]+c[2]*e[6],c[0]*e[1]+c[1]*e[4]+c[2]*e[7],c[0]*e[2]+c[1]*e[5]+c[2]*e[8],c[3]*e[0]+c[4]*e[3]+c[5]*e[6],c[3]*e[1]+c[4]*e[4]+c[5]*e[7],c[3]*e[2]+c[4]*e[5]+c[5]*e[8],c[6]*e[0]+c[7]*e[3]+c[8]*e[6], 39 | c[6]*e[1]+c[7]*e[4]+c[8]*e[7],c[6]*e[2]+c[7]*e[5]+c[8]*e[8]])}function ba(b,d,c,e){a.swirl=a.swirl||u("uniform float radius;uniform float angle;uniform vec2 center;","coord-=center;float distance=length(coord);if(distance>1;this.xa[e]>a?c=e:d=e}var e=this.xa[c]- 53 | this.xa[d],g=(this.xa[c]-a)/e;a=(a-this.xa[d])/e;return g*this.ya[d]+a*this.ya[c]+((g*g*g-g)*this.y2[d]+(a*a*a-a)*this.y2[c])*e*e/6};var r=function(){function b(b,c,d,f){this.gl=a;this.id=a.createTexture();this.width=b;this.height=c;this.format=d;this.type=f;a.bindTexture(a.TEXTURE_2D,this.id);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE);a.texParameteri(a.TEXTURE_2D, 54 | a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE);b&&c&&a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)}function d(a){null==c&&(c=document.createElement("canvas"));c.width=a.width;c.height=a.height;a=c.getContext("2d");a.clearRect(0,0,c.width,c.height);return a}b.fromElement=function(c){var d=new b(0,0,a.RGBA,a.UNSIGNED_BYTE);d.loadContentsOf(c);return d};b.prototype.loadContentsOf=function(b){this.width=b.width||b.videoWidth;this.height=b.height||b.videoHeight;a.bindTexture(a.TEXTURE_2D, 55 | this.id);a.texImage2D(a.TEXTURE_2D,0,this.format,this.format,this.type,b)};b.prototype.initFromBytes=function(b,c,d){this.width=b;this.height=c;this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,b,c,0,a.RGBA,this.type,new Uint8Array(d))};b.prototype.destroy=function(){a.deleteTexture(this.id);this.id=null};b.prototype.use=function(b){a.activeTexture(a.TEXTURE0+(b||0));a.bindTexture(a.TEXTURE_2D,this.id)};b.prototype.unuse=function(b){a.activeTexture(a.TEXTURE0+ 56 | (b||0));a.bindTexture(a.TEXTURE_2D,null)};b.prototype.ensureFormat=function(b,c,d,f){if(1==arguments.length){var h=arguments[0];b=h.width;c=h.height;d=h.format;f=h.type}if(b!=this.width||c!=this.height||d!=this.format||f!=this.type)this.width=b,this.height=c,this.format=d,this.type=f,a.bindTexture(a.TEXTURE_2D,this.id),a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)};b.prototype.drawTo=function(b){a.framebuffer=a.framebuffer||a.createFramebuffer();a.bindFramebuffer(a.FRAMEBUFFER, 57 | a.framebuffer);a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.id,0);if(a.checkFramebufferStatus(a.FRAMEBUFFER)!==a.FRAMEBUFFER_COMPLETE)throw Error("incomplete framebuffer");a.viewport(0,0,this.width,this.height);b();a.bindFramebuffer(a.FRAMEBUFFER,null)};var c=null;b.prototype.fillUsingCanvas=function(b){b(d(this));this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,c);return this}; 58 | b.prototype.toImage=function(b){this.use();h.getDefaultShader().drawRect();var f=4*this.width*this.height,k=new Uint8Array(f),n=d(this),p=n.createImageData(this.width,this.height);a.readPixels(0,0,this.width,this.height,a.RGBA,a.UNSIGNED_BYTE,k);for(var m=0;m screen y = landscape screen 215 | if (mean_dist0>mean_dist1){ 216 | var max_axis = trans_axis_x; 217 | var min_axis = mean_dist1*max_axis/mean_dist0; 218 | 219 | var trans_bl = [out_width/2-max_axis/2,out_height/2+min_axis/2]; 220 | var trans_br = [out_width/2+max_axis/2,out_height/2+min_axis/2]; 221 | var trans_tl = [out_width/2-max_axis/2,out_height/2-min_axis/2]; 222 | var trans_tr = [out_width/2+max_axis/2,out_height/2-min_axis/2]; 223 | 224 | } else { 225 | var max_axis = trans_axis_y; 226 | var min_axis = mean_dist0*max_axis/mean_dist1; 227 | 228 | var trans_bl = [out_width/2-min_axis/2,out_height/2+max_axis/2]; 229 | var trans_br = [out_width/2+min_axis/2,out_height/2+max_axis/2]; 230 | var trans_tl = [out_width/2-min_axis/2,out_height/2-max_axis/2]; 231 | var trans_tr = [out_width/2+min_axis/2,out_height/2-max_axis/2]; 232 | } 233 | 234 | var source_array = []; 235 | source_array.push(toScreenPosition(plan_definition.measures[0].view_point,camera)); //bottom-left origin point 236 | source_array.push(toScreenPosition(plan_definition.measures[1].view_point,camera)); //bottom-right axis_x_point 237 | source_array.push(toScreenPosition(plan_definition.measures[2].view_point,camera)); //top-right 238 | source_array.push(toScreenPosition(plan_definition.measures[3].view_point,camera)); //top-left 239 | 240 | var dest_array = []; 241 | dest_array.push(trans_bl); //bottom-left origin point 242 | dest_array.push(trans_br); //bottom-right axis_x_point 243 | dest_array.push(trans_tr); //top-right 244 | dest_array.push(trans_tl); //top-left 245 | 246 | function serialize_point_array(array){ 247 | res = []; 248 | for (i=0; i 0; --i){ 284 | obj = scene.children[i] 285 | if (!((obj === mesh)||(obj === mesh_click)||(obj === root_helper_object))){scene.remove(obj);} 286 | //scene.remove(obj); 287 | } 288 | } 289 | 290 | function init() { 291 | 292 | 293 | sv_obj = new google.maps.StreetViewPanorama(document.getElementById("sv")); 294 | google.maps.event.addListener(sv_obj, 'position_changed', function() { 295 | photographerHeading = sv_obj.getPhotographerPov().heading; 296 | lon = (parseFloat(heading) - (photographerHeading - 180)) 297 | }); 298 | 299 | // hack Google Maps to bypass API v3 key (needed since 22 June 2016 http://googlegeodevelopers.blogspot.com.es/2016/06/building-for-scale-updates-to-google.html) 300 | var target = document.head; 301 | var observer = new MutationObserver(function(mutations) { 302 | for (var i = 0; mutations[i]; ++i) { // notify when script to hack is added in HTML head 303 | if (mutations[i].addedNodes[0].nodeName == "SCRIPT" && mutations[i].addedNodes[0].src.match(/\/AuthenticationService.Authenticate?/g)) { 304 | var str = mutations[i].addedNodes[0].src.match(/[?&]callback=.*[&$]/g); 305 | if (str) { 306 | if (str[0][str[0].length - 1] == '&') { 307 | str = str[0].substring(10, str[0].length - 1); 308 | } else { 309 | str = str[0].substring(10); 310 | } 311 | var split = str.split("."); 312 | var object = split[0]; 313 | var method = split[1]; 314 | window[object][method] = null; // remove censorship message function _xdc_._jmzdv6 (AJAX callback name "_jmzdv6" differs depending on URL) 315 | //window[object] = {}; // when we removed the complete object _xdc_, Google Maps tiles did not load when we moved the map with the mouse (no problem with OpenStreetMap) 316 | } 317 | observer.disconnect(); 318 | } 319 | } 320 | }); 321 | var config = { attributes: true, childList: true, characterData: true } 322 | observer.observe(target, config); 323 | 324 | $('#boxclose').click(function(event){ 325 | event.stopPropagation(); 326 | event.preventDefault(); 327 | var overlay_container = document.getElementById('overlay_container'); 328 | overlay_container.className = "hide"; 329 | var main_container = document.getElementById("container") 330 | for (i=0; i 0) {var heading = link.heading} else {var heading = 360 + link.heading} 526 | 527 | helper_geometry_base.rotation.y = (heading - (photographerHeading - 180)) * Math.PI / 180.0; 528 | helper_geometry_base.add(helper_mesh); 529 | root_helper_object.add(helper_geometry_base); 530 | if (old_root_helper_object) { 531 | scene.remove(old_root_helper_object); 532 | } 533 | 534 | } 535 | }) 536 | 537 | } 538 | 539 | 540 | function build_pano( pano_id ) { 541 | 542 | 543 | //document.getElementById('info').innerHTML = "PANOID: "+pano_id 544 | document.getElementById("progress_icon").className = "show"; 545 | 546 | var pano_loader = new PANOMNOM.GoogleStreetViewLoader(); 547 | var depth_loader = new GSVPANO.PanoDepthLoader(); 548 | 549 | 550 | gsv.getPanoramaById(pano_id, 551 | function (data, status) { 552 | if (status === google.maps.StreetViewStatus.OK) { 553 | //sv_obj = google.maps.StreetViewPanorama("sv",{position:data.location.latLng}); 554 | sv_obj.setPano(pano_id); 555 | pano_loader.load( pano_id, quality_factor ); 556 | console.log('LOCATION lat lon:',data.location.latLng.lat(),data.location.latLng.lng()); 557 | get_links(pano_id); 558 | tracker_map.setCenter({ 559 | lat: data.location.latLng.lat(), 560 | lng: data.location.latLng.lng() 561 | }); 562 | tracker_marker.setPosition(data.location.latLng); 563 | 564 | } else { 565 | console.error("Unable to get starting pano ID "); 566 | } 567 | }); 568 | 569 | //pano_loader.load(new google.maps.LatLng(lat, lon)); 570 | 571 | 572 | //pano_loader.onError = function(message){ 573 | // console.log('PanoLoaderError:' + message) 574 | //}; 575 | 576 | 577 | pano_loader.addEventListener( 'load', function() { 578 | console.log("pano_loaded_start"); 579 | clear(); 580 | 581 | var pano_container = document.getElementById('pano_container'); 582 | while (pano_container.firstChild) { 583 | pano_container.removeChild(pano_container.firstChild); 584 | } 585 | this.canvas.id='pano_canvas'; 586 | pano_container.appendChild(this.canvas); 587 | 588 | var container; 589 | container = document.getElementById( 'container' ); 590 | while (container.firstChild) { 591 | container.removeChild(container.firstChild); 592 | } 593 | 594 | camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 ); 595 | camera.target = new THREE.Vector3( 0, 0, 0); 596 | 597 | var geometry = new THREE.SphereGeometry( 500, 120, 80 ); 598 | geometry.scale( -1, 1, 1 ); 599 | 600 | var pano_texture = new THREE.Texture(this.canvas); 601 | 602 | var material = new THREE.MeshBasicMaterial( { 603 | //map: new THREE.TextureLoader().load( 'test.png' ), 604 | map: pano_texture, 605 | side: THREE.DoubleSide 606 | } ); 607 | 608 | pano_texture.needsUpdate = true; 609 | 610 | if (mesh != null){ 611 | scene.remove( mesh ); 612 | } 613 | 614 | mesh = new THREE.Mesh( geometry, material ); 615 | scene.add( mesh ); 616 | 617 | renderer = new THREE.WebGLRenderer({ 618 | preserveDrawingBuffer: true 619 | }); 620 | renderer.setPixelRatio( window.devicePixelRatio ); 621 | renderer.setSize( window.innerWidth, window.innerHeight ); 622 | container.appendChild( renderer.domElement ); 623 | 624 | document.addEventListener( 'mousedown', onDocumentMouseDown, false ); 625 | document.addEventListener( 'mousemove', onDocumentMouseMove, false ); 626 | document.addEventListener( 'mouseup', onDocumentMouseUp, false ); 627 | document.addEventListener( 'wheel', onDocumentMouseWheel, false ); 628 | document.addEventListener( 'dblclick', onDocumentDblclick, false ); 629 | window.addEventListener( 'resize', onWindowResize, false ); 630 | console.log("pano_loaded_end"); 631 | console.log(this.panoId); 632 | depth_loader.load(this.panoId); 633 | 634 | }); 635 | 636 | depth_loader.onDepthLoad = function () { 637 | console.log("depth_loaded_start"); 638 | var canvas = document.createElement("canvas"); 639 | var context = canvas.getContext('2d'); 640 | canvas.setAttribute('width', this.depthMap.width); 641 | canvas.setAttribute('height', this.depthMap.height); 642 | var image = context.getImageData(0, 0, this.depthMap.width, this.depthMap.height); 643 | for (var y = 0; y < this.depthMap.height; ++y) { 644 | for (var x = 0; x < this.depthMap.width ; ++x) { 645 | var col = this.depthMap.depthMap[y * this.depthMap.width - x] / 50 * 255; 646 | image.data[4 * (y * this.depthMap.width + x) + 0] = col; 647 | image.data[4 * (y * this.depthMap.width + x) + 1] = col; 648 | image.data[4 * (y * this.depthMap.width + x) + 2] = 0; 649 | image.data[4 * (y * this.depthMap.width + x) + 3] = 255; 650 | } 651 | } 652 | context.putImageData(image, 0, 0); 653 | var depth_container = document.getElementById('depth_container'); 654 | while (depth_container.firstChild) { 655 | depth_container.removeChild(depth_container.firstChild); 656 | } 657 | 658 | depth_container.appendChild(canvas); 659 | 660 | var geometry_click = new THREE.SphereGeometry( 400, 120, 80 ); 661 | geometry_click.scale( -1, 1, 1 ); 662 | 663 | var depth_texture = new THREE.Texture(canvas); 664 | 665 | material_invisible = new THREE.MeshBasicMaterial( { 666 | //map: new THREE.TextureLoader().load( 'null.png' ), 667 | map: depth_texture, 668 | //color: 0x00ffff, 669 | wireframe: true, 670 | side: THREE.DoubleSide, 671 | wireframeLinewidth: 3.0, 672 | visible: false 673 | } ); 674 | 675 | material_grid = new THREE.MeshBasicMaterial( { 676 | //map: new THREE.TextureLoader().load( 'null.png' ), 677 | map: depth_texture, 678 | //color: 0x00ffff, 679 | wireframe: true, 680 | side: THREE.DoubleSide, 681 | wireframeLinewidth: 3.0, 682 | visible: true 683 | } ); 684 | 685 | material_visible = new THREE.MeshBasicMaterial( { 686 | //map: new THREE.TextureLoader().load( 'null.png' ), 687 | alphaMap: depth_texture, 688 | //color: 0x00ffff, 689 | opacity: 1.0, 690 | transparent: true, 691 | side: THREE.DoubleSide, 692 | visible: true 693 | } ); 694 | 695 | depth_texture.needsUpdate = true; 696 | 697 | if (mesh_click != null){ 698 | scene.remove( mesh_click ); 699 | } 700 | 701 | mesh_click = new THREE.Mesh( geometry_click, material_invisible ); 702 | scene.add( mesh_click ); 703 | 704 | depth_img = context; 705 | 706 | //Relative position calculation 707 | relative_positions = []; 708 | var n = 0; 709 | for (var y = 0; y < this.depthMap.height; ++y) { 710 | var lat = (y / this.depthMap.height) * 180.0 - 90.0; 711 | var r = Math.cos(lat * Math.PI / 180.0); 712 | var row_positions = []; 713 | for (var x = 0; x < this.depthMap.width ; ++x) { 714 | var depth = parseFloat(this.depthMap.depthMap[y * this.depthMap.width + (this.depthMap.width - x)]); 715 | var lng = (1-(x / this.depthMap.width)) * 360.0 - 180.0; 716 | var pos = new THREE.Vector3(); 717 | pos.x = (r * Math.cos(lng * Math.PI / 180.0)); 718 | pos.y = (Math.sin(lat * Math.PI / 180.0)); 719 | pos.z = (r * Math.sin(lng * Math.PI / 180.0)); 720 | pos.d = depth; 721 | pos.multiplyScalar(depth); 722 | pos.multiplyScalar(2.0); 723 | row_positions.push(pos); 724 | n++; 725 | } 726 | relative_positions.push(row_positions); 727 | } 728 | 729 | console.log("depth_loaded_end"); 730 | document.getElementById("progress_icon").className = "hide"; 731 | 732 | } 733 | 734 | } 735 | 736 | function onWindowResize() { 737 | 738 | camera.aspect = window.innerWidth / window.innerHeight; 739 | camera.updateProjectionMatrix(); 740 | 741 | renderer.setSize( window.innerWidth, window.innerHeight ); 742 | 743 | } 744 | 745 | function onDocumentMouseDown( event ) { 746 | 747 | //event.preventDefault(); 748 | 749 | isUserInteracting = true; 750 | 751 | onPointerDownPointerX = event.clientX; 752 | onPointerDownPointerY = event.clientY; 753 | 754 | onPointerDownLon = lon; 755 | onPointerDownLat = lat; 756 | 757 | mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1; 758 | mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1; 759 | raycaster.setFromCamera( mouse, camera ); 760 | 761 | var intersects_helper = raycaster.intersectObject( root_helper_object, true ); 762 | if (intersects_helper.length > 0 && intersects_helper[0].object.userData.length > 0) { 763 | build_pano(intersects_helper[0].object.userData); 764 | } 765 | 766 | } 767 | 768 | function onDocumentDblclick( event ) { 769 | 770 | function dist_line (idx1,idx2) { 771 | var measure_line = new THREE.Line3( measures[idx2].true_point, measures[idx1].true_point ); 772 | var view_line = new THREE.Line3( measures[idx2].view_point, measures[idx1].view_point ); 773 | distances.push(measure_line.distance()*6/measure_factor); 774 | var measure_text = new SpriteText2D((measure_line.distance()*6/measure_factor).toFixed(2), {align: textAlign.right, font: 'bold 12px Arial', fillStyle: '#00ff00' }); 775 | measure_text.position.set (view_line.center().x,view_line.center().y,view_line.center().z); 776 | measure_text.name = "measure_text"; 777 | scene.add(measure_text); 778 | features.push(measure_text); 779 | var measure_geom = new THREE.Geometry (); 780 | measure_geom.vertices.push(measures[idx2].view_point, measures[idx1].view_point); 781 | measure_line =new THREE.Line( measure_geom, new THREE.LineBasicMaterial({color: 0x00ff00, linewidth:3})); 782 | measure_line.name = "measure_line"; 783 | scene.add( measure_line ); 784 | features.push(measure_line); 785 | } 786 | 787 | mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1; 788 | mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1; 789 | raycaster.setFromCamera( mouse, camera ); 790 | 791 | var intersect = raycaster.intersectObject( mesh_click ); 792 | console.log(intersect[0].point); 793 | console.log(intersect[0].uv); 794 | var map_y = Math.round(256-256*intersect[0].uv.y); 795 | var map_x = Math.round(512*intersect[0].uv.x); 796 | 797 | if (relative_positions[map_y][map_x].d < 1000.0) { // check if click point has valid distance, otherwise is in depth map 798 | var geometry = new THREE.Geometry() 799 | geometry.vertices.push( new THREE.Vector3(intersect[0].point.x,intersect[0].point.y,intersect[0].point.z)); 800 | var material2 = new THREE.PointsMaterial( { 801 | size: 16, 802 | map: new THREE.TextureLoader().load( point2_texture ), 803 | sizeAttenuation: false, 804 | transparent : true } ); 805 | material2.color.setHSL( 1.0, 1.0, 1.0 ); 806 | var material1 = new THREE.PointsMaterial( { 807 | size: 32, 808 | map: new THREE.TextureLoader().load( point1_texture ), 809 | sizeAttenuation: false, 810 | transparent : true } ); 811 | material2.color.setHSL( 1.0, 1.0, 1.0 ); 812 | var puntatore1 = new THREE.Points( geometry, material1 ); 813 | var puntatore2 = new THREE.Points( geometry, material2 ); 814 | scene.add( puntatore1 ); 815 | scene.add( puntatore2 ); 816 | features.push(puntatore1); 817 | var SpriteText2D = THREE_Text.SpriteText2D; 818 | var textAlign = THREE_Text.textAlign; 819 | console.log(depth_img.getImageData(map_x, map_y, 1, 1).data); 820 | 821 | //code block for writing depth (distance from the actual point of view) as threejs text object 822 | //leaved here for debug pourpuse 823 | ///var depth_txt = relative_positions[map_y][map_x].d.toFixed(2).toString(); 824 | //var text2 = new SpriteText2D(depth_txt, {align: textAlign.right, font: '12px Arial', fillStyle: '#ff0000' }); 825 | //text2.position.set(intersect[0].point.x,intersect[0].point.y,intersect[0].point.z); 826 | //text2.name = "text2"; 827 | //scene.add(text2); 828 | //features.push(text2); 829 | 830 | measures.push({true_point:relative_positions[map_y][map_x],view_point:intersect[0].point}); 831 | console.log(measures.length); 832 | } 833 | 834 | if (measures.length > 1) { 835 | console.log(measures); 836 | dist_line(measures.length-2, measures.length-1); 837 | } 838 | if (measures.length == 4) { 839 | dist_line(0, measures.length-1); 840 | plan_definition = {measures:measures,distances:distances}; 841 | measures = []; 842 | distances = []; 843 | } 844 | 845 | } 846 | 847 | function onDocumentMouseMove( event ) { 848 | 849 | if ( isUserInteracting === true ) { 850 | 851 | lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon; 852 | lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat; 853 | 854 | } 855 | 856 | } 857 | 858 | function onDocumentMouseUp( event ) { 859 | 860 | isUserInteracting = false; 861 | 862 | } 863 | 864 | function onDocumentMouseWheel( event ) { 865 | 866 | camera.fov += event.deltaY * 0.25; 867 | camera.updateProjectionMatrix(); 868 | 869 | } 870 | 871 | function animate() { 872 | 873 | requestAnimationFrame( animate ); 874 | update(); 875 | 876 | } 877 | 878 | function update() { 879 | 880 | if ( isUserInteracting === false ) { 881 | 882 | lon += 0; 883 | 884 | } 885 | 886 | if (camera) { 887 | lat = Math.max( - 85, Math.min( 85, lat ) ); 888 | phi = THREE.Math.degToRad( 90 - lat ); 889 | theta = THREE.Math.degToRad( lon ); 890 | 891 | camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta ); 892 | camera.target.y = 500 * Math.cos( phi ); 893 | camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta ); 894 | 895 | camera.lookAt( camera.target ); 896 | 897 | renderer.render( scene, camera ); 898 | var actual_bearing_vector = camera.getWorldDirection(); 899 | //v_x = camera.target.x; 900 | //v_y = camera.target.y; 901 | //v_z = camera.target.z; 902 | var actual_bearing = THREE.Math.radToDeg(Math.atan2(actual_bearing_vector.x,actual_bearing_vector.z)) - photographerHeading - 270; 903 | if (actual_bearing > 0) {actual_bearing = 360 - actual_bearing} else {actual_bearing = - actual_bearing}; 904 | if (actual_bearing > 360) {actual_bearing = actual_bearing - 360} 905 | 906 | var actual_bearing_txt = actual_bearing.toFixed(2).toString(); 907 | heading = actual_bearing_txt; 908 | } 909 | } 910 | -------------------------------------------------------------------------------- /lib/dat.gui.min.js: -------------------------------------------------------------------------------- 1 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){a=a||document;var b=a.createElement("link");b.type="text/css";b.rel="stylesheet";b.href=e;a.getElementsByTagName("head")[0].appendChild(b)},inject:function(e,a){a=a||document;var b=document.createElement("style");b.type="text/css";b.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(b)}}}(); 2 | dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(b){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(b[f]=a[f])},this);return b},defaults:function(b){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(b[f])&&(b[f]=a[f])},this);return b},compose:function(){var b=a.call(arguments);return function(){for(var d=a.call(arguments),f=b.length-1;0<=f;f--)d=[b[f].apply(this,d)];return d[0]}}, 3 | each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var c=0,p=a.length;cthis.__max&&(a=this.__max);void 0!==this.__step&&0!=a%this.__step&&(a=Math.round(a/this.__step)*this.__step);return b.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return b}(dat.controllers.Controller,dat.utils.common); 17 | dat.controllers.NumberControllerBox=function(e,a,b){var d=function(f,c,e){function k(){var a=parseFloat(n.__input.value);b.isNaN(a)||n.setValue(a)}function l(a){var c=r-a.clientY;n.setValue(n.getValue()+c*n.__impliedStep);r=a.clientY}function q(){a.unbind(window,"mousemove",l);a.unbind(window,"mouseup",q)}this.__truncationSuspended=!1;d.superclass.call(this,f,c,e);var n=this,r;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",k);a.bind(this.__input, 18 | "blur",function(){k();n.__onFinishChange&&n.__onFinishChange.call(n,n.getValue())});a.bind(this.__input,"mousedown",function(c){a.bind(window,"mousemove",l);a.bind(window,"mouseup",q);r=c.clientY});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&(n.__truncationSuspended=!0,this.blur(),n.__truncationSuspended=!1)});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;b.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input,c;if(this.__truncationSuspended)c= 19 | this.getValue();else{c=this.getValue();var b=Math.pow(10,this.__precision);c=Math.round(c*b)/b}a.value=c;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); 20 | dat.controllers.NumberControllerSlider=function(e,a,b,d,f){function c(a,c,d,b,f){return b+(a-c)/(d-c)*(f-b)}var p=function(d,b,f,e,r){function y(d){d.preventDefault();var b=a.getOffset(h.__background),f=a.getWidth(h.__background);h.setValue(c(d.clientX,b.left,b.left+f,h.__min,h.__max));return!1}function g(){a.unbind(window,"mousemove",y);a.unbind(window,"mouseup",g);h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())}p.superclass.call(this,d,b,{min:f,max:e,step:r});var h=this;this.__background= 21 | document.createElement("div");this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(c){a.bind(window,"mousemove",y);a.bind(window,"mouseup",g);y(c)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};p.superclass=e;p.useDefaultStyles=function(){b.inject(f)};d.extend(p.prototype,e.prototype,{updateDisplay:function(){var a= 22 | (this.getValue()-this.__min)/(this.__max-this.__min);this.__foreground.style.width=100*a+"%";return p.superclass.prototype.updateDisplay.call(this)}});return p}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); 23 | dat.controllers.FunctionController=function(e,a,b){var d=function(b,c,e){d.superclass.call(this,b,c);var k=this;this.__button=document.createElement("div");this.__button.innerHTML=void 0===e?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();k.fire();return!1});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;b.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, 24 | this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 25 | dat.controllers.BooleanController=function(e,a,b){var d=function(b,c){d.superclass.call(this,b,c);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},!1);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;b.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& 26 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){!0===this.getValue()?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=!0):this.__checkbox.checked=!1;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 27 | dat.color.toString=function(e){return function(a){if(1==a.a||e.isUndefined(a.a)){for(a=a.hex.toString(16);6>a.length;)a="0"+a;return"#"+a}return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); 28 | dat.color.interpret=function(e,a){var b,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); 29 | return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return 3!= 30 | a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return 4!=a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(c){return a.isNumber(c.r)&&a.isNumber(c.g)&&a.isNumber(c.b)&&a.isNumber(c.a)?{space:"RGB",r:c.r,g:c.g,b:c.b,a:c.a}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(c){return a.isNumber(c.r)&& 31 | a.isNumber(c.g)&&a.isNumber(c.b)?{space:"RGB",r:c.r,g:c.g,b:c.b}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(c){return a.isNumber(c.h)&&a.isNumber(c.s)&&a.isNumber(c.v)&&a.isNumber(c.a)?{space:"HSV",h:c.h,s:c.s,v:c.v,a:c.a}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(d){return a.isNumber(d.h)&&a.isNumber(d.s)&&a.isNumber(d.v)?{space:"HSV",h:d.h,s:d.s,v:d.v}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d=!1; 32 | var c=1\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n', 59 | ".dg {\n /** Clear list styles */\n /* Auto-place container */\n /* Auto-placed GUI's */\n /* Line items that don't contain folders. */\n /** Folder names */\n /** Hides closed items */\n /** Controller row */\n /** Name-half (left) */\n /** Controller-half (right) */\n /** Controller placement */\n /** Shorter number boxes when slider is present. */\n /** Ensure the entire boolean and function row shows a hand */ }\n .dg ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n clear: both; }\n .dg.ac {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 0;\n z-index: 0; }\n .dg:not(.ac) .main {\n /** Exclude mains in ac so that we don't hide close button */\n overflow: hidden; }\n .dg.main {\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear; }\n .dg.main.taller-than-window {\n overflow-y: auto; }\n .dg.main.taller-than-window .close-button {\n opacity: 1;\n /* TODO, these are style notes */\n margin-top: -1px;\n border-top: 1px solid #2c2c2c; }\n .dg.main ul.closed .close-button {\n opacity: 1 !important; }\n .dg.main:hover .close-button,\n .dg.main .close-button.drag {\n opacity: 1; }\n .dg.main .close-button {\n /*opacity: 0;*/\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear;\n border: 0;\n position: absolute;\n line-height: 19px;\n height: 20px;\n /* TODO, these are style notes */\n cursor: pointer;\n text-align: center;\n background-color: #000; }\n .dg.main .close-button:hover {\n background-color: #111; }\n .dg.a {\n float: right;\n margin-right: 15px;\n overflow-x: hidden; }\n .dg.a.has-save > ul {\n margin-top: 27px; }\n .dg.a.has-save > ul.closed {\n margin-top: 0; }\n .dg.a .save-row {\n position: fixed;\n top: 0;\n z-index: 1002; }\n .dg li {\n -webkit-transition: height 0.1s ease-out;\n -o-transition: height 0.1s ease-out;\n -moz-transition: height 0.1s ease-out;\n transition: height 0.1s ease-out; }\n .dg li:not(.folder) {\n cursor: auto;\n height: 27px;\n line-height: 27px;\n overflow: hidden;\n padding: 0 4px 0 5px; }\n .dg li.folder {\n padding: 0;\n border-left: 4px solid rgba(0, 0, 0, 0); }\n .dg li.title {\n cursor: pointer;\n margin-left: -4px; }\n .dg .closed li:not(.title),\n .dg .closed ul li,\n .dg .closed ul li > * {\n height: 0;\n overflow: hidden;\n border: 0; }\n .dg .cr {\n clear: both;\n padding-left: 3px;\n height: 27px; }\n .dg .property-name {\n cursor: default;\n float: left;\n clear: left;\n width: 40%;\n overflow: hidden;\n text-overflow: ellipsis; }\n .dg .c {\n float: left;\n width: 60%; }\n .dg .c input[type=text] {\n border: 0;\n margin-top: 4px;\n padding: 3px;\n width: 100%;\n float: right; }\n .dg .has-slider input[type=text] {\n width: 30%;\n /*display: none;*/\n margin-left: 0; }\n .dg .slider {\n float: left;\n width: 66%;\n margin-left: -5px;\n margin-right: 0;\n height: 19px;\n margin-top: 4px; }\n .dg .slider-fg {\n height: 100%; }\n .dg .c input[type=checkbox] {\n margin-top: 9px; }\n .dg .c select {\n margin-top: 5px; }\n .dg .cr.function,\n .dg .cr.function .property-name,\n .dg .cr.function *,\n .dg .cr.boolean,\n .dg .cr.boolean * {\n cursor: pointer; }\n .dg .selector {\n display: none;\n position: absolute;\n margin-left: -9px;\n margin-top: 23px;\n z-index: 10; }\n .dg .c:hover .selector,\n .dg .selector.drag {\n display: block; }\n .dg li.save-row {\n padding: 0; }\n .dg li.save-row .button {\n display: inline-block;\n padding: 0px 6px; }\n .dg.dialogue {\n background-color: #222;\n width: 460px;\n padding: 15px;\n font-size: 13px;\n line-height: 15px; }\n\n/* TODO Separate style and structure */\n#dg-new-constructor {\n padding: 10px;\n color: #222;\n font-family: Monaco, monospace;\n font-size: 10px;\n border: 0;\n resize: none;\n box-shadow: inset 1px 1px 1px #888;\n word-wrap: break-word;\n margin: 12px 0;\n display: block;\n width: 440px;\n overflow-y: scroll;\n height: 100px;\n position: relative; }\n\n#dg-local-explain {\n display: none;\n font-size: 11px;\n line-height: 17px;\n border-radius: 3px;\n background-color: #333;\n padding: 8px;\n margin-top: 10px; }\n #dg-local-explain code {\n font-size: 10px; }\n\n#dat-gui-save-locally {\n display: none; }\n\n/** Main type */\n.dg {\n color: #eee;\n font: 11px 'Lucida Grande', sans-serif;\n text-shadow: 0 -1px 0 #111;\n /** Auto place */\n /* Controller row,
  • */\n /** Controllers */ }\n .dg.main {\n /** Scrollbar */ }\n .dg.main::-webkit-scrollbar {\n width: 5px;\n background: #1a1a1a; }\n .dg.main::-webkit-scrollbar-corner {\n height: 0;\n display: none; }\n .dg.main::-webkit-scrollbar-thumb {\n border-radius: 5px;\n background: #676767; }\n .dg li:not(.folder) {\n background: #1a1a1a;\n border-bottom: 1px solid #2c2c2c; }\n .dg li.save-row {\n line-height: 25px;\n background: #dad5cb;\n border: 0; }\n .dg li.save-row select {\n margin-left: 5px;\n width: 108px; }\n .dg li.save-row .button {\n margin-left: 5px;\n margin-top: 1px;\n border-radius: 2px;\n font-size: 9px;\n line-height: 7px;\n padding: 4px 4px 5px 4px;\n background: #c5bdad;\n color: #fff;\n text-shadow: 0 1px 0 #b0a58f;\n box-shadow: 0 -1px 0 #b0a58f;\n cursor: pointer; }\n .dg li.save-row .button.gears {\n background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;\n height: 7px;\n width: 8px; }\n .dg li.save-row .button:hover {\n background-color: #bab19e;\n box-shadow: 0 -1px 0 #b0a58f; }\n .dg li.folder {\n border-bottom: 0; }\n .dg li.title {\n padding-left: 16px;\n background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;\n cursor: pointer;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2); }\n .dg .closed li.title {\n background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }\n .dg .cr.boolean {\n border-left: 3px solid #806787; }\n .dg .cr.function {\n border-left: 3px solid #e61d5f; }\n .dg .cr.number {\n border-left: 3px solid #2fa1d6; }\n .dg .cr.number input[type=text] {\n color: #2fa1d6; }\n .dg .cr.string {\n border-left: 3px solid #1ed36f; }\n .dg .cr.string input[type=text] {\n color: #1ed36f; }\n .dg .cr.function:hover, .dg .cr.boolean:hover {\n background: #111; }\n .dg .c input[type=text] {\n background: #303030;\n outline: none; }\n .dg .c input[type=text]:hover {\n background: #3c3c3c; }\n .dg .c input[type=text]:focus {\n background: #494949;\n color: #fff; }\n .dg .c .slider {\n background: #303030;\n cursor: ew-resize; }\n .dg .c .slider-fg {\n background: #2fa1d6; }\n .dg .c .slider:hover {\n background: #3c3c3c; }\n .dg .c .slider:hover .slider-fg {\n background: #44abda; }\n", 60 | dat.controllers.factory=function(e,a,b,d,f,c,p){return function(k,l,q,n){var r=k[l];if(p.isArray(q)||p.isObject(q))return new e(k,l,q);if(p.isNumber(r))return p.isNumber(q)&&p.isNumber(n)?new b(k,l,q,n):new a(k,l,{min:q,max:n});if(p.isString(r))return new d(k,l);if(p.isFunction(r))return new f(k,l,"");if(p.isBoolean(r))return new c(k,l)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,b){var d= 61 | function(b,c){function e(){k.setValue(k.__input.value)}d.superclass.call(this,b,c);var k=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){k.__onFinishChange&&k.__onFinishChange.call(k,k.getValue())});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;b.extend(d.prototype, 62 | e.prototype,{updateDisplay:function(){a.isActive(this.__input)||(this.__input.value=this.getValue());return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, 63 | dat.controllers.ColorController=function(e,a,b,d,f){function c(a,b,d,c){a.style.background="";f.each(l,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+d+" 0%, "+c+" 100%); "})}function p(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; 64 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var k=function(e,n){function r(b){t(b);a.bind(window,"mousemove",t);a.bind(window, 65 | "mouseup",l)}function l(){a.unbind(window,"mousemove",t);a.unbind(window,"mouseup",l)}function g(){var a=d(this.value);!1!==a?(s.__color.__state=a,s.setValue(s.__color.toOriginal())):this.value=s.__color.toString()}function h(){a.unbind(window,"mousemove",u);a.unbind(window,"mouseup",h)}function t(b){b.preventDefault();var d=a.getWidth(s.__saturation_field),c=a.getOffset(s.__saturation_field),e=(b.clientX-c.left+document.body.scrollLeft)/d;b=1-(b.clientY-c.top+document.body.scrollTop)/d;1 66 | b&&(b=0);1e&&(e=0);s.__color.v=b;s.__color.s=e;s.setValue(s.__color.toOriginal());return!1}function u(b){b.preventDefault();var d=a.getHeight(s.__hue_field),c=a.getOffset(s.__hue_field);b=1-(b.clientY-c.top+document.body.scrollTop)/d;1b&&(b=0);s.__color.h=360*b;s.setValue(s.__color.toOriginal());return!1}k.superclass.call(this,e,n);this.__color=new b(this.getValue());this.__temp=new b(0);var s=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,!1); 67 | this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=document.createElement("input"); 68 | this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){13===a.keyCode&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(b){a.addClass(this,"drag").bind(window,"mouseup",function(b){a.removeClass(s.__selector,"drag")})});var v=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});f.extend(this.__field_knob.style, 69 | {position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(0.5>this.__color.v?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(v.style,{width:"100%",height:"100%", 70 | background:"none"});c(v,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});p(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",r);a.bind(this.__field_knob,"mousedown",r);a.bind(this.__hue_field,"mousedown",function(b){u(b);a.bind(window, 71 | "mousemove",u);a.bind(window,"mouseup",h)});this.__saturation_field.appendChild(v);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};k.superclass=e;f.extend(k.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue());if(!1!==a){var e=!1; 72 | f.each(b.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=!0,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var k=0.5>this.__color.v||0.5a&&(a+=1);return{h:360*a,s:e/c,v:c/255}},rgb_to_hex:function(a,b,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,b);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,b){return a>>8*b&255},hex_with_component:function(a,b,d){return d<<(e=8*b)|a&~(255<