├── images ├── Thumbs.db ├── play.png ├── clear64.png ├── eraser64.png ├── pencil64.png ├── readme1.png ├── readme2.png └── checkerboard.jpg ├── js ├── katex │ ├── fonts │ │ ├── KaTeX_Main-Bold.eot │ │ ├── KaTeX_Main-Bold.ttf │ │ ├── KaTeX_AMS-Regular.eot │ │ ├── KaTeX_AMS-Regular.ttf │ │ ├── KaTeX_AMS-Regular.woff │ │ ├── KaTeX_Main-Bold.woff │ │ ├── KaTeX_Main-Bold.woff2 │ │ ├── KaTeX_Main-Italic.eot │ │ ├── KaTeX_Main-Italic.ttf │ │ ├── KaTeX_Main-Italic.woff │ │ ├── KaTeX_Main-Regular.eot │ │ ├── KaTeX_Main-Regular.ttf │ │ ├── KaTeX_Math-Italic.eot │ │ ├── KaTeX_Math-Italic.ttf │ │ ├── KaTeX_Math-Italic.woff │ │ ├── KaTeX_Math-Regular.eot │ │ ├── KaTeX_Math-Regular.ttf │ │ ├── KaTeX_AMS-Regular.woff2 │ │ ├── KaTeX_Main-Italic.woff2 │ │ ├── KaTeX_Main-Regular.woff │ │ ├── KaTeX_Main-Regular.woff2 │ │ ├── KaTeX_Math-Italic.woff2 │ │ ├── KaTeX_Math-Regular.woff │ │ ├── KaTeX_Math-Regular.woff2 │ │ ├── KaTeX_Size1-Regular.eot │ │ ├── KaTeX_Size1-Regular.ttf │ │ ├── KaTeX_Size1-Regular.woff │ │ ├── KaTeX_Size2-Regular.eot │ │ ├── KaTeX_Size2-Regular.ttf │ │ ├── KaTeX_Size2-Regular.woff │ │ ├── KaTeX_Size3-Regular.eot │ │ ├── KaTeX_Size3-Regular.ttf │ │ ├── KaTeX_Size3-Regular.woff │ │ ├── KaTeX_Size4-Regular.eot │ │ ├── KaTeX_Size4-Regular.ttf │ │ ├── KaTeX_Size4-Regular.woff │ │ ├── KaTeX_Math-BoldItalic.eot │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ ├── KaTeX_Math-BoldItalic.woff │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ ├── KaTeX_Size1-Regular.woff2 │ │ ├── KaTeX_Size2-Regular.woff2 │ │ ├── KaTeX_Size3-Regular.woff2 │ │ └── KaTeX_Size4-Regular.woff2 │ └── README.md ├── drawingboard │ ├── controls │ │ ├── download.js │ │ ├── drawingmode.js │ │ ├── control.js │ │ ├── navigation.js │ │ ├── color.js │ │ └── size.js │ └── utils.js ├── controls │ ├── VRControls.js │ ├── OculusControls.js │ ├── DeviceOrientationControls.js │ ├── PointerLockControls.js │ ├── FirstPersonControls.js │ ├── FlyControls.js │ ├── EditorControls.js │ ├── OrthographicTrackballControls.js │ └── TrackballControls.js ├── colormaps │ ├── myColorMap_dark.js │ ├── myColorMap_gray.js │ └── myColorMap_light.js ├── createText.js ├── stats.min.js ├── yepnope.js ├── tween.min.js ├── nn │ ├── nn2.js │ ├── nn.js │ ├── nn_funcs_soft.js │ ├── nn_funcs_merge.js │ └── nn_funcs.js ├── GeometryUtils.js ├── newOrbit.js ├── qiao_OrbitControls.js └── sylvester.js ├── .idea └── vcs.xml ├── README.md ├── LICENSE ├── .gitignore └── css ├── main.css ├── main2.css ├── main5.css └── drawingboard2.css /images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/Thumbs.db -------------------------------------------------------------------------------- /images/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/play.png -------------------------------------------------------------------------------- /images/clear64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/clear64.png -------------------------------------------------------------------------------- /images/eraser64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/eraser64.png -------------------------------------------------------------------------------- /images/pencil64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/pencil64.png -------------------------------------------------------------------------------- /images/readme1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/readme1.png -------------------------------------------------------------------------------- /images/readme2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/readme2.png -------------------------------------------------------------------------------- /images/checkerboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/images/checkerboard.jpg -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Bold.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_AMS-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_AMS-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Italic.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Italic.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size1-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size1-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size1-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size2-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size2-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size2-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size2-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size3-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size3-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size3-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size3-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size3-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size4-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size4-Regular.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size4-Regular.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-BoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-BoldItalic.eot -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-BoldItalic.ttf -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-BoldItalic.woff -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Math-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Math-BoldItalic.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size1-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size1-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size2-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size2-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size3-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size3-Regular.woff2 -------------------------------------------------------------------------------- /js/katex/fonts/KaTeX_Size4-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlesLiuyx/3DVis_FullyConnectNN/HEAD/js/katex/fonts/KaTeX_Size4-Regular.woff2 -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /js/drawingboard/controls/download.js: -------------------------------------------------------------------------------- 1 | DrawingBoard.Control.Download = DrawingBoard.Control.extend({ 2 | 3 | name: 'download', 4 | 5 | initialize: function() { 6 | this.$el.append(''); 7 | this.$el.on('click', '.drawing-board-control-download-button', $.proxy(function(e) { 8 | this.board.downloadImg(); 9 | e.preventDefault(); 10 | }, this)); 11 | } 12 | 13 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3DVis_FullyConnectNN 2 | A 3D interactive visualization web application 3 | 4 | ## Usage 5 | 6 | ### Download 7 | 8 | ``` 9 | git clone https://github.com/CharlesLiuyx/3DVis_FullyConnectNN.git 10 | cd 3DVis_FullyConnectNN 11 | ``` 12 | 13 | ### Environment 14 | 15 | Open the directory by WebStorm 16 | 17 | Click explore to start a local server to run the project 18 | 19 | ![readme1](images/readme1.png) 20 | 21 | ## Preview 22 | 23 | ![readme1](images/readme2.png) 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 YaoXing Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # IDEA 61 | .idea/ 62 | -------------------------------------------------------------------------------- /js/drawingboard/controls/drawingmode.js: -------------------------------------------------------------------------------- 1 | DrawingBoard.Control.DrawingMode = DrawingBoard.Control.extend({ 2 | 3 | name: 'drawingmode', 4 | 5 | defaults: { 6 | pencil: true, 7 | eraser: true, 8 | filler: true 9 | }, 10 | 11 | initialize: function() { 12 | 13 | this.prevMode = this.board.getMode(); 14 | 15 | $.each(["pencil", "eraser", "filler"], $.proxy(function(k, value) { 16 | if (this.opts[value]) { 17 | this.$el.append(''); 18 | } 19 | }, this)); 20 | 21 | this.$el.on('click', 'button[data-mode]', $.proxy(function(e) { 22 | var value = $(e.currentTarget).attr('data-mode'); 23 | var mode = this.board.getMode(); 24 | if (mode !== value) this.prevMode = mode; 25 | var newMode = mode === value ? this.prevMode : value; 26 | this.board.setMode( newMode ); 27 | e.preventDefault(); 28 | }, this)); 29 | 30 | this.board.ev.bind('board:mode', $.proxy(function(mode) { 31 | this.toggleButtons(mode); 32 | }, this)); 33 | 34 | this.toggleButtons( this.board.getMode() ); 35 | }, 36 | 37 | toggleButtons: function(mode) { 38 | this.$el.find('button[data-mode]').each(function(k, item) { 39 | var $item = $(item); 40 | $item.toggleClass('active', mode === $item.attr('data-mode')); 41 | }); 42 | } 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /js/controls/VRControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dmarcos / https://github.com/dmarcos 3 | * @author mrdoob / http://mrdoob.com 4 | */ 5 | 6 | THREE.VRControls = function ( object, callback ) { 7 | 8 | var vrInput; 9 | 10 | var onVRDevices = function ( devices ) { 11 | 12 | for ( var i = 0; i < devices.length; i ++ ) { 13 | 14 | var device = devices[ i ]; 15 | 16 | if ( device instanceof PositionSensorVRDevice ) { 17 | 18 | vrInput = devices[ i ]; 19 | return; // We keep the first we encounter 20 | 21 | } 22 | 23 | } 24 | 25 | if ( callback !== undefined ) { 26 | 27 | callback( 'HMD not available' ); 28 | 29 | } 30 | 31 | }; 32 | 33 | if ( navigator.getVRDevices !== undefined ) { 34 | 35 | navigator.getVRDevices().then( onVRDevices ); 36 | 37 | } else if ( callback !== undefined ) { 38 | 39 | callback( 'Your browser is not VR Ready' ); 40 | 41 | } 42 | 43 | this.update = function () { 44 | 45 | if ( vrInput === undefined ) return; 46 | 47 | var state = vrInput.getState(); 48 | 49 | if ( state.orientation !== null ) { 50 | 51 | object.quaternion.copy( state.orientation ); 52 | 53 | } 54 | 55 | if ( state.position !== null ) { 56 | 57 | object.position.copy( state.position ); 58 | 59 | } 60 | 61 | }; 62 | 63 | this.zeroSensor = function () { 64 | 65 | if ( vrInput === undefined ) return; 66 | 67 | vrInput.zeroSensor(); 68 | 69 | }; 70 | 71 | }; 72 | -------------------------------------------------------------------------------- /js/drawingboard/controls/control.js: -------------------------------------------------------------------------------- 1 | DrawingBoard.Control = function(drawingBoard, opts) { 2 | this.board = drawingBoard; 3 | this.opts = $.extend({}, this.defaults, opts); 4 | 5 | this.$el = $(document.createElement('div')).addClass('drawing-board-control'); 6 | if (this.name) 7 | this.$el.addClass('drawing-board-control-' + this.name); 8 | 9 | this.board.ev.bind('board:reset', $.proxy(this.onBoardReset, this)); 10 | 11 | this.initialize.apply(this, arguments); 12 | return this; 13 | }; 14 | 15 | DrawingBoard.Control.prototype = { 16 | 17 | name: '', 18 | 19 | defaults: {}, 20 | 21 | initialize: function() { 22 | 23 | }, 24 | 25 | addToBoard: function() { 26 | this.board.addControl(this); 27 | }, 28 | 29 | onBoardReset: function(opts) { 30 | 31 | } 32 | 33 | }; 34 | 35 | //extend directly taken from backbone.js 36 | DrawingBoard.Control.extend = function(protoProps, staticProps) { 37 | var parent = this; 38 | var child; 39 | if (protoProps && protoProps.hasOwnProperty('constructor')) { 40 | child = protoProps.constructor; 41 | } else { 42 | child = function(){ return parent.apply(this, arguments); }; 43 | } 44 | $.extend(child, parent, staticProps); 45 | var Surrogate = function(){ this.constructor = child; }; 46 | Surrogate.prototype = parent.prototype; 47 | child.prototype = new Surrogate(); 48 | if (protoProps) $.extend(child.prototype, protoProps); 49 | child.__super__ = parent.prototype; 50 | return child; 51 | }; -------------------------------------------------------------------------------- /js/colormaps/myColorMap_dark.js: -------------------------------------------------------------------------------- 1 | var redLookup = [ 2 | 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.08,0.09,0.10,0.11,0.12,0.12,0.13,0.14,0.14,0.15,0.15,0.16,0.16,0.17,0.17,0.17,0.17,0.18,0.18,0.18,0.18,0.18,0.18,0.17,0.17,0.17,0.17,0.16,0.16,0.15,0.15,0.14,0.14,0.14,0.14,0.14,0.14,0.13,0.13,0.13,0.13,0.12,0.12,0.12,0.12,0.11,0.11,0.11,0.10,0.10,0.10,0.09,0.09,0.09,0.08,0.08,0.08,0.07,0.07,0.07,0.06,0.06,0.06,0.05,0.05,0.05,0.04,0.04,0.04,0.04,0.03,0.03,0.03,0.02,0.02,0.02,0.02,0.01,0.01,0.01,0.01,0.01,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00]; 3 | var greenLookup = [ 4 | 0.00,0.01,0.02,0.03,0.04,0.05,0.05,0.06,0.07,0.08,0.08,0.09,0.09,0.10,0.10,0.11,0.11,0.12,0.12,0.13,0.13,0.13,0.13,0.14,0.14,0.14,0.14,0.14,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.15,0.14,0.15,0.15,0.15,0.16,0.16,0.17,0.18,0.18,0.19,0.20,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.31,0.32,0.33,0.35,0.36,0.37,0.39,0.41,0.42,0.44,0.46,0.48,0.49,0.51,0.53,0.55,0.58,0.60,0.62,0.64,0.66,0.69,0.71,0.74,0.76,0.79,0.82,0.84,0.87,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; 5 | var blueLookup = [ 6 | 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.89,0.88,0.88,0.87,0.86,0.85,0.83,0.82,0.81,0.80]; 7 | -------------------------------------------------------------------------------- /js/colormaps/myColorMap_gray.js: -------------------------------------------------------------------------------- 1 | var redLookup = [ 2 | 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; 3 | var greenLookup = [ 4 | 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; 5 | var blueLookup = [ 6 | 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; 7 | -------------------------------------------------------------------------------- /js/colormaps/myColorMap_light.js: -------------------------------------------------------------------------------- 1 | var redLookup = [ 2 | 1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.98,0.96,0.95,0.93,0.91,0.88,0.86,0.84,0.82,0.79,0.77,0.74,0.72,0.69,0.67,0.64,0.61,0.58,0.55,0.52,0.50,0.47,0.43,0.40,0.37,0.34,0.31,0.28,0.24,0.21,0.18,0.14,0.11,0.10,0.10,0.09,0.09,0.08,0.07,0.07,0.06,0.06,0.05,0.05,0.04,0.04,0.04,0.03,0.03,0.03,0.02,0.02,0.02,0.01,0.01,0.01,0.01,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00]; 3 | var greenLookup = [ 4 | 1.00,0.98,0.96,0.94,0.92,0.90,0.88,0.86,0.84,0.83,0.81,0.79,0.77,0.75,0.74,0.72,0.70,0.69,0.67,0.65,0.64,0.62,0.60,0.59,0.57,0.56,0.54,0.53,0.51,0.50,0.49,0.47,0.46,0.44,0.43,0.42,0.40,0.39,0.38,0.37,0.36,0.34,0.33,0.32,0.31,0.30,0.29,0.28,0.27,0.26,0.24,0.24,0.23,0.22,0.21,0.20,0.19,0.18,0.17,0.16,0.16,0.15,0.14,0.13,0.12,0.12,0.11,0.13,0.15,0.17,0.20,0.22,0.24,0.27,0.29,0.32,0.34,0.37,0.39,0.42,0.45,0.47,0.50,0.53,0.56,0.58,0.61,0.64,0.67,0.70,0.73,0.76,0.79,0.82,0.85,0.88,0.91,0.94,0.97,1.00]; 5 | var blueLookup = [ 6 | 1.00,0.98,0.96,0.95,0.93,0.92,0.90,0.89,0.88,0.87,0.87,0.86,0.86,0.85,0.85,0.85,0.85,0.85,0.85,0.85,0.86,0.86,0.87,0.88,0.88,0.89,0.90,0.91,0.93,0.94,0.95,0.97,0.98,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00]; 7 | -------------------------------------------------------------------------------- /js/controls/OculusControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author possan / http://possan.se/ 3 | * 4 | * Oculus headtracking control 5 | * - use together with the oculus-rest project to get headtracking 6 | * coordinates from the rift: http://github.com/possan/oculus-rest 7 | */ 8 | 9 | THREE.OculusControls = function ( object ) { 10 | 11 | this.object = object; 12 | this.target = new THREE.Vector3( 0, 0, 0 ); 13 | 14 | this.enabled = true; 15 | this.headquat = new THREE.Quaternion(); 16 | 17 | this.loadAjaxJSON = function ( url, callback ) { 18 | var xhr = new XMLHttpRequest(); 19 | xhr.onreadystatechange = function () { 20 | if ( xhr.readyState === xhr.DONE ) { 21 | if ( xhr.status === 200 || xhr.status === 0 ) { 22 | if ( xhr.responseText ) { 23 | var json = JSON.parse( xhr.responseText ); 24 | callback( json ); 25 | } 26 | } 27 | } 28 | }; 29 | xhr.open( "GET", url, true ); 30 | xhr.withCredentials = false; 31 | xhr.send( null ); 32 | }; 33 | 34 | this.gotCoordinates = function( r ) { 35 | this.headquat.set(r.quat.x, r.quat.y, r.quat.z, r.quat.w); 36 | this.queuePoll(); 37 | } 38 | 39 | this.pollOnce = function() { 40 | this.loadAjaxJSON('http://localhost:50000', bind(this, this.gotCoordinates)); 41 | } 42 | 43 | this.queuePoll = function() { 44 | setTimeout(bind(this, this.pollOnce), 10); 45 | } 46 | 47 | this.update = function( delta ) { 48 | if ( this.enabled === false ) return; 49 | this.object.quaternion.multiply(this.headquat); 50 | }; 51 | 52 | function bind( scope, fn ) { 53 | return function () { 54 | fn.apply( scope, arguments ); 55 | }; 56 | }; 57 | 58 | this.connect = function() { 59 | this.queuePoll(); 60 | }; 61 | }; 62 | -------------------------------------------------------------------------------- /js/drawingboard/controls/navigation.js: -------------------------------------------------------------------------------- 1 | DrawingBoard.Control.Navigation = DrawingBoard.Control.extend({ 2 | 3 | name: 'navigation', 4 | 5 | defaults: { 6 | back: true, 7 | forward: true, 8 | reset: true 9 | }, 10 | 11 | initialize: function() { 12 | var el = ''; 13 | if (this.opts.back) el += ''; 14 | if (this.opts.forward) el += ''; 15 | if (this.opts.reset) el += ''; 16 | this.$el.append(el); 17 | 18 | if (this.opts.back) { 19 | var $back = this.$el.find('.drawing-board-control-navigation-back'); 20 | this.board.ev.bind('historyNavigation', $.proxy(function(pos) { 21 | if (pos === 1) 22 | $back.attr('disabled', 'disabled'); 23 | else 24 | $back.removeAttr('disabled'); 25 | }, this)); 26 | this.$el.on('click', '.drawing-board-control-navigation-back', $.proxy(function(e) { 27 | this.board.goBackInHistory(); 28 | e.preventDefault(); 29 | }, this)); 30 | } 31 | 32 | if (this.opts.forward) { 33 | var $forward = this.$el.find('.drawing-board-control-navigation-forward'); 34 | this.board.ev.bind('historyNavigation', $.proxy(function(pos) { 35 | if (pos === this.board.history.values.length) 36 | $forward.attr('disabled', 'disabled'); 37 | else 38 | $forward.removeAttr('disabled'); 39 | }, this)); 40 | this.$el.on('click', '.drawing-board-control-navigation-forward', $.proxy(function(e) { 41 | this.board.goForthInHistory(); 42 | e.preventDefault(); 43 | }, this)); 44 | } 45 | 46 | if (this.opts.reset) { 47 | this.$el.on('click', '.drawing-board-control-navigation-reset', $.proxy(function(e) { 48 | this.board.reset({ background: true }); 49 | e.preventDefault(); 50 | }, this)); 51 | } 52 | } 53 | }); -------------------------------------------------------------------------------- /js/createText.js: -------------------------------------------------------------------------------- 1 | function createText() { 2 | group = new THREE.Group(); 3 | group.position.y = 100; 4 | group.name = 'text'; 5 | scene.add( group ); 6 | 7 | material = new THREE.MeshFaceMaterial( [ 8 | new THREE.MeshPhongMaterial( { color: 0xFFFFFF, shading: THREE.FlatShading } ), // front 9 | new THREE.MeshPhongMaterial( { color: 0xFFFFFF, shading: THREE.SmoothShading } ) // side 10 | ]); 11 | 12 | textGeo = new THREE.TextGeometry( text, { 13 | 14 | size: size, 15 | height: height, 16 | curveSegments: curveSegments, 17 | 18 | font: font, 19 | weight: weight, 20 | style: style, 21 | 22 | bevelThickness: bevelThickness, 23 | bevelSize: bevelSize, 24 | bevelEnabled: bevelEnabled, 25 | 26 | material: 1, 27 | extrudeMaterial: 1 28 | 29 | }); 30 | 31 | textGeo.computeBoundingBox(); 32 | textGeo.computeVertexNormals(); 33 | 34 | if ( ! bevelEnabled ) { 35 | 36 | var triangleAreaHeuristics = 0.1 * ( height * size ); 37 | 38 | for ( var i = 0; i < textGeo.faces.length; i ++ ) { 39 | 40 | var face = textGeo.faces[ i ]; 41 | 42 | if ( face.materialIndex == 1 ) { 43 | 44 | for ( var j = 0; j < face.vertexNormals.length; j ++ ) { 45 | 46 | face.vertexNormals[ j ].z = 0; 47 | face.vertexNormals[ j ].normalize(); 48 | 49 | } 50 | 51 | var va = textGeo.vertices[ face.a ]; 52 | var vb = textGeo.vertices[ face.b ]; 53 | var vc = textGeo.vertices[ face.c ]; 54 | 55 | var s = THREE.GeometryUtils.triangleArea( va, vb, vc ); 56 | 57 | if ( s > triangleAreaHeuristics ) { 58 | 59 | for ( var j = 0; j < face.vertexNormals.length; j ++ ) { 60 | 61 | face.vertexNormals[ j ].copy( face.normal ); 62 | 63 | } 64 | 65 | } 66 | 67 | } 68 | 69 | } 70 | 71 | } 72 | 73 | var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x ); 74 | 75 | textMesh1 = new THREE.Mesh( textGeo, material ); 76 | 77 | textMesh1.position.x = centerOffset; 78 | textMesh1.position.y = hover; 79 | textMesh1.position.z = -1; 80 | 81 | textMesh1.rotation.x = 0; 82 | textMesh1.rotation.y = Math.PI * 2; 83 | 84 | group.add( textMesh1 ); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /js/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){var l=Date.now(),m=l,g=0,n=Infinity,o=0,h=0,p=Infinity,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px"; 3 | i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div"); 4 | k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display= 5 | "block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{REVISION:11,domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height= 6 | a+"px",m=b,r=0);return b},update:function(){l=this.end()}}}; 7 | -------------------------------------------------------------------------------- /js/katex/README.md: -------------------------------------------------------------------------------- 1 | # [KaTeX](https://khan.github.io/KaTeX/) [![Build Status](https://travis-ci.org/Khan/KaTeX.svg?branch=master)](https://travis-ci.org/Khan/KaTeX) 2 | 3 | KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web. 4 | 5 | * **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](http://jsperf.com/katex-vs-mathjax/). 6 | * **Print quality:** KaTeX’s layout is based on Donald Knuth’s TeX, the gold standard for math typesetting. 7 | * **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources. 8 | * **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML. 9 | 10 | KaTeX supports all major browsers, including Chrome, Safari, Firefox, Opera, and IE 8 - IE 11. 11 | 12 | ## Usage 13 | 14 | You can [download KaTeX](https://github.com/khan/katex/releases) and host it on your server or include the `katex.min.js` and `katex.min.css` files on your page directly from a CDN: 15 | 16 | ```html 17 | 18 | 19 | ``` 20 | 21 | #### In-browser rendering 22 | 23 | Call `katex.render` with a TeX expression and a DOM element to render into: 24 | 25 | ```js 26 | katex.render("c = \\pm\\sqrt{a^2 + b^2}", element); 27 | ``` 28 | 29 | #### Server side rendering or rendering to a string 30 | 31 | To generate HTML on the server or to generate an HTML string of the rendered math, you can use `katex.renderToString`: 32 | 33 | ```js 34 | var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}"); 35 | // '...' 36 | ``` 37 | 38 | Make sure to include the CSS and font files, but there is no need to include the JavaScript. 39 | 40 | #### Rendering options 41 | 42 | You can provide an object of options as the last argument to `katex.render` and `katex.renderToString`. Available options are: 43 | 44 | - `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`) 45 | 46 | For example: 47 | 48 | ```js 49 | katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, { displayMode: true }); 50 | ``` 51 | 52 | ## Contributing 53 | 54 | See [CONTRIBUTING.md](CONTRIBUTING.md) 55 | 56 | ## License 57 | 58 | KaTeX is licensed under the [MIT License](http://opensource.org/licenses/MIT). 59 | -------------------------------------------------------------------------------- /js/controls/DeviceOrientationControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author richt / http://richt.me 3 | * @author WestLangley / http://github.com/WestLangley 4 | * 5 | * W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html) 6 | */ 7 | 8 | THREE.DeviceOrientationControls = function ( object ) { 9 | 10 | var scope = this; 11 | 12 | this.object = object; 13 | this.object.rotation.reorder( "YXZ" ); 14 | 15 | this.enabled = true; 16 | 17 | this.deviceOrientation = {}; 18 | this.screenOrientation = 0; 19 | 20 | var onDeviceOrientationChangeEvent = function ( event ) { 21 | 22 | scope.deviceOrientation = event; 23 | 24 | }; 25 | 26 | var onScreenOrientationChangeEvent = function () { 27 | 28 | scope.screenOrientation = window.orientation || 0; 29 | 30 | }; 31 | 32 | // The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' 33 | 34 | var setObjectQuaternion = function () { 35 | 36 | var zee = new THREE.Vector3( 0, 0, 1 ); 37 | 38 | var euler = new THREE.Euler(); 39 | 40 | var q0 = new THREE.Quaternion(); 41 | 42 | var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis 43 | 44 | return function ( quaternion, alpha, beta, gamma, orient ) { 45 | 46 | euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us 47 | 48 | quaternion.setFromEuler( euler ); // orient the device 49 | 50 | quaternion.multiply( q1 ); // camera looks out the back of the device, not the top 51 | 52 | quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation 53 | 54 | } 55 | 56 | }(); 57 | 58 | this.connect = function() { 59 | 60 | onScreenOrientationChangeEvent(); // run once on load 61 | 62 | window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false ); 63 | window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false ); 64 | 65 | scope.enabled = true; 66 | 67 | }; 68 | 69 | this.disconnect = function() { 70 | 71 | window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false ); 72 | window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false ); 73 | 74 | scope.enabled = false; 75 | 76 | }; 77 | 78 | this.update = function () { 79 | 80 | if ( scope.enabled === false ) return; 81 | 82 | var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad( scope.deviceOrientation.alpha ) : 0; // Z 83 | var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad( scope.deviceOrientation.beta ) : 0; // X' 84 | var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.gamma ) : 0; // Y'' 85 | var orient = scope.screenOrientation ? THREE.Math.degToRad( scope.screenOrientation ) : 0; // O 86 | 87 | setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient ); 88 | 89 | }; 90 | 91 | this.connect(); 92 | 93 | }; 94 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | } 4 | body { 5 | font-family: Arial; 6 | background-color: #222222; 7 | background: rgb(50,60,70); /* Old browsers */ 8 | background: -moz-radial-gradient(center, ellipse cover, rgba(50,60,70,1) 0%, rgba(20,20,20,1) 100%); /* FF3.6+ */ 9 | background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(50,60,70,1)), color-stop(100%,rgba(20,20,20,1))); /* Chrome,Safari4+ */ 10 | background: -webkit-radial-gradient(center, ellipse cover, rgba(50,60,70,1) 0%,rgba(20,20,20,1) 100%); /* Chrome10+,Safari5.1+ */ 11 | background: -o-radial-gradient(center, ellipse cover, rgba(50,60,70,1) 0%,rgba(20,20,20,1) 100%); /* Opera 12+ */ 12 | background: -ms-radial-gradient(center, ellipse cover, rgba(50,60,70,1) 0%,rgba(20,20,20,1) 100%); /* IE10+ */ 13 | background: radial-gradient(ellipse at center, rgba(50,60,70,1) 0%,rgba(20,20,20,1) 100%); /* W3C */ 14 | 15 | margin: 0; 16 | font-family: Arial; 17 | overflow: hidden; 18 | } 19 | #webgl_container { 20 | z-index: 10; 21 | overflow:hidden; 22 | } 23 | #canvasContainer { 24 | z-index: 50; 25 | opacity: 0.8; 26 | width:282px; 27 | position:absolute; 28 | top: 0px; 29 | right: 0px; 30 | padding:5px; 31 | overflow:hidden; 32 | background: rgb(30,35,40); 33 | } 34 | .board { 35 | width: 282px; 36 | height: 361px; 37 | padding-bottom:10px; 38 | } 39 | .tinyBoard { 40 | margin: 0 auto; 41 | background-color:#000; 42 | width: 28px; 43 | height: 28px; 44 | border: solid thin #ccc; 45 | overflow:hidden; 46 | float:right; 47 | 48 | } 49 | #draw { 50 | color: #fff; 51 | font-size:20px; 52 | text-align:left; 53 | padding: 5px 0; 54 | } 55 | .info { 56 | color: #fff; 57 | font-size:20px; 58 | text-align:right; 59 | float:left; 60 | height:37px; 61 | width:240px; 62 | } 63 | .ans { 64 | font-size: 24px; 65 | color: #fff; 66 | margin: 0 auto; 67 | background-color:#000; 68 | width: 28px; 69 | height: 28px; 70 | border: solid thin #ccc; 71 | float:right; 72 | text-align:center; 73 | } 74 | #infobox { 75 | width:350px; 76 | position:absolute; 77 | bottom:100px; 78 | left:100px; 79 | background-color:#999; 80 | opacity: 0.9; 81 | 82 | 83 | -webkit-transition: opacity 0.5s ease; 84 | -moz-transition: opacity 0.5s ease; 85 | -ms-transition: opacity 0.5s ease; 86 | -o-transition: opacity 0.5s ease; 87 | transition: opacity 0.5s ease; 88 | 89 | 90 | border: thin solid white; 91 | -webkit-user-select: none; 92 | padding: 0; 93 | margin: 0; 94 | 95 | /* box-shadow: 5px 5px 10px #000; */ 96 | } 97 | #infobox:hover { 98 | /*visibility: hidden;*/ 99 | } 100 | #nodeType { 101 | font-weight: bold; 102 | text-align: center; 103 | background-color: #def; 104 | padding: 5px; 105 | } 106 | #nodeInputContainer { 107 | background-color:#bcd; 108 | padding: 5px; 109 | } 110 | #calcContainer { 111 | background-color:#9ab; 112 | padding: 5px; 113 | } 114 | #nodeOutputContainer { 115 | background-color:#789; 116 | padding: 5px; 117 | } 118 | .label { 119 | float:left; 120 | margin-right: 5px; 121 | } 122 | .math { 123 | margin-top: -2px; 124 | } -------------------------------------------------------------------------------- /css/main2.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | } 4 | body { 5 | font-family: Arial; 6 | background-color: #222222; 7 | background: rgb(60,100,140); /* Old browsers */ 8 | background: -moz-radial-gradient(center, ellipse cover, rgba(60,100,140,1) 0%, rgba(20,20,20,1) 100%); /* FF3.6+ */ 9 | background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(60,100,140,1)), color-stop(100%,rgba(20,20,20,1))); /* Chrome,Safari4+ */ 10 | background: -webkit-radial-gradient(center, ellipse cover, rgba(60,100,140,1) 0%,rgba(20,20,20,1) 100%); /* Chrome10+,Safari5.1+ */ 11 | background: -o-radial-gradient(center, ellipse cover, rgba(60,100,140,1) 0%,rgba(20,20,20,1) 100%); /* Opera 12+ */ 12 | background: -ms-radial-gradient(center, ellipse cover, rgba(60,100,140,1) 0%,rgba(20,20,20,1) 100%); /* IE10+ */ 13 | background: radial-gradient(ellipse at center, rgba(60,100,140,1) 0%,rgba(20,20,20,1) 100%); /* W3C */ 14 | 15 | margin: 0; 16 | font-family: Arial; 17 | overflow: hidden; 18 | } 19 | #webgl_container { 20 | z-index: 10; 21 | overflow:hidden; 22 | } 23 | #canvasContainer { 24 | z-index: 50; 25 | opacity: 0.8; 26 | width:282px; 27 | position:absolute; 28 | top: 0px; 29 | right: 0px; 30 | padding:5px; 31 | overflow:hidden; 32 | background: rgb(30,35,40); 33 | } 34 | .board { 35 | width: 282px; 36 | height: 361px; 37 | padding-bottom:10px; 38 | } 39 | .tinyBoard { 40 | margin: 0 auto; 41 | background-color:#000; 42 | width: 28px; 43 | height: 28px; 44 | border: solid thin #ccc; 45 | overflow:hidden; 46 | float:right; 47 | 48 | } 49 | #draw { 50 | color: #fff; 51 | font-size:20px; 52 | text-align:left; 53 | padding: 5px 0; 54 | } 55 | .info { 56 | color: #fff; 57 | font-size:20px; 58 | text-align:right; 59 | float:left; 60 | height:37px; 61 | width:240px; 62 | } 63 | .ans { 64 | font-size: 24px; 65 | color: #fff; 66 | margin: 0 auto; 67 | background-color:#000; 68 | width: 28px; 69 | height: 28px; 70 | border: solid thin #ccc; 71 | float:right; 72 | text-align:center; 73 | } 74 | #infobox { 75 | width:350px; 76 | position:absolute; 77 | bottom:100px; 78 | left:100px; 79 | background-color:#999; 80 | opacity: 0.9; 81 | 82 | 83 | -webkit-transition: opacity 0.5s ease; 84 | -moz-transition: opacity 0.5s ease; 85 | -ms-transition: opacity 0.5s ease; 86 | -o-transition: opacity 0.5s ease; 87 | transition: opacity 0.5s ease; 88 | 89 | 90 | border: thin solid white; 91 | -webkit-user-select: none; 92 | padding: 0; 93 | margin: 0; 94 | 95 | /* box-shadow: 5px 5px 10px #000; */ 96 | } 97 | #infobox:hover { 98 | /*visibility: hidden;*/ 99 | } 100 | #nodeType { 101 | font-weight: bold; 102 | text-align: center; 103 | background-color: #def; 104 | padding: 5px; 105 | } 106 | #nodeInputContainer { 107 | background-color:#bcd; 108 | padding: 5px; 109 | } 110 | #calcContainer { 111 | background-color:#9ab; 112 | padding: 5px; 113 | } 114 | #nodeOutputContainer { 115 | background-color:#789; 116 | padding: 5px; 117 | } 118 | .label { 119 | float:left; 120 | margin-right: 5px; 121 | } 122 | .math { 123 | margin-top: -2px; 124 | } -------------------------------------------------------------------------------- /js/yepnope.js: -------------------------------------------------------------------------------- 1 | /*yepnope1.5.x|WTFPL*/ 2 | (function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f' + 39 | '
{{rainbows}}
' + 40 | ''; 41 | var oneColorTpl = '
'; 42 | var rainbows = ''; 43 | $.each([0.75, 0.5, 0.25], $.proxy(function(key, val) { 44 | var i = 0; 45 | var additionalColor = null; 46 | rainbows += '
'; 47 | if (val == 0.25) additionalColor = this._rgba(0, 0, 0, 1); 48 | if (val == 0.5) additionalColor = this._rgba(150, 150, 150, 1); 49 | if (val == 0.75) additionalColor = this._rgba(255, 255, 255, 1); 50 | rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: additionalColor.toString() }); 51 | while (i <= 330) { 52 | rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: this._hsl2Rgba(this._hsl(i-60, 1, val)).toString() }); 53 | i+=30; 54 | } 55 | rainbows += '
'; 56 | }, this)); 57 | 58 | this.$el.append( $( DrawingBoard.Utils.tpl(tpl, {color: this.board.color, rainbows: rainbows }) ) ); 59 | this.$el.find('.drawing-board-control-colors-rainbows').addClass('drawing-board-utils-hidden'); 60 | }, 61 | 62 | onBoardReset: function(opts) { 63 | this.board.setColor(this.$el.find('.drawing-board-control-colors-current').attr('data-color')); 64 | }, 65 | 66 | _rgba: function(r, g, b, a) { 67 | return { r: r, g: g, b: b, a: a, toString: function() { return "rgba(" + r +", " + g + ", " + b + ", " + a + ")"; } }; 68 | }, 69 | 70 | _hsl: function(h, s, l) { 71 | return { h: h, s: s, l: l, toString: function() { return "hsl(" + h +", " + s*100 + "%, " + l*100 + "%)"; } }; 72 | }, 73 | 74 | _hex2Rgba: function(hex) { 75 | var num = parseInt(hex.substring(1), 16); 76 | return this._rgba(num >> 16, num >> 8 & 255, num & 255, 1); 77 | }, 78 | 79 | //conversion function (modified a bit) taken from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript 80 | _hsl2Rgba: function(hsl) { 81 | var h = hsl.h/360, s = hsl.s, l = hsl.l, r, g, b; 82 | function hue2rgb(p, q, t) { 83 | if(t < 0) t += 1; 84 | if(t > 1) t -= 1; 85 | if(t < 1/6) return p + (q - p) * 6 * t; 86 | if(t < 1/2) return q; 87 | if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; 88 | return p; 89 | } 90 | if (s === 0) { 91 | r = g = b = l; // achromatic 92 | } else { 93 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 94 | var p = 2 * l - q; 95 | r = Math.floor( (hue2rgb(p, q, h + 1/3)) * 255); 96 | g = Math.floor( (hue2rgb(p, q, h)) * 255); 97 | b = Math.floor( (hue2rgb(p, q, h - 1/3)) * 255); 98 | } 99 | return this._rgba(r, g, b, 1); 100 | } 101 | }); -------------------------------------------------------------------------------- /js/drawingboard/controls/size.js: -------------------------------------------------------------------------------- 1 | DrawingBoard.Control.Size = DrawingBoard.Control.extend({ 2 | 3 | name: 'size', 4 | 5 | defaults: { 6 | type: "auto", 7 | dropdownValues: [1, 3, 6, 10, 20, 30, 40, 50], 8 | min: 1, 9 | max: 50 10 | }, 11 | 12 | types: ['dropdown', 'range'], 13 | 14 | initialize: function() { 15 | if (this.opts.type == "auto") 16 | this.opts.type = this._iHasRangeInput() ? 'range' : 'dropdown'; 17 | var tpl = $.inArray(this.opts.type, this.types) > -1 ? this['_' + this.opts.type + 'Template']() : false; 18 | if (!tpl) return false; 19 | 20 | this.val = this.board.opts.size; 21 | 22 | this.$el.append( $( tpl ) ); 23 | this.$el.attr('data-drawing-board-type', this.opts.type); 24 | this.updateView(); 25 | 26 | var that = this; 27 | 28 | if (this.opts.type == "range") { 29 | this.$el.on('change', '.drawing-board-control-size-range-input', function(e) { 30 | that.val = $(this).val(); 31 | that.updateView(); 32 | 33 | that.board.ev.trigger('size:changed', that.val); 34 | 35 | e.preventDefault(); 36 | }); 37 | } 38 | 39 | if (this.opts.type == "dropdown") { 40 | this.$el.on('click', '.drawing-board-control-size-dropdown-current', $.proxy(function(e) { 41 | this.$el.find('.drawing-board-control-size-dropdown').toggleClass('drawing-board-utils-hidden'); 42 | }, this)); 43 | 44 | this.$el.on('click', '[data-size]', function(e) { 45 | that.val = parseInt($(this).attr('data-size'), 0); 46 | that.updateView(); 47 | 48 | that.board.ev.trigger('size:changed', that.val); 49 | 50 | e.preventDefault(); 51 | }); 52 | } 53 | }, 54 | 55 | _rangeTemplate: function() { 56 | var tpl = '
' + 57 | '' + 58 | '' + 59 | '
'; 60 | return DrawingBoard.Utils.tpl(tpl, { 61 | min: this.opts.min, 62 | max: this.opts.max, 63 | size: this.board.opts.size 64 | }); 65 | }, 66 | 67 | _dropdownTemplate: function() { 68 | var tpl = '
' + 69 | '
' + 70 | '
'; 78 | return tpl; 79 | }, 80 | 81 | onBoardReset: function(opts) { 82 | this.updateView(); 83 | }, 84 | 85 | updateView: function() { 86 | var val = this.val; 87 | this.board.ctx.lineWidth = val; 88 | 89 | this.$el.find('.drawing-board-control-size-range-current, .drawing-board-control-size-dropdown-current span').css({ 90 | width: val + 'px', 91 | height: val + 'px', 92 | borderRadius: val + 'px', 93 | marginLeft: -1*val/2 + 'px', 94 | marginTop: -1*val/2 + 'px' 95 | }); 96 | 97 | this.$el.find('.drawing-board-control-inner').attr('title', val); 98 | 99 | if (this.opts.type == 'dropdown') { 100 | var closest = null; 101 | $.each(this.opts.dropdownValues, function(i, size) { 102 | if (closest === null || Math.abs(size - val) < Math.abs(closest - val)) 103 | closest = size; 104 | }); 105 | this.$el.find('.drawing-board-control-size-dropdown').addClass('drawing-board-utils-hidden'); 106 | } 107 | }, 108 | 109 | _iHasRangeInput: function() { 110 | var inputElem = document.createElement('input'), 111 | smile = ':)', 112 | docElement = document.documentElement, 113 | inputElemType = 'range', 114 | available; 115 | inputElem.setAttribute('type', inputElemType); 116 | available = inputElem.type !== 'text'; 117 | inputElem.value = smile; 118 | inputElem.style.cssText = 'position:absolute;visibility:hidden;'; 119 | if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { 120 | docElement.appendChild(inputElem); 121 | defaultView = document.defaultView; 122 | available = defaultView.getComputedStyle && 123 | defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && 124 | (inputElem.offsetHeight !== 0); 125 | docElement.removeChild(inputElem); 126 | } 127 | return !!available; 128 | } 129 | }); -------------------------------------------------------------------------------- /js/tween.min.js: -------------------------------------------------------------------------------- 1 | // tween.js - http://github.com/sole/tween.js 2 | 'use strict';var TWEEN=TWEEN||function(){var a=[];return{REVISION:"7",getAll:function(){return a},removeAll:function(){a=[]},add:function(c){a.push(c)},remove:function(c){c=a.indexOf(c);-1!==c&&a.splice(c,1)},update:function(c){if(0===a.length)return!1;for(var b=0,d=a.length,c=void 0!==c?c:Date.now();b(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}},Cubic:{In:function(a){return a*a*a},Out:function(a){return--a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a:0.5*((a-=2)*a*a+2)}},Quartic:{In:function(a){return a*a*a*a},Out:function(a){return 1- --a*a*a*a},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)}},Quintic:{In:function(a){return a*a*a* 7 | a*a},Out:function(a){return--a*a*a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)}},Sinusoidal:{In:function(a){return 1-Math.cos(a*Math.PI/2)},Out:function(a){return Math.sin(a*Math.PI/2)},InOut:function(a){return 0.5*(1-Math.cos(Math.PI*a))}},Exponential:{In:function(a){return 0===a?0:Math.pow(1024,a-1)},Out:function(a){return 1===a?1:1-Math.pow(2,-10*a)},InOut:function(a){return 0===a?0:1===a?1:1>(a*=2)?0.5*Math.pow(1024,a-1):0.5*(-Math.pow(2,-10*(a-1))+2)}},Circular:{In:function(a){return 1- 8 | Math.sqrt(1-a*a)},Out:function(a){return Math.sqrt(1- --a*a)},InOut:function(a){return 1>(a*=2)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)}},Elastic:{In:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return-(b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4))},Out:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return b*Math.pow(2,-10*a)*Math.sin((a-c)* 9 | 2*Math.PI/0.4)+1},InOut:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return 1>(a*=2)?-0.5*b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4):0.5*b*Math.pow(2,-10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4)+1}},Back:{In:function(a){return a*a*(2.70158*a-1.70158)},Out:function(a){return--a*a*(2.70158*a+1.70158)+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*(3.5949095*a-2.5949095):0.5*((a-=2)*a*(3.5949095*a+2.5949095)+2)}},Bounce:{In:function(a){return 1- 10 | TWEEN.Easing.Bounce.Out(1-a)},Out:function(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+0.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+0.9375:7.5625*(a-=2.625/2.75)*a+0.984375},InOut:function(a){return 0.5>a?0.5*TWEEN.Easing.Bounce.In(2*a):0.5*TWEEN.Easing.Bounce.Out(2*a-1)+0.5}}}; 11 | TWEEN.Interpolation={Linear:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.Linear;return 0>c?f(a[0],a[1],d):1b?b:e+1],d-e)},Bezier:function(a,c){var b=0,d=a.length-1,e=Math.pow,f=TWEEN.Interpolation.Utils.Bernstein,h;for(h=0;h<=d;h++)b+=e(1-c,d-h)*e(c,h)*a[h]*f(d,h);return b},CatmullRom:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.CatmullRom;return a[0]===a[b]?(0>c&&(e=Math.floor(d=b*(1+c))),f(a[(e- 12 | 1+b)%b],a[e],a[(e+1)%b],a[(e+2)%b],d-e)):0>c?a[0]-(f(a[0],a[0],a[1],a[1],-d)-a[0]):1= 0; i--) 95 | width += parseInt($el.css(props[i]).replace('px', ''), 10); 96 | return width; 97 | }; 98 | 99 | DrawingBoard.Utils.boxBorderWidth = function($el, withPadding, withMargin) { 100 | return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'width'); 101 | }; 102 | 103 | DrawingBoard.Utils.boxBorderHeight = function($el, withPadding, withMargin) { 104 | return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'height'); 105 | }; 106 | 107 | DrawingBoard.Utils.isColor = function(string) { 108 | if (!string || !string.length) return false; 109 | return (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i).test(string) || $.inArray(string.substring(0, 3), ['rgb', 'hsl']) !== -1; 110 | }; 111 | 112 | /** 113 | * Packs an RGB color into a single integer. 114 | */ 115 | DrawingBoard.Utils.RGBToInt = function(r, g, b) { 116 | var c = 0; 117 | c |= (r & 255) << 16; 118 | c |= (g & 255) << 8; 119 | c |= (b & 255); 120 | return c; 121 | }; 122 | 123 | /** 124 | * Returns informations on the pixel located at (x,y). 125 | */ 126 | DrawingBoard.Utils.pixelAt = function(image, x, y) { 127 | var i = (y * image.width + x) * 4; 128 | var c = DrawingBoard.Utils.RGBToInt( 129 | image.data[i], 130 | image.data[i + 1], 131 | image.data[i + 2] 132 | ); 133 | 134 | return [ 135 | i, // INDEX 136 | x, // X 137 | y, // Y 138 | c // COLOR 139 | ]; 140 | }; 141 | 142 | /** 143 | * Compares two colors with the given tolerance (between 0 and 255). 144 | */ 145 | DrawingBoard.Utils.compareColors = function(a, b, tolerance) { 146 | if (tolerance === 0) { 147 | return (a === b); 148 | } 149 | 150 | var ra = (a >> 16) & 255, rb = (b >> 16) & 255, 151 | ga = (a >> 8) & 255, gb = (b >> 8) & 255, 152 | ba = a & 255, bb = b & 255; 153 | 154 | return (Math.abs(ra - rb) <= tolerance) 155 | && (Math.abs(ga - gb) <= tolerance) 156 | && (Math.abs(ba - bb) <= tolerance); 157 | }; 158 | 159 | (function() { 160 | var lastTime = 0; 161 | var vendors = ['ms', 'moz', 'webkit', 'o']; 162 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 163 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 164 | window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; 165 | } 166 | }()); 167 | -------------------------------------------------------------------------------- /js/nn/nn2.js: -------------------------------------------------------------------------------- 1 | var allZeroes = false; 2 | var nPixels = 784; 3 | var nHiddenNodes_1 = 300; 4 | var nHiddenNodes_2 = 100; 5 | var nHiddenLayers = 2; 6 | var nFinalNodes = 10; 7 | var nNodes = 300 + 100 + 28*28 + 10; 8 | var allNodeOutputs = new Array(nNodes); 9 | var isComputed = false; 10 | var goodStart = false; 11 | 12 | function getNNOutput() { 13 | var imageData = tinyCtx.getImageData(0, 0, 28, 28); 14 | 15 | var data = imageData.data; 16 | 17 | var pixel = 0; 18 | var input = new Array(nPixels); 19 | 20 | for(var i = 0, n = data.length; i < n; i += 4) { 21 | var gray; 22 | if (data[i]) { 23 | input[pixel] = ((data[i]/255)*1.275)-0.1;// * 1.175; 24 | } 25 | else { 26 | input[pixel] = -0.1; 27 | } 28 | allNodeOutputs[pixel] = input[pixel]; 29 | pixel++; 30 | } 31 | 32 | var input32 = reshapeArray(input); 33 | var inp = Vector.create(input32); 34 | 35 | var hidden_outputs_1 = Vector.Zero(nHiddenNodes_1); 36 | var hidden_outputs_1a = new Array(nHiddenNodes_1); 37 | var hidden_outputs_2 = Vector.Zero(nHiddenNodes_2); 38 | var hidden_outputs_2a = new Array(nHiddenNodes_2); 39 | var final_outputsa = new Array(nFinalNodes); 40 | 41 | for (i=1; i<=nHiddenNodes_1; i++){ 42 | var weights = hidden_weights_1.row(i); 43 | var sum = inp.dot(weights); 44 | sum += hidden_biases_1.e(i); 45 | hidden_outputs_1a[i-1] = sigma(sum); 46 | allNodeOutputs[nPixels+i-1]=hidden_outputs_1a[i-1]; 47 | } 48 | hidden_outputs_1.setElements(hidden_outputs_1a); 49 | 50 | for (i=1; i<=nHiddenNodes_2; i++){ 51 | var weights = hidden_weights_2.row(i); 52 | var sum = hidden_outputs_1.dot(weights); 53 | sum += hidden_biases_2.e(i); 54 | hidden_outputs_2a[i-1] = sigma(sum); 55 | allNodeOutputs[nPixels+nHiddenNodes_1+i-1]=hidden_outputs_2a[i-1]; 56 | } 57 | hidden_outputs_2.setElements(hidden_outputs_2a); 58 | 59 | var sums = final_weights.x(hidden_outputs_2); 60 | var newSums = sums.add(final_biases); 61 | 62 | for (i=1; i<=nFinalNodes; i++){ 63 | final_outputsa[i-1] = sigma(newSums.e(i)); 64 | allNodeOutputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=final_outputsa[i-1]; 65 | } 66 | 67 | 68 | normalizeWithinLayer(allNodeOutputs); 69 | 70 | if (!allZeroes){ 71 | var ind1 = maxInd(final_outputsa); 72 | final_outputsa[ind] = -10; 73 | var ind2 = maxInd(final_outputsa); 74 | document.getElementById("ans1").innerHTML = ind1; 75 | document.getElementById("ans2").innerHTML = ind2; 76 | } else { 77 | document.getElementById("ans1").innerHTML = ""; 78 | document.getElementById("ans2").innerHTML = ""; 79 | } 80 | 81 | isComputed = true; 82 | 83 | 84 | cleanScene(); 85 | drawCubes(); 86 | 87 | 88 | //console.log(imageData); 89 | imageData.data = null; 90 | imageData = null; 91 | //console.log(imageData); 92 | }; 93 | 94 | function sigma(x) { 95 | return 1.7159*math.tanh(0.6667*x); 96 | } 97 | function reshapeArray(arr){ 98 | // The input array walks along pixels ltr ltr ltr. 99 | // For proper input, we need it to walk ttb ttb ttb. 100 | var arr2 = new Array(1024); 101 | for (count = 0; count < 1024; count++){ 102 | arr2[count] = -0.1; 103 | } 104 | for (count = 0; count < 768; count++){ 105 | var row = math.floor(count/28)+2; 106 | var col = (count)%28+2; 107 | var newInd = col*32 + row; 108 | arr2[newInd] = arr[count]; 109 | } 110 | return arr2; 111 | } 112 | function maxInd(arr) { 113 | ind = 0; 114 | val = arr[0]; 115 | for (i=1; ival){ 117 | ind = i; 118 | val = arr[i]; 119 | } 120 | } 121 | return ind; 122 | } 123 | function normalizeWithinLayer(arr) { 124 | var len = arr.length; 125 | 126 | var minPixel = 100; 127 | var minHidden1 = 100; 128 | var minHidden2 = 100; 129 | var minFinal = 100; 130 | 131 | var maxPixel = -100; 132 | var maxHidden1 = -100; 133 | var maxHidden2 = -100; 134 | var maxFinal = -100; 135 | for (var i=0;imaxPixel) 138 | maxPixel = arr[i]; 139 | else if (arr[i]maxHidden1) 143 | maxHidden1 = arr[i]; 144 | else if (arr[i]maxHidden2) 148 | maxHidden2 = arr[i]; 149 | else if (arr[i]maxFinal) 153 | maxFinal = arr[i]; 154 | else if (arr[i]val){ 117 | ind = i; 118 | val = arr[i]; 119 | } 120 | } 121 | return ind; 122 | } 123 | function normalizeWithinLayer(arr) { 124 | var len = arr.length; 125 | 126 | var minPixel = 100; 127 | var minHidden1 = 100; 128 | var minHidden2 = 100; 129 | var minFinal = 100; 130 | 131 | var maxPixel = -100; 132 | var maxHidden1 = -100; 133 | var maxHidden2 = -100; 134 | var maxFinal = -100; 135 | for (var i=0;imaxPixel) 138 | maxPixel = arr[i]; 139 | else if (arr[i]maxHidden1) 143 | maxHidden1 = arr[i]; 144 | else if (arr[i]maxHidden2) 148 | maxHidden2 = arr[i]; 149 | else if (arr[i]maxFinal) 153 | maxFinal = arr[i]; 154 | else if (arr[i]val){ 119 | ind = i; 120 | val = arr[i]; 121 | } 122 | } 123 | return ind; 124 | } 125 | function normalizeWithinLayer(arr) { 126 | var len = arr.length; 127 | 128 | var minPixel = 100; 129 | var minHidden1 = 100; 130 | var minHidden2 = 100; 131 | var minFinal = 100; 132 | 133 | var maxPixel = -100; 134 | var maxHidden1 = -100; 135 | var maxHidden2 = -100; 136 | var maxFinal = -100; 137 | for (var i=0;imaxPixel) 140 | maxPixel = arr[i]; 141 | else if (arr[i]maxHidden1) 145 | maxHidden1 = arr[i]; 146 | else if (arr[i]maxHidden2) 150 | maxHidden2 = arr[i]; 151 | else if (arr[i]maxFinal) 155 | maxFinal = arr[i]; 156 | else if (arr[i] 1 ) { 45 | 46 | a = 1 - a; 47 | b = 1 - b; 48 | 49 | } 50 | 51 | var c = 1 - a - b; 52 | 53 | point.copy( vectorA ); 54 | point.multiplyScalar( a ); 55 | 56 | vector.copy( vectorB ); 57 | vector.multiplyScalar( b ); 58 | 59 | point.add( vector ); 60 | 61 | vector.copy( vectorC ); 62 | vector.multiplyScalar( c ); 63 | 64 | point.add( vector ); 65 | 66 | return point; 67 | 68 | }; 69 | 70 | }(), 71 | 72 | // Get random point in face (triangle) 73 | // (uniform distribution) 74 | 75 | randomPointInFace: function ( face, geometry, useCachedAreas ) { 76 | 77 | var vA, vB, vC; 78 | 79 | vA = geometry.vertices[ face.a ]; 80 | vB = geometry.vertices[ face.b ]; 81 | vC = geometry.vertices[ face.c ]; 82 | 83 | return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); 84 | 85 | }, 86 | 87 | // Get uniformly distributed random points in mesh 88 | // - create array with cumulative sums of face areas 89 | // - pick random number from 0 to total area 90 | // - find corresponding place in area array by binary search 91 | // - get random point in face 92 | 93 | randomPointsInGeometry: function ( geometry, n ) { 94 | 95 | var face, i, 96 | faces = geometry.faces, 97 | vertices = geometry.vertices, 98 | il = faces.length, 99 | totalArea = 0, 100 | cumulativeAreas = [], 101 | vA, vB, vC, vD; 102 | 103 | // precompute face areas 104 | 105 | for ( i = 0; i < il; i ++ ) { 106 | 107 | face = faces[ i ]; 108 | 109 | vA = vertices[ face.a ]; 110 | vB = vertices[ face.b ]; 111 | vC = vertices[ face.c ]; 112 | 113 | face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC ); 114 | 115 | totalArea += face._area; 116 | 117 | cumulativeAreas[ i ] = totalArea; 118 | 119 | } 120 | 121 | // binary search cumulative areas array 122 | 123 | function binarySearchIndices( value ) { 124 | 125 | function binarySearch( start, end ) { 126 | 127 | // return closest larger index 128 | // if exact number is not found 129 | 130 | if ( end < start ) 131 | return start; 132 | 133 | var mid = start + Math.floor( ( end - start ) / 2 ); 134 | 135 | if ( cumulativeAreas[ mid ] > value ) { 136 | 137 | return binarySearch( start, mid - 1 ); 138 | 139 | } else if ( cumulativeAreas[ mid ] < value ) { 140 | 141 | return binarySearch( mid + 1, end ); 142 | 143 | } else { 144 | 145 | return mid; 146 | 147 | } 148 | 149 | } 150 | 151 | var result = binarySearch( 0, cumulativeAreas.length - 1 ) 152 | return result; 153 | 154 | } 155 | 156 | // pick random face weighted by face area 157 | 158 | var r, index, 159 | result = []; 160 | 161 | var stats = {}; 162 | 163 | for ( i = 0; i < n; i ++ ) { 164 | 165 | r = THREE.Math.random16() * totalArea; 166 | 167 | index = binarySearchIndices( r ); 168 | 169 | result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true ); 170 | 171 | if ( ! stats[ index ] ) { 172 | 173 | stats[ index ] = 1; 174 | 175 | } else { 176 | 177 | stats[ index ] += 1; 178 | 179 | } 180 | 181 | } 182 | 183 | return result; 184 | 185 | }, 186 | 187 | randomPointsInBufferGeometry: function ( geometry, n ) { 188 | 189 | var i, 190 | vertices = geometry.attributes.position.array, 191 | totalArea = 0, 192 | cumulativeAreas = [], 193 | vA, vB, vC; 194 | 195 | // precompute face areas 196 | vA = new THREE.Vector3(); 197 | vB = new THREE.Vector3(); 198 | vC = new THREE.Vector3(); 199 | 200 | // geometry._areas = []; 201 | var il = vertices.length / 9; 202 | 203 | for ( i = 0; i < il; i ++ ) { 204 | 205 | vA.set( vertices[i * 9 + 0], vertices[i * 9 + 1], vertices[i * 9 + 2] ); 206 | vB.set( vertices[i * 9 + 3], vertices[i * 9 + 4], vertices[i * 9 + 5] ); 207 | vC.set( vertices[i * 9 + 6], vertices[i * 9 + 7], vertices[i * 9 + 8] ); 208 | 209 | area = THREE.GeometryUtils.triangleArea( vA, vB, vC ); 210 | totalArea += area; 211 | 212 | cumulativeAreas.push(totalArea); 213 | } 214 | 215 | // binary search cumulative areas array 216 | 217 | function binarySearchIndices( value ) { 218 | 219 | function binarySearch( start, end ) { 220 | 221 | // return closest larger index 222 | // if exact number is not found 223 | 224 | if ( end < start ) 225 | return start; 226 | 227 | var mid = start + Math.floor( ( end - start ) / 2 ); 228 | 229 | if ( cumulativeAreas[ mid ] > value ) { 230 | 231 | return binarySearch( start, mid - 1 ); 232 | 233 | } else if ( cumulativeAreas[ mid ] < value ) { 234 | 235 | return binarySearch( mid + 1, end ); 236 | 237 | } else { 238 | 239 | return mid; 240 | 241 | } 242 | 243 | } 244 | 245 | var result = binarySearch( 0, cumulativeAreas.length - 1 ) 246 | return result; 247 | 248 | } 249 | 250 | // pick random face weighted by face area 251 | 252 | var r, index, 253 | result = []; 254 | 255 | for ( i = 0; i < n; i ++ ) { 256 | 257 | r = THREE.Math.random16() * totalArea; 258 | 259 | index = binarySearchIndices( r ); 260 | 261 | // result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true ); 262 | vA.set( vertices[index * 9 + 0], vertices[index * 9 + 1], vertices[index * 9 + 2] ); 263 | vB.set( vertices[index * 9 + 3], vertices[index * 9 + 4], vertices[index * 9 + 5] ); 264 | vC.set( vertices[index * 9 + 6], vertices[index * 9 + 7], vertices[index * 9 + 8] ); 265 | result[ i ] = THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); 266 | 267 | } 268 | 269 | return result; 270 | 271 | }, 272 | 273 | // Get triangle area (half of parallelogram) 274 | // http://mathworld.wolfram.com/TriangleArea.html 275 | 276 | triangleArea: function () { 277 | 278 | var vector1 = new THREE.Vector3(); 279 | var vector2 = new THREE.Vector3(); 280 | 281 | return function ( vectorA, vectorB, vectorC ) { 282 | 283 | vector1.subVectors( vectorB, vectorA ); 284 | vector2.subVectors( vectorC, vectorA ); 285 | vector1.cross( vector2 ); 286 | 287 | return 0.5 * vector1.length(); 288 | 289 | }; 290 | 291 | }(), 292 | 293 | center: function ( geometry ) { 294 | 295 | console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); 296 | return geometry.center(); 297 | 298 | } 299 | 300 | }; -------------------------------------------------------------------------------- /js/controls/FlyControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author James Baicoianu / http://www.baicoianu.com/ 3 | */ 4 | 5 | THREE.FlyControls = function ( object, domElement ) { 6 | 7 | this.object = object; 8 | 9 | this.domElement = ( domElement !== undefined ) ? domElement : document; 10 | if ( domElement ) this.domElement.setAttribute( 'tabindex', -1 ); 11 | 12 | // API 13 | 14 | this.movementSpeed = 1.0; 15 | this.rollSpeed = 0.005; 16 | 17 | this.dragToLook = false; 18 | this.autoForward = false; 19 | 20 | // disable default target object behavior 21 | 22 | // internals 23 | 24 | this.tmpQuaternion = new THREE.Quaternion(); 25 | 26 | this.mouseStatus = 0; 27 | 28 | this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; 29 | this.moveVector = new THREE.Vector3( 0, 0, 0 ); 30 | this.rotationVector = new THREE.Vector3( 0, 0, 0 ); 31 | 32 | this.handleEvent = function ( event ) { 33 | 34 | if ( typeof this[ event.type ] == 'function' ) { 35 | 36 | this[ event.type ]( event ); 37 | 38 | } 39 | 40 | }; 41 | 42 | this.keydown = function( event ) { 43 | 44 | if ( event.altKey ) { 45 | 46 | return; 47 | 48 | } 49 | 50 | //event.preventDefault(); 51 | 52 | switch ( event.keyCode ) { 53 | 54 | case 16: /* shift */ this.movementSpeedMultiplier = .1; break; 55 | 56 | case 87: /*W*/ this.moveState.forward = 1; break; 57 | case 83: /*S*/ this.moveState.back = 1; break; 58 | 59 | case 65: /*A*/ this.moveState.left = 1; break; 60 | case 68: /*D*/ this.moveState.right = 1; break; 61 | 62 | case 82: /*R*/ this.moveState.up = 1; break; 63 | case 70: /*F*/ this.moveState.down = 1; break; 64 | 65 | case 38: /*up*/ this.moveState.pitchUp = 1; break; 66 | case 40: /*down*/ this.moveState.pitchDown = 1; break; 67 | 68 | case 37: /*left*/ this.moveState.yawLeft = 1; break; 69 | case 39: /*right*/ this.moveState.yawRight = 1; break; 70 | 71 | case 81: /*Q*/ this.moveState.rollLeft = 1; break; 72 | case 69: /*E*/ this.moveState.rollRight = 1; break; 73 | 74 | } 75 | 76 | this.updateMovementVector(); 77 | this.updateRotationVector(); 78 | 79 | }; 80 | 81 | this.keyup = function( event ) { 82 | 83 | switch( event.keyCode ) { 84 | 85 | case 16: /* shift */ this.movementSpeedMultiplier = 1; break; 86 | 87 | case 87: /*W*/ this.moveState.forward = 0; break; 88 | case 83: /*S*/ this.moveState.back = 0; break; 89 | 90 | case 65: /*A*/ this.moveState.left = 0; break; 91 | case 68: /*D*/ this.moveState.right = 0; break; 92 | 93 | case 82: /*R*/ this.moveState.up = 0; break; 94 | case 70: /*F*/ this.moveState.down = 0; break; 95 | 96 | case 38: /*up*/ this.moveState.pitchUp = 0; break; 97 | case 40: /*down*/ this.moveState.pitchDown = 0; break; 98 | 99 | case 37: /*left*/ this.moveState.yawLeft = 0; break; 100 | case 39: /*right*/ this.moveState.yawRight = 0; break; 101 | 102 | case 81: /*Q*/ this.moveState.rollLeft = 0; break; 103 | case 69: /*E*/ this.moveState.rollRight = 0; break; 104 | 105 | } 106 | 107 | this.updateMovementVector(); 108 | this.updateRotationVector(); 109 | 110 | }; 111 | 112 | this.mousedown = function( event ) { 113 | 114 | if ( this.domElement !== document ) { 115 | 116 | this.domElement.focus(); 117 | 118 | } 119 | 120 | event.preventDefault(); 121 | event.stopPropagation(); 122 | 123 | if ( this.dragToLook ) { 124 | 125 | this.mouseStatus ++; 126 | 127 | } else { 128 | 129 | switch ( event.button ) { 130 | 131 | case 0: this.moveState.forward = 1; break; 132 | case 2: this.moveState.back = 1; break; 133 | 134 | } 135 | 136 | this.updateMovementVector(); 137 | 138 | } 139 | 140 | }; 141 | 142 | this.mousemove = function( event ) { 143 | 144 | if ( !this.dragToLook || this.mouseStatus > 0 ) { 145 | 146 | var container = this.getContainerDimensions(); 147 | var halfWidth = container.size[ 0 ] / 2; 148 | var halfHeight = container.size[ 1 ] / 2; 149 | 150 | this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; 151 | this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; 152 | 153 | this.updateRotationVector(); 154 | 155 | } 156 | 157 | }; 158 | 159 | this.mouseup = function( event ) { 160 | 161 | event.preventDefault(); 162 | event.stopPropagation(); 163 | 164 | if ( this.dragToLook ) { 165 | 166 | this.mouseStatus --; 167 | 168 | this.moveState.yawLeft = this.moveState.pitchDown = 0; 169 | 170 | } else { 171 | 172 | switch ( event.button ) { 173 | 174 | case 0: this.moveState.forward = 0; break; 175 | case 2: this.moveState.back = 0; break; 176 | 177 | } 178 | 179 | this.updateMovementVector(); 180 | 181 | } 182 | 183 | this.updateRotationVector(); 184 | 185 | }; 186 | 187 | this.update = function( delta ) { 188 | 189 | var moveMult = delta * this.movementSpeed; 190 | var rotMult = delta * this.rollSpeed; 191 | 192 | this.object.translateX( this.moveVector.x * moveMult ); 193 | this.object.translateY( this.moveVector.y * moveMult ); 194 | this.object.translateZ( this.moveVector.z * moveMult ); 195 | 196 | this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize(); 197 | this.object.quaternion.multiply( this.tmpQuaternion ); 198 | 199 | // expose the rotation vector for convenience 200 | this.object.rotation.setFromQuaternion( this.object.quaternion, this.object.rotation.order ); 201 | 202 | 203 | }; 204 | 205 | this.updateMovementVector = function() { 206 | 207 | var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0; 208 | 209 | this.moveVector.x = ( -this.moveState.left + this.moveState.right ); 210 | this.moveVector.y = ( -this.moveState.down + this.moveState.up ); 211 | this.moveVector.z = ( -forward + this.moveState.back ); 212 | 213 | //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); 214 | 215 | }; 216 | 217 | this.updateRotationVector = function() { 218 | 219 | this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp ); 220 | this.rotationVector.y = ( -this.moveState.yawRight + this.moveState.yawLeft ); 221 | this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft ); 222 | 223 | //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); 224 | 225 | }; 226 | 227 | this.getContainerDimensions = function() { 228 | 229 | if ( this.domElement != document ) { 230 | 231 | return { 232 | size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ], 233 | offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ] 234 | }; 235 | 236 | } else { 237 | 238 | return { 239 | size : [ window.innerWidth, window.innerHeight ], 240 | offset : [ 0, 0 ] 241 | }; 242 | 243 | } 244 | 245 | }; 246 | 247 | function bind( scope, fn ) { 248 | 249 | return function () { 250 | 251 | fn.apply( scope, arguments ); 252 | 253 | }; 254 | 255 | }; 256 | 257 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 258 | 259 | this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false ); 260 | this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false ); 261 | this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false ); 262 | 263 | window.addEventListener( 'keydown', bind( this, this.keydown ), false ); 264 | window.addEventListener( 'keyup', bind( this, this.keyup ), false ); 265 | 266 | this.updateMovementVector(); 267 | this.updateRotationVector(); 268 | 269 | }; 270 | -------------------------------------------------------------------------------- /css/drawingboard2.css: -------------------------------------------------------------------------------- 1 | .drawing-board, .drawing-board * { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } 2 | 3 | .drawing-board-utils-hidden, .drawing-board-controls-hidden { display: none !important; } 4 | 5 | .drawing-board { position: relative; display: block; } 6 | 7 | .drawing-board-canvas-wrapper { position: relative; margin: 0; border: 1px solid #ddd; } 8 | 9 | .drawing-board-canvas { position: absolute; top: 0; left: 0; z-index: 10; width: auto; } 10 | 11 | .drawing-board-canvas { cursor: crosshair; z-index: 20; } 12 | 13 | .drawing-board-cursor { position: absolute; top: 0; left: 0; pointer-events: none; border-radius: 50%; background: #ccc; background: rgba(0, 0, 0, 0.2); z-index: 30; } 14 | 15 | .drawing-board-control > button, .drawing-board-control-colors-rainbows, .drawing-board-control-size .drawing-board-control-inner, .drawing-board-control-size-dropdown { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; overflow: hidden; border: none; background-color: #666; padding: 2px 4px; border: 1px solid #ccc; box-shadow: 0 1px 3px -2px #121212, inset 0 2px 5px 0 rgba(255, 255, 255, 0.3); -webkit-box-shadow: 0 1px 3px -2px #121212, inset 0 2px 5px 0 rgba(255, 255, 255, 0.3); height: 64px; } 16 | 17 | .drawing-board-control > button { cursor: pointer; min-width: 64px; line-height: 14px; } 18 | .drawing-board-control > button:hover { background-color: #999; } 19 | /*.drawing-board-control > button:focus { background-color: #666; }*/ 20 | .drawing-board-control > button:active, .drawing-board-control > button.active { box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.2); -webkit-box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.2); background-color: #ccc; } 21 | .drawing-board-control > button[disabled] { color: black; } 22 | .drawing-board-control > button[disabled]:hover, .drawing-board-control > button[disabled]:focus, .drawing-board-control > button[disabled]:active, .drawing-board-control > button[disabled].active { background-color: #666; box-shadow: 0 1px 3px -2px #121212, inset 0 2px 5px 0 rgba(255, 255, 255, 0.3); -webkit-box-shadow: 0 1px 3px -2px #121212, inset 0 2px 5px 0 rgba(255, 255, 255, 0.3); cursor: default; } 23 | 24 | .drawing-board-controls { margin: 0 auto; text-align: center; font-size: 0; display: table; border-spacing: 9.33333px 0; position: relative; min-height: 64px; } 25 | .drawing-board-controls[data-align="left"] { margin: 0; left: -9.33333px; } 26 | .drawing-board-controls[data-align="right"] { margin: 0 0 0 auto; right: -9.33333px; } 27 | .drawing-board-canvas-wrapper + .drawing-board-controls, .drawing-board-controls + .drawing-board-canvas-wrapper { margin-top: 5px; } 28 | 29 | .drawing-board-controls-hidden { height: 0; min-height: 0; padding: 0; margin: 0; border: 0; } 30 | 31 | .drawing-board-control { display: table-cell; border-collapse: separate; vertical-align: middle; font-size: 16px; height: 100%; } 32 | 33 | .drawing-board-control-inner { position: relative; height: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } 34 | 35 | .drawing-board-control > button { margin: 0; vertical-align: middle; } 36 | 37 | .drawing-board-control-colors { font-size: 0; line-height: 0; } 38 | 39 | .drawing-board-control-colors-current { border: 1px solid #ccc; cursor: pointer; display: inline-block; width: 26px; height: 26px; } 40 | 41 | .drawing-board-control-colors-rainbows { display: inline-block; margin-left: 5px; position: absolute; left: 0; top: 33px; margin-left: 0; z-index: 100; width: 250px; height: auto; padding: 4px; } 42 | 43 | .drawing-board-control-colors-rainbow { height: 18px; } 44 | 45 | .drawing-board-control-colors-picker:first-child { margin-right: 5px; } 46 | 47 | .drawing-board-control-colors-picker { display: inline-block; width: 18px; height: 18px; cursor: pointer; } 48 | 49 | .drawing-board-control-colors-picker[data-color="rgba(255, 255, 255, 1)"] { width: 16px; height: 17px; border: 1px solid #ccc; border-bottom: none; } 50 | 51 | .drawing-board-control-colors-picker:hover { width: 16px; height: 16px; border: 1px solid #555; } 52 | 53 | .drawing-board-control-drawingmode > button { margin-right: 2px; } 54 | .drawing-board-control-drawingmode > button:last-child { margin-right: 0; } 55 | 56 | .drawing-board-control-drawingmode-pencil-button { overflow: hidden; *text-indent: -9999px; background-image: url('../images/pencil64.png'); background-position: 50% 50%; background-repeat: no-repeat; } 57 | .drawing-board-control-drawingmode-pencil-button:before { content: ""; display: block; width: 0; height: 100%; } 58 | 59 | .drawing-board-control-drawingmode-eraser-button { overflow: hidden; *text-indent: -9999px; background-image: url('../images/eraser64.png'); background-position: 50% 50%; background-repeat: no-repeat; } 60 | 61 | .drawing-board-control-drawingmode-eraser-button:before { content: ""; display: block; width: 0; height: 100%; } 62 | 63 | .drawing-board-control-drawingmode-filler-button { overflow: hidden; *text-indent: -9999px; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnNJREFUeNp0k0trE1EUx89MJpNJooYYXBgDNtCKdRPwlbqoCKUtaNVNA0Uo7UbMxoVPEARTXEi+QWfnwn6DEAlEkrSLttTGRiULEQlJ8yChmbzI++E50yTUJA78uMy953/u/557LmOz2WDEZ2m1WrckSRJSqdR2tVrdHQyYebwHtVoNuFHqTqczhQnWKaBYLDoKhcIuzgHDMKBSqeD20qd+LNdsNocSoFhRr9ctpVLJigl4xIIJQizLAmG4cAPa7bYcy9Iug5TL5UYikbD6/X7Rbre/IUcYe3WUW5ZsnQQzW9LpNOPz+UQc5aBM5mgdh7vI9FCCAesW2tnr9YqZTAby+bw8f3AQRP6853n+Ph5hemSCntjj8YjZbFYWx2IxeS2RSEMwuA87O79eqdXquVolK+GxnP0EPbHb7RZJSGABIR6PA11zJHKIR2MhHA5DIPDj7eH3j95KpfK60Wg8Yntil8slkqgnpioLghacTidoNDpEC3q9HnheCc3s1jZeLcW943pirPw/4lKpBkqlDubnl/riycnLsLy88EKj0fhzuRyZv8RFo1E6wpBYkiqy7Z54YmIcVlYeyOKC4mYwJ0nHRaQuM5vNT6hB/iceG7sIq6sPnwmC4MerDkby40AOCCoiddie1Wp92W7zQ2KTyQSLizNP8T0EsPLBbxEDnCj0GkM2qIEwyZRCobizsfH5A1ZXFhuN52F29vpz3HkL574mk8lj24Y5wsHkvjjoX0BOIWc5jruHzbK2ufmzEwpFO3jnDhQv4JoROYdoERVyGjEgZ8iBDlF3FzXo4go6utZ9lftY4N/dXisjR0i1G0ublv8KMAA0ZoUlicxrhwAAAABJRU5ErkJggg=='); background-position: 50% 50%; background-repeat: no-repeat; } 64 | .drawing-board-control-drawingmode-filler-button:before { content: ""; display: block; width: 0; height: 100%; } 65 | 66 | .drawing-board-control-navigation > button { font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: bold; margin-right: 2px; } 67 | .drawing-board-control-navigation > button:last-child { margin-right: 0; } 68 | 69 | .drawing-board-control-size[data-drawing-board-type="range"] .drawing-board-control-inner { width: 75px; } 70 | .drawing-board-control-size[data-drawing-board-type="dropdown"] .drawing-board-control-inner { overflow: visible; } 71 | 72 | .drawing-board-control-size-range-input { position: relative; width: 100%; z-index: 100; margin: 0; padding: 0; border: 0; } 73 | 74 | .drawing-board-control-size-range-current, .drawing-board-control-size-dropdown-current span, .drawing-board-control-size-dropdown span { display: block; background: #ff0; opacity: .8; } 75 | 76 | .drawing-board-control-size-range-current { display: inline-block; opacity: .15; position: absolute; pointer-events: none; left: 50%; top: 50%; z-index: 50; } 77 | 78 | .drawing-board-control-size-dropdown-current { display: block; height: 100%; width: 40px; overflow: hidden; position: relative; } 79 | .drawing-board-control-size-dropdown-current span { position: absolute; left: 50%; top: 50%; } 80 | 81 | .drawing-board-control-size-dropdown { position: absolute; left: -6px; top: 33px; height: auto; list-style-type: none; margin: 0; padding: 0; z-index: 100; } 82 | .drawing-board-control-size-dropdown li { display: block; padding: 4px; margin: 3px 0; min-height: 16px; } 83 | .drawing-board-control-size-dropdown li:hover { background: #ccc; } 84 | .drawing-board-control-size-dropdown span { margin: 0 auto; } 85 | 86 | .drawing-board-control-download-button { overflow: hidden; *text-indent: -9999px; background-image: url('../images/play.png'); background-position: 50% 50%; background-repeat: no-repeat; } 87 | .drawing-board-control-download-button:before { content: ""; display: block; width: 0; height: 100%; } 88 | .drawing-board-control-navigation-reset{overflow: hidden; *text-indent: -9999px; background-image: url('../images/clear64.png'); background-position: 50% 50%; background-repeat: no-repeat; } -------------------------------------------------------------------------------- /js/controls/EditorControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author qiao / https://github.com/qiao 3 | * @author mrdoob / http://mrdoob.com 4 | * @author alteredq / http://alteredqualia.com/ 5 | * @author WestLangley / http://github.com/WestLangley 6 | */ 7 | 8 | THREE.EditorControls = function ( object, domElement ) { 9 | 10 | domElement = ( domElement !== undefined ) ? domElement : document; 11 | 12 | // API 13 | 14 | this.enabled = true; 15 | this.center = new THREE.Vector3(); 16 | 17 | // internals 18 | 19 | var scope = this; 20 | var vector = new THREE.Vector3(); 21 | 22 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; 23 | var state = STATE.NONE; 24 | 25 | var center = this.center; 26 | var normalMatrix = new THREE.Matrix3(); 27 | var pointer = new THREE.Vector2(); 28 | var pointerOld = new THREE.Vector2(); 29 | 30 | // events 31 | 32 | var changeEvent = { type: 'change' }; 33 | 34 | this.focus = function ( target, frame ) { 35 | 36 | var scale = new THREE.Vector3(); 37 | target.matrixWorld.decompose( center, new THREE.Quaternion(), scale ); 38 | 39 | if ( frame && target.geometry ) { 40 | 41 | scale = ( scale.x + scale.y + scale.z ) / 3; 42 | center.add(target.geometry.boundingSphere.center.clone().multiplyScalar( scale )); 43 | var radius = target.geometry.boundingSphere.radius * ( scale ); 44 | var pos = object.position.clone().sub( center ).normalize().multiplyScalar( radius * 2 ); 45 | object.position.copy( center ).add( pos ); 46 | 47 | } 48 | 49 | object.lookAt( center ); 50 | 51 | scope.dispatchEvent( changeEvent ); 52 | 53 | }; 54 | 55 | this.pan = function ( delta ) { 56 | 57 | var distance = object.position.distanceTo( center ); 58 | 59 | delta.multiplyScalar( distance * 0.001 ); 60 | delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) ); 61 | 62 | object.position.add( delta ); 63 | center.add( delta ); 64 | 65 | scope.dispatchEvent( changeEvent ); 66 | 67 | }; 68 | 69 | this.zoom = function ( delta ) { 70 | 71 | var distance = object.position.distanceTo( center ); 72 | 73 | delta.multiplyScalar( distance * 0.001 ); 74 | 75 | if ( delta.length() > distance ) return; 76 | 77 | delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) ); 78 | 79 | object.position.add( delta ); 80 | 81 | scope.dispatchEvent( changeEvent ); 82 | 83 | }; 84 | 85 | this.rotate = function ( delta ) { 86 | 87 | vector.copy( object.position ).sub( center ); 88 | 89 | var theta = Math.atan2( vector.x, vector.z ); 90 | var phi = Math.atan2( Math.sqrt( vector.x * vector.x + vector.z * vector.z ), vector.y ); 91 | 92 | theta += delta.x; 93 | phi += delta.y; 94 | 95 | var EPS = 0.000001; 96 | 97 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); 98 | 99 | var radius = vector.length(); 100 | 101 | vector.x = radius * Math.sin( phi ) * Math.sin( theta ); 102 | vector.y = radius * Math.cos( phi ); 103 | vector.z = radius * Math.sin( phi ) * Math.cos( theta ); 104 | 105 | object.position.copy( center ).add( vector ); 106 | 107 | object.lookAt( center ); 108 | 109 | scope.dispatchEvent( changeEvent ); 110 | 111 | }; 112 | 113 | // mouse 114 | 115 | function onMouseDown( event ) { 116 | 117 | if ( scope.enabled === false ) return; 118 | 119 | event.preventDefault(); 120 | 121 | if ( event.button === 0 ) { 122 | 123 | state = STATE.ROTATE; 124 | 125 | } else if ( event.button === 1 ) { 126 | 127 | state = STATE.ZOOM; 128 | 129 | } else if ( event.button === 2 ) { 130 | 131 | state = STATE.PAN; 132 | 133 | } 134 | 135 | pointerOld.set( event.clientX, event.clientY ); 136 | 137 | domElement.addEventListener( 'mousemove', onMouseMove, false ); 138 | domElement.addEventListener( 'mouseup', onMouseUp, false ); 139 | domElement.addEventListener( 'mouseout', onMouseUp, false ); 140 | domElement.addEventListener( 'dblclick', onMouseUp, false ); 141 | 142 | } 143 | 144 | function onMouseMove( event ) { 145 | 146 | if ( scope.enabled === false ) return; 147 | 148 | event.preventDefault(); 149 | 150 | pointer.set( event.clientX, event.clientY ); 151 | 152 | var movementX = pointer.x - pointerOld.x; 153 | var movementY = pointer.y - pointerOld.y; 154 | 155 | if ( state === STATE.ROTATE ) { 156 | 157 | scope.rotate( new THREE.Vector3( - movementX * 0.005, - movementY * 0.005, 0 ) ); 158 | 159 | } else if ( state === STATE.ZOOM ) { 160 | 161 | scope.zoom( new THREE.Vector3( 0, 0, movementY ) ); 162 | 163 | } else if ( state === STATE.PAN ) { 164 | 165 | scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); 166 | 167 | } 168 | 169 | pointerOld.set( event.clientX, event.clientY ); 170 | 171 | } 172 | 173 | function onMouseUp( event ) { 174 | 175 | domElement.removeEventListener( 'mousemove', onMouseMove, false ); 176 | domElement.removeEventListener( 'mouseup', onMouseUp, false ); 177 | domElement.removeEventListener( 'mouseout', onMouseUp, false ); 178 | domElement.removeEventListener( 'dblclick', onMouseUp, false ); 179 | 180 | state = STATE.NONE; 181 | 182 | } 183 | 184 | function onMouseWheel( event ) { 185 | 186 | event.preventDefault(); 187 | 188 | // if ( scope.enabled === false ) return; 189 | 190 | var delta = 0; 191 | 192 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 193 | 194 | delta = - event.wheelDelta; 195 | 196 | } else if ( event.detail ) { // Firefox 197 | 198 | delta = event.detail * 10; 199 | 200 | } 201 | 202 | scope.zoom( new THREE.Vector3( 0, 0, delta ) ); 203 | 204 | } 205 | 206 | domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 207 | domElement.addEventListener( 'mousedown', onMouseDown, false ); 208 | domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 209 | domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 210 | 211 | // touch 212 | 213 | var touch = new THREE.Vector3(); 214 | 215 | var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; 216 | var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; 217 | 218 | var prevDistance = null; 219 | 220 | function touchStart( event ) { 221 | 222 | if ( scope.enabled === false ) return; 223 | 224 | switch ( event.touches.length ) { 225 | 226 | case 1: 227 | touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 228 | touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 229 | break; 230 | 231 | case 2: 232 | touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 233 | touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ); 234 | prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] ); 235 | break; 236 | 237 | } 238 | 239 | prevTouches[ 0 ].copy( touches[ 0 ] ); 240 | prevTouches[ 1 ].copy( touches[ 1 ] ); 241 | 242 | } 243 | 244 | 245 | function touchMove( event ) { 246 | 247 | if ( scope.enabled === false ) return; 248 | 249 | event.preventDefault(); 250 | event.stopPropagation(); 251 | 252 | var getClosest = function( touch, touches ) { 253 | 254 | var closest = touches[ 0 ]; 255 | 256 | for ( var i in touches ) { 257 | if ( closest.distanceTo(touch) > touches[ i ].distanceTo(touch) ) closest = touches[ i ]; 258 | } 259 | 260 | return closest; 261 | 262 | } 263 | 264 | switch ( event.touches.length ) { 265 | 266 | case 1: 267 | touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 268 | touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 269 | scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ] ,prevTouches ) ).multiplyScalar( - 0.005 ) ); 270 | break; 271 | 272 | case 2: 273 | touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ); 274 | touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ); 275 | distance = touches[ 0 ].distanceTo( touches[ 1 ] ); 276 | scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) ); 277 | prevDistance = distance; 278 | 279 | 280 | var offset0 = touches[ 0 ].clone().sub( getClosest( touches[ 0 ] ,prevTouches ) ); 281 | var offset1 = touches[ 1 ].clone().sub( getClosest( touches[ 1 ] ,prevTouches ) ); 282 | offset0.x = -offset0.x; 283 | offset1.x = -offset1.x; 284 | 285 | scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) ); 286 | 287 | break; 288 | 289 | } 290 | 291 | prevTouches[ 0 ].copy( touches[ 0 ] ); 292 | prevTouches[ 1 ].copy( touches[ 1 ] ); 293 | 294 | } 295 | 296 | domElement.addEventListener( 'touchstart', touchStart, false ); 297 | domElement.addEventListener( 'touchmove', touchMove, false ); 298 | 299 | }; 300 | 301 | THREE.EditorControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 302 | -------------------------------------------------------------------------------- /js/nn/nn_funcs_merge.js: -------------------------------------------------------------------------------- 1 | function setupWeightArrays() { 2 | var maxWeight, minWeight; 3 | //console.log('doing setupWeightarrays'); 4 | var i, j; 5 | hidden_weights_1a = Create2DArray(nHiddenNodes_1,nPixels); 6 | maxWeight = -100; 7 | minWeight = 100; 8 | for (i=1; i<=nHiddenNodes_1; i++){ 9 | for (j=1; j<=nPixels; j++){ 10 | var weight = hidden_weights_1.e(i,j); 11 | if (weight > maxWeight) 12 | maxWeight = weight; 13 | if (weight < minWeight) 14 | minWeight = weight; 15 | } 16 | } 17 | for (i=1; i<=nHiddenNodes_1; i++){ 18 | for (j=1; j<=nPixels; j++){ 19 | var weight = hidden_weights_1.e(i,j); 20 | hidden_weights_1a[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 21 | } 22 | } 23 | 24 | hidden_weights_2a = Create2DArray(nHiddenNodes_2,nHiddenNodes_1); 25 | maxWeight = -100; 26 | minWeight = 100; 27 | for (i=1; i<=nHiddenNodes_2; i++){ 28 | for (j=1; j<=nHiddenNodes_1; j++){ 29 | var weight = hidden_weights_2.e(i,j); 30 | if (weight > maxWeight) 31 | maxWeight = weight; 32 | if (weight < minWeight) 33 | minWeight = weight; 34 | } 35 | } 36 | for (i=1; i<=nHiddenNodes_2; i++){ 37 | for (j=1; j<=nHiddenNodes_1; j++){ 38 | var weight = hidden_weights_2.e(i,j); 39 | hidden_weights_2a[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 40 | } 41 | } 42 | 43 | final_weightsa = Create2DArray(nFinalNodes,nHiddenNodes_2); 44 | maxWeight = -100; 45 | minWeight = 100; 46 | for (i=1; i<=nFinalNodes; i++){ 47 | for (j=1; j<=nHiddenNodes_2; j++){ 48 | var weight = final_weights.e(i,j); 49 | if (weight > maxWeight) 50 | maxWeight = weight; 51 | if (weight < minWeight) 52 | minWeight = weight; 53 | } 54 | } 55 | for (i=1; i<=nFinalNodes; i++){ 56 | for (j=1; j<=nHiddenNodes_2; j++){ 57 | var weight = final_weights.e(i,j); 58 | final_weightsa[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 59 | } 60 | } 61 | 62 | } 63 | 64 | 65 | function getNNOutput() { 66 | //console.log('getting nn output'); 67 | var imageData = tinyCtx.getImageData(0, 0, 28, 28); 68 | 69 | var data = imageData.data; 70 | 71 | var pixel = 0; 72 | var input = new Array(nPixels); 73 | 74 | for(var i = 0, n = data.length; i < n; i += 4) { 75 | if (goodStart){ 76 | if (data[i]) { 77 | input[pixel] = ((data[i]/255)*1.275)-0.1;// * 1.175; 78 | } 79 | else { 80 | input[pixel] = -0.1; 81 | } 82 | } else { 83 | input[pixel] = 0; 84 | } 85 | allNodeInputs[pixel] = input[pixel]; 86 | allNodeOutputs[pixel] = input[pixel]; 87 | allNodeNums[pixel] = pixel+1; 88 | pixel++; 89 | } 90 | for (var i = 0; i < nPixels; i++) { 91 | if (input[i] == 0 || input[i] == -0.1) { 92 | allZeroes = true; 93 | } else { 94 | //console.log('found ' + input[i]); 95 | allZeroes = false; 96 | break; 97 | } 98 | } 99 | 100 | //console.log(input.length); 101 | var input32 = reshapeArray(input); 102 | //console.log(input32.length); 103 | var inp = Vector.create(input32); 104 | //console.log(inp.inspect()); 105 | var hidden_outputs_1 = Vector.Zero(nHiddenNodes_1); 106 | var hidden_outputs_1a = new Array(nHiddenNodes_1); 107 | var hidden_outputs_2 = Vector.Zero(nHiddenNodes_2); 108 | var hidden_outputs_2a = new Array(nHiddenNodes_2); 109 | var final_outputsa = new Array(nFinalNodes); 110 | 111 | //console.log('there are ' + nHiddenNodes_1 + ' hidden nodes'); 112 | for (var i=1; i<=nHiddenNodes_1; i++){ 113 | if (!allZeroes){ 114 | var weights = hidden_weights_1.row(i); 115 | var sum = inp.dot(weights); 116 | 117 | //console.log('sum for node ' + i + ' = ' + sum); 118 | sum += hidden_biases_1.e(i); 119 | hidden_outputs_1a[i-1] = sigma(sum); 120 | allNodeInputs[nPixels+i-1] = sum; 121 | allNodeOutputs[nPixels+i-1]=hidden_outputs_1a[i-1]; 122 | //console.log('output for node ' + i + ' = ' + hidden_outputs_1a[i-1]); 123 | } else { 124 | hidden_outputs_1a[i-1] = 0; 125 | allNodeInputs[nPixels+i-1] = 0; 126 | allNodeOutputs[nPixels+i-1]= 0; 127 | } 128 | allNodeNums[nPixels+i-1] = i; 129 | } 130 | hidden_outputs_1.setElements(hidden_outputs_1a); 131 | 132 | for (i=1; i<=nHiddenNodes_2; i++){ 133 | if (!allZeroes){ 134 | var weights = hidden_weights_2.row(i); 135 | var sum = hidden_outputs_1.dot(weights); 136 | sum += hidden_biases_2.e(i); 137 | hidden_outputs_2a[i-1] = sigma(sum); 138 | allNodeInputs[nPixels+nHiddenNodes_1+i-1]=sum; 139 | allNodeOutputs[nPixels+nHiddenNodes_1+i-1]=hidden_outputs_2a[i-1]; 140 | 141 | } else { 142 | hidden_outputs_2a[i-1] = 0; 143 | allNodeInputs[nPixels+nHiddenNodes_1+i-1]=0; 144 | allNodeOutputs[nPixels+nHiddenNodes_1+i-1]=0; 145 | } 146 | allNodeNums[nPixels+nHiddenNodes_1+i-1] = i; 147 | } 148 | hidden_outputs_2.setElements(hidden_outputs_2a); 149 | 150 | var sums = final_weights.x(hidden_outputs_2); 151 | var newSums = sums.add(final_biases); 152 | 153 | for (i=1; i<=nFinalNodes; i++){ 154 | if (!allZeroes){ 155 | final_outputsa[i-1] = sigma(newSums.e(i)); 156 | allNodeInputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=newSums.e(i); 157 | allNodeOutputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=final_outputsa[i-1]; 158 | } else { 159 | final_outputsa[i-1] = 0; 160 | allNodeInputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=0; 161 | allNodeOutputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=0; 162 | } 163 | allNodeNums[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1] = i; 164 | } 165 | 166 | allNodeOutputsRaw = allNodeOutputs.slice(); 167 | normalizeWithinLayer(allNodeOutputs); 168 | 169 | if (!allZeroes){ 170 | var ind1 = maxInd(final_outputsa); 171 | finalOutputID = nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1 + ind1 - 10; 172 | final_outputsa[ind] = -10; 173 | var ind2 = maxInd(final_outputsa); 174 | document.getElementById("ans1").innerHTML = ind1; 175 | document.getElementById("ans2").innerHTML = ind2; 176 | } else { 177 | document.getElementById("ans1").innerHTML = ""; 178 | document.getElementById("ans2").innerHTML = ""; 179 | } 180 | 181 | isComputed = true; 182 | 183 | 184 | //console.log('officially, output for node 1134 = ' + allNodeOutputsRaw[1134] + ", normalized to " + allNodeOutputs[1134]); 185 | 186 | updateCubes(); 187 | //updateEdges(); 188 | 189 | //console.log(imageData); 190 | imageData.data = null; 191 | imageData = null; 192 | //console.log(imageData); 193 | }; 194 | 195 | function sigma(x) { 196 | return 1.7159*math.tanh(0.666667*x); 197 | } 198 | function reshapeArray(arr){ 199 | // The input array walks along pixels ltr ltr ltr. 200 | // For proper input, we need it to walk ttb ttb ttb. 201 | var arr2 = new Array(784); 202 | for (count = 0; count < 784; count++){ 203 | if (goodStart) { 204 | arr2[count] = -0.1; 205 | } else { 206 | arr2[count] = 0; 207 | } 208 | } 209 | for (count = 0; count < 784; count++){ 210 | var row = math.floor(count/28); 211 | var col = (count)%28; 212 | var newInd = col*28 + row; 213 | arr2[newInd] = arr[count]; 214 | } 215 | return arr2; 216 | } 217 | function maxInd(arr) { 218 | ind = 0; 219 | val = arr[0]; 220 | for (i=1; ival){ 222 | ind = i; 223 | val = arr[i]; 224 | } 225 | } 226 | return ind; 227 | } 228 | function normalizeWithinLayer(arr) { 229 | var len = arr.length; 230 | 231 | var minPixel = 100; 232 | var minHidden1 = 100; 233 | var minHidden2 = 100; 234 | var minFinal = 100; 235 | 236 | var maxPixel = -100; 237 | var maxHidden1 = -100; 238 | var maxHidden2 = -100; 239 | var maxFinal = -100; 240 | for (var i=0;imaxPixel) 243 | maxPixel = arr[i]; 244 | else if (arr[i]maxHidden1) 248 | maxHidden1 = arr[i]; 249 | else if (arr[i]maxHidden2) 253 | maxHidden2 = arr[i]; 254 | else if (arr[i]maxFinal) 258 | maxFinal = arr[i]; 259 | else if (arr[i] maxWeight) 12 | maxWeight = weight; 13 | if (weight < minWeight) 14 | minWeight = weight; 15 | } 16 | } 17 | for (i=1; i<=nHiddenNodes_1; i++){ 18 | for (j=1; j<=nPixels; j++){ 19 | var weight = hidden_weights_1.e(i,j); 20 | hidden_weights_1a[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 21 | } 22 | } 23 | 24 | hidden_weights_2a = Create2DArray(nHiddenNodes_2,nHiddenNodes_1); 25 | maxWeight = -100; 26 | minWeight = 100; 27 | for (i=1; i<=nHiddenNodes_2; i++){ 28 | for (j=1; j<=nPixels; j++){ 29 | var weight = hidden_weights_2.e(i,j); 30 | if (weight > maxWeight) 31 | maxWeight = weight; 32 | if (weight < minWeight) 33 | minWeight = weight; 34 | } 35 | } 36 | for (i=1; i<=nHiddenNodes_2; i++){ 37 | for (j=1; j<=nHiddenNodes_1; j++){ 38 | var weight = hidden_weights_2.e(i,j); 39 | hidden_weights_2a[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 40 | } 41 | } 42 | 43 | final_weightsa = Create2DArray(nFinalNodes,nHiddenNodes_2); 44 | maxWeight = -100; 45 | minWeight = 100; 46 | for (i=1; i<=nFinalNodes; i++){ 47 | for (j=1; j<=nHiddenNodes_2; j++){ 48 | var weight = final_weights.e(i,j); 49 | if (weight > maxWeight) 50 | maxWeight = weight; 51 | if (weight < minWeight) 52 | minWeight = weight; 53 | } 54 | } 55 | for (i=1; i<=nFinalNodes; i++){ 56 | for (j=1; j<=nHiddenNodes_2; j++){ 57 | var weight = final_weights.e(i,j); 58 | final_weightsa[i-1][j-1] = (weight - minWeight)/(maxWeight-minWeight); 59 | } 60 | } 61 | 62 | } 63 | 64 | 65 | function getNNOutput() { 66 | //console.log('getting nn output'); 67 | var imageData = tinyCtx.getImageData(0, 0, 28, 28); 68 | 69 | var data = imageData.data; 70 | 71 | var pixel = 0; 72 | var input = new Array(nPixels); 73 | 74 | for(var i = 0, n = data.length; i < n; i += 4) { 75 | if (goodStart){ 76 | if (data[i]) { 77 | input[pixel] = ((data[i]/255)*1.275)-0.1;// * 1.175; 78 | } 79 | else { 80 | input[pixel] = -0.1; 81 | } 82 | } else { 83 | input[pixel] = 0; 84 | } 85 | allNodeInputs[pixel] = input[pixel]; 86 | allNodeOutputs[pixel] = input[pixel]; 87 | allNodeNums[pixel] = pixel+1; 88 | pixel++; 89 | } 90 | 91 | //console.log(input.length); 92 | var input32 = reshapeArray(input); 93 | //console.log(input32.length); 94 | var inp = Vector.create(input32); 95 | //console.log(inp.inspect()); 96 | var hidden_outputs_1 = Vector.Zero(nHiddenNodes_1); 97 | var hidden_outputs_1a = new Array(nHiddenNodes_1); 98 | var hidden_outputs_2 = Vector.Zero(nHiddenNodes_2); 99 | var hidden_outputs_2a = new Array(nHiddenNodes_2); 100 | var final_outputsa = new Array(nFinalNodes); 101 | 102 | //console.log('there are ' + nHiddenNodes_1 + ' hidden nodes'); 103 | for (var i=1; i<=nHiddenNodes_1; i++){ 104 | if (goodStart){ 105 | var weights = hidden_weights_1.row(i); 106 | var sum = inp.dot(weights); 107 | 108 | //console.log('sum for node ' + i + ' = ' + sum); 109 | sum += hidden_biases_1.e(i); 110 | hidden_outputs_1a[i-1] = sigma(sum); 111 | allNodeInputs[nPixels+i-1] = sum; 112 | allNodeOutputs[nPixels+i-1]=hidden_outputs_1a[i-1]; 113 | //console.log('output for node ' + i + ' = ' + hidden_outputs_1a[i-1]); 114 | } else { 115 | hidden_outputs_1a[i-1] = 0; 116 | allNodeInputs[nPixels+i-1] = 0; 117 | allNodeOutputs[nPixels+i-1]= 0; 118 | } 119 | allNodeNums[nPixels+i-1] = i; 120 | } 121 | hidden_outputs_1.setElements(hidden_outputs_1a); 122 | 123 | for (i=1; i<=nHiddenNodes_2; i++){ 124 | if (goodStart){ 125 | var weights = hidden_weights_2.row(i); 126 | var sum = hidden_outputs_1.dot(weights); 127 | sum += hidden_biases_2.e(i); 128 | hidden_outputs_2a[i-1] = sigma(sum); 129 | allNodeInputs[nPixels+nHiddenNodes_1+i-1]=sum; 130 | allNodeOutputs[nPixels+nHiddenNodes_1+i-1]=hidden_outputs_2a[i-1]; 131 | 132 | } else { 133 | hidden_outputs_2a[i-1] = 0; 134 | allNodeInputs[nPixels+nHiddenNodes_1+i-1]=0; 135 | allNodeOutputs[nPixels+nHiddenNodes_1+i-1]=0; 136 | } 137 | allNodeNums[nPixels+nHiddenNodes_1+i-1] = i; 138 | } 139 | hidden_outputs_2.setElements(hidden_outputs_2a); 140 | 141 | var sums = final_weights.x(hidden_outputs_2); 142 | var newSums = sums.add(final_biases); 143 | 144 | for (i=1; i<=nFinalNodes; i++){ 145 | if (goodStart){ 146 | final_outputsa[i-1] = sigma(newSums.e(i)); 147 | allNodeInputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=newSums.e(i); 148 | allNodeOutputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=final_outputsa[i-1]; 149 | } else { 150 | final_outputsa[i-1] = 0; 151 | allNodeInputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=0; 152 | allNodeOutputs[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1]=0; 153 | } 154 | allNodeNums[nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1] = i; 155 | } 156 | 157 | allNodeOutputsRaw = allNodeOutputs.slice(); 158 | normalizeWithinLayer(allNodeOutputs); 159 | 160 | if (!allZeroes){ 161 | var ind1 = maxInd(final_outputsa); 162 | finalOutputID = nPixels+nHiddenNodes_1+nHiddenNodes_2+i-1 + ind1 - 10; 163 | final_outputsa[ind] = -10; 164 | var ind2 = maxInd(final_outputsa); 165 | document.getElementById("ans1").innerHTML = ind1; 166 | document.getElementById("ans2").innerHTML = ind2; 167 | } else { 168 | document.getElementById("ans1").innerHTML = ""; 169 | document.getElementById("ans2").innerHTML = ""; 170 | } 171 | 172 | isComputed = true; 173 | 174 | updateCubes(); 175 | updateEdges(); 176 | 177 | 178 | //console.log(imageData); 179 | imageData.data = null; 180 | imageData = null; 181 | //console.log(imageData); 182 | }; 183 | 184 | function sigma(x) { 185 | return 1.7159*math.tanh(0.666667*x); 186 | } 187 | function reshapeArray(arr){ 188 | // The input array walks along pixels ltr ltr ltr. 189 | // For proper input, we need it to walk ttb ttb ttb. 190 | var arr2 = new Array(784); 191 | for (count = 0; count < 784; count++){ 192 | if (goodStart) { 193 | arr2[count] = -0.1; 194 | } else { 195 | arr2[count] = 0; 196 | } 197 | } 198 | for (count = 0; count < 784; count++){ 199 | var row = math.floor(count/28); 200 | var col = (count)%28; 201 | var newInd = col*28 + row; 202 | arr2[newInd] = arr[count]; 203 | } 204 | return arr2; 205 | } 206 | function maxInd(arr) { 207 | ind = 0; 208 | val = arr[0]; 209 | for (i=1; ival){ 211 | ind = i; 212 | val = arr[i]; 213 | } 214 | } 215 | return ind; 216 | } 217 | function normalizeWithinLayer(arr) { 218 | var len = arr.length; 219 | 220 | var minPixel = 100; 221 | var minHidden1 = 100; 222 | var minHidden2 = 100; 223 | var minFinal = 100; 224 | 225 | var maxPixel = -100; 226 | var maxHidden1 = -100; 227 | var maxHidden2 = -100; 228 | var maxFinal = -100; 229 | for (var i=0;imaxPixel) 232 | maxPixel = arr[i]; 233 | else if (arr[i]maxHidden1) 237 | maxHidden1 = arr[i]; 238 | else if (arr[i]maxHidden2) 242 | maxHidden2 = arr[i]; 243 | else if (arr[i]maxFinal) 247 | maxFinal = arr[i]; 248 | else if (arr[i] 0 ) { 213 | 214 | this.dispatchEvent( changeEvent ); 215 | 216 | lastPosition.copy( this.object.position ); 217 | 218 | } 219 | 220 | }; 221 | 222 | 223 | function getAutoRotationAngle() { 224 | 225 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 226 | 227 | } 228 | 229 | function getZoomScale() { 230 | 231 | return Math.pow( 0.95, scope.userZoomSpeed ); 232 | 233 | } 234 | 235 | function onMouseDown( event ) { 236 | 237 | momentumOn = false; 238 | 239 | momentumLeft = momentumUp = 0; 240 | 241 | if ( scope.enabled === false ) return; 242 | if ( scope.userRotate === false ) return; 243 | 244 | event.preventDefault(); 245 | 246 | if ( event.button === 0 ) { 247 | 248 | _state = STATE.ROTATE; 249 | 250 | rotateStart.set( event.clientX, event.clientY ); 251 | 252 | } else if ( event.button === 1 ) { 253 | 254 | _state = STATE.ZOOM; 255 | 256 | zoomStart.set( event.clientX, event.clientY ); 257 | 258 | } else if ( event.button === 2 ) { 259 | 260 | _state = STATE.PAN; 261 | 262 | } 263 | 264 | document.addEventListener( 'mousemove', onMouseMove, false ); 265 | document.addEventListener( 'mouseup', onMouseUp, false ); 266 | 267 | } 268 | 269 | var momentumLeft, momentumUp; 270 | 271 | function onMouseMove( event ) { 272 | 273 | if ( scope.enabled === false ) return; 274 | 275 | event.preventDefault(); 276 | 277 | if ( _state === STATE.ROTATE ) { 278 | 279 | rotateEnd.set( event.clientX, event.clientY ); 280 | rotateDelta.subVectors( rotateEnd, rotateStart ); 281 | 282 | momentumLeft = event.webkitMovementX; 283 | momentumUp = event.webkitMovementY; 284 | // momentumLeft += 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed; 285 | // momentumUp += 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed; 286 | 287 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); 288 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); 289 | 290 | rotateStart.copy( rotateEnd ); 291 | 292 | } // else if ( _state === STATE.ZOOM ) { 293 | 294 | // zoomEnd.set( event.clientX, event.clientY ); 295 | // zoomDelta.subVectors( zoomEnd, zoomStart ); 296 | 297 | // if ( zoomDelta.y > 0 ) { 298 | 299 | // scope.zoomIn(); 300 | 301 | // } else { 302 | 303 | // scope.zoomOut(); 304 | 305 | // } 306 | 307 | // zoomStart.copy( zoomEnd ); 308 | 309 | } else if ( _state === STATE.PAN ) { 310 | 311 | var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 312 | var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 313 | 314 | scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); 315 | 316 | } 317 | 318 | } 319 | 320 | var momentumOn = false; 321 | 322 | function onMouseUp( event ) { 323 | 324 | momentumOn = true; 325 | 326 | if ( scope.enabled === false ) return; 327 | if ( scope.userRotate === false ) return; 328 | 329 | document.removeEventListener( 'mousemove', onMouseMove, false ); 330 | document.removeEventListener( 'mouseup', onMouseUp, false ); 331 | 332 | _state = STATE.NONE; 333 | 334 | } 335 | 336 | function onMouseWheel( event ) { 337 | 338 | if ( scope.enabled === false ) return; 339 | if ( scope.userZoom === false ) return; 340 | event.preventDefault(); 341 | event.stopPropagation(); 342 | 343 | var delta = 0; 344 | 345 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 346 | 347 | delta = event.wheelDelta / 40; 348 | 349 | } else if ( event.detail ) { // Firefox 350 | 351 | delta = - event.detail / 3; 352 | 353 | } 354 | 355 | _zoomStart += delta * 0.001; 356 | 357 | } 358 | 359 | function onKeyDown( event ) { 360 | 361 | if ( scope.enabled === false ) return; 362 | if ( scope.userPan === false ) return; 363 | 364 | switch ( event.keyCode ) { 365 | 366 | case scope.keys.UP: 367 | scope.pan( new THREE.Vector3( 0, 1, 0 ) ); 368 | break; 369 | case scope.keys.BOTTOM: 370 | scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); 371 | break; 372 | case scope.keys.LEFT: 373 | scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); 374 | break; 375 | case scope.keys.RIGHT: 376 | scope.pan( new THREE.Vector3( 1, 0, 0 ) ); 377 | break; 378 | } 379 | 380 | } 381 | 382 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 383 | this.domElement.addEventListener( 'mousedown', onMouseDown, false ); 384 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 385 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 386 | this.domElement.addEventListener( 'keydown', onKeyDown, false); 387 | 388 | }; 389 | 390 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 391 | -------------------------------------------------------------------------------- /js/qiao_OrbitControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author qiao / https://github.com/qiao 3 | * @author mrdoob / http://mrdoob.com 4 | * @author alteredq / http://alteredqualia.com/ 5 | * @author WestLangley / http://github.com/WestLangley 6 | * 7 | * customized for momentum (zoom and phi/delta) by paulkaplan 8 | */ 9 | 10 | THREE.OrbitControls = function ( object, domElement ) { 11 | 12 | this.object = object; 13 | this.domElement = ( domElement !== undefined ) ? domElement : document; 14 | 15 | // API 16 | 17 | this.enabled = true; 18 | 19 | this.center = new THREE.Vector3(); 20 | 21 | this.userZoom = true; 22 | this.userZoomSpeed = 1.0; 23 | 24 | this.userRotate = true; 25 | this.userRotateSpeed = 1.0; 26 | 27 | this.userPan = true; 28 | this.userPanSpeed = 2.0; 29 | 30 | this.autoRotate = false; 31 | this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 32 | 33 | this.minPolarAngle = 0; // radians 34 | this.maxPolarAngle = Math.PI; // radians 35 | 36 | this.minDistance = 0; 37 | this.maxDistance = Infinity; 38 | 39 | this.zoomDampingFactor = 0.2; 40 | 41 | this.momentumDampingFactor = 0.8; 42 | this.momentumScalingFactor = 0.005; 43 | 44 | this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; 45 | 46 | // internals 47 | 48 | var scope = this; 49 | 50 | var EPS = 0.000001; 51 | var PIXELS_PER_ROUND = 1800; 52 | 53 | var rotateStart = new THREE.Vector2(); 54 | var rotateEnd = new THREE.Vector2(); 55 | var rotateDelta = new THREE.Vector2(); 56 | 57 | var zoomStart = new THREE.Vector2(); 58 | var zoomEnd = new THREE.Vector2(); 59 | var zoomDelta = new THREE.Vector2(); 60 | 61 | var _zoomEnd = 0; 62 | var _zoomStart = 0; 63 | 64 | var phiDelta = 0; 65 | var thetaDelta = 0; 66 | var scale = 1; 67 | 68 | var lastPosition = new THREE.Vector3(); 69 | 70 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; 71 | var state = STATE.NONE; 72 | 73 | // events 74 | 75 | var changeEvent = { type: 'change' }; 76 | 77 | 78 | this.rotateLeft = function ( angle ) { 79 | 80 | if ( angle === undefined ) { 81 | 82 | angle = getAutoRotationAngle(); 83 | 84 | } 85 | 86 | thetaDelta -= angle; 87 | 88 | }; 89 | 90 | this.rotateRight = function ( angle ) { 91 | 92 | if ( angle === undefined ) { 93 | 94 | angle = getAutoRotationAngle(); 95 | 96 | } 97 | 98 | thetaDelta += angle; 99 | 100 | }; 101 | 102 | this.rotateUp = function ( angle ) { 103 | 104 | if ( angle === undefined ) { 105 | 106 | angle = getAutoRotationAngle(); 107 | 108 | } 109 | 110 | phiDelta -= angle; 111 | 112 | }; 113 | 114 | this.rotateDown = function ( angle ) { 115 | 116 | if ( angle === undefined ) { 117 | 118 | angle = getAutoRotationAngle(); 119 | 120 | } 121 | 122 | phiDelta += angle; 123 | 124 | }; 125 | 126 | this.zoomCamera = function(){ 127 | var _this = this; 128 | 129 | var factor = 1.0 + ( _zoomEnd - _zoomStart ) * this.userZoomSpeed; 130 | scale *= factor; 131 | 132 | 133 | _zoomStart += ( _zoomEnd - _zoomStart ) * this.zoomDampingFactor; 134 | 135 | 136 | }; 137 | 138 | 139 | this.pan = function ( distance ) { 140 | 141 | distance.transformDirection( this.object.matrix ); 142 | distance.multiplyScalar( scope.userPanSpeed ); 143 | 144 | this.object.position.add( distance ); 145 | this.center.add( distance ); 146 | 147 | }; 148 | 149 | this.momentum = function(){ 150 | if(!momentumOn) return; 151 | 152 | // console.log('momentum-ing: '+momentumUp+" "+momentumLeft); 153 | 154 | if(Math.abs(momentumUp + momentumLeft) < 10e-5){ momentumOn = false; return } 155 | 156 | momentumUp *= this.momentumDampingFactor; 157 | momentumLeft *= this.momentumDampingFactor; 158 | 159 | thetaDelta -= this.momentumScalingFactor * momentumLeft; 160 | phiDelta -= this.momentumScalingFactor * momentumUp; 161 | 162 | }; 163 | 164 | this.update = function () { 165 | this.zoomCamera(); 166 | this.momentum(); 167 | // console.log(scale) 168 | 169 | var position = this.object.position; 170 | var offset = position.clone().sub( this.center ); 171 | 172 | // angle from z-axis around y-axis 173 | 174 | var theta = Math.atan2( offset.x, offset.z ); 175 | 176 | // angle from y-axis 177 | 178 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 179 | 180 | if ( this.autoRotate ) { 181 | 182 | this.rotateLeft( getAutoRotationAngle() ); 183 | 184 | } 185 | 186 | theta += thetaDelta; 187 | phi += phiDelta; 188 | 189 | // restrict phi to be between desired limits 190 | phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); 191 | 192 | // restrict phi to be betwee EPS and PI-EPS 193 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); 194 | 195 | var radius = offset.length() * scale; 196 | 197 | // restrict radius to be between desired limits 198 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); 199 | 200 | offset.x = radius * Math.sin( phi ) * Math.sin( theta ); 201 | offset.y = radius * Math.cos( phi ); 202 | offset.z = radius * Math.sin( phi ) * Math.cos( theta ); 203 | 204 | position.copy( this.center ).add( offset ); 205 | 206 | this.object.lookAt( this.center ); 207 | 208 | thetaDelta = 0; 209 | phiDelta = 0; 210 | scale = 1; 211 | 212 | if ( lastPosition.distanceTo( this.object.position ) > 0 ) { 213 | 214 | this.dispatchEvent( changeEvent ); 215 | 216 | lastPosition.copy( this.object.position ); 217 | 218 | } 219 | 220 | }; 221 | 222 | 223 | function getAutoRotationAngle() { 224 | 225 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 226 | 227 | } 228 | 229 | function getZoomScale() { 230 | 231 | return Math.pow( 0.95, scope.userZoomSpeed ); 232 | 233 | } 234 | 235 | function onMouseDown( event ) { 236 | 237 | momentumOn = false; 238 | 239 | momentumLeft = momentumUp = 0; 240 | 241 | if ( scope.enabled === false ) return; 242 | if ( scope.userRotate === false ) return; 243 | 244 | event.preventDefault(); 245 | 246 | if ( event.button === 0 ) { 247 | 248 | state = STATE.ROTATE; 249 | 250 | rotateStart.set( event.clientX, event.clientY ); 251 | 252 | } else if ( event.button === 1 ) { 253 | 254 | state = STATE.ZOOM; 255 | 256 | zoomStart.set( event.clientX, event.clientY ); 257 | 258 | } else if ( event.button === 2 ) { 259 | 260 | state = STATE.PAN; 261 | 262 | } 263 | 264 | document.addEventListener( 'mousemove', onMouseMove, false ); 265 | document.addEventListener( 'mouseup', onMouseUp, false ); 266 | 267 | } 268 | 269 | var momentumLeft, momentumUp; 270 | 271 | function onMouseMove( event ) { 272 | 273 | if ( scope.enabled === false ) return; 274 | 275 | event.preventDefault(); 276 | 277 | if ( state === STATE.ROTATE ) { 278 | 279 | rotateEnd.set( event.clientX, event.clientY ); 280 | rotateDelta.subVectors( rotateEnd, rotateStart ); 281 | 282 | momentumLeft = event.webkitMovementX; 283 | momentumUp = event.webkitMovementY; 284 | // momentumLeft += 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed; 285 | // momentumUp += 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed; 286 | 287 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); 288 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); 289 | 290 | rotateStart.copy( rotateEnd ); 291 | 292 | } // else if ( state === STATE.ZOOM ) { 293 | 294 | // zoomEnd.set( event.clientX, event.clientY ); 295 | // zoomDelta.subVectors( zoomEnd, zoomStart ); 296 | 297 | // if ( zoomDelta.y > 0 ) { 298 | 299 | // scope.zoomIn(); 300 | 301 | // } else { 302 | 303 | // scope.zoomOut(); 304 | 305 | // } 306 | 307 | // zoomStart.copy( zoomEnd ); 308 | 309 | } else if ( state === STATE.PAN ) { 310 | 311 | var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 312 | var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 313 | 314 | scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); 315 | 316 | } 317 | 318 | } 319 | 320 | var momentumOn = false; 321 | 322 | function onMouseUp( event ) { 323 | 324 | momentumOn = true; 325 | 326 | if ( scope.enabled === false ) return; 327 | if ( scope.userRotate === false ) return; 328 | 329 | document.removeEventListener( 'mousemove', onMouseMove, false ); 330 | document.removeEventListener( 'mouseup', onMouseUp, false ); 331 | 332 | state = STATE.NONE; 333 | 334 | } 335 | 336 | function onMouseWheel( event ) { 337 | 338 | if ( scope.enabled === false ) return; 339 | if ( scope.userZoom === false ) return; 340 | event.preventDefault(); 341 | event.stopPropagation(); 342 | 343 | var delta = 0; 344 | 345 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 346 | 347 | delta = event.wheelDelta / 40; 348 | 349 | } else if ( event.detail ) { // Firefox 350 | 351 | delta = - event.detail / 3; 352 | 353 | } 354 | 355 | _zoomStart += delta * 0.001; 356 | 357 | } 358 | 359 | function onKeyDown( event ) { 360 | 361 | if ( scope.enabled === false ) return; 362 | if ( scope.userPan === false ) return; 363 | 364 | switch ( event.keyCode ) { 365 | 366 | case scope.keys.UP: 367 | scope.pan( new THREE.Vector3( 0, 1, 0 ) ); 368 | break; 369 | case scope.keys.BOTTOM: 370 | scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); 371 | break; 372 | case scope.keys.LEFT: 373 | scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); 374 | break; 375 | case scope.keys.RIGHT: 376 | scope.pan( new THREE.Vector3( 1, 0, 0 ) ); 377 | break; 378 | } 379 | 380 | } 381 | 382 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 383 | this.domElement.addEventListener( 'mousedown', onMouseDown, false ); 384 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 385 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 386 | this.domElement.addEventListener( 'keydown', onKeyDown, false); 387 | 388 | }; 389 | 390 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 391 | -------------------------------------------------------------------------------- /js/sylvester.js: -------------------------------------------------------------------------------- 1 | eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9 17={3i:\'0.1.3\',16:1e-6};l v(){}v.23={e:l(i){8(i<1||i>7.4.q)?w:7.4[i-1]},2R:l(){8 7.4.q},1u:l(){8 F.1x(7.2u(7))},24:l(a){9 n=7.4.q;9 V=a.4||a;o(n!=V.q){8 1L}J{o(F.13(7.4[n-1]-V[n-1])>17.16){8 1L}}H(--n);8 2x},1q:l(){8 v.u(7.4)},1b:l(a){9 b=[];7.28(l(x,i){b.19(a(x,i))});8 v.u(b)},28:l(a){9 n=7.4.q,k=n,i;J{i=k-n;a(7.4[i],i+1)}H(--n)},2q:l(){9 r=7.1u();o(r===0){8 7.1q()}8 7.1b(l(x){8 x/r})},1C:l(a){9 V=a.4||a;9 n=7.4.q,k=n,i;o(n!=V.q){8 w}9 b=0,1D=0,1F=0;7.28(l(x,i){b+=x*V[i-1];1D+=x*x;1F+=V[i-1]*V[i-1]});1D=F.1x(1D);1F=F.1x(1F);o(1D*1F===0){8 w}9 c=b/(1D*1F);o(c<-1){c=-1}o(c>1){c=1}8 F.37(c)},1m:l(a){9 b=7.1C(a);8(b===w)?w:(b<=17.16)},34:l(a){9 b=7.1C(a);8(b===w)?w:(F.13(b-F.1A)<=17.16)},2k:l(a){9 b=7.2u(a);8(b===w)?w:(F.13(b)<=17.16)},2j:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x+V[i-1]})},2C:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x-V[i-1]})},22:l(k){8 7.1b(l(x){8 x*k})},x:l(k){8 7.22(k)},2u:l(a){9 V=a.4||a;9 i,2g=0,n=7.4.q;o(n!=V.q){8 w}J{2g+=7.4[n-1]*V[n-1]}H(--n);8 2g},2f:l(a){9 B=a.4||a;o(7.4.q!=3||B.q!=3){8 w}9 A=7.4;8 v.u([(A[1]*B[2])-(A[2]*B[1]),(A[2]*B[0])-(A[0]*B[2]),(A[0]*B[1])-(A[1]*B[0])])},2A:l(){9 m=0,n=7.4.q,k=n,i;J{i=k-n;o(F.13(7.4[i])>F.13(m)){m=7.4[i]}}H(--n);8 m},2Z:l(x){9 a=w,n=7.4.q,k=n,i;J{i=k-n;o(a===w&&7.4[i]==x){a=i+1}}H(--n);8 a},3g:l(){8 S.2X(7.4)},2d:l(){8 7.1b(l(x){8 F.2d(x)})},2V:l(x){8 7.1b(l(y){8(F.13(y-x)<=17.16)?x:y})},1o:l(a){o(a.K){8 a.1o(7)}9 V=a.4||a;o(V.q!=7.4.q){8 w}9 b=0,2b;7.28(l(x,i){2b=x-V[i-1];b+=2b*2b});8 F.1x(b)},3a:l(a){8 a.1h(7)},2T:l(a){8 a.1h(7)},1V:l(t,a){9 V,R,x,y,z;2S(7.4.q){27 2:V=a.4||a;o(V.q!=2){8 w}R=S.1R(t).4;x=7.4[0]-V[0];y=7.4[1]-V[1];8 v.u([V[0]+R[0][0]*x+R[0][1]*y,V[1]+R[1][0]*x+R[1][1]*y]);1I;27 3:o(!a.U){8 w}9 C=a.1r(7).4;R=S.1R(t,a.U).4;x=7.4[0]-C[0];y=7.4[1]-C[1];z=7.4[2]-C[2];8 v.u([C[0]+R[0][0]*x+R[0][1]*y+R[0][2]*z,C[1]+R[1][0]*x+R[1][1]*y+R[1][2]*z,C[2]+R[2][0]*x+R[2][1]*y+R[2][2]*z]);1I;2P:8 w}},1t:l(a){o(a.K){9 P=7.4.2O();9 C=a.1r(P).4;8 v.u([C[0]+(C[0]-P[0]),C[1]+(C[1]-P[1]),C[2]+(C[2]-(P[2]||0))])}1d{9 Q=a.4||a;o(7.4.q!=Q.q){8 w}8 7.1b(l(x,i){8 Q[i-1]+(Q[i-1]-x)})}},1N:l(){9 V=7.1q();2S(V.4.q){27 3:1I;27 2:V.4.19(0);1I;2P:8 w}8 V},2n:l(){8\'[\'+7.4.2K(\', \')+\']\'},26:l(a){7.4=(a.4||a).2O();8 7}};v.u=l(a){9 V=25 v();8 V.26(a)};v.i=v.u([1,0,0]);v.j=v.u([0,1,0]);v.k=v.u([0,0,1]);v.2J=l(n){9 a=[];J{a.19(F.2F())}H(--n);8 v.u(a)};v.1j=l(n){9 a=[];J{a.19(0)}H(--n);8 v.u(a)};l S(){}S.23={e:l(i,j){o(i<1||i>7.4.q||j<1||j>7.4[0].q){8 w}8 7.4[i-1][j-1]},33:l(i){o(i>7.4.q){8 w}8 v.u(7.4[i-1])},2E:l(j){o(j>7.4[0].q){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][j-1])}H(--n);8 v.u(a)},2R:l(){8{2D:7.4.q,1p:7.4[0].q}},2D:l(){8 7.4.q},1p:l(){8 7.4[0].q},24:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(7.4.q!=M.q||7.4[0].q!=M[0].q){8 1L}9 b=7.4.q,15=b,i,G,10=7.4[0].q,j;J{i=15-b;G=10;J{j=10-G;o(F.13(7.4[i][j]-M[i][j])>17.16){8 1L}}H(--G)}H(--b);8 2x},1q:l(){8 S.u(7.4)},1b:l(a){9 b=[],12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;b[i]=[];J{j=10-G;b[i][j]=a(7.4[i][j],i+1,j+1)}H(--G)}H(--12);8 S.u(b)},2i:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4.q==M.q&&7.4[0].q==M[0].q)},2j:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x+M[i-1][j-1]})},2C:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x-M[i-1][j-1]})},2B:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4[0].q==M.q)},22:l(a){o(!a.4){8 7.1b(l(x){8 x*a})}9 b=a.1u?2x:1L;9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2B(M)){8 w}9 d=7.4.q,15=d,i,G,10=M[0].q,j;9 e=7.4[0].q,4=[],21,20,c;J{i=15-d;4[i]=[];G=10;J{j=10-G;21=0;20=e;J{c=e-20;21+=7.4[i][c]*M[c][j]}H(--20);4[i][j]=21}H(--G)}H(--d);9 M=S.u(4);8 b?M.2E(1):M},x:l(a){8 7.22(a)},32:l(a,b,c,d){9 e=[],12=c,i,G,j;9 f=7.4.q,1p=7.4[0].q;J{i=c-12;e[i]=[];G=d;J{j=d-G;e[i][j]=7.4[(a+i-1)%f][(b+j-1)%1p]}H(--G)}H(--12);8 S.u(e)},31:l(){9 a=7.4.q,1p=7.4[0].q;9 b=[],12=1p,i,G,j;J{i=1p-12;b[i]=[];G=a;J{j=a-G;b[i][j]=7.4[j][i]}H(--G)}H(--12);8 S.u(b)},1y:l(){8(7.4.q==7.4[0].q)},2A:l(){9 m=0,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(F.13(7.4[i][j])>F.13(m)){m=7.4[i][j]}}H(--G)}H(--12);8 m},2Z:l(x){9 a=w,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(7.4[i][j]==x){8{i:i+1,j:j+1}}}H(--G)}H(--12);8 w},30:l(){o(!7.1y){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][i])}H(--n);8 v.u(a)},1K:l(){9 M=7.1q(),1c;9 n=7.4.q,k=n,i,1s,1n=7.4[0].q,p;J{i=k-n;o(M.4[i][i]==0){2e(j=i+1;j17.16){1Y++;1I}}H(--G)}H(--a);8 1Y},3d:l(){8 7.1Y()},2W:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}9 T=7.1q(),1p=T.4[0].q;9 b=T.4.q,15=b,i,G,10=M[0].q,j;o(b!=M.q){8 w}J{i=15-b;G=10;J{j=10-G;T.4[i][1p+j]=M[i][j]}H(--G)}H(--b);8 T},2w:l(){o(!7.1y()||7.2y()){8 w}9 a=7.4.q,15=a,i,j;9 M=7.2W(S.I(a)).1K();9 b,1n=M.4[0].q,p,1c,2v;9 c=[],2c;J{i=a-1;1c=[];b=1n;c[i]=[];2v=M.4[i][i];J{p=1n-b;2c=M.4[i][p]/2v;1c.19(2c);o(p>=15){c[i].19(2c)}}H(--b);M.4[i]=1c;2e(j=0;j3||b.4.q>3){8 w}9 c=b.1u();o(c===0){8 w}7.K=a;7.U=v.u([b.4[0]/c,b.4[1]/c,b.4[2]/c]);8 7}};14.u=l(a,b){9 L=25 14();8 L.1Z(a,b)};14.X=14.u(v.1j(3),v.i);14.Y=14.u(v.1j(3),v.j);14.Z=14.u(v.1j(3),v.k);l 11(){}11.23={24:l(a){8(7.1h(a.K)&&7.1m(a))},1q:l(){8 11.u(7.K,7.W)},2U:l(a){9 V=a.4||a;8 11.u([7.K.4[0]+V[0],7.K.4[1]+V[1],7.K.4[2]+(V[2]||0)],7.W)},1m:l(a){9 b;o(a.W){b=7.W.1C(a.W);8(F.13(b)<=17.16||F.13(F.1A-b)<=17.16)}1d o(a.U){8 7.W.2k(a.U)}8 w},2k:l(a){9 b=7.W.1C(a.W);8(F.13(F.1A/2-b)<=17.16)},1o:l(a){o(7.1v(a)||7.1h(a)){8 0}o(a.K){9 A=7.K.4,B=a.K.4,N=7.W.4;8 F.13((A[0]-B[0])*N[0]+(A[1]-B[1])*N[1]+(A[2]-B[2])*N[2])}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;8 F.13((A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2])}},1h:l(a){o(a.W){8 w}o(a.U){8(7.1h(a.K)&&7.1h(a.K.2j(a.U)))}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=F.13(N[0]*(A[0]-P[0])+N[1]*(A[1]-P[1])+N[2]*(A[2]-(P[2]||0)));8(b<=17.16)}},1v:l(a){o(1g(a.U)==\'1f\'&&1g(a.W)==\'1f\'){8 w}8!7.1m(a)},1U:l(a){o(!7.1v(a)){8 w}o(a.U){9 A=a.K.4,D=a.U.4,P=7.K.4,N=7.W.4;9 b=(N[0]*(P[0]-A[0])+N[1]*(P[1]-A[1])+N[2]*(P[2]-A[2]))/(N[0]*D[0]+N[1]*D[1]+N[2]*D[2]);8 v.u([A[0]+D[0]*b,A[1]+D[1]*b,A[2]+D[2]*b])}1d o(a.W){9 c=7.W.2f(a.W).2q();9 N=7.W.4,A=7.K.4,O=a.W.4,B=a.K.4;9 d=S.1j(2,2),i=0;H(d.2y()){i++;d=S.u([[N[i%3],N[(i+1)%3]],[O[i%3],O[(i+1)%3]]])}9 e=d.2w().4;9 x=N[0]*A[0]+N[1]*A[1]+N[2]*A[2];9 y=O[0]*B[0]+O[1]*B[1]+O[2]*B[2];9 f=[e[0][0]*x+e[0][1]*y,e[1][0]*x+e[1][1]*y];9 g=[];2e(9 j=1;j<=3;j++){g.19((i==j)?0:f[(j+(5-i)%3)%3])}8 14.u(g,c)}},1r:l(a){9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=(A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2];8 v.u([P[0]+N[0]*b,P[1]+N[1]*b,(P[2]||0)+N[2]*b])},1V:l(t,a){9 R=S.1R(t,a.U).4;9 C=a.1r(7.K).4;9 A=7.K.4,N=7.W.4;9 b=C[0],1E=C[1],1J=C[2],1w=A[0],18=A[1],1a=A[2];9 x=1w-b,y=18-1E,z=1a-1J;8 11.u([b+R[0][0]*x+R[0][1]*y+R[0][2]*z,1E+R[1][0]*x+R[1][1]*y+R[1][2]*z,1J+R[2][0]*x+R[2][1]*y+R[2][2]*z],[R[0][0]*N[0]+R[0][1]*N[1]+R[0][2]*N[2],R[1][0]*N[0]+R[1][1]*N[1]+R[1][2]*N[2],R[2][0]*N[0]+R[2][1]*N[1]+R[2][2]*N[2]])},1t:l(a){o(a.W){9 A=7.K.4,N=7.W.4;9 b=A[0],18=A[1],1a=A[2],2M=N[0],2L=N[1],2Q=N[2];9 c=7.K.1t(a).4;9 d=b+2M,2p=18+2L,2m=1a+2Q;9 Q=a.1r([d,2p,2m]).4;9 e=[Q[0]+(Q[0]-d)-c[0],Q[1]+(Q[1]-2p)-c[1],Q[2]+(Q[2]-2m)-c[2]];8 11.u(c,e)}1d o(a.U){8 7.1V(F.1A,a)}1d{9 P=a.4||a;8 11.u(7.K.1t([P[0],P[1],(P[2]||0)]),7.W)}},1Z:l(a,b,c){a=v.u(a);a=a.1N();o(a===w){8 w}b=v.u(b);b=b.1N();o(b===w){8 w}o(1g(c)==\'1f\'){c=w}1d{c=v.u(c);c=c.1N();o(c===w){8 w}}9 d=a.4[0],18=a.4[1],1a=a.4[2];9 e=b.4[0],1W=b.4[1],1X=b.4[2];9 f,1i;o(c!==w){9 g=c.4[0],2l=c.4[1],2t=c.4[2];f=v.u([(1W-18)*(2t-1a)-(1X-1a)*(2l-18),(1X-1a)*(g-d)-(e-d)*(2t-1a),(e-d)*(2l-18)-(1W-18)*(g-d)]);1i=f.1u();o(1i===0){8 w}f=v.u([f.4[0]/1i,f.4[1]/1i,f.4[2]/1i])}1d{1i=F.1x(e*e+1W*1W+1X*1X);o(1i===0){8 w}f=v.u([b.4[0]/1i,b.4[1]/1i,b.4[2]/1i])}7.K=a;7.W=f;8 7}};11.u=l(a,b,c){9 P=25 11();8 P.1Z(a,b,c)};11.2I=11.u(v.1j(3),v.k);11.2H=11.u(v.1j(3),v.i);11.2G=11.u(v.1j(3),v.j);11.36=11.2I;11.35=11.2H;11.3j=11.2G;9 $V=v.u;9 $M=S.u;9 $L=14.u;9 $P=11.u;',62,206,'||||elements|||this|return|var||||||||||||function|||if||length||||create|Vector|null|||||||||Math|nj|while||do|anchor||||||||Matrix||direction||normal||||kj|Plane|ni|abs|Line|ki|precision|Sylvester|A2|push|A3|map|els|else||undefined|typeof|contains|mod|Zero|D3|D2|isParallelTo|kp|distanceFrom|cols|dup|pointClosestTo|np|reflectionIn|modulus|intersects|A1|sqrt|isSquare|X2|PI|X3|angleFrom|mod1|C2|mod2|sin|cos|break|C3|toRightTriangular|false|Y3|to3D|E2|E1|E3|Rotation|Y2|Y1|intersectionWith|rotate|v12|v13|rank|setVectors|nc|sum|multiply|prototype|eql|new|setElements|case|each|PA3|PA2|part|new_element|round|for|cross|product|AD2|isSameSizeAs|add|isPerpendicularTo|v22|AN3|inspect|AD3|AN2|toUnitVector|PsubQ3|PsubQ2|v23|dot|divisor|inverse|true|isSingular|determinant|max|canMultiplyFromLeft|subtract|rows|col|random|ZX|YZ|XY|Random|join|N2|N1|D1|slice|default|N3|dimensions|switch|liesIn|translate|snapTo|augment|Diagonal|trace|indexOf|diagonal|transpose|minor|row|isAntiparallelTo|ZY|YX|acos|RotationZ|RotationY|liesOn|RotationX|inv|rk|tr|det|toDiagonalMatrix|toUpperTriangular|version|XZ'.split('|'),0,{})) -------------------------------------------------------------------------------- /js/controls/OrthographicTrackballControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Eberhard Graether / http://egraether.com/ 3 | * @author Patrick Fuller / http://patrick-fuller.com 4 | */ 5 | 6 | THREE.OrthographicTrackballControls = function ( object, domElement ) { 7 | 8 | var _this = this; 9 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 }; 10 | 11 | this.object = object; 12 | this.domElement = ( domElement !== undefined ) ? domElement : document; 13 | 14 | // API 15 | 16 | this.enabled = true; 17 | 18 | this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 }; 19 | this.radius = ( this.screen.width + this.screen.height ) / 4; 20 | 21 | this.rotateSpeed = 1.0; 22 | this.zoomSpeed = 1.2; 23 | this.panSpeed = 0.3; 24 | 25 | this.noRotate = false; 26 | this.noZoom = false; 27 | this.noPan = false; 28 | 29 | this.staticMoving = false; 30 | this.dynamicDampingFactor = 0.2; 31 | 32 | this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; 33 | 34 | // internals 35 | 36 | this.target = new THREE.Vector3(); 37 | 38 | var lastPosition = new THREE.Vector3(); 39 | 40 | var _state = STATE.NONE, 41 | _prevState = STATE.NONE, 42 | 43 | _eye = new THREE.Vector3(), 44 | 45 | _rotateStart = new THREE.Vector3(), 46 | _rotateEnd = new THREE.Vector3(), 47 | 48 | _zoomStart = new THREE.Vector2(), 49 | _zoomEnd = new THREE.Vector2(), 50 | _zoomFactor = 1, 51 | 52 | _touchZoomDistanceStart = 0, 53 | _touchZoomDistanceEnd = 0, 54 | 55 | _panStart = new THREE.Vector2(), 56 | _panEnd = new THREE.Vector2(); 57 | 58 | // for reset 59 | 60 | this.target0 = this.target.clone(); 61 | this.position0 = this.object.position.clone(); 62 | this.up0 = this.object.up.clone(); 63 | 64 | this.left0 = this.object.left; 65 | this.right0 = this.object.right; 66 | this.top0 = this.object.top; 67 | this.bottom0 = this.object.bottom; 68 | this.center0 = new THREE.Vector2((this.left0 + this.right0) / 2.0, (this.top0 + this.bottom0) / 2.0); 69 | 70 | // events 71 | 72 | var changeEvent = { type: 'change' }; 73 | 74 | 75 | // methods 76 | 77 | this.handleResize = function () { 78 | 79 | this.screen.width = window.innerWidth; 80 | this.screen.height = window.innerHeight; 81 | 82 | this.screen.offsetLeft = 0; 83 | this.screen.offsetTop = 0; 84 | 85 | this.radius = ( this.screen.width + this.screen.height ) / 4; 86 | 87 | }; 88 | 89 | this.handleEvent = function ( event ) { 90 | 91 | if ( typeof this[ event.type ] == 'function' ) { 92 | 93 | this[ event.type ]( event ); 94 | 95 | } 96 | 97 | }; 98 | 99 | this.getMouseOnScreen = function ( clientX, clientY ) { 100 | 101 | return new THREE.Vector2( 102 | ( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5, 103 | ( clientY - _this.screen.offsetTop ) / _this.radius * 0.5 104 | ); 105 | 106 | }; 107 | 108 | this.getMouseProjectionOnBall = function ( clientX, clientY ) { 109 | 110 | var mouseOnBall = new THREE.Vector3( 111 | ( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius, 112 | ( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius, 113 | 0.0 114 | ); 115 | 116 | var length = mouseOnBall.length(); 117 | 118 | if ( length > 1.0 ) { 119 | 120 | mouseOnBall.normalize(); 121 | 122 | } else { 123 | 124 | mouseOnBall.z = Math.sqrt( 1.0 - length * length ); 125 | 126 | } 127 | 128 | _eye.copy( _this.object.position ).sub( _this.target ); 129 | 130 | var projection = _this.object.up.clone().setLength( mouseOnBall.y ); 131 | projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) ); 132 | projection.add( _eye.setLength( mouseOnBall.z ) ); 133 | 134 | return projection; 135 | 136 | }; 137 | 138 | this.rotateCamera = function () { 139 | 140 | var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() ); 141 | 142 | if ( angle ) { 143 | 144 | var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(), 145 | quaternion = new THREE.Quaternion(); 146 | 147 | angle *= _this.rotateSpeed; 148 | 149 | quaternion.setFromAxisAngle( axis, -angle ); 150 | 151 | _eye.applyQuaternion( quaternion ); 152 | _this.object.up.applyQuaternion( quaternion ); 153 | 154 | _rotateEnd.applyQuaternion( quaternion ); 155 | 156 | if ( _this.staticMoving ) { 157 | 158 | _rotateStart.copy( _rotateEnd ); 159 | 160 | } else { 161 | 162 | quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) ); 163 | _rotateStart.applyQuaternion( quaternion ); 164 | 165 | } 166 | 167 | } 168 | 169 | }; 170 | 171 | this.zoomCamera = function () { 172 | 173 | if ( _state === STATE.TOUCH_ZOOM ) { 174 | 175 | var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; 176 | _touchZoomDistanceStart = _touchZoomDistanceEnd; 177 | _zoomFactor *= factor; 178 | 179 | _this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) * _this.center0.x; 180 | _this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) * _this.center0.x; 181 | _this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) * _this.center0.y; 182 | _this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) * _this.center0.y; 183 | 184 | } else { 185 | 186 | var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed; 187 | 188 | if ( factor !== 1.0 && factor > 0.0 ) { 189 | _zoomFactor *= factor; 190 | 191 | _this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) * _this.center0.x; 192 | _this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) * _this.center0.x; 193 | _this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) * _this.center0.y; 194 | _this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) * _this.center0.y; 195 | 196 | if ( _this.staticMoving ) { 197 | 198 | _zoomStart.copy( _zoomEnd ); 199 | 200 | } else { 201 | 202 | _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; 203 | 204 | } 205 | 206 | } 207 | 208 | } 209 | 210 | }; 211 | 212 | this.panCamera = function () { 213 | 214 | var mouseChange = _panEnd.clone().sub( _panStart ); 215 | 216 | if ( mouseChange.lengthSq() ) { 217 | 218 | mouseChange.multiplyScalar( _eye.length() * _this.panSpeed ); 219 | 220 | var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x ); 221 | pan.add( _this.object.up.clone().setLength( mouseChange.y ) ); 222 | 223 | _this.object.position.add( pan ); 224 | _this.target.add( pan ); 225 | 226 | if ( _this.staticMoving ) { 227 | 228 | _panStart = _panEnd; 229 | 230 | } else { 231 | 232 | _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) ); 233 | 234 | } 235 | 236 | } 237 | 238 | }; 239 | 240 | this.update = function () { 241 | 242 | _eye.subVectors( _this.object.position, _this.target ); 243 | 244 | if ( !_this.noRotate ) { 245 | 246 | _this.rotateCamera(); 247 | 248 | } 249 | 250 | if ( !_this.noZoom ) { 251 | 252 | _this.zoomCamera(); 253 | _this.object.updateProjectionMatrix(); 254 | 255 | } 256 | 257 | if ( !_this.noPan ) { 258 | 259 | _this.panCamera(); 260 | 261 | } 262 | 263 | _this.object.position.addVectors( _this.target, _eye ); 264 | 265 | _this.object.lookAt( _this.target ); 266 | 267 | if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) { 268 | 269 | _this.dispatchEvent( changeEvent ); 270 | 271 | lastPosition.copy( _this.object.position ); 272 | 273 | } 274 | 275 | }; 276 | 277 | this.reset = function () { 278 | 279 | _state = STATE.NONE; 280 | _prevState = STATE.NONE; 281 | 282 | _this.target.copy( _this.target0 ); 283 | _this.object.position.copy( _this.position0 ); 284 | _this.object.up.copy( _this.up0 ); 285 | 286 | _eye.subVectors( _this.object.position, _this.target ); 287 | 288 | _this.object.left = _this.left0; 289 | _this.object.right = _this.right0; 290 | _this.object.top = _this.top0; 291 | _this.object.bottom = _this.bottom0; 292 | 293 | _this.object.lookAt( _this.target ); 294 | 295 | _this.dispatchEvent( changeEvent ); 296 | 297 | lastPosition.copy( _this.object.position ); 298 | 299 | }; 300 | 301 | // listeners 302 | 303 | function keydown( event ) { 304 | 305 | if ( _this.enabled === false ) return; 306 | 307 | window.removeEventListener( 'keydown', keydown ); 308 | 309 | _prevState = _state; 310 | 311 | if ( _state !== STATE.NONE ) { 312 | 313 | return; 314 | 315 | } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) { 316 | 317 | _state = STATE.ROTATE; 318 | 319 | } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) { 320 | 321 | _state = STATE.ZOOM; 322 | 323 | } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) { 324 | 325 | _state = STATE.PAN; 326 | 327 | } 328 | 329 | } 330 | 331 | function keyup( event ) { 332 | 333 | if ( _this.enabled === false ) return; 334 | 335 | _state = _prevState; 336 | 337 | window.addEventListener( 'keydown', keydown, false ); 338 | 339 | } 340 | 341 | function mousedown( event ) { 342 | 343 | if ( _this.enabled === false ) return; 344 | 345 | event.preventDefault(); 346 | event.stopPropagation(); 347 | 348 | if ( _state === STATE.NONE ) { 349 | 350 | _state = event.button; 351 | 352 | } 353 | 354 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 355 | 356 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY ); 357 | 358 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 359 | 360 | _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 361 | 362 | } else if ( _state === STATE.PAN && !_this.noPan ) { 363 | 364 | _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 365 | 366 | } 367 | 368 | document.addEventListener( 'mousemove', mousemove, false ); 369 | document.addEventListener( 'mouseup', mouseup, false ); 370 | 371 | } 372 | 373 | function mousemove( event ) { 374 | 375 | if ( _this.enabled === false ) return; 376 | 377 | event.preventDefault(); 378 | event.stopPropagation(); 379 | 380 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 381 | 382 | _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY ); 383 | 384 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 385 | 386 | _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 387 | 388 | } else if ( _state === STATE.PAN && !_this.noPan ) { 389 | 390 | _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 391 | 392 | } 393 | 394 | } 395 | 396 | function mouseup( event ) { 397 | 398 | if ( _this.enabled === false ) return; 399 | 400 | event.preventDefault(); 401 | event.stopPropagation(); 402 | 403 | _state = STATE.NONE; 404 | 405 | document.removeEventListener( 'mousemove', mousemove ); 406 | document.removeEventListener( 'mouseup', mouseup ); 407 | 408 | } 409 | 410 | function mousewheel( event ) { 411 | 412 | if ( _this.enabled === false ) return; 413 | 414 | event.preventDefault(); 415 | event.stopPropagation(); 416 | 417 | var delta = 0; 418 | 419 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 420 | 421 | delta = event.wheelDelta / 40; 422 | 423 | } else if ( event.detail ) { // Firefox 424 | 425 | delta = - event.detail / 3; 426 | 427 | } 428 | 429 | _zoomStart.y += delta * 0.01; 430 | 431 | } 432 | 433 | function touchstart( event ) { 434 | 435 | if ( _this.enabled === false ) return; 436 | 437 | switch ( event.touches.length ) { 438 | 439 | case 1: 440 | _state = STATE.TOUCH_ROTATE; 441 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 442 | break; 443 | 444 | case 2: 445 | _state = STATE.TOUCH_ZOOM; 446 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 447 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 448 | _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); 449 | break; 450 | 451 | case 3: 452 | _state = STATE.TOUCH_PAN; 453 | _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 454 | break; 455 | 456 | default: 457 | _state = STATE.NONE; 458 | 459 | } 460 | 461 | } 462 | 463 | function touchmove( event ) { 464 | 465 | if ( _this.enabled === false ) return; 466 | 467 | event.preventDefault(); 468 | event.stopPropagation(); 469 | 470 | switch ( event.touches.length ) { 471 | 472 | case 1: 473 | _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 474 | break; 475 | 476 | case 2: 477 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 478 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 479 | _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ) 480 | break; 481 | 482 | case 3: 483 | _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 484 | break; 485 | 486 | default: 487 | _state = STATE.NONE; 488 | 489 | } 490 | 491 | } 492 | 493 | function touchend( event ) { 494 | 495 | if ( _this.enabled === false ) return; 496 | 497 | switch ( event.touches.length ) { 498 | 499 | case 1: 500 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 501 | break; 502 | 503 | case 2: 504 | _touchZoomDistanceStart = _touchZoomDistanceEnd = 0; 505 | break; 506 | 507 | case 3: 508 | _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 509 | break; 510 | 511 | } 512 | 513 | _state = STATE.NONE; 514 | 515 | } 516 | 517 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 518 | 519 | this.domElement.addEventListener( 'mousedown', mousedown, false ); 520 | 521 | this.domElement.addEventListener( 'mousewheel', mousewheel, false ); 522 | this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox 523 | 524 | this.domElement.addEventListener( 'touchstart', touchstart, false ); 525 | this.domElement.addEventListener( 'touchend', touchend, false ); 526 | this.domElement.addEventListener( 'touchmove', touchmove, false ); 527 | 528 | window.addEventListener( 'keydown', keydown, false ); 529 | window.addEventListener( 'keyup', keyup, false ); 530 | 531 | this.handleResize(); 532 | 533 | }; 534 | 535 | THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 536 | -------------------------------------------------------------------------------- /js/controls/TrackballControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Eberhard Graether / http://egraether.com/ 3 | * @author Mark Lundin / http://mark-lundin.com 4 | */ 5 | 6 | THREE.TrackballControls = function ( object, domElement ) { 7 | 8 | var _this = this; 9 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 }; 10 | 11 | this.object = object; 12 | this.domElement = ( domElement !== undefined ) ? domElement : document; 13 | 14 | // API 15 | 16 | this.enabled = true; 17 | 18 | this.screen = { left: 0, top: 0, width: 0, height: 0 }; 19 | 20 | this.rotateSpeed = 1.0; 21 | this.zoomSpeed = 1.2; 22 | this.panSpeed = 0.3; 23 | 24 | this.noRotate = false; 25 | this.noZoom = false; 26 | this.noPan = false; 27 | this.noRoll = false; 28 | 29 | this.staticMoving = false; 30 | this.dynamicDampingFactor = 0.2; 31 | 32 | this.minDistance = 0; 33 | this.maxDistance = Infinity; 34 | 35 | this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; 36 | 37 | // internals 38 | 39 | this.target = new THREE.Vector3(); 40 | 41 | var EPS = 0.000001; 42 | 43 | var lastPosition = new THREE.Vector3(); 44 | 45 | var _state = STATE.NONE, 46 | _prevState = STATE.NONE, 47 | 48 | _eye = new THREE.Vector3(), 49 | 50 | _rotateStart = new THREE.Vector3(), 51 | _rotateEnd = new THREE.Vector3(), 52 | 53 | _zoomStart = new THREE.Vector2(), 54 | _zoomEnd = new THREE.Vector2(), 55 | 56 | _touchZoomDistanceStart = 0, 57 | _touchZoomDistanceEnd = 0, 58 | 59 | _panStart = new THREE.Vector2(), 60 | _panEnd = new THREE.Vector2(); 61 | 62 | // for reset 63 | 64 | this.target0 = this.target.clone(); 65 | this.position0 = this.object.position.clone(); 66 | this.up0 = this.object.up.clone(); 67 | 68 | // events 69 | 70 | var changeEvent = { type: 'change' }; 71 | var startEvent = { type: 'start'}; 72 | var endEvent = { type: 'end'}; 73 | 74 | 75 | // methods 76 | 77 | this.handleResize = function () { 78 | 79 | if ( this.domElement === document ) { 80 | 81 | this.screen.left = 0; 82 | this.screen.top = 0; 83 | this.screen.width = window.innerWidth; 84 | this.screen.height = window.innerHeight; 85 | 86 | } else { 87 | 88 | var box = this.domElement.getBoundingClientRect(); 89 | // adjustments come from similar code in the jquery offset() function 90 | var d = this.domElement.ownerDocument.documentElement; 91 | this.screen.left = box.left + window.pageXOffset - d.clientLeft; 92 | this.screen.top = box.top + window.pageYOffset - d.clientTop; 93 | this.screen.width = box.width; 94 | this.screen.height = box.height; 95 | 96 | } 97 | 98 | }; 99 | 100 | this.handleEvent = function ( event ) { 101 | 102 | if ( typeof this[ event.type ] == 'function' ) { 103 | 104 | this[ event.type ]( event ); 105 | 106 | } 107 | 108 | }; 109 | 110 | var getMouseOnScreen = ( function () { 111 | 112 | var vector = new THREE.Vector2(); 113 | 114 | return function ( pageX, pageY ) { 115 | 116 | vector.set( 117 | ( pageX - _this.screen.left ) / _this.screen.width, 118 | ( pageY - _this.screen.top ) / _this.screen.height 119 | ); 120 | 121 | return vector; 122 | 123 | }; 124 | 125 | }() ); 126 | 127 | var getMouseProjectionOnBall = ( function () { 128 | 129 | var vector = new THREE.Vector3(); 130 | var objectUp = new THREE.Vector3(); 131 | var mouseOnBall = new THREE.Vector3(); 132 | 133 | return function ( pageX, pageY ) { 134 | 135 | mouseOnBall.set( 136 | ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5), 137 | ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5), 138 | 0.0 139 | ); 140 | 141 | var length = mouseOnBall.length(); 142 | 143 | if ( _this.noRoll ) { 144 | 145 | if ( length < Math.SQRT1_2 ) { 146 | 147 | mouseOnBall.z = Math.sqrt( 1.0 - length*length ); 148 | 149 | } else { 150 | 151 | mouseOnBall.z = .5 / length; 152 | 153 | } 154 | 155 | } else if ( length > 1.0 ) { 156 | 157 | mouseOnBall.normalize(); 158 | 159 | } else { 160 | 161 | mouseOnBall.z = Math.sqrt( 1.0 - length * length ); 162 | 163 | } 164 | 165 | _eye.copy( _this.object.position ).sub( _this.target ); 166 | 167 | vector.copy( _this.object.up ).setLength( mouseOnBall.y ) 168 | vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) ); 169 | vector.add( _eye.setLength( mouseOnBall.z ) ); 170 | 171 | return vector; 172 | 173 | }; 174 | 175 | }() ); 176 | 177 | this.rotateCamera = (function(){ 178 | 179 | var axis = new THREE.Vector3(), 180 | quaternion = new THREE.Quaternion(); 181 | 182 | 183 | return function () { 184 | 185 | var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() ); 186 | 187 | if ( angle ) { 188 | 189 | axis.crossVectors( _rotateStart, _rotateEnd ).normalize(); 190 | 191 | angle *= _this.rotateSpeed; 192 | 193 | quaternion.setFromAxisAngle( axis, -angle ); 194 | 195 | _eye.applyQuaternion( quaternion ); 196 | _this.object.up.applyQuaternion( quaternion ); 197 | 198 | _rotateEnd.applyQuaternion( quaternion ); 199 | 200 | if ( _this.staticMoving ) { 201 | 202 | _rotateStart.copy( _rotateEnd ); 203 | 204 | } else { 205 | 206 | quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) ); 207 | _rotateStart.applyQuaternion( quaternion ); 208 | 209 | } 210 | 211 | } 212 | } 213 | 214 | }()); 215 | 216 | this.zoomCamera = function () { 217 | 218 | if ( _state === STATE.TOUCH_ZOOM_PAN ) { 219 | 220 | var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; 221 | _touchZoomDistanceStart = _touchZoomDistanceEnd; 222 | _eye.multiplyScalar( factor ); 223 | 224 | } else { 225 | 226 | var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed; 227 | 228 | if ( factor !== 1.0 && factor > 0.0 ) { 229 | 230 | _eye.multiplyScalar( factor ); 231 | 232 | if ( _this.staticMoving ) { 233 | 234 | _zoomStart.copy( _zoomEnd ); 235 | 236 | } else { 237 | 238 | _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; 239 | 240 | } 241 | 242 | } 243 | 244 | } 245 | 246 | }; 247 | 248 | this.panCamera = (function(){ 249 | 250 | var mouseChange = new THREE.Vector2(), 251 | objectUp = new THREE.Vector3(), 252 | pan = new THREE.Vector3(); 253 | 254 | return function () { 255 | 256 | mouseChange.copy( _panEnd ).sub( _panStart ); 257 | 258 | if ( mouseChange.lengthSq() ) { 259 | 260 | mouseChange.multiplyScalar( _eye.length() * _this.panSpeed ); 261 | 262 | pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x ); 263 | pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) ); 264 | 265 | _this.object.position.add( pan ); 266 | _this.target.add( pan ); 267 | 268 | if ( _this.staticMoving ) { 269 | 270 | _panStart.copy( _panEnd ); 271 | 272 | } else { 273 | 274 | _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) ); 275 | 276 | } 277 | 278 | } 279 | } 280 | 281 | }()); 282 | 283 | this.checkDistances = function () { 284 | 285 | if ( !_this.noZoom || !_this.noPan ) { 286 | 287 | if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) { 288 | 289 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) ); 290 | 291 | } 292 | 293 | if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) { 294 | 295 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) ); 296 | 297 | } 298 | 299 | } 300 | 301 | }; 302 | 303 | this.update = function () { 304 | 305 | _eye.subVectors( _this.object.position, _this.target ); 306 | 307 | if ( !_this.noRotate ) { 308 | 309 | _this.rotateCamera(); 310 | 311 | } 312 | 313 | if ( !_this.noZoom ) { 314 | 315 | _this.zoomCamera(); 316 | 317 | } 318 | 319 | if ( !_this.noPan ) { 320 | 321 | _this.panCamera(); 322 | 323 | } 324 | 325 | _this.object.position.addVectors( _this.target, _eye ); 326 | 327 | _this.checkDistances(); 328 | 329 | _this.object.lookAt( _this.target ); 330 | 331 | if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) { 332 | 333 | _this.dispatchEvent( changeEvent ); 334 | 335 | lastPosition.copy( _this.object.position ); 336 | 337 | } 338 | 339 | }; 340 | 341 | this.reset = function () { 342 | 343 | _state = STATE.NONE; 344 | _prevState = STATE.NONE; 345 | 346 | _this.target.copy( _this.target0 ); 347 | _this.object.position.copy( _this.position0 ); 348 | _this.object.up.copy( _this.up0 ); 349 | 350 | _eye.subVectors( _this.object.position, _this.target ); 351 | 352 | _this.object.lookAt( _this.target ); 353 | 354 | _this.dispatchEvent( changeEvent ); 355 | 356 | lastPosition.copy( _this.object.position ); 357 | 358 | }; 359 | 360 | // listeners 361 | 362 | function keydown( event ) { 363 | 364 | if ( _this.enabled === false ) return; 365 | 366 | window.removeEventListener( 'keydown', keydown ); 367 | 368 | _prevState = _state; 369 | 370 | if ( _state !== STATE.NONE ) { 371 | 372 | return; 373 | 374 | } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) { 375 | 376 | _state = STATE.ROTATE; 377 | 378 | } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) { 379 | 380 | _state = STATE.ZOOM; 381 | 382 | } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) { 383 | 384 | _state = STATE.PAN; 385 | 386 | } 387 | 388 | } 389 | 390 | function keyup( event ) { 391 | 392 | if ( _this.enabled === false ) return; 393 | 394 | _state = _prevState; 395 | 396 | window.addEventListener( 'keydown', keydown, false ); 397 | 398 | } 399 | 400 | function mousedown( event ) { 401 | 402 | if ( _this.enabled === false ) return; 403 | 404 | event.preventDefault(); 405 | event.stopPropagation(); 406 | 407 | if ( _state === STATE.NONE ) { 408 | 409 | _state = event.button; 410 | 411 | } 412 | 413 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 414 | 415 | _rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) ); 416 | _rotateEnd.copy( _rotateStart ); 417 | 418 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 419 | 420 | _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 421 | _zoomEnd.copy(_zoomStart); 422 | 423 | } else if ( _state === STATE.PAN && !_this.noPan ) { 424 | 425 | _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 426 | _panEnd.copy(_panStart) 427 | 428 | } 429 | 430 | document.addEventListener( 'mousemove', mousemove, false ); 431 | document.addEventListener( 'mouseup', mouseup, false ); 432 | 433 | _this.dispatchEvent( startEvent ); 434 | 435 | } 436 | 437 | function mousemove( event ) { 438 | 439 | if ( _this.enabled === false ) return; 440 | 441 | event.preventDefault(); 442 | event.stopPropagation(); 443 | 444 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 445 | 446 | _rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) ); 447 | 448 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 449 | 450 | _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 451 | 452 | } else if ( _state === STATE.PAN && !_this.noPan ) { 453 | 454 | _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); 455 | 456 | } 457 | 458 | } 459 | 460 | function mouseup( event ) { 461 | 462 | if ( _this.enabled === false ) return; 463 | 464 | event.preventDefault(); 465 | event.stopPropagation(); 466 | 467 | _state = STATE.NONE; 468 | 469 | document.removeEventListener( 'mousemove', mousemove ); 470 | document.removeEventListener( 'mouseup', mouseup ); 471 | _this.dispatchEvent( endEvent ); 472 | 473 | } 474 | 475 | function mousewheel( event ) { 476 | 477 | if ( _this.enabled === false ) return; 478 | 479 | event.preventDefault(); 480 | event.stopPropagation(); 481 | 482 | var delta = 0; 483 | 484 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 485 | 486 | delta = event.wheelDelta / 40; 487 | 488 | } else if ( event.detail ) { // Firefox 489 | 490 | delta = - event.detail / 3; 491 | 492 | } 493 | 494 | _zoomStart.y += delta * 0.01; 495 | _this.dispatchEvent( startEvent ); 496 | _this.dispatchEvent( endEvent ); 497 | 498 | } 499 | 500 | function touchstart( event ) { 501 | 502 | if ( _this.enabled === false ) return; 503 | 504 | switch ( event.touches.length ) { 505 | 506 | case 1: 507 | _state = STATE.TOUCH_ROTATE; 508 | _rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 509 | _rotateEnd.copy( _rotateStart ); 510 | break; 511 | 512 | case 2: 513 | _state = STATE.TOUCH_ZOOM_PAN; 514 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 515 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 516 | _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); 517 | 518 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; 519 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; 520 | _panStart.copy( getMouseOnScreen( x, y ) ); 521 | _panEnd.copy( _panStart ); 522 | break; 523 | 524 | default: 525 | _state = STATE.NONE; 526 | 527 | } 528 | _this.dispatchEvent( startEvent ); 529 | 530 | 531 | } 532 | 533 | function touchmove( event ) { 534 | 535 | if ( _this.enabled === false ) return; 536 | 537 | event.preventDefault(); 538 | event.stopPropagation(); 539 | 540 | switch ( event.touches.length ) { 541 | 542 | case 1: 543 | _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 544 | break; 545 | 546 | case 2: 547 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 548 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 549 | _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ); 550 | 551 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; 552 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; 553 | _panEnd.copy( getMouseOnScreen( x, y ) ); 554 | break; 555 | 556 | default: 557 | _state = STATE.NONE; 558 | 559 | } 560 | 561 | } 562 | 563 | function touchend( event ) { 564 | 565 | if ( _this.enabled === false ) return; 566 | 567 | switch ( event.touches.length ) { 568 | 569 | case 1: 570 | _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); 571 | _rotateStart.copy( _rotateEnd ); 572 | break; 573 | 574 | case 2: 575 | _touchZoomDistanceStart = _touchZoomDistanceEnd = 0; 576 | 577 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; 578 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; 579 | _panEnd.copy( getMouseOnScreen( x, y ) ); 580 | _panStart.copy( _panEnd ); 581 | break; 582 | 583 | } 584 | 585 | _state = STATE.NONE; 586 | _this.dispatchEvent( endEvent ); 587 | 588 | } 589 | 590 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 591 | 592 | this.domElement.addEventListener( 'mousedown', mousedown, false ); 593 | 594 | this.domElement.addEventListener( 'mousewheel', mousewheel, false ); 595 | this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox 596 | 597 | this.domElement.addEventListener( 'touchstart', touchstart, false ); 598 | this.domElement.addEventListener( 'touchend', touchend, false ); 599 | this.domElement.addEventListener( 'touchmove', touchmove, false ); 600 | 601 | window.addEventListener( 'keydown', keydown, false ); 602 | window.addEventListener( 'keyup', keyup, false ); 603 | 604 | this.handleResize(); 605 | 606 | // force an update at start 607 | this.update(); 608 | 609 | }; 610 | 611 | THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 612 | --------------------------------------------------------------------------------