' +
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 | '
';
71 | $.each(this.opts.dropdownValues, function(i, size) {
72 | tpl += DrawingBoard.Utils.tpl(
73 | ' ',
74 | { size: size }
75 | );
76 | });
77 | tpl += '
';
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 |
--------------------------------------------------------------------------------