├── .gitignore ├── README.md ├── css └── styles.css ├── img ├── ash_uvgrid01.jpg ├── noWebGL.png └── water.jpg ├── index.html ├── js ├── LilyPad3D.js ├── Main.js ├── Params.js ├── extra.js └── modernizr.custom.31336.js └── vendor ├── RequestAnimationFrame.js ├── Stats.js ├── dat.gui.min.js ├── jquery-1.6.1.min.js ├── jquery-1.7.1.min.js ├── jquery.easing.1.3.js ├── jstween-1.0.min.js ├── perlin-noise-classical.js ├── perlin-noise-simplex.js ├── three ├── Three.js ├── controls │ ├── EditorControls.js │ ├── FirstPersonControls.js │ ├── FlyControls.js │ ├── OrbitControls.js │ ├── PathControls.js │ ├── PointerLockControls.js │ └── TrackballControls.js ├── custom │ ├── ThreeCanvas.js │ ├── ThreeDOM.js │ ├── ThreeExtras.js │ ├── ThreeSVG.js │ └── ThreeWebGL.js └── three.min.js ├── toxi ├── toxi-color.js ├── toxi-core.js ├── toxi-physics2d.js ├── toxiclibs.js └── uncompressed │ ├── toxi-color-debug.js │ ├── toxi-core-debug.js │ ├── toxi-physics2d-debug.js │ └── toxiclibs-debug.js └── un ├── BoilerPlate.js ├── Trace.js ├── Unctrl.js └── Utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .project 3 | .psd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Lilypad 2 | ======== 3 | 4 | Lily pad is an experiment that explores paper folding inspired by the form of a lily pad floating on top of water. 5 | -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #050505 ; 3 | margin: 0; 4 | padding: 0; 5 | overflow: hidden; 6 | } 7 | 8 | 9 | #notification { 10 | position:absolute; 11 | bottom: 10px; 12 | left: 10px; 13 | padding: 10px 15px 10px 15px; 14 | background: #001122; 15 | font-family: arial, helvetica, sans-serif; 16 | color:#61757f; 17 | font-size:0.8em; 18 | line-height: 1.6em; 19 | text-align:left; 20 | } 21 | 22 | #notification a:hover, #notification a:link, #notification a:visited{ 23 | color:#c3dbdf; 24 | text-decoration: none; 25 | 26 | } 27 | 28 | 29 | #loader { 30 | position:absolute; 31 | font-family:Arial,Helvetica, sans-serif; 32 | font-size:1.0em; 33 | text-align:center; 34 | background-color: #050505; 35 | opacity:.75; 36 | width:100%; 37 | height:100%; 38 | color:#FFF; 39 | display:none; 40 | } 41 | 42 | #noWebGL{ 43 | position: absolute; 44 | bottom: 0px; 45 | left: 0px; 46 | } 47 | 48 | #container3D { 49 | position: absolute; 50 | } 51 | 52 | #guiContainer { 53 | position:absolute; 54 | background-color: #111; 55 | right:-15px; 56 | height:100%; 57 | } 58 | #about { 59 | font: 12px 'Lucida Grande', sans-serif; 60 | position:absolute; 61 | color:#999; 62 | width:230px; 63 | height:48px; 64 | padding: 10px; 65 | right:0px; 66 | } 67 | #about a { 68 | color:#E61D5F; 69 | text-decoration: none; 70 | } 71 | 72 | .close-button{ 73 | display:none; 74 | } 75 | .dg.main{ 76 | margin-top:70px; 77 | } -------------------------------------------------------------------------------- /img/ash_uvgrid01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mannytan/lilypad/4054a404a1690de91e6d0d8596dff5a5370c752c/img/ash_uvgrid01.jpg -------------------------------------------------------------------------------- /img/noWebGL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mannytan/lilypad/4054a404a1690de91e6d0d8596dff5a5370c752c/img/noWebGL.png -------------------------------------------------------------------------------- /img/water.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mannytan/lilypad/4054a404a1690de91e6d0d8596dff5a5370c752c/img/water.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | uncontrol :: lilyPad 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 51 | 52 | 53 | 54 | 55 | 56 |
57 |
58 |
Lilypad is an experiment that uses paper folding methods as texture.
uncontrol.com
59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /js/LilyPad3D.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by unctrl.com 3 | * User: mannytan 4 | * Date: 8/22/11 5 | */ 6 | 7 | 8 | LILYPAD.LilyPad3D = function(name) { 9 | var scope = this; 10 | 11 | UNCTRL.BoilerPlate.call(this); 12 | 13 | this.name = 'LilyPad3D'; 14 | 15 | // 3d vars 16 | this.container = null; 17 | this.projector = null; 18 | this.camera = null; 19 | this.scene = null; 20 | this.raycaster = null; 21 | this.intersected = null; 22 | this.controls = null; 23 | this.cube = null; 24 | 25 | this.stageWidth = 0; 26 | this.stageHeight = 0; 27 | this.stageOffsetX = 0; 28 | this.stageOffsetY = 0; 29 | 30 | this.count = 0; 31 | this.centerCount = 0; 32 | 33 | this.pointLightA = null; 34 | 35 | this.customPlanes = null; 36 | this.customWirePlanes = null; 37 | this.water = null; 38 | this.ground = null; 39 | 40 | this.particles = null; 41 | 42 | this.totalPlanesH = getUrlVars()["totalWidth"] ? getUrlVars()["totalWidth"] : 28; 43 | this.totalPlanesV = getUrlVars()["totalDepth"] ? getUrlVars()["totalDepth"] : 12; 44 | this.totalVerticesH = this.totalPlanesH*2 + 1; 45 | this.totalVerticesV = this.totalPlanesV*2 + 1; 46 | this.totalVertices = this.totalVerticesH * this.totalVerticesV; 47 | 48 | this.maxHeightCache = null; 49 | this.maxHeightCacheSize = 20; 50 | 51 | this.colorOffset = .5; 52 | 53 | this.haloLine = null; 54 | 55 | this.halo = null; 56 | this.haloDot = null; 57 | 58 | // --------------------------------------------------------- 59 | // instantiation 60 | // --------------------------------------------------------- 61 | 62 | this.init = function() { 63 | this.traceFunction("init"); 64 | 65 | // this.perlin = new ClassicalNoise(); 66 | this.perlin = new SimplexNoise(); 67 | return this; 68 | }; 69 | 70 | this.createEnvironment = function() { 71 | // this.traceFunction("createEnvironment"); 72 | 73 | this.projector = new THREE.Projector(); // used for mouse position in 3d space 74 | this.scene = new THREE.Scene(); 75 | this.base = new THREE.Object3D(); 76 | this.scene.add(this.base); 77 | 78 | this.camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 3000 ); 79 | this.camera.position.x = 0; 80 | this.camera.position.y = 300; 81 | this.camera.position.z = 400; 82 | 83 | this.controls = new THREE.TrackballControls( this.camera, document.getElementById('container3D')); 84 | this.controls.rotateSpeed = 1.0; 85 | this.controls.zoomSpeed = 1.2; 86 | this.controls.panSpeed = 0.8; 87 | this.controls.noZoom = false; 88 | this.controls.noPan = false; 89 | this.controls.staticMoving = true; 90 | this.controls.dynamicDampingFactor = 0.3; 91 | this.controls.keys = [ 65, 83, 68 ]; 92 | 93 | this.renderer = new THREE.WebGLRenderer({ 94 | antialias: true 95 | }); 96 | 97 | this.renderer.setClearColor(0xEEEEEE, 1); 98 | this.renderer.setSize(this.stageWidth, this.stageHeight); 99 | 100 | this.renderer.gammaInput = true; 101 | this.renderer.gammaOutput = true; 102 | this.renderer.physicallyBasedShading = true; 103 | 104 | this.renderer.shadowMapEnabled = true; 105 | this.renderer.shadowMapCullFace = THREE.CullFaceBack; 106 | 107 | this.container = document.getElementById('container3D'); 108 | this.container.appendChild(this.renderer.domElement); 109 | 110 | return this; 111 | }; 112 | 113 | this.createLights = function() { 114 | 115 | this.scene.add( new THREE.AmbientLight( 0xCCCCCC ) ); 116 | 117 | var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.6 ); 118 | hemiLight.color.setHSL( 0.6, 1, 0.6 ); 119 | hemiLight.groundColor.setHSL( 0.095, 1, 0.75 ); 120 | hemiLight.position.set( 0, 300, 0 ); 121 | this.scene.add( hemiLight ); 122 | 123 | this.dirLight = new THREE.DirectionalLight( 0xffffff, 1 ); 124 | // this.dirLight.color.setHSL( 0.1, 1, 0.95 ); 125 | this.dirLight.position.set( -2.5, 2.5, 2.5 ); 126 | this.dirLight.position.multiplyScalar( 100 ); 127 | this.scene.add( this.dirLight ); 128 | 129 | this.dirLight.castShadow = true; 130 | this.dirLight.shadowMapWidth = 3500; 131 | this.dirLight.shadowMapHeight = 3500; 132 | 133 | var d = 800; 134 | 135 | this.dirLight.shadowCameraLeft = -d; 136 | this.dirLight.shadowCameraRight = d; 137 | this.dirLight.shadowCameraTop = d; 138 | this.dirLight.shadowCameraBottom = -d; 139 | 140 | this.dirLight.shadowCameraFar = 3500; 141 | this.dirLight.shadowBias = -0.0001; 142 | this.dirLight.shadowDarkness = 0.35; 143 | // this.dirLight.shadowCameraVisible = true; 144 | 145 | return this; 146 | }; 147 | 148 | this.createListeners = function() { 149 | this.container.addEventListener('mousedown', function(event) { 150 | scope.onDocumentMouseDown(event); 151 | }, false); 152 | 153 | return this; 154 | }; 155 | 156 | this.createPrimaryElements = function() { 157 | 158 | var i,j,k,id, 159 | particle, 160 | faceNormal, 161 | geometry, 162 | material; 163 | 164 | var percentage; 165 | 166 | // backbone dots 167 | material = new THREE.ParticleBasicMaterial( { color: 0xFFFFFF, size: 1} ); 168 | geometry = new THREE.Geometry(); 169 | for(i = 0; i < this.totalVertices; i++) { 170 | geometry.vertices.push(new THREE.Vector3()); 171 | } 172 | 173 | this.particles = new THREE.ParticleSystem( geometry, material ); 174 | this.base.add(this.particles); 175 | this.particles.visible = false; 176 | 177 | var colorSpeed = LILYPAD.Params.colorSpeed; 178 | var colorRange = LILYPAD.Params.colorRange; 179 | 180 | this.customPlanes = []; 181 | for(i = 0; i < this.totalPlanesV; i++) { 182 | geometry = this.getCustomGeometry(this.totalPlanesH, i, i*30, 30); 183 | // main plane 184 | material = new THREE.MeshLambertMaterial( { 185 | ambient: 0x000000, 186 | color: new THREE.Color().setHSL( (i/this.totalPlanesV*colorRange + colorSpeed)%1 , 1, .5), 187 | specular: 0x336699, 188 | shininess: 30, 189 | shading: THREE.SmoothShading, 190 | side:THREE.DoubleSide 191 | }); 192 | 193 | customPlane = new THREE.Mesh( geometry, material ); 194 | customPlane.castShadow = true; 195 | customPlane.receiveShadow = true; 196 | this.base.add(customPlane); 197 | this.customPlanes.push(customPlane); 198 | } 199 | 200 | var cache = []; 201 | for(i = 0; i < this.maxHeightCacheSize; i++) { 202 | cache.push(0); 203 | }; 204 | this.maxHeightCache = []; 205 | var id = 0; 206 | for(j = 0; j < this.totalVerticesV; j++) { 207 | for(i = 0; i < this.totalVerticesH; i++) { 208 | this.maxHeightCache.push(cache.slice()); 209 | id++; 210 | } 211 | } 212 | 213 | return this; 214 | }; 215 | 216 | this.createSecondaryElements = function() { 217 | 218 | var width = 1000; 219 | var height = 600; 220 | var depth = 1000; 221 | 222 | var colorSpeed = LILYPAD.Params.colorSpeed; 223 | var colorRange = LILYPAD.Params.colorRange; 224 | var geometry, 225 | material; 226 | 227 | // water 228 | material = new THREE.MeshPhongMaterial( { 229 | ambient: 0x333333, 230 | color: 0xFFFFFF, 231 | side:THREE.DoubleSide, 232 | transparent: true, 233 | opacity: .9, 234 | specular: 0x050505}); 235 | geometry = new THREE.PlaneGeometry( width*10, depth*10 ,100,100); 236 | 237 | this.water = new THREE.Mesh( geometry, material ); 238 | this.water.rotation.x = -Math.PI/2; 239 | this.water.position.y = -100; 240 | this.water.receiveShadow = true; 241 | this.base.add( this.water ); 242 | 243 | // ground 244 | material = new THREE.MeshPhongMaterial( { 245 | ambient: 0x333333, 246 | color: 0xFFFFFF, 247 | side:THREE.DoubleSide, 248 | transparent: true, 249 | opacity: .9, 250 | specular: 0x050505}); 251 | geometry = new THREE.PlaneGeometry( width*10, depth*10 ); 252 | 253 | this.ground = new THREE.Mesh( geometry, material ); 254 | this.ground.rotation.x = -Math.PI/2; 255 | this.ground.position.y = -height*0.5; 256 | this.ground.receiveShadow = true; 257 | this.base.add( this.ground ); 258 | 259 | // wireframe plane 260 | material = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe:true, transparent:true, opacity:0.05 } ) 261 | material.side = THREE.DoubleSide; 262 | this.customWirePlanes = []; 263 | for(i = 0; i < this.totalPlanesV; i++) { 264 | geometry = this.getCustomGeometry(this.totalPlanesH, i, i*30, 30); 265 | customPlane = new THREE.Mesh( geometry, material ); 266 | this.base.add(customPlane); 267 | customPlane.visible = false; 268 | this.customWirePlanes.push(customPlane); 269 | } 270 | 271 | // draw halo 272 | material = new THREE.LineBasicMaterial({ color: 0xFFFFFF, wireframe:true, linewidth:.5 }); 273 | geometry = new THREE.Geometry(); 274 | geometry.vertices.push(new THREE.Vector3(), new THREE.Vector3()); 275 | this.haloLine = new THREE.Line(geometry, material); 276 | this.haloLine.type = THREE.Lines; 277 | this.base.add(this.haloLine); 278 | 279 | material = new THREE.LineBasicMaterial({ color: 0xFFFFFF, wireframe:true, linewidth:.5}); 280 | geometry = new THREE.Geometry(); 281 | for(i = 0; i < this.totalVerticesH; i++) { 282 | geometry.vertices.push(new THREE.Vector3(Math.random()*100-50, Math.random()*100-50, Math.random()*100-50 )); 283 | } 284 | this.halo = new THREE.Line( geometry, material ); 285 | this.halo.type = THREE.LineStrip; 286 | this.base.add(this.halo); 287 | 288 | // draw sphere 289 | geometry = new THREE.SphereGeometry( 1, 5, 5 ); 290 | material = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe:true, linewidth:.5 } ) 291 | 292 | this.haloDot = new THREE.Mesh( geometry, material ); 293 | this.base.add(this.haloDot); 294 | 295 | return this; 296 | }; 297 | 298 | 299 | // --------------------------------------------------------- 300 | // utility 301 | // --------------------------------------------------------- 302 | 303 | // strip order is based on fold direction 304 | // 305 | // strip order 1 strip order 2 totalPlanesH distribution 306 | // 0 - 3 - 6 0 - 3 - 6 1 plane = 3 + 6 307 | // | \ | / | | / | \ | 2 plane = 3 + 6 + 6 308 | // 1 - 4 - 7 1 - 4 - 7 3 plane = 3 + 6 + 6 + 6 309 | // | / | \ | | \ | / | 310 | // 2 - 5 - 8 2 - 5 - 8 311 | this.getCustomGeometry = function(totalPlanesH, orderId, offset, height){ 312 | var geometry = new THREE.Geometry(); 313 | var id = 0; 314 | var percentage = 0; 315 | var i,j; 316 | var totalVertices = 3+(6)*totalPlanesH; 317 | var incV = 3; 318 | var incH = 1 + (2)*totalPlanesH; 319 | 320 | for(i = 0; i < totalVertices; i++) { 321 | geometry.vertices.push(new THREE.Vector3()); 322 | } 323 | 324 | for(j = 0; j < incH; j++) { 325 | for(i = 0; i < incV; i++) { 326 | percentage = j/(incH-1.0)*TWO_PI; 327 | geometry.vertices[id].x = Math.sin(percentage)*100; 328 | geometry.vertices[id].y = i/(incV-1)*height + offset; 329 | geometry.vertices[id].z = Math.cos(percentage)*100; 330 | id++; 331 | } 332 | } 333 | 334 | if(orderId%2===0){ 335 | for(j = 0; j < totalPlanesH; j++) { 336 | id = j*6; 337 | 338 | geometry.faces.push( new THREE.Face3( id+3, id+6, id+7 ) ); 339 | geometry.faces.push( new THREE.Face3( id+3, id+7, id+4 ) ); 340 | geometry.faces.push( new THREE.Face3( id+3, id+4, id+1 ) ); 341 | geometry.faces.push( new THREE.Face3( id+3, id+1, id+0 ) ); 342 | geometry.faces.push( new THREE.Face3( id+5, id+2, id+1 ) ); 343 | geometry.faces.push( new THREE.Face3( id+5, id+1, id+4 ) ); 344 | geometry.faces.push( new THREE.Face3( id+5, id+4, id+7 ) ); 345 | geometry.faces.push( new THREE.Face3( id+5, id+7, id+8 ) ); 346 | } 347 | } else { 348 | for(j = 0; j < totalPlanesH; j++) { 349 | id = j*6; 350 | geometry.faces.push( new THREE.Face3( id+4, id+1, id+0 ) ); 351 | geometry.faces.push( new THREE.Face3( id+4, id+0, id+3 ) ); 352 | geometry.faces.push( new THREE.Face3( id+4, id+3, id+6 ) ); 353 | geometry.faces.push( new THREE.Face3( id+4, id+6, id+7 ) ); 354 | 355 | geometry.faces.push( new THREE.Face3( id+4, id+7, id+8 ) ); 356 | geometry.faces.push( new THREE.Face3( id+4, id+8, id+5 ) ); 357 | geometry.faces.push( new THREE.Face3( id+4, id+5, id+2 ) ); 358 | geometry.faces.push( new THREE.Face3( id+4, id+2, id+1 ) ); 359 | } 360 | } 361 | 362 | geometry.computeFaceNormals(); 363 | geometry.computeVertexNormals(); 364 | return geometry; 365 | }; 366 | 367 | // --------------------------------------------------------- 368 | // listeners 369 | // --------------------------------------------------------- 370 | this.onDocumentMouseDown = function(event) { 371 | this.traceFunction("onDocumentMouseDown"); 372 | event.preventDefault(); 373 | 374 | var mouse = new THREE.Vector2(); 375 | mouse.x = ( event.clientX / (window.innerWidth-LILYPAD.Params.guiWidth) ) * 2 - 1; 376 | mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; 377 | var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 ); 378 | this.projector.unprojectVector( vector, this.camera ); 379 | var raycaster = new THREE.Raycaster( this.camera.position, vector.sub( this.camera.position ).normalize() ); 380 | var intersects = raycaster.intersectObjects( [this.water] ); 381 | if ( intersects.length > 0 ) { 382 | this.dispatchEvent("MORPH_SHAPE",[]); 383 | } else { 384 | 385 | } 386 | }; 387 | 388 | // --------------------------------------------------------- 389 | // public functions 390 | // --------------------------------------------------------- 391 | 392 | this.parse = function() { 393 | var i,j,k,id, 394 | particle, 395 | faceNormal, 396 | geometry, 397 | material; 398 | 399 | this.base.rotation.y += LILYPAD.Params.orbitSpeed; 400 | 401 | var centerSpeed = LILYPAD.Params.centerSpeed*.1; 402 | var noiseSpeed = LILYPAD.Params.noiseSpeed; 403 | var noiseAmount = LILYPAD.Params.noiseAmount; 404 | var noiseIntensity = LILYPAD.Params.noiseIntensity; 405 | var multiplier = LILYPAD.Params.multiplier; 406 | var centerRadius = LILYPAD.Params.centerRadius; 407 | var centerOffset = LILYPAD.Params.centerOffset; 408 | 409 | var waterHeight = LILYPAD.Params.waterHeight; 410 | var outerRadius = LILYPAD.Params.radius; 411 | var radiusRange = LILYPAD.Params.radiusRange; 412 | var wrapAmount = LILYPAD.Params.wrapAmount; 413 | var spikes = 0; 414 | var maxHeight = 0; 415 | 416 | var heightCountIncrement = (multiplier*2-multiplier) 417 | var heightOffset = LILYPAD.Params.heightOffset; 418 | var maxHeightRange = LILYPAD.Params.maxHeightRange; 419 | var heightCounter = -(this.totalVerticesV-1)*.5 * heightCountIncrement; 420 | 421 | var heightExtra = 0; 422 | var isOdd = null; 423 | var isEven = null; 424 | 425 | var centerX, centerY, centerZ; 426 | 427 | var wrappOffset = (1-wrapAmount)*TWO_PI*.5; 428 | var wrappMultiplier = (wrapAmount); 429 | var a, b; 430 | 431 | geometry = this.particles.geometry; 432 | id = 0; 433 | 434 | for(j = 0; j < this.totalVerticesV; j++) { 435 | for(i = 0; i < this.totalVerticesH; i++) { 436 | 437 | // fold specifically meant to account for tiling along a polar/clynidrical map 438 | // http://www.sjeiti.com/creating-tileable-noise-maps/ 439 | percentage = ((i+this.count)/(this.totalVerticesH-1))*TWO_PI; 440 | fold = this.perlin.noise3d( Math.cos(percentage)*noiseAmount+this.count*.1, Math.sin(percentage)*noiseAmount, (j/this.totalVerticesV+this.count*.1)); 441 | fold *= noiseIntensity; 442 | 443 | // spikes calculation 444 | outerRadius = LILYPAD.Params.radius - j/(this.totalVerticesV-1)*radiusRange * LILYPAD.Params.radius; 445 | spikes = outerRadius - fold*outerRadius; 446 | maxHeight = fold*multiplier*10; 447 | heightCountIncrement = (multiplier*2-multiplier) 448 | 449 | isOdd = i%2==1; 450 | isEven = i%2==0; 451 | 452 | // center radius motion 453 | percentage = (j/this.totalVerticesV+this.centerCount)*TWO_PI; 454 | centerX = Math.cos(percentage)*centerRadius*(j/this.totalVerticesV*2-1 + centerOffset); 455 | centerZ = Math.sin(percentage)*centerRadius*(j/this.totalVerticesV*2-1 + centerOffset); 456 | 457 | heightExtra = 0; 458 | if(isEven && j%4==0){ 459 | heightExtra += maxHeight; 460 | } else if(isEven && j%4==2){ 461 | heightExtra -= maxHeight; 462 | } else if(isOdd && j%4==2){ 463 | heightExtra += maxHeight; 464 | } else if(isOdd && j%4==0){ 465 | heightExtra -= maxHeight; 466 | } 467 | 468 | percentage = i/(this.totalVerticesH-1.0) * TWO_PI * wrappMultiplier + wrappOffset; 469 | 470 | if(isEven && j%4==1 || isOdd && j%4==3){ 471 | geometry.vertices[id].x = Math.sin(percentage)*outerRadius + centerX; 472 | // geometry.vertices[id].y = maxHeight; //heightCounter+heightExtra; 473 | geometry.vertices[id].y = maxHeight + this.maxHeightCache[id][0]; //heightCounter+heightExtra; 474 | geometry.vertices[id].z = Math.cos(percentage)*outerRadius + centerZ; 475 | 476 | } else { 477 | geometry.vertices[id].x = Math.sin(percentage)*outerRadius + centerX; 478 | // geometry.vertices[id].y = this.maxHeightCache[id][this.maxHeightCacheSize-1]; //heightCounter+heightExtra; 479 | geometry.vertices[id].y = maxHeight*maxHeightRange + heightOffset; //heightCounter+heightExtra; 480 | geometry.vertices[id].z = Math.cos(percentage)*outerRadius + centerZ; 481 | } 482 | 483 | id++; 484 | } 485 | 486 | heightCounter += heightCountIncrement; 487 | } 488 | 489 | percentage = (this.centerCount)*TWO_PI; 490 | centerX = Math.cos(percentage)*centerRadius*(j/this.totalVerticesV*2-1 + centerOffset); 491 | centerZ = Math.sin(percentage)*centerRadius*(j/this.totalVerticesV*2-1 + centerOffset); 492 | 493 | // adjusts color 494 | this.colorOffset += LILYPAD.Params.colorSpeed; 495 | var colorRange = LILYPAD.Params.colorRange; 496 | 497 | for(i = 0; i < this.totalPlanesV; i++) { 498 | this.customPlanes[i].material.color = new THREE.Color().setHSL( (i/this.totalPlanesV*colorRange + this.colorOffset)%1 , .75, .5); 499 | } 500 | this.water.material.color = new THREE.Color().setHSL( (1*(colorRange) + this.colorOffset+.125)%1 , 1, .25); 501 | this.ground.material.color = new THREE.Color().setHSL( (1*(colorRange) + this.colorOffset+.125)%1 , .5, .05); 502 | 503 | // var clearColor = new THREE.Color().setHSL( (1*(colorRange) + this.colorOffset+.15)%1 , 1.0, .75); 504 | // this.renderer.setClearColor(clearColor); 505 | 506 | 507 | // assigns vertices from particles to planes 508 | // order is refactored to traverse from x -> y to y -> x 509 | var vertice; 510 | var particle; 511 | var kOffset, jOffset, iOffset; 512 | var verticesPerPlane = this.totalPlanesH*4+2; 513 | for(k = 0; k < this.totalPlanesV; k++) { 514 | id = 0; 515 | for(j = 0; j < this.totalVerticesH; j++) { 516 | for(i = 0; i < 3; i++) { 517 | kOffset = k * (verticesPerPlane); 518 | jOffset = i * this.totalVerticesH; 519 | iOffset = j; 520 | this.customPlanes[k].geometry.vertices[id].copy( this.particles.geometry.vertices[kOffset + jOffset + iOffset]); 521 | this.customWirePlanes[k].geometry.vertices[id].copy( this.particles.geometry.vertices[kOffset + jOffset + iOffset]); 522 | id++; 523 | } 524 | } 525 | } 526 | 527 | var scalar = 4;//centerRadius*centerOffset; 528 | 529 | outerRadius = LILYPAD.Params.radius - LILYPAD.Params.radius*radiusRange; 530 | for(j = 0; j < this.totalVerticesH; j++) { 531 | percentage = j/(this.totalVerticesH-1)*TWO_PI; 532 | 533 | fold = this.perlin.noise3d( Math.cos(percentage)*noiseAmount, Math.sin(percentage)*noiseAmount, (this.count)); 534 | fold *= noiseIntensity*.5; 535 | 536 | // spikes calculation 537 | outerRadius = LILYPAD.Params.radius*1.125 - radiusRange * LILYPAD.Params.radius; 538 | spikes = outerRadius - fold*outerRadius; 539 | maxHeight = fold*multiplier; 540 | 541 | this.halo.geometry.vertices[j].x = Math.cos(percentage)*outerRadius + 0; 542 | this.halo.geometry.vertices[j].y = 200 + maxHeight;//200 + waterHeight; 543 | this.halo.geometry.vertices[j].z = Math.sin(percentage)*outerRadius + 0; 544 | } 545 | 546 | percentage = (this.centerCount)*TWO_PI; 547 | 548 | fold = this.perlin.noise3d( Math.cos(percentage)*noiseAmount, Math.sin(percentage)*noiseAmount, (this.count)); 549 | fold *= noiseIntensity; 550 | outerRadius = LILYPAD.Params.radius*1.125 - radiusRange * LILYPAD.Params.radius; 551 | spikes = outerRadius - fold*outerRadius; 552 | maxHeight = fold*multiplier*.5; 553 | 554 | this.haloLine.geometry.vertices[0].x = centerX; 555 | this.haloLine.geometry.vertices[0].y = 200 + maxHeight; 556 | this.haloLine.geometry.vertices[0].z = centerZ; 557 | 558 | this.haloLine.geometry.vertices[1].x = Math.cos(percentage)*outerRadius + 0; 559 | this.haloLine.geometry.vertices[1].y = 200 + maxHeight;//200+waterHeight; 560 | this.haloLine.geometry.vertices[1].z = Math.sin(percentage)*outerRadius + 0; 561 | 562 | this.haloDot.position.x = centerX; 563 | this.haloDot.position.y = 200 + maxHeight; 564 | this.haloDot.position.z = centerZ; 565 | 566 | this.centerCount+= centerSpeed; 567 | this.count+=noiseSpeed*.1; 568 | 569 | // changes the y position of the ground relative to shape 570 | this.water.position.y = waterHeight; 571 | 572 | // changes light source 573 | var percentage = this.count*.05*TWO_PI; 574 | this.dirLight.position.x = Math.cos(percentage)*100; 575 | this.dirLight.position.z = Math.sin(percentage)*100; 576 | 577 | return this; 578 | }; 579 | 580 | this.draw = function() { 581 | 582 | // update particles 583 | this.particles.geometry.verticesNeedUpdate = true; 584 | 585 | // updates halo 586 | this.halo.geometry.verticesNeedUpdate = true; 587 | this.haloLine.geometry.verticesNeedUpdate = true; 588 | 589 | // update shapes 590 | for(i = 0; i < this.customPlanes.length; i++) { 591 | this.customPlanes[i].geometry.verticesNeedUpdate = true; 592 | this.customWirePlanes[i].geometry.verticesNeedUpdate = true; 593 | } 594 | 595 | this.controls.update(); 596 | this.renderer.render( this.scene , this.camera ); 597 | 598 | return this; 599 | }; 600 | 601 | this.toggleWireFrame = function(){ 602 | var i,total = this.customPlanes.length; 603 | if (this.particles.visible===false){ 604 | this.particles.visible = true; 605 | this.water.visible = false; 606 | for(i=0;i",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+p.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f'+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l> 9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}}; 10 | 11 | -------------------------------------------------------------------------------- /vendor/jquery.easing.1.3.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 3 | * 4 | * Uses the built in easing capabilities added In jQuery 1.1 5 | * to offer multiple easing options 6 | * 7 | * TERMS OF USE - jQuery Easing 8 | * 9 | * Open source under the BSD License. 10 | * 11 | * Copyright © 2008 George McGinley Smith 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * Redistributions of source code must retain the above copyright notice, this list of 18 | * conditions and the following disclaimer. 19 | * Redistributions in binary form must reproduce the above copyright notice, this list 20 | * of conditions and the following disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * Neither the name of the author nor the names of contributors may be used to endorse 24 | * or promote products derived from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 27 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 31 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 34 | * OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | */ 37 | 38 | // t: current time, b: begInnIng value, c: change In value, d: duration 39 | jQuery.easing['jswing'] = jQuery.easing['swing']; 40 | 41 | jQuery.extend( jQuery.easing, 42 | { 43 | def: 'easeOutQuad', 44 | swing: function (x, t, b, c, d) { 45 | //alert(jQuery.easing.default); 46 | return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 47 | }, 48 | easeInQuad: function (x, t, b, c, d) { 49 | return c*(t/=d)*t + b; 50 | }, 51 | easeOutQuad: function (x, t, b, c, d) { 52 | return -c *(t/=d)*(t-2) + b; 53 | }, 54 | easeInOutQuad: function (x, t, b, c, d) { 55 | if ((t/=d/2) < 1) return c/2*t*t + b; 56 | return -c/2 * ((--t)*(t-2) - 1) + b; 57 | }, 58 | easeInCubic: function (x, t, b, c, d) { 59 | return c*(t/=d)*t*t + b; 60 | }, 61 | easeOutCubic: function (x, t, b, c, d) { 62 | return c*((t=t/d-1)*t*t + 1) + b; 63 | }, 64 | easeInOutCubic: function (x, t, b, c, d) { 65 | if ((t/=d/2) < 1) return c/2*t*t*t + b; 66 | return c/2*((t-=2)*t*t + 2) + b; 67 | }, 68 | easeInQuart: function (x, t, b, c, d) { 69 | return c*(t/=d)*t*t*t + b; 70 | }, 71 | easeOutQuart: function (x, t, b, c, d) { 72 | return -c * ((t=t/d-1)*t*t*t - 1) + b; 73 | }, 74 | easeInOutQuart: function (x, t, b, c, d) { 75 | if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 76 | return -c/2 * ((t-=2)*t*t*t - 2) + b; 77 | }, 78 | easeInQuint: function (x, t, b, c, d) { 79 | return c*(t/=d)*t*t*t*t + b; 80 | }, 81 | easeOutQuint: function (x, t, b, c, d) { 82 | return c*((t=t/d-1)*t*t*t*t + 1) + b; 83 | }, 84 | easeInOutQuint: function (x, t, b, c, d) { 85 | if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 86 | return c/2*((t-=2)*t*t*t*t + 2) + b; 87 | }, 88 | easeInSine: function (x, t, b, c, d) { 89 | return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 90 | }, 91 | easeOutSine: function (x, t, b, c, d) { 92 | return c * Math.sin(t/d * (Math.PI/2)) + b; 93 | }, 94 | easeInOutSine: function (x, t, b, c, d) { 95 | return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 96 | }, 97 | easeInExpo: function (x, t, b, c, d) { 98 | return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 99 | }, 100 | easeOutExpo: function (x, t, b, c, d) { 101 | return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 102 | }, 103 | easeInOutExpo: function (x, t, b, c, d) { 104 | if (t==0) return b; 105 | if (t==d) return b+c; 106 | if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 107 | return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 108 | }, 109 | easeInCirc: function (x, t, b, c, d) { 110 | return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 111 | }, 112 | easeOutCirc: function (x, t, b, c, d) { 113 | return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 114 | }, 115 | easeInOutCirc: function (x, t, b, c, d) { 116 | if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 117 | return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 118 | }, 119 | easeInElastic: function (x, t, b, c, d) { 120 | var s=1.70158;var p=0;var a=c; 121 | if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 122 | if (a < Math.abs(c)) { a=c; var s=p/4; } 123 | else var s = p/(2*Math.PI) * Math.asin (c/a); 124 | return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 125 | }, 126 | easeOutElastic: function (x, t, b, c, d) { 127 | var s=1.70158;var p=0;var a=c; 128 | if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 129 | if (a < Math.abs(c)) { a=c; var s=p/4; } 130 | else var s = p/(2*Math.PI) * Math.asin (c/a); 131 | return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 132 | }, 133 | easeInOutElastic: function (x, t, b, c, d) { 134 | var s=1.70158;var p=0;var a=c; 135 | if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 136 | if (a < Math.abs(c)) { a=c; var s=p/4; } 137 | else var s = p/(2*Math.PI) * Math.asin (c/a); 138 | if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 139 | return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 140 | }, 141 | easeInBack: function (x, t, b, c, d, s) { 142 | if (s == undefined) s = 1.70158; 143 | return c*(t/=d)*t*((s+1)*t - s) + b; 144 | }, 145 | easeOutBack: function (x, t, b, c, d, s) { 146 | if (s == undefined) s = 1.70158; 147 | return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 148 | }, 149 | easeInOutBack: function (x, t, b, c, d, s) { 150 | if (s == undefined) s = 1.70158; 151 | if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 152 | return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 153 | }, 154 | easeInBounce: function (x, t, b, c, d) { 155 | return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 156 | }, 157 | easeOutBounce: function (x, t, b, c, d) { 158 | if ((t/=d) < (1/2.75)) { 159 | return c*(7.5625*t*t) + b; 160 | } else if (t < (2/2.75)) { 161 | return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 162 | } else if (t < (2.5/2.75)) { 163 | return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 164 | } else { 165 | return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 166 | } 167 | }, 168 | easeInOutBounce: function (x, t, b, c, d) { 169 | if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 170 | return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 171 | } 172 | }); 173 | 174 | /* 175 | * 176 | * TERMS OF USE - EASING EQUATIONS 177 | * 178 | * Open source under the BSD License. 179 | * 180 | * Copyright © 2001 Robert Penner 181 | * All rights reserved. 182 | * 183 | * Redistribution and use in source and binary forms, with or without modification, 184 | * are permitted provided that the following conditions are met: 185 | * 186 | * Redistributions of source code must retain the above copyright notice, this list of 187 | * conditions and the following disclaimer. 188 | * Redistributions in binary form must reproduce the above copyright notice, this list 189 | * of conditions and the following disclaimer in the documentation and/or other materials 190 | * provided with the distribution. 191 | * 192 | * Neither the name of the author nor the names of contributors may be used to endorse 193 | * or promote products derived from this software without specific prior written permission. 194 | * 195 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 196 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 197 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 198 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 199 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 200 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 201 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 202 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 203 | * OF THE POSSIBILITY OF SUCH DAMAGE. 204 | * 205 | */ -------------------------------------------------------------------------------- /vendor/jstween-1.0.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JSTween JavaScript Library v1.0 3 | * http://www.jstween.org/ 4 | * 5 | * Copyright 2011, Marco Wolfsheimer 6 | * JSTween by Marco Wolfsheimer is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. 7 | * 8 | * Date: Sun Mar 13 12:46:40 2011 -0000 9 | */ 10 | var JSTween=(function(e){var d=/[\-]{0,1}[0-9\.]{1,}|#[0-9\.abcdef]{3,6}/gi,r=/[pxemtcin%]{1,2}|deg/gi,p=/[0-9\.\-]{1,}/gi,a=/[0-9a-f]{3,6}/gi,j=/^#/,f=/^[0-9\.\-]{1,}([pxemtcin%]{1,2}|deg)$/,m=/[a-z]{1,}/,q=/^rgb\(/,c=/^scroll/,g=/-([a-z])/ig,u=/^-ms/ig,o={opacity:["opacity","-moz-opacity","filter"],shadow:["box-shadow","-moz-box-shadow","-o-box-shadow","-ms-box-shadow","-webkit-box-shadow"],transform:["-moz-transform","transform","-o-transform","-ms-transform","-webkit-transform"],transformOrigin:["-moz-transform-origin","transform-origin","-o-transform-origin","-ms-transform-origin","-webkit-transform-origin"],borderRadius:["-moz-border-radius","border-radius","-webkit-border-radius"],borderRadiusTopLeft:["-moz-border-radius-topleft","border-top-left-radius","-webkit-border-top-left-radius"],borderRadiusTopRight:["-moz-border-radius-topright","border-top-right-radius","-webkit-border-top-right-radius"],borderRadiusBottomLeft:["-moz-border-radius-bottomleft","border-bottom-left-radius","-webkit-border-bottom-left-radius"],borderRadiusBottomRight:["-moz-border-radius-bottomright","border-bottom-right-radius","-webkit-border-bottom-right-radius"],backgroundSize:["background-size","-moz-background-size","-o-background-size","-webkit-background-size"]},t={},l=[],h=0,n=0,v=false,b=false,k=0,s={};e.init=function(){e.framerate(45);e.cssSupport();try{e.attach()}catch(w){return}};e.attach=function(){jQuery.JSTween=e;jQuery.fn.tween=function(w){var x,y=this.length;for(x=0;x0){if(this[0].__animate!==undefined){if(w!==undefined&&this[0].__animate.state[w]!==undefined){return this[0].__animate.state[w]}else{if(w===undefined){return this[0].__animate.state}}}}};jQuery.fn.transform=function(y){var w,x=this.length;for(w=0;wx.stop){x.stop=w[y].end}}}x.start=x.stop;for(y in w){if(w.hasOwnProperty(y)){if(w[y].timen){n=B}}}if(typeof z.onStart==="function"){e.addCallback(h+(Math.round(w.start*s.frameRate)),D,"callback",z.onStart)}if(typeof z.onFrame==="function"){for(frame=h+Math.round(w.start*s.frameRate);frame<=h+Math.round(w.stop*s.frameRate);frame++){e.addCallback(frame,D,"callback",z.onFrame)}}if(typeof z.onStop==="function"){e.addCallback(h+(Math.round(w.stop*s.frameRate)),D,"callback",z.onStop)}};e.makeFrame=function(B,w,y,A,x,C,z){if(w!==undefined){if(t[B]===undefined){t[B]={};t[B][w]={};t[B][w][y]={value:A,units:x,callback:[],skip:z}}else{if(t[B][w]===undefined){t[B][w]={};t[B][w][y]={value:A,units:x,callback:[],skip:z}}else{if(t[B][w][y]===undefined){t[B][w][y]={value:A,units:x,callback:[],skip:z}}else{if(A!==false){t[B][w][y].value=A}if(x!==false){t[B][w][y].units=x}t[B][w][y].skip=z}}}if(typeof C==="function"){t[B][w][y].callback.push(C)}}else{if(t[B]===undefined){t[B]={}}}};e.addCallback=function(y,w,x,z){e.makeFrame(y,w,x,false,false,z,true)};e.play=function(){if(v===false){b=false;v=true;k=e.timestamp();e.playHead()}};e.clear=function(w,x){var y;if(w!==undefined&&x!==undefined&&w.__animate!==undefined){for(y in t){if(t.hasOwnProperty(y)&&t[y][w.__animate.id]!==undefined&&t[y][w.__animate.id][x]!==undefined){delete t[y][w.__animate.id][x]}}}else{if(w!==undefined&&w.__animate!==undefined){for(y in t){if(t.hasOwnProperty(y)&&t[y][w.__animate.id]!==undefined){delete t[y][w.__animate.id]}}}else{for(y in t){if(t.hasOwnProperty(y)){delete t[y]}}}}};e.timestamp=function(){var w=new Date();return w.getTime()};e.playHead=function(){var z,w,y,x;if(h<=n){x=(s.frameDelay-((e.timestamp()-k)-(h*s.frameDelay)));if(x<0){x=0}else{if(x>s.frameDelay){x=s.frameDelay}}setTimeout(function(){e.playHead(x?true:false)},x);for(w in t[h]){if(t[h].hasOwnProperty(w)){z=t[h][w];for(y in z){if(z.hasOwnProperty(y)){e.action(w,y,z[y].value,z[y].units,z[y].callback,(z[y].skip===true?true:(x?true:false)))}}}}delete t[h];h++;b=e.timestamp()}else{b=v=false;h=0}};e.action=function(w,z,A,x,B,y){if(y===true&&A!==false){switch(z){case"zIndex":l[w].style.zIndex=A;break;case"alpha":e.opacity(l[w],A);break;case"transparency":e.opacity(l[w],A);break;case"opacity":e.opacity(l[w],A);break;case"scroll":e.scroll(l[w],z,A);break;case"scrollTop":e.scroll(l[w],z,A);break;case"scrollLeft":e.scroll(l[w],z,A);break;case"scrollTo":e.scroll(l[w],z,A);break;case"shadow":e.shadow(l[w],A);break;case"boxShadow":e.shadow(l[w],A);break;case"rotate":e.rotate(l[w],A);break;case"transformOrigin":e.transformOrigin(l[w],A);break;case"transform":e.transform(l[w],A);break;case"backgroundSize":e.backgroundSize(l[w],A);break;case"borderRadius":e.borderRadius(l[w],A,x);break;case"borderRadiusTopRight":e.borderRadiusCorner(l[w],"top","right",A,x);break;case"borderRadiusTopLeft":e.borderRadiusCorner(l[w],"top","left",A,x);break;case"borderRadiusBottomRight":e.borderRadiusCorner(l[w],"bottom","right",A,x);break;case"borderRadiusBottomLeft":e.borderRadiusCorner(l[w],"bottom","left",A,x);break;default:if(typeof A==="string"){l[w].style[z]=A}else{l[w].style[z]=A+x}break}}l[w].__animate.state[z]={value:A,units:x};if(B!==undefined&&B.length>0){for(i=0;iy0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) 60 | else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1) 61 | // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 62 | // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 63 | // c = (3-sqrt(3))/6 64 | var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 65 | var y1 = y0 - j1 + G2; 66 | var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords 67 | var y2 = y0 - 1.0 + 2.0 * G2; 68 | // Work out the hashed gradient indices of the three simplex corners 69 | var ii = i & 255; 70 | var jj = j & 255; 71 | var gi0 = this.perm[ii+this.perm[jj]] % 12; 72 | var gi1 = this.perm[ii+i1+this.perm[jj+j1]] % 12; 73 | var gi2 = this.perm[ii+1+this.perm[jj+1]] % 12; 74 | // Calculate the contribution from the three corners 75 | var t0 = 0.5 - x0*x0-y0*y0; 76 | if(t0<0) n0 = 0.0; 77 | else { 78 | t0 *= t0; 79 | n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient 80 | } 81 | var t1 = 0.5 - x1*x1-y1*y1; 82 | if(t1<0) n1 = 0.0; 83 | else { 84 | t1 *= t1; 85 | n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1); 86 | } 87 | var t2 = 0.5 - x2*x2-y2*y2; 88 | if(t2<0) n2 = 0.0; 89 | else { 90 | t2 *= t2; 91 | n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2); 92 | } 93 | // Add contributions from each corner to get the final noise value. 94 | // The result is scaled to return values in the interval [-1,1]. 95 | return 70.0 * (n0 + n1 + n2); 96 | }; 97 | 98 | // 3D simplex noise 99 | SimplexNoise.prototype.noise3d = function(xin, yin, zin) { 100 | var n0, n1, n2, n3; // Noise contributions from the four corners 101 | // Skew the input space to determine which simplex cell we're in 102 | var F3 = 1.0/3.0; 103 | var s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D 104 | var i = Math.floor(xin+s); 105 | var j = Math.floor(yin+s); 106 | var k = Math.floor(zin+s); 107 | var G3 = 1.0/6.0; // Very nice and simple unskew factor, too 108 | var t = (i+j+k)*G3; 109 | var X0 = i-t; // Unskew the cell origin back to (x,y,z) space 110 | var Y0 = j-t; 111 | var Z0 = k-t; 112 | var x0 = xin-X0; // The x,y,z distances from the cell origin 113 | var y0 = yin-Y0; 114 | var z0 = zin-Z0; 115 | // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 116 | // Determine which simplex we are in. 117 | var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 118 | var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 119 | if(x0>=y0) { 120 | if(y0>=z0) 121 | { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order 122 | else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order 123 | else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order 124 | } 125 | else { // x0 0 ) { 147 | 148 | var container = this.getContainerDimensions(); 149 | var halfWidth = container.size[ 0 ] / 2; 150 | var halfHeight = container.size[ 1 ] / 2; 151 | 152 | this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; 153 | this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; 154 | 155 | this.updateRotationVector(); 156 | 157 | } 158 | 159 | }; 160 | 161 | this.mouseup = function( event ) { 162 | 163 | event.preventDefault(); 164 | event.stopPropagation(); 165 | 166 | if ( this.dragToLook ) { 167 | 168 | this.mouseStatus --; 169 | 170 | this.moveState.yawLeft = this.moveState.pitchDown = 0; 171 | 172 | } else { 173 | 174 | switch ( event.button ) { 175 | 176 | case 0: this.moveState.forward = 0; break; 177 | case 2: this.moveState.back = 0; break; 178 | 179 | } 180 | 181 | this.updateMovementVector(); 182 | 183 | } 184 | 185 | this.updateRotationVector(); 186 | 187 | }; 188 | 189 | this.update = function( delta ) { 190 | 191 | var moveMult = delta * this.movementSpeed; 192 | var rotMult = delta * this.rollSpeed; 193 | 194 | this.object.translateX( this.moveVector.x * moveMult ); 195 | this.object.translateY( this.moveVector.y * moveMult ); 196 | this.object.translateZ( this.moveVector.z * moveMult ); 197 | 198 | this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize(); 199 | this.object.quaternion.multiply( this.tmpQuaternion ); 200 | 201 | // expose the rotation vector for convenience 202 | this.object.rotation.setEulerFromQuaternion( this.object.quaternion, this.object.eulerOrder ); 203 | 204 | 205 | }; 206 | 207 | this.updateMovementVector = function() { 208 | 209 | var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0; 210 | 211 | this.moveVector.x = ( -this.moveState.left + this.moveState.right ); 212 | this.moveVector.y = ( -this.moveState.down + this.moveState.up ); 213 | this.moveVector.z = ( -forward + this.moveState.back ); 214 | 215 | //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); 216 | 217 | }; 218 | 219 | this.updateRotationVector = function() { 220 | 221 | this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp ); 222 | this.rotationVector.y = ( -this.moveState.yawRight + this.moveState.yawLeft ); 223 | this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft ); 224 | 225 | //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); 226 | 227 | }; 228 | 229 | this.getContainerDimensions = function() { 230 | 231 | if ( this.domElement != document ) { 232 | 233 | return { 234 | size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ], 235 | offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ] 236 | }; 237 | 238 | } else { 239 | 240 | return { 241 | size : [ window.innerWidth, window.innerHeight ], 242 | offset : [ 0, 0 ] 243 | }; 244 | 245 | } 246 | 247 | }; 248 | 249 | function bind( scope, fn ) { 250 | 251 | return function () { 252 | 253 | fn.apply( scope, arguments ); 254 | 255 | }; 256 | 257 | }; 258 | 259 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 260 | 261 | this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false ); 262 | this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false ); 263 | this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false ); 264 | 265 | this.domElement.addEventListener( 'keydown', bind( this, this.keydown ), false ); 266 | this.domElement.addEventListener( 'keyup', bind( this, this.keyup ), false ); 267 | 268 | this.updateMovementVector(); 269 | this.updateRotationVector(); 270 | 271 | }; 272 | -------------------------------------------------------------------------------- /vendor/three/controls/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 | 8 | THREE.OrbitControls = function ( object, domElement ) { 9 | 10 | this.object = object; 11 | this.domElement = ( domElement !== undefined ) ? domElement : document; 12 | 13 | // API 14 | 15 | this.enabled = true; 16 | 17 | this.center = new THREE.Vector3(); 18 | 19 | this.userZoom = true; 20 | this.userZoomSpeed = 1.0; 21 | 22 | this.userRotate = true; 23 | this.userRotateSpeed = 1.0; 24 | 25 | this.userPan = true; 26 | this.userPanSpeed = 2.0; 27 | 28 | this.autoRotate = false; 29 | this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 30 | 31 | this.minPolarAngle = 0; // radians 32 | this.maxPolarAngle = Math.PI; // radians 33 | 34 | this.minDistance = 0; 35 | this.maxDistance = Infinity; 36 | 37 | this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; 38 | 39 | // internals 40 | 41 | var scope = this; 42 | 43 | var EPS = 0.000001; 44 | var PIXELS_PER_ROUND = 1800; 45 | 46 | var rotateStart = new THREE.Vector2(); 47 | var rotateEnd = new THREE.Vector2(); 48 | var rotateDelta = new THREE.Vector2(); 49 | 50 | var zoomStart = new THREE.Vector2(); 51 | var zoomEnd = new THREE.Vector2(); 52 | var zoomDelta = new THREE.Vector2(); 53 | 54 | var phiDelta = 0; 55 | var thetaDelta = 0; 56 | var scale = 1; 57 | 58 | var lastPosition = new THREE.Vector3(); 59 | 60 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; 61 | var state = STATE.NONE; 62 | 63 | // events 64 | 65 | var changeEvent = { type: 'change' }; 66 | 67 | 68 | this.rotateLeft = function ( angle ) { 69 | 70 | if ( angle === undefined ) { 71 | 72 | angle = getAutoRotationAngle(); 73 | 74 | } 75 | 76 | thetaDelta -= angle; 77 | 78 | }; 79 | 80 | this.rotateRight = function ( angle ) { 81 | 82 | if ( angle === undefined ) { 83 | 84 | angle = getAutoRotationAngle(); 85 | 86 | } 87 | 88 | thetaDelta += angle; 89 | 90 | }; 91 | 92 | this.rotateUp = function ( angle ) { 93 | 94 | if ( angle === undefined ) { 95 | 96 | angle = getAutoRotationAngle(); 97 | 98 | } 99 | 100 | phiDelta -= angle; 101 | 102 | }; 103 | 104 | this.rotateDown = function ( angle ) { 105 | 106 | if ( angle === undefined ) { 107 | 108 | angle = getAutoRotationAngle(); 109 | 110 | } 111 | 112 | phiDelta += angle; 113 | 114 | }; 115 | 116 | this.zoomIn = function ( zoomScale ) { 117 | 118 | if ( zoomScale === undefined ) { 119 | 120 | zoomScale = getZoomScale(); 121 | 122 | } 123 | 124 | scale /= zoomScale; 125 | 126 | }; 127 | 128 | this.zoomOut = function ( zoomScale ) { 129 | 130 | if ( zoomScale === undefined ) { 131 | 132 | zoomScale = getZoomScale(); 133 | 134 | } 135 | 136 | scale *= zoomScale; 137 | 138 | }; 139 | 140 | this.pan = function ( distance ) { 141 | 142 | distance.transformDirection( this.object.matrix ); 143 | distance.multiplyScalar( scope.userPanSpeed ); 144 | 145 | this.object.position.add( distance ); 146 | this.center.add( distance ); 147 | 148 | }; 149 | 150 | this.update = function () { 151 | 152 | var position = this.object.position; 153 | var offset = position.clone().sub( this.center ); 154 | 155 | // angle from z-axis around y-axis 156 | 157 | var theta = Math.atan2( offset.x, offset.z ); 158 | 159 | // angle from y-axis 160 | 161 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 162 | 163 | if ( this.autoRotate ) { 164 | 165 | this.rotateLeft( getAutoRotationAngle() ); 166 | 167 | } 168 | 169 | theta += thetaDelta; 170 | phi += phiDelta; 171 | 172 | // restrict phi to be between desired limits 173 | phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); 174 | 175 | // restrict phi to be betwee EPS and PI-EPS 176 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); 177 | 178 | var radius = offset.length() * scale; 179 | 180 | // restrict radius to be between desired limits 181 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); 182 | 183 | offset.x = radius * Math.sin( phi ) * Math.sin( theta ); 184 | offset.y = radius * Math.cos( phi ); 185 | offset.z = radius * Math.sin( phi ) * Math.cos( theta ); 186 | 187 | position.copy( this.center ).add( offset ); 188 | 189 | this.object.lookAt( this.center ); 190 | 191 | thetaDelta = 0; 192 | phiDelta = 0; 193 | scale = 1; 194 | 195 | if ( lastPosition.distanceTo( this.object.position ) > 0 ) { 196 | 197 | this.dispatchEvent( changeEvent ); 198 | 199 | lastPosition.copy( this.object.position ); 200 | 201 | } 202 | 203 | }; 204 | 205 | 206 | function getAutoRotationAngle() { 207 | 208 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 209 | 210 | } 211 | 212 | function getZoomScale() { 213 | 214 | return Math.pow( 0.95, scope.userZoomSpeed ); 215 | 216 | } 217 | 218 | function onMouseDown( event ) { 219 | 220 | if ( scope.enabled === false ) return; 221 | if ( scope.userRotate === false ) return; 222 | 223 | event.preventDefault(); 224 | 225 | if ( event.button === 0 ) { 226 | 227 | state = STATE.ROTATE; 228 | 229 | rotateStart.set( event.clientX, event.clientY ); 230 | 231 | } else if ( event.button === 1 ) { 232 | 233 | state = STATE.ZOOM; 234 | 235 | zoomStart.set( event.clientX, event.clientY ); 236 | 237 | } else if ( event.button === 2 ) { 238 | 239 | state = STATE.PAN; 240 | 241 | } 242 | 243 | document.addEventListener( 'mousemove', onMouseMove, false ); 244 | document.addEventListener( 'mouseup', onMouseUp, false ); 245 | 246 | } 247 | 248 | function onMouseMove( event ) { 249 | 250 | if ( scope.enabled === false ) return; 251 | 252 | event.preventDefault(); 253 | 254 | if ( state === STATE.ROTATE ) { 255 | 256 | rotateEnd.set( event.clientX, event.clientY ); 257 | rotateDelta.subVectors( rotateEnd, rotateStart ); 258 | 259 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); 260 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); 261 | 262 | rotateStart.copy( rotateEnd ); 263 | 264 | } else if ( state === STATE.ZOOM ) { 265 | 266 | zoomEnd.set( event.clientX, event.clientY ); 267 | zoomDelta.subVectors( zoomEnd, zoomStart ); 268 | 269 | if ( zoomDelta.y > 0 ) { 270 | 271 | scope.zoomIn(); 272 | 273 | } else { 274 | 275 | scope.zoomOut(); 276 | 277 | } 278 | 279 | zoomStart.copy( zoomEnd ); 280 | 281 | } else if ( state === STATE.PAN ) { 282 | 283 | var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 284 | var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 285 | 286 | scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); 287 | 288 | } 289 | 290 | } 291 | 292 | function onMouseUp( event ) { 293 | 294 | if ( scope.enabled === false ) return; 295 | if ( scope.userRotate === false ) return; 296 | 297 | document.removeEventListener( 'mousemove', onMouseMove, false ); 298 | document.removeEventListener( 'mouseup', onMouseUp, false ); 299 | 300 | state = STATE.NONE; 301 | 302 | } 303 | 304 | function onMouseWheel( event ) { 305 | 306 | if ( scope.enabled === false ) return; 307 | if ( scope.userZoom === false ) return; 308 | 309 | var delta = 0; 310 | 311 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 312 | 313 | delta = event.wheelDelta; 314 | 315 | } else if ( event.detail ) { // Firefox 316 | 317 | delta = - event.detail; 318 | 319 | } 320 | 321 | if ( delta > 0 ) { 322 | 323 | scope.zoomOut(); 324 | 325 | } else { 326 | 327 | scope.zoomIn(); 328 | 329 | } 330 | 331 | } 332 | 333 | function onKeyDown( event ) { 334 | 335 | if ( scope.enabled === false ) return; 336 | if ( scope.userPan === false ) return; 337 | 338 | switch ( event.keyCode ) { 339 | 340 | case scope.keys.UP: 341 | scope.pan( new THREE.Vector3( 0, 1, 0 ) ); 342 | break; 343 | case scope.keys.BOTTOM: 344 | scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); 345 | break; 346 | case scope.keys.LEFT: 347 | scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); 348 | break; 349 | case scope.keys.RIGHT: 350 | scope.pan( new THREE.Vector3( 1, 0, 0 ) ); 351 | break; 352 | } 353 | 354 | } 355 | 356 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 357 | this.domElement.addEventListener( 'mousedown', onMouseDown, false ); 358 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 359 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 360 | this.domElement.addEventListener( 'keydown', onKeyDown, false ); 361 | 362 | }; 363 | 364 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 365 | -------------------------------------------------------------------------------- /vendor/three/controls/PathControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.PathControls = function ( object, domElement ) { 6 | 7 | this.object = object; 8 | this.domElement = ( domElement !== undefined ) ? domElement : document; 9 | 10 | this.id = "PathControls" + THREE.PathControlsIdCounter ++; 11 | 12 | // API 13 | 14 | this.duration = 10 * 1000; // milliseconds 15 | this.waypoints = []; 16 | 17 | this.useConstantSpeed = true; 18 | this.resamplingCoef = 50; 19 | 20 | this.debugPath = new THREE.Object3D(); 21 | this.debugDummy = new THREE.Object3D(); 22 | 23 | this.animationParent = new THREE.Object3D(); 24 | 25 | this.lookSpeed = 0.005; 26 | this.lookVertical = true; 27 | this.lookHorizontal = true; 28 | this.verticalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] }; 29 | this.horizontalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] }; 30 | 31 | // internals 32 | 33 | this.target = new THREE.Object3D(); 34 | 35 | this.mouseX = 0; 36 | this.mouseY = 0; 37 | 38 | this.lat = 0; 39 | this.lon = 0; 40 | 41 | this.phi = 0; 42 | this.theta = 0; 43 | 44 | var PI2 = Math.PI * 2; 45 | 46 | this.viewHalfX = 0; 47 | this.viewHalfY = 0; 48 | 49 | if ( this.domElement !== document ) { 50 | 51 | this.domElement.setAttribute( 'tabindex', -1 ); 52 | 53 | } 54 | 55 | // methods 56 | 57 | this.handleResize = function () { 58 | 59 | if ( this.domElement === document ) { 60 | 61 | this.viewHalfX = window.innerWidth / 2; 62 | this.viewHalfY = window.innerHeight / 2; 63 | 64 | } else { 65 | 66 | this.viewHalfX = this.domElement.offsetWidth / 2; 67 | this.viewHalfY = this.domElement.offsetHeight / 2; 68 | 69 | } 70 | 71 | }; 72 | 73 | this.update = function ( delta ) { 74 | 75 | var srcRange, dstRange; 76 | 77 | if( this.lookHorizontal ) this.lon += this.mouseX * this.lookSpeed * delta; 78 | if( this.lookVertical ) this.lat -= this.mouseY * this.lookSpeed * delta; 79 | 80 | this.lon = Math.max( 0, Math.min( 360, this.lon ) ); 81 | this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); 82 | 83 | this.phi = THREE.Math.degToRad( 90 - this.lat ); 84 | this.theta = THREE.Math.degToRad( this.lon ); 85 | 86 | this.phi = normalize_angle_rad( this.phi ); 87 | 88 | // constrain vertical look angle 89 | 90 | srcRange = this.verticalAngleMap.srcRange; 91 | dstRange = this.verticalAngleMap.dstRange; 92 | 93 | var tmpPhi = THREE.Math.mapLinear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); 94 | var tmpPhiFullRange = dstRange[ 1 ] - dstRange[ 0 ]; 95 | var tmpPhiNormalized = ( tmpPhi - dstRange[ 0 ] ) / tmpPhiFullRange; 96 | 97 | this.phi = QuadraticEaseInOut( tmpPhiNormalized ) * tmpPhiFullRange + dstRange[ 0 ]; 98 | 99 | // constrain horizontal look angle 100 | 101 | srcRange = this.horizontalAngleMap.srcRange; 102 | dstRange = this.horizontalAngleMap.dstRange; 103 | 104 | var tmpTheta = THREE.Math.mapLinear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); 105 | var tmpThetaFullRange = dstRange[ 1 ] - dstRange[ 0 ]; 106 | var tmpThetaNormalized = ( tmpTheta - dstRange[ 0 ] ) / tmpThetaFullRange; 107 | 108 | this.theta = QuadraticEaseInOut( tmpThetaNormalized ) * tmpThetaFullRange + dstRange[ 0 ]; 109 | 110 | var targetPosition = this.target.position, 111 | position = this.object.position; 112 | 113 | targetPosition.x = 100 * Math.sin( this.phi ) * Math.cos( this.theta ); 114 | targetPosition.y = 100 * Math.cos( this.phi ); 115 | targetPosition.z = 100 * Math.sin( this.phi ) * Math.sin( this.theta ); 116 | 117 | this.object.lookAt( this.target.position ); 118 | 119 | }; 120 | 121 | this.onMouseMove = function ( event ) { 122 | 123 | if ( this.domElement === document ) { 124 | 125 | this.mouseX = event.pageX - this.viewHalfX; 126 | this.mouseY = event.pageY - this.viewHalfY; 127 | 128 | } else { 129 | 130 | this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; 131 | this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; 132 | 133 | } 134 | 135 | }; 136 | 137 | // utils 138 | 139 | function normalize_angle_rad( a ) { 140 | 141 | var b = a % PI2; 142 | return b >= 0 ? b : b + PI2; 143 | 144 | }; 145 | 146 | function distance( a, b ) { 147 | 148 | var dx = a[ 0 ] - b[ 0 ], 149 | dy = a[ 1 ] - b[ 1 ], 150 | dz = a[ 2 ] - b[ 2 ]; 151 | 152 | return Math.sqrt( dx * dx + dy * dy + dz * dz ); 153 | 154 | }; 155 | 156 | function QuadraticEaseInOut ( k ) { 157 | 158 | if ( ( k *= 2 ) < 1 ) return 0.5 * k * k; 159 | return - 0.5 * ( --k * ( k - 2 ) - 1 ); 160 | 161 | }; 162 | 163 | function bind( scope, fn ) { 164 | 165 | return function () { 166 | 167 | fn.apply( scope, arguments ); 168 | 169 | }; 170 | 171 | }; 172 | 173 | function initAnimationPath( parent, spline, name, duration ) { 174 | 175 | var animationData = { 176 | 177 | name: name, 178 | fps: 0.6, 179 | length: duration, 180 | 181 | hierarchy: [] 182 | 183 | }; 184 | 185 | var i, 186 | parentAnimation, childAnimation, 187 | path = spline.getControlPointsArray(), 188 | sl = spline.getLength(), 189 | pl = path.length, 190 | t = 0, 191 | first = 0, 192 | last = pl - 1; 193 | 194 | parentAnimation = { parent: -1, keys: [] }; 195 | parentAnimation.keys[ first ] = { time: 0, pos: path[ first ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] }; 196 | parentAnimation.keys[ last ] = { time: duration, pos: path[ last ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] }; 197 | 198 | for ( i = 1; i < pl - 1; i++ ) { 199 | 200 | // real distance (approximation via linear segments) 201 | 202 | t = duration * sl.chunks[ i ] / sl.total; 203 | 204 | // equal distance 205 | 206 | //t = duration * ( i / pl ); 207 | 208 | // linear distance 209 | 210 | //t += duration * distance( path[ i ], path[ i - 1 ] ) / sl.total; 211 | 212 | parentAnimation.keys[ i ] = { time: t, pos: path[ i ] }; 213 | 214 | } 215 | 216 | animationData.hierarchy[ 0 ] = parentAnimation; 217 | 218 | THREE.AnimationHandler.add( animationData ); 219 | 220 | return new THREE.Animation( parent, name, THREE.AnimationHandler.CATMULLROM_FORWARD, false ); 221 | 222 | }; 223 | 224 | 225 | function createSplineGeometry( spline, n_sub ) { 226 | 227 | var i, index, position, 228 | geometry = new THREE.Geometry(); 229 | 230 | for ( i = 0; i < spline.points.length * n_sub; i ++ ) { 231 | 232 | index = i / ( spline.points.length * n_sub ); 233 | position = spline.getPoint( index ); 234 | 235 | geometry.vertices[ i ] = new THREE.Vector3( position.x, position.y, position.z ); 236 | 237 | } 238 | 239 | return geometry; 240 | 241 | }; 242 | 243 | function createPath( parent, spline ) { 244 | 245 | var lineGeo = createSplineGeometry( spline, 10 ), 246 | particleGeo = createSplineGeometry( spline, 10 ), 247 | lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ), 248 | lineObj = new THREE.Line( lineGeo, lineMat ), 249 | particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleBasicMaterial( { color: 0xffaa00, size: 3 } ) ); 250 | 251 | lineObj.scale.set( 1, 1, 1 ); 252 | parent.add( lineObj ); 253 | 254 | particleObj.scale.set( 1, 1, 1 ); 255 | parent.add( particleObj ); 256 | 257 | var waypoint, 258 | geo = new THREE.SphereGeometry( 1, 16, 8 ), 259 | mat = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); 260 | 261 | for ( var i = 0; i < spline.points.length; i ++ ) { 262 | 263 | waypoint = new THREE.Mesh( geo, mat ); 264 | waypoint.position.copy( spline.points[ i ] ); 265 | parent.add( waypoint ); 266 | 267 | } 268 | 269 | }; 270 | 271 | this.init = function ( ) { 272 | 273 | // constructor 274 | 275 | this.spline = new THREE.Spline(); 276 | this.spline.initFromArray( this.waypoints ); 277 | 278 | if ( this.useConstantSpeed ) { 279 | 280 | this.spline.reparametrizeByArcLength( this.resamplingCoef ); 281 | 282 | } 283 | 284 | if ( this.createDebugDummy ) { 285 | 286 | var dummyParentMaterial = new THREE.MeshLambertMaterial( { color: 0x0077ff } ), 287 | dummyChildMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00 } ), 288 | dummyParentGeo = new THREE.CubeGeometry( 10, 10, 20 ), 289 | dummyChildGeo = new THREE.CubeGeometry( 2, 2, 10 ); 290 | 291 | this.animationParent = new THREE.Mesh( dummyParentGeo, dummyParentMaterial ); 292 | 293 | var dummyChild = new THREE.Mesh( dummyChildGeo, dummyChildMaterial ); 294 | dummyChild.position.set( 0, 10, 0 ); 295 | 296 | this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration ); 297 | 298 | this.animationParent.add( this.object ); 299 | this.animationParent.add( this.target ); 300 | this.animationParent.add( dummyChild ); 301 | 302 | } else { 303 | 304 | this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration ); 305 | this.animationParent.add( this.target ); 306 | this.animationParent.add( this.object ); 307 | 308 | } 309 | 310 | if ( this.createDebugPath ) { 311 | 312 | createPath( this.debugPath, this.spline ); 313 | 314 | } 315 | 316 | this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false ); 317 | 318 | }; 319 | 320 | this.handleResize(); 321 | 322 | }; 323 | 324 | THREE.PathControlsIdCounter = 0; 325 | -------------------------------------------------------------------------------- /vendor/three/controls/PointerLockControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com/ 3 | */ 4 | 5 | THREE.PointerLockControls = function ( camera ) { 6 | 7 | var scope = this; 8 | 9 | var pitchObject = new THREE.Object3D(); 10 | pitchObject.add( camera ); 11 | 12 | var yawObject = new THREE.Object3D(); 13 | yawObject.position.y = 10; 14 | yawObject.add( pitchObject ); 15 | 16 | var moveForward = false; 17 | var moveBackward = false; 18 | var moveLeft = false; 19 | var moveRight = false; 20 | 21 | var isOnObject = false; 22 | var canJump = false; 23 | 24 | var velocity = new THREE.Vector3(); 25 | 26 | var PI_2 = Math.PI / 2; 27 | 28 | var onMouseMove = function ( event ) { 29 | 30 | if ( scope.enabled === false ) return; 31 | 32 | var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 33 | var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 34 | 35 | yawObject.rotation.y -= movementX * 0.002; 36 | pitchObject.rotation.x -= movementY * 0.002; 37 | 38 | pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) ); 39 | 40 | }; 41 | 42 | var onKeyDown = function ( event ) { 43 | 44 | switch ( event.keyCode ) { 45 | 46 | case 38: // up 47 | case 87: // w 48 | moveForward = true; 49 | break; 50 | 51 | case 37: // left 52 | case 65: // a 53 | moveLeft = true; break; 54 | 55 | case 40: // down 56 | case 83: // s 57 | moveBackward = true; 58 | break; 59 | 60 | case 39: // right 61 | case 68: // d 62 | moveRight = true; 63 | break; 64 | 65 | case 32: // space 66 | if ( canJump === true ) velocity.y += 10; 67 | canJump = false; 68 | break; 69 | 70 | } 71 | 72 | }; 73 | 74 | var onKeyUp = function ( event ) { 75 | 76 | switch( event.keyCode ) { 77 | 78 | case 38: // up 79 | case 87: // w 80 | moveForward = false; 81 | break; 82 | 83 | case 37: // left 84 | case 65: // a 85 | moveLeft = false; 86 | break; 87 | 88 | case 40: // down 89 | case 83: // a 90 | moveBackward = false; 91 | break; 92 | 93 | case 39: // right 94 | case 68: // d 95 | moveRight = false; 96 | break; 97 | 98 | } 99 | 100 | }; 101 | 102 | document.addEventListener( 'mousemove', onMouseMove, false ); 103 | document.addEventListener( 'keydown', onKeyDown, false ); 104 | document.addEventListener( 'keyup', onKeyUp, false ); 105 | 106 | this.enabled = false; 107 | 108 | this.getObject = function () { 109 | 110 | return yawObject; 111 | 112 | }; 113 | 114 | this.isOnObject = function ( boolean ) { 115 | 116 | isOnObject = boolean; 117 | canJump = boolean; 118 | 119 | }; 120 | 121 | this.update = function ( delta ) { 122 | 123 | if ( scope.enabled === false ) return; 124 | 125 | delta *= 0.1; 126 | 127 | velocity.x += ( - velocity.x ) * 0.08 * delta; 128 | velocity.z += ( - velocity.z ) * 0.08 * delta; 129 | 130 | velocity.y -= 0.25 * delta; 131 | 132 | if ( moveForward ) velocity.z -= 0.12 * delta; 133 | if ( moveBackward ) velocity.z += 0.12 * delta; 134 | 135 | if ( moveLeft ) velocity.x -= 0.12 * delta; 136 | if ( moveRight ) velocity.x += 0.12 * delta; 137 | 138 | if ( isOnObject === true ) { 139 | 140 | velocity.y = Math.max( 0, velocity.y ); 141 | 142 | } 143 | 144 | yawObject.translateX( velocity.x ); 145 | yawObject.translateY( velocity.y ); 146 | yawObject.translateZ( velocity.z ); 147 | 148 | if ( yawObject.position.y < 10 ) { 149 | 150 | velocity.y = 0; 151 | yawObject.position.y = 10; 152 | 153 | canJump = true; 154 | 155 | } 156 | 157 | }; 158 | 159 | }; 160 | -------------------------------------------------------------------------------- /vendor/three/controls/TrackballControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Eberhard Graether / http://egraether.com/ 3 | */ 4 | 5 | THREE.TrackballControls = function ( object, domElement ) { 6 | 7 | var _this = this; 8 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 }; 9 | 10 | this.object = object; 11 | this.domElement = ( domElement !== undefined ) ? domElement : document; 12 | 13 | // API 14 | 15 | this.enabled = true; 16 | 17 | this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 }; 18 | this.radius = ( this.screen.width + this.screen.height ) / 4; 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 | 28 | this.staticMoving = false; 29 | this.dynamicDampingFactor = 0.2; 30 | 31 | this.minDistance = 0; 32 | this.maxDistance = Infinity; 33 | 34 | this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; 35 | 36 | // internals 37 | 38 | this.target = new THREE.Vector3(); 39 | 40 | var lastPosition = new THREE.Vector3(); 41 | 42 | var _state = STATE.NONE, 43 | _prevState = STATE.NONE, 44 | 45 | _eye = new THREE.Vector3(), 46 | 47 | _rotateStart = new THREE.Vector3(), 48 | _rotateEnd = new THREE.Vector3(), 49 | 50 | _zoomStart = new THREE.Vector2(), 51 | _zoomEnd = new THREE.Vector2(), 52 | 53 | _touchZoomDistanceStart = 0, 54 | _touchZoomDistanceEnd = 0, 55 | 56 | _panStart = new THREE.Vector2(), 57 | _panEnd = new THREE.Vector2(); 58 | 59 | // for reset 60 | 61 | this.target0 = this.target.clone(); 62 | this.position0 = this.object.position.clone(); 63 | this.up0 = this.object.up.clone(); 64 | 65 | // events 66 | 67 | var changeEvent = { type: 'change' }; 68 | 69 | 70 | // methods 71 | 72 | this.handleResize = function () { 73 | 74 | this.screen.width = window.innerWidth; 75 | this.screen.height = window.innerHeight; 76 | 77 | this.screen.offsetLeft = 0; 78 | this.screen.offsetTop = 0; 79 | 80 | this.radius = ( this.screen.width + this.screen.height ) / 4; 81 | 82 | }; 83 | 84 | this.handleEvent = function ( event ) { 85 | 86 | if ( typeof this[ event.type ] == 'function' ) { 87 | 88 | this[ event.type ]( event ); 89 | 90 | } 91 | 92 | }; 93 | 94 | this.getMouseOnScreen = function ( clientX, clientY ) { 95 | 96 | return new THREE.Vector2( 97 | ( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5, 98 | ( clientY - _this.screen.offsetTop ) / _this.radius * 0.5 99 | ); 100 | 101 | }; 102 | 103 | this.getMouseProjectionOnBall = function ( clientX, clientY ) { 104 | 105 | var mouseOnBall = new THREE.Vector3( 106 | ( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius, 107 | ( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius, 108 | 0.0 109 | ); 110 | 111 | var length = mouseOnBall.length(); 112 | 113 | if ( length > 1.0 ) { 114 | 115 | mouseOnBall.normalize(); 116 | 117 | } else { 118 | 119 | mouseOnBall.z = Math.sqrt( 1.0 - length * length ); 120 | 121 | } 122 | 123 | _eye.copy( _this.object.position ).sub( _this.target ); 124 | 125 | var projection = _this.object.up.clone().setLength( mouseOnBall.y ); 126 | projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) ); 127 | projection.add( _eye.setLength( mouseOnBall.z ) ); 128 | 129 | return projection; 130 | 131 | }; 132 | 133 | this.rotateCamera = function () { 134 | 135 | var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() ); 136 | 137 | if ( angle ) { 138 | 139 | var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(), 140 | quaternion = new THREE.Quaternion(); 141 | 142 | angle *= _this.rotateSpeed; 143 | 144 | quaternion.setFromAxisAngle( axis, -angle ); 145 | 146 | _eye.applyQuaternion( quaternion ); 147 | _this.object.up.applyQuaternion( quaternion ); 148 | 149 | _rotateEnd.applyQuaternion( quaternion ); 150 | 151 | if ( _this.staticMoving ) { 152 | 153 | _rotateStart.copy( _rotateEnd ); 154 | 155 | } else { 156 | 157 | quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) ); 158 | _rotateStart.applyQuaternion( quaternion ); 159 | 160 | } 161 | 162 | } 163 | 164 | }; 165 | 166 | this.zoomCamera = function () { 167 | 168 | if ( _state === STATE.TOUCH_ZOOM ) { 169 | 170 | var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; 171 | _touchZoomDistanceStart = _touchZoomDistanceEnd; 172 | _eye.multiplyScalar( factor ); 173 | 174 | } else { 175 | 176 | var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed; 177 | 178 | if ( factor !== 1.0 && factor > 0.0 ) { 179 | 180 | _eye.multiplyScalar( factor ); 181 | 182 | if ( _this.staticMoving ) { 183 | 184 | _zoomStart.copy( _zoomEnd ); 185 | 186 | } else { 187 | 188 | _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; 189 | 190 | } 191 | 192 | } 193 | 194 | } 195 | 196 | }; 197 | 198 | this.panCamera = function () { 199 | 200 | var mouseChange = _panEnd.clone().sub( _panStart ); 201 | 202 | if ( mouseChange.lengthSq() ) { 203 | 204 | mouseChange.multiplyScalar( _eye.length() * _this.panSpeed ); 205 | 206 | var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x ); 207 | pan.add( _this.object.up.clone().setLength( mouseChange.y ) ); 208 | 209 | _this.object.position.add( pan ); 210 | _this.target.add( pan ); 211 | 212 | if ( _this.staticMoving ) { 213 | 214 | _panStart = _panEnd; 215 | 216 | } else { 217 | 218 | _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) ); 219 | 220 | } 221 | 222 | } 223 | 224 | }; 225 | 226 | this.checkDistances = function () { 227 | 228 | if ( !_this.noZoom || !_this.noPan ) { 229 | 230 | if ( _this.object.position.lengthSq() > _this.maxDistance * _this.maxDistance ) { 231 | 232 | _this.object.position.setLength( _this.maxDistance ); 233 | 234 | } 235 | 236 | if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) { 237 | 238 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) ); 239 | 240 | } 241 | 242 | } 243 | 244 | }; 245 | 246 | this.update = function () { 247 | 248 | _eye.subVectors( _this.object.position, _this.target ); 249 | 250 | if ( !_this.noRotate ) { 251 | 252 | _this.rotateCamera(); 253 | 254 | } 255 | 256 | if ( !_this.noZoom ) { 257 | 258 | _this.zoomCamera(); 259 | 260 | } 261 | 262 | if ( !_this.noPan ) { 263 | 264 | _this.panCamera(); 265 | 266 | } 267 | 268 | _this.object.position.addVectors( _this.target, _eye ); 269 | 270 | _this.checkDistances(); 271 | 272 | _this.object.lookAt( _this.target ); 273 | 274 | if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) { 275 | 276 | _this.dispatchEvent( changeEvent ); 277 | 278 | lastPosition.copy( _this.object.position ); 279 | 280 | } 281 | 282 | }; 283 | 284 | this.reset = function () { 285 | 286 | _state = STATE.NONE; 287 | _prevState = STATE.NONE; 288 | 289 | _this.target.copy( _this.target0 ); 290 | _this.object.position.copy( _this.position0 ); 291 | _this.object.up.copy( _this.up0 ); 292 | 293 | _eye.subVectors( _this.object.position, _this.target ); 294 | 295 | _this.object.lookAt( _this.target ); 296 | 297 | _this.dispatchEvent( changeEvent ); 298 | 299 | lastPosition.copy( _this.object.position ); 300 | 301 | }; 302 | 303 | // listeners 304 | 305 | function keydown( event ) { 306 | 307 | if ( _this.enabled === false ) return; 308 | 309 | window.removeEventListener( 'keydown', keydown ); 310 | 311 | _prevState = _state; 312 | 313 | if ( _state !== STATE.NONE ) { 314 | 315 | return; 316 | 317 | } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) { 318 | 319 | _state = STATE.ROTATE; 320 | 321 | } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) { 322 | 323 | _state = STATE.ZOOM; 324 | 325 | } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) { 326 | 327 | _state = STATE.PAN; 328 | 329 | } 330 | 331 | } 332 | 333 | function keyup( event ) { 334 | 335 | if ( _this.enabled === false ) return; 336 | 337 | _state = _prevState; 338 | 339 | window.addEventListener( 'keydown', keydown, false ); 340 | 341 | } 342 | 343 | function mousedown( event ) { 344 | 345 | if ( _this.enabled === false ) return; 346 | 347 | event.preventDefault(); 348 | event.stopPropagation(); 349 | 350 | if ( _state === STATE.NONE ) { 351 | 352 | _state = event.button; 353 | 354 | } 355 | 356 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 357 | 358 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY ); 359 | 360 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 361 | 362 | _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 363 | 364 | } else if ( _state === STATE.PAN && !_this.noPan ) { 365 | 366 | _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 367 | 368 | } 369 | 370 | document.addEventListener( 'mousemove', mousemove, false ); 371 | document.addEventListener( 'mouseup', mouseup, false ); 372 | 373 | } 374 | 375 | function mousemove( event ) { 376 | 377 | if ( _this.enabled === false ) return; 378 | 379 | event.preventDefault(); 380 | event.stopPropagation(); 381 | 382 | if ( _state === STATE.ROTATE && !_this.noRotate ) { 383 | 384 | _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY ); 385 | 386 | } else if ( _state === STATE.ZOOM && !_this.noZoom ) { 387 | 388 | _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 389 | 390 | } else if ( _state === STATE.PAN && !_this.noPan ) { 391 | 392 | _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY ); 393 | 394 | } 395 | 396 | } 397 | 398 | function mouseup( event ) { 399 | 400 | if ( _this.enabled === false ) return; 401 | 402 | event.preventDefault(); 403 | event.stopPropagation(); 404 | 405 | _state = STATE.NONE; 406 | 407 | document.removeEventListener( 'mousemove', mousemove ); 408 | document.removeEventListener( 'mouseup', mouseup ); 409 | 410 | } 411 | 412 | function mousewheel( event ) { 413 | 414 | if ( _this.enabled === false ) return; 415 | 416 | event.preventDefault(); 417 | event.stopPropagation(); 418 | 419 | var delta = 0; 420 | 421 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 422 | 423 | delta = event.wheelDelta / 40; 424 | 425 | } else if ( event.detail ) { // Firefox 426 | 427 | delta = - event.detail / 3; 428 | 429 | } 430 | 431 | _zoomStart.y += delta * 0.01; 432 | 433 | } 434 | 435 | function touchstart( event ) { 436 | 437 | if ( _this.enabled === false ) return; 438 | 439 | switch ( event.touches.length ) { 440 | 441 | case 1: 442 | _state = STATE.TOUCH_ROTATE; 443 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 444 | break; 445 | 446 | case 2: 447 | _state = STATE.TOUCH_ZOOM; 448 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 449 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 450 | _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); 451 | break; 452 | 453 | case 3: 454 | _state = STATE.TOUCH_PAN; 455 | _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 456 | break; 457 | 458 | default: 459 | _state = STATE.NONE; 460 | 461 | } 462 | 463 | } 464 | 465 | function touchmove( event ) { 466 | 467 | if ( _this.enabled === false ) return; 468 | 469 | event.preventDefault(); 470 | event.stopPropagation(); 471 | 472 | switch ( event.touches.length ) { 473 | 474 | case 1: 475 | _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 476 | break; 477 | 478 | case 2: 479 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 480 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 481 | _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ) 482 | break; 483 | 484 | case 3: 485 | _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 486 | break; 487 | 488 | default: 489 | _state = STATE.NONE; 490 | 491 | } 492 | 493 | } 494 | 495 | function touchend( event ) { 496 | 497 | if ( _this.enabled === false ) return; 498 | 499 | switch ( event.touches.length ) { 500 | 501 | case 1: 502 | _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 503 | break; 504 | 505 | case 2: 506 | _touchZoomDistanceStart = _touchZoomDistanceEnd = 0; 507 | break; 508 | 509 | case 3: 510 | _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 511 | break; 512 | 513 | } 514 | 515 | _state = STATE.NONE; 516 | 517 | } 518 | 519 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 520 | 521 | this.domElement.addEventListener( 'mousedown', mousedown, false ); 522 | 523 | this.domElement.addEventListener( 'mousewheel', mousewheel, false ); 524 | this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox 525 | 526 | this.domElement.addEventListener( 'touchstart', touchstart, false ); 527 | this.domElement.addEventListener( 'touchend', touchend, false ); 528 | this.domElement.addEventListener( 'touchmove', touchmove, false ); 529 | 530 | window.addEventListener( 'keydown', keydown, false ); 531 | window.addEventListener( 'keyup', keyup, false ); 532 | 533 | this.handleResize(); 534 | 535 | }; 536 | 537 | THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); 538 | -------------------------------------------------------------------------------- /vendor/toxi/toxi-color.js: -------------------------------------------------------------------------------- 1 | // toxi-color r43 - http://github.com/hapticdata/toxiclibsjs 2 | toxi.color=toxi.color||{}; 3 | (function(){var h=function(a){var b="0000";if(a>=0&&a<=15)b="000"+a.toString(16);else if(a>=16&&a<=255)b="00"+a.toString(16);else if(a>=256&&a<=4095)b="0"+a.toString(16);else if(a>=4096&&a<=65535)b=a.toString(16);return b};toxi.color.TColor=function(a){this.rgb=Array(3);this.hsv=Array(3);this.cmyk=Array(4);this._alpha=1;if(a!==undefined){this.cmyk=a.toCMYKAArray().splice(0,4);this.hsv=a.toHSVAArray().splice(0,3);this.rgb=a.toRGBAArray().splice(0,3);this._alpha=a._alpha}};toxi.color.TColor.prototype= 4 | {add:function(a){return this.copy().addSelf(a)},addSelf:function(a){this.rgb[0]=toxi.MathUtils.min(this.rgb[0]+a.rgb[0],1);this.rgb[1]=toxi.MathUtils.min(this.rgb[1]+a.rgb[1],1);this.rgb[2]=toxi.MathUtils.min(this.rgb[2]+a.rgb[2],1);return this.setRGB(rgb)},adjustConstrast:function(a){return this.hsv[2]<0.5?this.darken(a):this.lighten(a)},adjustHSV:function(a,b,d){return this.setHSV([this.hsv[0]+a,this.hsv[1]+b,this.hsv[2]+d])},adjustRGB:function(a,b,d){return this.setRGB([this.rgb[0]+a,this.rgb[1]+ 5 | b,this.rgb[2]+d])},alpha:function(){return this._alpha},analog:function(a,b){this.rotateRYB(toxi.MathUtils.degrees(a)*toxi.MathUtils.normalizedRandom());this.hsv[1]+=b*toxi.MathUtils.normalizedRandom();this.hsv[2]+=b*toxi.MathUtils.normalizedRandom();return this.setHSV(this.hsv)},black:function(){return this.cmyk[3]},blend:function(a,b){if(b===undefined)b=0.5;var d=a.toRGBAArray();this.rgb[0]+=(d[0]-this.rgb[0])*b;this.rgb[1]+=(d[1]-this.rgb[1])*b;this.rgb[2]+=(d[2]-this.rgb[2])*b;this._alpha+=(a.alpha()- 6 | this._alpha)*b;return this.setRGB(this.rgb)},blue:function(){return this.rgb[2]},brightness:function(){return this.hsv[2]},complement:function(){return this.rotateRYB(180)},copy:function(){return new toxi.color.TColor(this)},cyan:function(){return this.cmyk[0]},darken:function(a){this.hsv[2]=toxi.MathUtils.clip(this.hsv[2]-a,0,1);return this.setHSV(this.hsv)},desaturate:function(a){this.hsv[1]=toxi.MathUtils.clip(this.hsv[1]-a,0,1);return this.setHSV(this.hsv)},differenceTo:function(a){return toxi.color.TColor.newRGB(Math.abs(this.rgb[0]- 7 | a.rgb[0]),Math.abs(this.rgb[1]-a.rgb[1]),Math.abs(this.rgb[2]-a.rgb[2]))},distanceToCMYK:function(a){var b=a.toCMYKAArray();a=this.cmyk[0]-b[0];var d=this.cmyk[1]-b[1],c=this.cmyk[2]-b[2];b=this.cmyk[3]-b[3];return Math.sqrt(a*a+d*d+c*c+b*b)},distanceToHSV:function(a){var b=this.hsv[0]*toxi.MathUtils.TWO_PI,d=a.hue()*toxi.MathUtils.TWO_PI;b=new toxi.Vec3D(Math.cos(b)*this.hsv[1],Math.sin(b)*this.hsv[1],this.hsv[2]);a=new toxi.Vec3D(Math.cos(d)*a.saturation(),Math.sin(d)*a.saturation(),a.brightness()); 8 | return b.distanceTo(a)},distanceToRGB:function(a){var b=a.toRGBAArray();a=this.rgb[0]-b[0];var d=this.rgb[1]-b[1];b=this.rgb[2]-b[2];return Math.sqrt(a*a+d*d+b*b)},equals:function(a){if(a!==undefined&&a instanceof toxi.color.TColor){var b=a.rgb[0]-this.rgb[0],d=a.rgb[1]-this.rgb[1],c=a.rgb[2]-this.rgb[2];a=a.alpha()-this._alpha;return Math.sqrt(b*b+d*d+c*c+a*a)=toxi.color.TColor.WHITE_POINT&&this.rgb[0]==this.rgb[1]&&this.rgb[0]==this.rgb[2]},lighten:function(a){this.hsv[2]=toxi.MathUtils.clip(this.hsv[2]+a,0,1);return this.setHSV(this.hsv)},luminance:function(){return this.rgb[0]*0.299+this.rgb[1]*0.587+this.rgb[2]*0.114},magenta:function(){return this.cmyk[1]},red:function(){return this.rgb[0]},rotateRYB:function(a){parseInt(toxi.MathUtils.degrees(a),10);var b=this.hsv[0]*360,d=0, 12 | c,e;a%=360;var f=0;for(d=0;d>16&255)*toxi.TColor.INV8BIT,(a>>8&255)*toxi.TColor.INV8BIT,(a&255)*toxi.TColor.INV8BIT);this._alpha=(a>>>24)*toxi.TColor.INV8BIT;return this},setBlack:function(a){this.cmyk[3]=a;return this.setCMYK(cmyk)},setBlue:function(a){this.rgb[2]=a;return this.setRGB(this.rgb)},setBrightness:function(a){this.hsv[2]= 14 | toxi.MathUtils.clip(a,0,1);return this.setHSV(this.hsv)},setCMYK:function(a,b,d,c){if(a instanceof Array){b=a[1];d=a[2];c=a[3];a=a[0]}this.cmyk[0]=a;this.cmyk[1]=b;this.cmyk[2]=d;this.cmyk[3]=c;this.rgb=toxi.color.TColor.cmykToRGB(this.cmyk[0],this.cmyk[1],this.cmyk[2],this.cmyk[3]);this.hsv=toxi.color.TColor.rgbToHSV(this.rgb[0],this.rgb[1],this.rgb[2]);return this},setCyan:function(a){this.cmyk[0]=a;return this.setCMYK(this.cmyk)},setGreen:function(a){this.rgb[1]=a;return this.setRGB(this.rgb)}, 15 | setHSV:function(a,b,d){if(a instanceof Array){b=a[1];d=a[2];a=a[0]}a=[a,b,d];this.hsv[0]=a[0]%1;this.hsv[0]<0&&this.hsv[0]++;this.hsv[1]=toxi.MathUtils.clip(a[1],0,1);this.hsv[2]=toxi.MathUtils.clip(a[2],0,1);this.rgb=toxi.color.TColor.hsvToRGB(this.hsv[0],this.hsv[1],this.hsv[2]);this.cmyk=toxi.color.TColor.rgbToCMYK(this.rgb[0],this.rgb[1],this.rgb[2]);return this},setHue:function(a){a%=1;a<0&&a++;this.hsv[0]=a;this.setHSV(this.hsv)},setMagenta:function(a){this.cmyk[1]=a;return this.setCMYK(this.cmyk)}, 16 | setRed:function(a){this.rgb[0]=a;return this.setRGB(this.rgb)},setRGB:function(a,b,d){if(a instanceof Array){b=a[1];d=a[2];a=a[0]}this.rgb[0]=toxi.MathUtils.clip(a,0,1);this.rgb[1]=toxi.MathUtils.clip(b,0,1);this.rgb[2]=toxi.MathUtils.clip(d,0,1);this.cmyk=toxi.color.TColor.rgbToCMYK(this.rgb[0],this.rgb[1],this.rgb[2]);this.hsv=toxi.color.TColor.rgbToHSV(this.rgb[0],this.rgb[1],this.rgb[2]);return this},setSaturation:function(a){this.hsv[1]=toxi.MathUtils.clip(a,0,1);return this.setHSV(this.hsv)}, 17 | setYellow:function(a){this.cmyk[2]=a;return this.setCMYK(this.cmyk)},sub:function(a){return this.copy().subSelf(a)},subSelf:function(a){this.rgb[0]=toxi.MathUtils.max(this.rgb[0]-a.rgb[0],0);this.rgb[1]=toxi.MathUtils.max(this.rgb[1]-a.rgb[1],0);this.rgb[2]=toxi.MathUtils.max(this.rgb[2]-a.rgb[2],0);return this.setRGB(this.rgb)},toARGB:function(){var a=parseInt(this.rgb[0]*255,10),b=parseInt(this.rgb[1]*255,10),d=parseInt(this.rgb[2]*255,10),c=parseInt(this._alpha*255,10);return a<<16|b<<8|d|c<<24}, 18 | toCMYKAArray:function(a){if(a===undefined)a=[];a[0]=this.cmyk[0];a[1]=this.cmyk[1];a[2]=this.cmyk[2];a[3]=this._alpha;return a},toHex:function(){var a=h(this.toARGB());if(a.length>6)a=a.substring(2);return a},toHSVAArray:function(a){if(a===undefined)a=[];a[0]=this.hsv[0];a[1]=this.hsv[1];a[2]=this.hsv[2];a[3]=this._alpha;return a},toRGBAArray:function(a,b){if(a===undefined){a=[];b=0}a[b++]=this.rgb[0];a[b++]=this.rgb[1];a[b++]=this.rgb[2];a[b]=this._alpha;return a},toString:function(){return"toxi.color.TColor: rgb: "+ 19 | this.rgb[0]+", "+this.rgb[1]+", "+this.rgb[2]+" hsv: "+this.hsv[0]+","+this.hsv[1]+","+this.hsv[2]+" cmyk: "+this.cmyk[0]+", "+this.cmyk[1]+","+this.cmyk[2]+","+this.cmyk[3]+" alpha: "+this._alpha},yellow:function(){return this.cmyk[2]}};toxi.color.TColor.INV60DEGREES=60/360;toxi.color.TColor.INV8BIT=1/255;toxi.color.TColor.EPS=0.0010;toxi.color.TColor.BLACK_POINT=0.08;toxi.color.TColor.WHITE_POINT=1;toxi.color.TColor.GREY_THRESHOLD=0.01;toxi.color.TColor.cmykToRGB=function(a,b,d,c,e){if(e===undefined)e= 20 | [0,0,0];e[0]=1-Math.min(1,a+c);e[1]=1-Math.min(1,b+c);e[2]=1-Math.min(1,d+c);return e};toxi.color.TColor.hexToRGB=function(a,b){if(b===undefined)b=[];a=a.charAt(0)=="#"?a.substring(1,7):a;b[0]=parseInt(a.substring(0,2),16)*toxi.color.TColor.INV8BIT;b[1]=parseInt(a.substring(2,4),16)*toxi.color.TColor.INV8BIT;b[2]=parseInt(a.substring(4,6),16)*toxi.color.TColor.INV8BIT;return b};toxi.color.TColor.hsvToRGB=function(a,b,d,c){if(c===undefined)c=[];if(b===0)c[0]=c[1]=c[2]=d;else{a/=toxi.color.TColor.INV60DEGREES; 21 | var e=parseInt(a,10),f=a-e;a=d*(1-b);var g=d*(1-b*f);b=d*(1-b*(1-f));if(e===0){c[0]=d;c[1]=b;c[2]=a}else if(e==1){c[0]=g;c[1]=d;c[2]=a}else if(e==2){c[0]=a;c[1]=d;c[2]=b}else if(e==3){c[0]=a;c[1]=g;c[2]=d}else if(e==4){c[0]=b;c[1]=a;c[2]=d}else{c[0]=d;c[1]=a;c[2]=g}}return c};toxi.color.TColor.labToRGB=function(a,b,d,c){if(c===undefined)c=[];a=(a+16)/116;b=b/500+a;var e=a-d/200;d=0;c[0]=b;c[1]=a;c[2]=e;for(d=0;d<3;d++){a=Math.pow(c[d],3);c[d]=a>0.008856?a:(c[d]-16/116)/7.787}b=c[0]*0.95047;a=c[1]; 22 | e=c[2]*1.08883;c[0]=b*3.2406+a*-1.5372+e*-0.4986;c[1]=b*-0.9689+a*1.8758+e*0.0415;c[2]=b*0.0557+a*-0.204+e*1.057;a=1/2.4;for(d=0;d<3;d++)c[d]=c[d]>0.0031308?1.055*Math.pow(c[d],a)-0.055:12.92*c[d];return c};toxi.color.TColor.newARGB=function(a){return toxi.color.TColor.newRGBA((a>>16&255)*toxi.color.TColor.INV8BIT,(a>>8&255)*toxi.color.TColor.INV8BIT,(a&255)*toxi.color.TColor.INV8BIT,(a>>>24)*toxi.color.TColor.INV8BIT)};toxi.color.TColor.newCMYK=function(a,b,d,c){return toxi.color.TColor.newCMYKA(a, 23 | b,d,c,1)};toxi.color.TColor.newCMYKA=function(a,b,d,c,e){var f=new toxi.color.TColor;f.setCMYK([a,b,d,c]);f.setAlpha(toxi.MathUtils.clip(e,0,1));return f};toxi.color.TColor.newGray=function(a){return toxi.color.TColor.newGrayAlpha(a,1)};toxi.color.TColor.newGrayAlpha=function(a,b){var d=new toxi.color.TColor;d.setRGB([a,a,a]);d.setAlpha(b);return d};toxi.color.TColor.newHex=function(a){var b=new toxi.color.TColor;b.setRGB(toxi.color.TColor.hexToRGB(a));b.setAlpha(1);return b};toxi.color.TColor.newHSV= 24 | function(a,b,d){return toxi.color.TColor.newHSVA(a,b,d,1)};toxi.color.TColor.newHSVA=function(a,b,d,c){var e=new toxi.color.TColor;e.setHSV(a,b,d);e.setAlpha(toxi.MathUtils.clip(c,0,1));return e};toxi.color.TColor.newRandom=function(){return toxi.color.TColor.newRGBA(Math.random(),Math.random(),Math.random(),1)};toxi.color.TColor.newRGB=function(a,b,d){return toxi.color.TColor.newRGBA(a,b,d,1)};toxi.color.TColor.newRGBA=function(a,b,d,c){var e=new toxi.color.TColor;e.setRGB([a,b,d]);e.setAlpha(toxi.MathUtils.clip(c, 25 | 0,1));return e};toxi.color.TColor.rgbToCMYK=function(a,b,d,c){if(c===undefined)c=[];c[0]=1-a;c[1]=1-b;c[2]=1-d;c[3]=toxi.MathUtils.min(c[0],c[1],c[2]);c[0]=toxi.MathUtils.clip(c[0]-c[3],0,1);c[1]=toxi.MathUtils.clip(c[1]-c[3],0,1);c[2]=toxi.MathUtils.clip(c[2]-c[3],0,1);c[3]=toxi.MathUtils.clip(c[3],0,1);return c};toxi.color.TColor.rgbToHex=function(a,b,d){return h(toxi.MathUtils.clip(a,0,1)*255)+h(toxi.MathUtils.clip(b,0,1)*255)+h(toxi.MathUtils.clip(d,0,1)*255)};toxi.color.TColor.rgbToHSV=function(a, 26 | b,d,c){if(c===undefined)c=[];var e=0,f=0,g=toxi.MathUtils.max(a,b,d),i=g-toxi.MathUtils.min(a,b,d);if(g!==0)f=i/g;if(f!==0)e=a==g?(b-d)/i:b==g?2+(d-a)/i:4+(a-b)/i;e*=toxi.color.TColor.INV60DEGREES;if(e<0)e+=1;c[0]=e;c[1]=f;c[2]=g;return c};toxi.color.TColor.RED=toxi.color.TColor.newRGB(1,0,0);toxi.color.TColor.RYB_WHEEL=[new toxi.Vec2D(0,0),new toxi.Vec2D(15,8),new toxi.Vec2D(30,17),new toxi.Vec2D(45,26),new toxi.Vec2D(60,34),new toxi.Vec2D(75,41),new toxi.Vec2D(90,48),new toxi.Vec2D(105,54),new toxi.Vec2D(120, 27 | 60),new toxi.Vec2D(135,81),new toxi.Vec2D(150,103),new toxi.Vec2D(165,123),new toxi.Vec2D(180,138),new toxi.Vec2D(195,155),new toxi.Vec2D(210,171),new toxi.Vec2D(225,187),new toxi.Vec2D(240,204),new toxi.Vec2D(255,219),new toxi.Vec2D(270,234),new toxi.Vec2D(285,251),new toxi.Vec2D(300,267),new toxi.Vec2D(315,282),new toxi.Vec2D(330,298),new toxi.Vec2D(345,329),new toxi.Vec2D(360,0)];toxi.color.TColor.GREEN=toxi.color.TColor.newRGB(0,1,0);toxi.color.TColor.BLUE=toxi.color.TColor.newRGB(0,0,1);toxi.color.TColor.CYAN= 28 | toxi.color.TColor.newRGB(0,1,1);toxi.color.TColor.MAGENTA=toxi.color.TColor.newRGB(1,0,1);toxi.color.TColor.YELLOW=toxi.color.TColor.newRGB(1,1,0);toxi.color.TColor.BLACK=toxi.color.TColor.newRGB(0,0,0);toxi.color.TColor.WHITE=toxi.color.TColor.newRGB(1,1,1)})(); 29 | -------------------------------------------------------------------------------- /vendor/toxi/toxi-physics2d.js: -------------------------------------------------------------------------------- 1 | // toxi-physics2d r43 - http://github.com/hapticdata/toxiclibsjs 2 | toxi.physics2d=toxi.physics2d||{};toxi.physics2d.removeItemFrom=function(a,b){var c=b.indexOf(a);if(c>-1)return b.splice(c,1)};toxi.physics2d.VerletParticle2D=function(a,b,c){this.force=new toxi.Vec2D;if(a instanceof toxi.Vec2D)if(a instanceof toxi.physics2d.VerletParticle2D){b=a.y;c=a.weight;a=a.x;this.isLocked=a.isLocked}else{if(b===undefined){b=a.y;c=1}else{c=b;b=a.y}a=a.x}toxi.Vec2D.apply(this,[a,b]);this.isLocked=false;this.prev=new toxi.Vec2D(this);this.temp=new toxi.Vec2D;c=c||1;this.setWeight(c)}; 3 | toxi.extend(toxi.physics2d.VerletParticle2D,toxi.Vec2D);toxi.physics2d.VerletParticle2D.prototype.addBehavior=function(a,b){if(this.behaviors===undefined)this.behaviors=[];if(a===undefined)throw{name:"TypeError",message:"behavior was undefined"};b=b===undefined?1:b;a.configure(b);this.behaviors.push(a);return this};toxi.physics2d.VerletParticle2D.prototype.addConstraint=function(a){if(this.constraints===undefined)this.constraints=[];this.constraints.push(a);return this}; 4 | toxi.physics2d.VerletParticle2D.prototype.addForce=function(a){this.force.addSelf(a);return this};toxi.physics2d.VerletParticle2D.prototype.addVelocity=function(a){this.prev.subSelf(a);return this};toxi.physics2d.VerletParticle2D.prototype.applyBehaviors=function(){if(this.behaviors!==undefined){var a=0;for(a=0;a1){this.theta=b;this.rootPos=new toxi.Vec2D(a)}else{this.rootPos=new toxi.Vec2D;this.theta=a}if(parseInt(this.theta,10)!=this.theta)this.theta=toxi.MathUtils.radians(this.theta)};toxi.physics2d.AngularConstraint.prototype.applyConstraint=function(a){var b=a.sub(this.rootPos),c=toxi.MathUtils.floor(b.heading()/this.theta)*this.theta;a.set(this.rootPos.add(toxi.Vec2D.fromTheta(c).scaleSelf(b.magnitude())))}; 17 | toxi.physics2d.AxisConstraint=function(a,b){this.axis=a;this.constraint=b};toxi.physics2d.AxisConstraint.prototype.applyConstraint=function(a){a.setComponent(this.axis,this.constraint)};toxi.physics2d.CircularConstraint=function(a,b){if(arguments.length==1)this.circle=a;else{console.log("a: "+a);this.circle=new toxi.Circle(a,b)}};toxi.physics2d.CircularConstraint.prototype.applyConstraint=function(a){this.circle.containsPoint(a)&&a.set(this.circle.add(a.sub(this.circle).normalizeTo(this.circle.getRadius())))}; 18 | toxi.physics2d.MaxConstraint=function(a,b){this.axis=a;this.threshold=b};toxi.physics2d.MaxConstraint.prototype.applyConstraint=function(a){a.getComponent(this.axis)>this.threshold&&a.setComponent(this.axis,this.threshold)};toxi.physics2d.MinConstraint=function(a,b){this.axis=a;this.threshold=b};toxi.physics2d.MinConstraint.prototype.applyConstraint=function(a){a.getComponent(this.axis)1)this.rect=new toxi.Rect(a,b);this.intersectRay=new toxi.Ray2D(this.rect.getCentroid(),new toxi.Vec2D)}; 20 | toxi.physics2d.RectConstraint.prototype={applyConstraint:function(a){this.rect.containsPoint(a)&&a.set(this.rect.intersectsRay(this.intersectRay.setDirection(this.intersectRay.sub(a)),0,Number.MAX_VALUE))},getBox:function(){return this.rect.copy()},setBox:function(a){this.rect=a.copy();this.intersectRay.set(this.rect.getCentroid())}};toxi.physics2d.ParticlePath2D=function(a){toxi.Spline2D.call(this,a);this.particles=[]};toxi.extend(toxi.physics2d.ParticlePath2D,toxi.Spline2D); 21 | (function(){toxi.physics2d.ParticlePath2D.prototype.createParticles=function(a,b,c,d){this.particles=[];this.computeVertices(b);b=0;c=this.getDecimatedVertices(c,true);for(b=0;bthis.restLengthSquared&&this.parent.update.call(this,a)}; 27 | toxi.physics2d.VerletConstrainedSpring2D=function(a,b,c,d,e){toxi.physics2d.VerletSpring2D.call(this,a,b,c,d);this.limit=e===undefined?Number.MAX_VALUE:e};toxi.extend(toxi.physics2d.VerletConstrainedSpring2D,toxi.physics2d.VerletSpring2D); 28 | toxi.physics2d.VerletConstrainedSpring2D.update=function(a){var b=this.b.sub(this.a),c=b.magnitude()+toxi.physics2d.VerletSpring2D.EPS;c=(c-this.restLength)/(c*(this.a.invWeight+this.b.invWeight))*this.strength;if(!this.a.isLocked&&!this.isALocked){this.a.addSelf(b.scale(c*this.a.invWeight).limit(this.limit));a&&this.a.applyConstraints()}if(!this.b.isLocked&&!this.isBLocked){this.b.subSelf(b.scale(c*this.b.invWeight).limit(this.limit));a&&this.b.applyConstraints()}}; 29 | toxi.physics2d.VerletMinDistanceSpring2D=function(a,b,c,d){toxi.physics2d.VerletSpring2D.call(this,a,b,c,d);this.setRestLength(c)};toxi.extend(toxi.physics2d.VerletMinDistanceSpring2D,toxi.physics2d.VerletSpring2D);toxi.physics2d.VerletMinDistanceSpring2D.prototype.update=function(a){this.b.distanceToSquared(this.a)0;a--)for(b=0;b -1){ 7 | return array.splice(index,1); 8 | } 9 | return undefined; 10 | }; 11 | toxi.physics2d.VerletParticle2D = function(x,y,w){ 12 | this.force = new toxi.Vec2D(); 13 | if(x instanceof toxi.Vec2D){ 14 | if(x instanceof toxi.physics2d.VerletParticle2D){ 15 | 16 | y = x.y; 17 | w = x.weight; 18 | x = x.x; 19 | this.isLocked = x.isLocked; 20 | 21 | } else if(y === undefined){ 22 | y = x.y; 23 | w = 1; 24 | x = x.x; 25 | } else { 26 | w = y; 27 | y = x.y; 28 | x = x.x; 29 | } 30 | } 31 | toxi.Vec2D.apply(this,[x,y]); 32 | this.isLocked = false; 33 | this.prev = new toxi.Vec2D(this); 34 | this.temp = new toxi.Vec2D(); 35 | w = w || 1; 36 | this.setWeight(w); 37 | }; 38 | 39 | toxi.extend(toxi.physics2d.VerletParticle2D,toxi.Vec2D); 40 | 41 | toxi.physics2d.VerletParticle2D.prototype.addBehavior = function(behavior,timeStep){ 42 | if(this.behaviors === undefined){ 43 | this.behaviors = []; 44 | } 45 | if(behavior === undefined){ 46 | throw { name: "TypeError", message: "behavior was undefined"}; 47 | } 48 | timeStep = (timeStep === undefined)? 1 : timeStep; 49 | behavior.configure(timeStep); 50 | this.behaviors.push(behavior); 51 | return this; 52 | }; 53 | 54 | toxi.physics2d.VerletParticle2D.prototype.addConstraint = function(c){ 55 | if(this.constraints === undefined){ 56 | this.constraints = []; 57 | } 58 | this.constraints.push(c); 59 | return this; 60 | }; 61 | 62 | toxi.physics2d.VerletParticle2D.prototype.addForce = function(f){ 63 | this.force.addSelf(f); 64 | return this; 65 | }; 66 | 67 | toxi.physics2d.VerletParticle2D.prototype.addVelocity = function(v){ 68 | this.prev.subSelf(v); 69 | return this; 70 | }; 71 | 72 | toxi.physics2d.VerletParticle2D.prototype.applyBehaviors = function(){ 73 | if(this.behaviors !== undefined){ 74 | var i = 0; 75 | for(i = 0;i 1){ 341 | var p = theta_p; 342 | this.theta = theta; 343 | this.rootPos = new toxi.Vec2D(p); 344 | } else { 345 | this.rootPos = new toxi.Vec2D(); 346 | this.theta = theta_p; 347 | } 348 | if(parseInt(this.theta,10) != this.theta){ 349 | this.theta = toxi.MathUtils.radians(this.theta); 350 | } 351 | }; 352 | 353 | 354 | toxi.physics2d.AngularConstraint.prototype.applyConstraint = function(p){ 355 | var delta = p.sub(this.rootPos); 356 | var heading = toxi.MathUtils.floor(delta.heading() / this.theta) * this.theta; 357 | p.set(this.rootPos.add(toxi.Vec2D.fromTheta(heading).scaleSelf(delta.magnitude()))); 358 | };/** 359 | * Constrains a particle's movement by locking a given axis to a fixed value. 360 | */ 361 | toxi.physics2d.AxisConstraint = function(axis,constraintAmount){ 362 | this.axis = axis; 363 | this.constraint = constraintAmount; 364 | }; 365 | 366 | toxi.physics2d.AxisConstraint.prototype.applyConstraint = function(p){ 367 | p.setComponent(this.axis,this.constraint); 368 | };toxi.physics2d.CircularConstraint = function(a,b){ 369 | if(arguments.length == 1){ 370 | this.circle = a; 371 | } else { 372 | console.log("a: "+a); 373 | this.circle = new toxi.Circle(a,b); 374 | } 375 | }; 376 | 377 | toxi.physics2d.CircularConstraint.prototype.applyConstraint = function(p){ 378 | if(this.circle.containsPoint(p)){ 379 | p.set(this.circle.add(p.sub(this.circle).normalizeTo(this.circle.getRadius()))); 380 | } 381 | };toxi.physics2d.MaxConstraint = function(axis,threshold){ 382 | this.axis = axis; 383 | this.threshold = threshold; 384 | }; 385 | 386 | toxi.physics2d.MaxConstraint.prototype.applyConstraint = function(p){ 387 | if(p.getComponent(this.axis) > this.threshold){ 388 | p.setComponent(this.axis,this.threshold); 389 | } 390 | };toxi.physics2d.MinConstraint = function(axis,threshold){ 391 | this.axis = axis; 392 | this.threshold = threshold; 393 | }; 394 | 395 | toxi.physics2d.MinConstraint.prototype.applyConstraint = function(p){ 396 | if(p.getComponent(this.axis) < this.threshold){ 397 | p.setComponent(this.axis, this.threshold); 398 | } 399 | };toxi.physics2d.RectConstraint = function(a,b){ 400 | if(arguments.length == 1){ 401 | this.rect = a.copy(); 402 | } else if(arguments.length > 1){ 403 | this.rect = new toxi.Rect(a,b); 404 | } 405 | this.intersectRay = new toxi.Ray2D(this.rect.getCentroid(), new toxi.Vec2D()); 406 | }; 407 | 408 | toxi.physics2d.RectConstraint.prototype = { 409 | applyConstraint: function(p){ 410 | if(this.rect.containsPoint(p)){ 411 | p.set(this.rect.intersectsRay(this.intersectRay.setDirection(this.intersectRay.sub(p)),0,Number.MAX_VALUE)); 412 | } 413 | }, 414 | 415 | getBox: function(){ 416 | return this.rect.copy(); 417 | }, 418 | 419 | setBox: function(rect){ 420 | this.rect = rect.copy(); 421 | this.intersectRay.set(this.rect.getCentroid()); 422 | } 423 | };toxi.physics2d.ParticlePath2D = function(points){ 424 | toxi.Spline2D.call(this,points); 425 | this.particles = []; 426 | }; 427 | toxi.extend(toxi.physics2d.ParticlePath2D,toxi.Spline2D); 428 | 429 | (function(){ 430 | //protected 431 | var createSingleParticle = function(pos,mass){ 432 | return new toxi.physics2d.VerletParticle2D(pos,mass); 433 | }; 434 | 435 | //public 436 | toxi.physics2d.ParticlePath2D.prototype.createParticles = function(physics,subDiv,step,mass){ 437 | this.particles = []; 438 | this.computeVertices(subDiv); 439 | var i = 0; 440 | var dv = this.getDecimatedVertices(step,true); 441 | for(i = 0; i < dv; i++){ 442 | var p = this.createSingleParticle(v,mass); 443 | this.particles.push(p); 444 | physics.addParticle(p); 445 | } 446 | return this.particles; 447 | }; 448 | 449 | 450 | })();/** 451 | * Utility builder/grouping/management class to connect a set of particles into 452 | * a physical string/thread. Custom spring types can be used by subclassing this 453 | * class and overwriting the 454 | * {@link #createSpring(VerletParticle2D, VerletParticle2D, float, float)} 455 | method. 456 | */ 457 | 458 | /** 459 | Construct a ParticleString2D, 460 | parameter options: 461 | 1 - options object 462 | 3 - VerletPhysics2D physics, Array plist, Number strength 463 | 6 - VerletPhysics2D physic, Vec2D pos, Vec2D step, Number num, Number mass, Number strength 464 | */ 465 | 466 | toxi.physics2d.ParticleString2D = function(){ 467 | var opts = { 468 | physics: undefined, 469 | plist: undefined, 470 | pos: undefined, 471 | step: undefined, 472 | num: undefined, 473 | mass: undefined, 474 | strength: undefined 475 | }, 476 | is6ParamConstructor = false; 477 | if(arguments.length === 0){ 478 | throw new Error("Incorrect Parameters"); 479 | } else if(arguments.length == 1){ //options object 480 | var arg = arguments[0]; 481 | for(var prop in arg){ 482 | opts[prop] = arg[prop]; 483 | } 484 | } else { 485 | opts.physics = arguments[0]; 486 | if(arguments.length == 6){ 487 | opts.pos = arguments[1]; 488 | opts.step = arguments[2]; 489 | opts.num = arguments[3]; 490 | opts.mass = arguments[4]; 491 | opts.strength = arguments[5]; 492 | } else { 493 | opts.plist = arguments[1]; 494 | opts.strength = arguments[2]; 495 | } 496 | } 497 | if(opts.num !== undefined && opts.pos !== undefined && opts.step !== undefined && opts.mass !== undefined){ 498 | is6ParamConstructor = true; 499 | } 500 | if(!is6ParamConstructor && opts.plist === undefined){ 501 | throw new Error("Incorrect Parameters, please supply plist or num, pos, step & mass"); 502 | } 503 | 504 | 505 | this.physics = opts.physics; 506 | this.links = []; 507 | 508 | var prev, 509 | p, 510 | s, 511 | strength, 512 | i = 0; 513 | 514 | 515 | if(is6ParamConstructor){ 516 | var pos = opts.pos.copy(), 517 | step = opts.step, 518 | mass = opts.mass, 519 | len = step.magnitude(); 520 | this.particles = []; 521 | strength = opts.strength; 522 | 523 | for(i = 0; i < opts.num; i++){ 524 | p = new toxi.physics2d.VerletParticle2D(pos.copy(),mass); 525 | this.particles.push(p); 526 | this.physics.particles.push(p); 527 | if(prev !== undefined){ 528 | s = this.createSpring(prev,p,len,strength); 529 | this.links.push(s); 530 | this.physics.addSpring(s); 531 | } 532 | prev = p; 533 | pos.addSelf(step); 534 | } 535 | } else { 536 | strength = opts.strength; 537 | this.particles = opts.plist || []; 538 | 539 | 540 | for(i = 0; i < this.particles.length; i++){ 541 | p = this.particles[i]; 542 | this.physics.addParticle(p); 543 | if(prev !== undefined){ 544 | s = this.createSpring(prev,p,prev.distanceTo(p),strength); 545 | this.links.push(s); 546 | this.physics.addSpring(s); 547 | } 548 | prev = p; 549 | } 550 | } 551 | }; 552 | toxi.physics2d.ParticleString2D.prototype = { 553 | clear: function(){ 554 | for(var i = 0, len = this.links.length; i < len; i++){ 555 | this.physics.removeSpringElements(s); 556 | } 557 | this.particles.clear(); 558 | this.links.clear(); 559 | }, 560 | createSpring: function(a,b,len,strength){ 561 | return new toxi.physics2d.VerletSpring2D(a,b,len,strength); 562 | }, 563 | 564 | getHead: function(){ 565 | return this.particles[0]; 566 | }, 567 | 568 | getNumParticles: function(){ 569 | return this.particles.length; 570 | }, 571 | 572 | getTail: function(){ 573 | return this.particles[this.particles.length-1]; 574 | } 575 | 576 | };/** 577 | * Creates a pullback spring (default restlength=0.5) between 2 particles and 578 | * locks the first one given at the current position. The spring is only 579 | * enforced if the current length of the spring exceeds the rest length. This 580 | * behaviour is the opposite to the {@link VerletMinDistanceSpring2D}. 581 | */ 582 | 583 | toxi.physics2d.PullBackString2D = function(a,b,strength){ 584 | toxi.physics2d.VerletSpring2D.apply(this,[a,b,0,strength]); 585 | a.lock(); 586 | this.setRestLength(0.5); 587 | }; 588 | toxi.extend(toxi.physics2d.PullBackString2D,toxi.physics2d.VerletSpring2D); 589 | 590 | toxi.physics2d.PullBackString2D.prototype.update = function(applyConstraints){ 591 | if(this.b.distanceToSquared(this.a) > this.restLengthSquared){ 592 | this.parent.update.call(this,applyConstraints); 593 | } 594 | };toxi.physics2d.VerletConstrainedSpring2D = function(particleA, particleB, len, str, limit){ 595 | toxi.physics2d.VerletSpring2D.call(this,particleA,particleB,len,str); 596 | this.limit = (limit === undefined) ? Number.MAX_VALUE : limit; 597 | }; 598 | 599 | toxi.extend(toxi.physics2d.VerletConstrainedSpring2D,toxi.physics2d.VerletSpring2D); 600 | 601 | 602 | toxi.physics2d.VerletConstrainedSpring2D.update = function(applyConstraints){ 603 | var delta = this.b.sub(this.a); 604 | // add minute offset to avoid div-by-zero errors 605 | var dist = delta.magnitude() + toxi.physics2d.VerletSpring2D.EPS; 606 | var normDistStrength = (dist - this.restLength) / (dist * (this.a.invWeight + this.b.invWeight))* this.strength; 607 | if (!this.a.isLocked && !this.isALocked) { 608 | this.a.addSelf(delta.scale(normDistStrength * this.a.invWeight).limit(this.limit)); 609 | if (applyConstraints) { 610 | this.a.applyConstraints(); 611 | } 612 | } 613 | if (!this.b.isLocked && !this.isBLocked) { 614 | this.b.subSelf(delta.scale(normDistStrength * this.b.invWeight).limit(this.limit)); 615 | if (applyConstraints) { 616 | this.b.applyConstraints(); 617 | } 618 | } 619 | };toxi.physics2d.VerletMinDistanceSpring2D = function(particleA,particleB,len,str){ 620 | toxi.physics2d.VerletSpring2D.call(this,particleA,particleB,len,str); 621 | this.setRestLength(len); 622 | }; 623 | 624 | 625 | toxi.extend(toxi.physics2d.VerletMinDistanceSpring2D,toxi.physics2d.VerletSpring2D); 626 | 627 | toxi.physics2d.VerletMinDistanceSpring2D.prototype.update = function(applyConstraints){ 628 | if(this.b.distanceToSquared(this.a) < this.restLengthSquared){ 629 | this.parent.update.call(this,applyConstraints); 630 | } 631 | };toxi.physics2d.VerletPhysics2D = function(gravity, numIterations, drag, timeStep){ 632 | var opts = { 633 | numIterations: 50, 634 | drag: 0, 635 | timeStep: 1 636 | }, 637 | args; 638 | if(arguments.length == 1 && (arguments[0].gravity || arguments[0].numIterations || arguments[0].timeStep || arguments[0].drag)){ //options object literal 639 | args = arguments[0]; 640 | if(args.gravity !== undefined){ 641 | gravity = args.gravity; 642 | } 643 | if(args.numIterations !== undefined){ 644 | opts.numIterations = args.gravity; 645 | } 646 | if(args.drag !== undefined){ 647 | opts.drag = args.drag; 648 | } 649 | if(args.timeStep !== undefined){ 650 | opts.timeStep = args.timeStep; 651 | } 652 | } 653 | this.behaviors = []; 654 | this.particles = []; 655 | this.springs = []; 656 | this.numIterations = opts.numIterations; 657 | this.timeStep = opts.timeStep; 658 | this.setDrag(opts.drag); 659 | 660 | if(gravity){ 661 | if(gravity instanceof toxi.physics2d.GravityBehavior){ 662 | this.addBehavior(gravity); 663 | } else if(gravity instanceof Object && gravity.hasOwnProperty('x') && gravity.hasOwnProperty('y')){ 664 | this.addBehavior( 665 | new toxi.physics2d.GravityBehavior( 666 | new toxi.Vec2D(gravity) 667 | ) 668 | ); 669 | } 670 | } 671 | }; 672 | 673 | toxi.physics2d.VerletPhysics2D.addConstraintToAll = function(c, list){ 674 | for(var i=0;i 0; i--){ 838 | for(j = 0;j "); 28 | } -------------------------------------------------------------------------------- /vendor/un/Unctrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by unctrl.com 3 | * User: mannytan 4 | * Date: 8/22/11 5 | */ 6 | 7 | var UNCTRL = UNCTRL || {}; -------------------------------------------------------------------------------- /vendor/un/Utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by . 3 | * User: manuelt 4 | * unsorted utils, will ned to convert to a framework eventually 5 | */ 6 | function distanceTo(a, b) { 7 | var dx = a.x - b.x; 8 | var dy = a.y - b.y; 9 | return Math.sqrt((dx * dx) + (dy * dy)); 10 | } 11 | 12 | function dotProduct(v0, v) { 13 | return (v0.x * v.x) + (v0.y * v.y); 14 | } 15 | 16 | function crossProduct(v0, v) { 17 | return(v0.x * v.y) - (v.x * v0.y); 18 | } 19 | function randomRange(min, max) { 20 | return ((Math.random() * (max - min)) + min); 21 | } 22 | function randomRange(min, max, expo) { 23 | return toDecimal(((Math.random() * (max - min)) + min), expo); 24 | } 25 | function toDecimal(arg, expo) { 26 | return parseFloat(arg.toFixed(expo)); 27 | } 28 | 29 | function clamp(min, max, value) { 30 | return Math.max(min, Math.min(max, value)); 31 | } 32 | 33 | function shuffleArray(total){ 34 | var a = []; 35 | var b = []; 36 | for (var i=0; i0) { 40 | b.push(a.splice( (Math.random()*a.length) , 1)|0); 41 | } 42 | return b; 43 | } 44 | 45 | function getUrlVars() { 46 | var vars = {}; 47 | var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { 48 | vars[key] = value; 49 | }); 50 | return vars; 51 | } 52 | 53 | var TO_DEGREES = 180 / Math.PI; 54 | var TO_RADIANS = Math.PI / 180; 55 | var TWO_PI = Math.PI * 2; 56 | var ONE_PI = Math.PI; 57 | 58 | function hsvToHex(h, s, v){ 59 | 60 | var r, g, b; 61 | 62 | var i = Math.floor(h * 6); 63 | var f = h * 6 - i; 64 | var p = v * (1 - s); 65 | var q = v * (1 - f * s); 66 | var t = v * (1 - (1 - f) * s); 67 | 68 | switch(i % 6){ 69 | case 0: r = v, g = t, b = p; break; 70 | case 1: r = q, g = v, b = p; break; 71 | case 2: r = p, g = v, b = t; break; 72 | case 3: r = p, g = q, b = v; break; 73 | case 4: r = t, g = p, b = v; break; 74 | case 5: r = v, g = p, b = q; break; 75 | } 76 | 77 | return "0x" + (((1 << 24) + ((r * 255) << 16) + ((g * 255) << 8) + (b * 255))|0).toString(16).slice(1); 78 | 79 | } 80 | --------------------------------------------------------------------------------