├── screenshots └── lines.jpg ├── README.md ├── index.html ├── LICENSE ├── camera_v1.05.js ├── main.js ├── gl-matrix-min.js └── dat.gui.min.js /screenshots/lines.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Domenicobrz/Variable-width-lines-algorithm/HEAD/screenshots/lines.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Variable-width-lines-algorithm 2 | 3 | 4 | 5 | Quick webGL implementation of an algorithm which creates variable width lines supporting miter and bevel join 6 | 7 | The algorithm works by projecting 3D lines to screen space coordinates which are subsequently expanded to form arbitrarily large lines -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Domenicobrz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /camera_v1.05.js: -------------------------------------------------------------------------------- 1 | //expects gl-matrix-min to be defined before the current script 2 | //^ potresti creare la tua lookAt function così elimini questa dipendenza 3 | //expects a variable called zoom (perspective focal length) to be connected with the projection/orthogonal matrix 4 | //you can't change the camera variable name (unless you'd like to find and replace) 5 | 6 | 7 | 8 | 9 | 10 | 11 | //se lo zoom è alto aumentiamo lo smoothness? stile minecraft! 12 | 13 | 14 | 15 | 16 | /* 17 | 18 | HOW TO USE: 19 | 20 | var camera = new createCamera(); 21 | 22 | INSIDE DRAW: 23 | 24 | var view = camera.getViewMatrix(deltatime, 0.3); 25 | 26 | */ 27 | 28 | 29 | 30 | //namespacia tutte le variabili 31 | //tutti i metodi devono essere interni a camera 32 | 33 | 34 | 35 | 36 | 37 | //you should really namespace all those functions 38 | 39 | 40 | function createCamera() 41 | { 42 | /* functions */ 43 | this.getViewMatrix = getViewMatrix; 44 | this.params = camera_params; 45 | this.camera_keydown = camera_keydown; 46 | this.camera_keyup = camera_keyup; 47 | this.camera_mousemove = camera_mousemove; 48 | this.camera_mousedown = camera_mousedown; 49 | this.camera_mouseup = camera_mouseup; 50 | this.camera_zoom = camera_zoom; 51 | 52 | this.camera_touchdown = camera_touchdown; 53 | this.camera_touchup = camera_touchup; 54 | this.camera_touchmove = camera_touchmove; 55 | 56 | 57 | 58 | this.pos = vec3.fromValues(0, 0, 0); 59 | this.up = vec3.fromValues(0, 1, 0); 60 | this.front = vec3.fromValues(0, 0, -1); 61 | this.frontCross = vec3.fromValues(0, 0, 0); 62 | this.dir = vec3.fromValues(0, 0, 0); 63 | 64 | 65 | /* optional args */ 66 | this.speed = 5.0; 67 | this.zoom_smoothness = 0.1; 68 | 69 | 70 | 71 | //to use the autocentered view specify 72 | //autocentered as true 73 | //where to look with this.look 74 | //and a radius distance with this.radius 75 | this.autoCentered = false; 76 | this.autoRotate = false; 77 | this.autoRotateSpeed = 3.0; //degree/sec 78 | this.radius = 3.0; 79 | this.look = [0,0,0]; 80 | this.mousecontrols = true; 81 | this.depth_of_field_transform_count = 0; 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | this.lookAt = mat4.create(); 91 | this.yaw = -3.14/2; //-90 e sai perchè 92 | this.pitch = 0; 93 | this.deltaRot = [0.0, 0.0]; 94 | this.lastPos = [null, null]; 95 | this.deltazoom = 0; 96 | 97 | this.dragging = false; 98 | this.startingZoom = window.zoom; 99 | this.zoomdefined = false; 100 | //tries to make camera movement smoother by checking for frameskips 101 | this.smoothDeltaTimeCheck = true; 102 | this.rotationSensitivity = 0.002; 103 | 104 | 105 | this.pressedKeys = { w: false, 106 | s: false, 107 | a: false, 108 | d: false, 109 | space: false, 110 | shift: false, 111 | la: false, 112 | ua: false, 113 | ra: false, 114 | da: false }; 115 | 116 | 117 | 118 | 119 | if(this.mousecontrols) { 120 | window.addEventListener("keydown", this.camera_keydown.bind(this)); 121 | window.addEventListener("keyup", this.camera_keyup.bind(this)); 122 | document.getElementById('canvas').addEventListener("mousemove", this.camera_mousemove.bind(this)); 123 | document.getElementById('canvas').addEventListener("mousedown", this.camera_mousedown.bind(this)); 124 | window.addEventListener("mouseup", this.camera_mouseup.bind(this)); 125 | 126 | 127 | document.getElementById('canvas').addEventListener("touchstart", this.camera_touchdown.bind(this)); 128 | document.getElementById('canvas').addEventListener("touchmove", this.camera_touchmove.bind(this)); 129 | window.addEventListener("touchend", this.camera_touchup.bind(this)); 130 | //window.addEventListener('mousewheel', this.camera_zoom.bind(this)); 131 | // For Firefox 132 | window.addEventListener('DOMMouseScroll', this.camera_zoom.bind(this)); 133 | } 134 | } 135 | 136 | function camera_params(zoom_smoothness, 137 | speed, 138 | _zoom, 139 | smoothDeltatime, 140 | rotationSensitivity) 141 | { 142 | if(zoom_smoothness !== undefined) 143 | this.zoom_smoothness = zoom_smoothness; 144 | 145 | if(speed !== undefined) 146 | this.speed = speed; 147 | 148 | if(_zoom !== undefined) 149 | this.startingZoom = _zoom; 150 | 151 | if(smoothDeltatime !== undefined) 152 | this.smoothDeltaTimeCheck = smoothDeltatime; 153 | 154 | if(rotationSensitivity !== undefined) 155 | this.rotationSensitivity = rotationSensitivity; 156 | } 157 | 158 | function getViewMatrix(deltatime, smoothness) 159 | { 160 | //smooths agains frameskipping 161 | if(this.smoothDeltaTimeCheck && deltatime <= 0.03333) 162 | { 163 | if(deltatime < 0.010) 164 | { } 165 | else 166 | deltatime = 0.016; 167 | } 168 | 169 | if(!this.zoomdefined) 170 | { 171 | this.startingZoom = zoom; 172 | this.zoomdefined = true; 173 | } 174 | 175 | if(this.autoCentered) 176 | { 177 | return camera_getAutocenteredViewMatrix.call(this, deltatime, smoothness, this.radius); 178 | } 179 | 180 | 181 | 182 | if(this.pressedKeys.w || this.pressedKeys.ua) { 183 | this.pos[0] += deltatime * this.speed * this.front[0]; 184 | this.pos[1] += deltatime * this.speed * this.front[1]; 185 | this.pos[2] += deltatime * this.speed * this.front[2]; 186 | } 187 | if(this.pressedKeys.s || this.pressedKeys.da) { 188 | this.pos[0] -= deltatime * this.speed * this.front[0]; 189 | this.pos[1] -= deltatime * this.speed * this.front[1]; 190 | this.pos[2] -= deltatime * this.speed * this.front[2]; 191 | } 192 | if(this.pressedKeys.d || this.pressedKeys.ra) { 193 | this.frontCross = vec3.cross(this.frontCross, this.front, this.up); 194 | vec3.normalize(this.frontCross, this.frontCross); 195 | this.pos[0] += deltatime * this.speed * this.frontCross[0]; 196 | this.pos[1] += deltatime * this.speed * this.frontCross[1]; 197 | this.pos[2] += deltatime * this.speed * this.frontCross[2]; 198 | } 199 | if(this.pressedKeys.a || this.pressedKeys.la) { 200 | this.frontCross = vec3.cross(this.frontCross, this.front, this.up); 201 | vec3.normalize(this.frontCross, this.frontCross); 202 | this.pos[0] -= deltatime * this.speed * this.frontCross[0]; 203 | this.pos[1] -= deltatime * this.speed * this.frontCross[1]; 204 | this.pos[2] -= deltatime * this.speed * this.frontCross[2]; 205 | } 206 | if(this.pressedKeys.space) { 207 | this.pos[0] += deltatime * this.speed * this.up[0]; 208 | this.pos[1] += deltatime * this.speed * this.up[1]; 209 | this.pos[2] += deltatime * this.speed * this.up[2]; 210 | } 211 | if(this.pressedKeys.shift) { 212 | this.pos[0] -= deltatime * this.speed * this.up[0]; 213 | this.pos[1] -= deltatime * this.speed * this.up[1]; 214 | this.pos[2] -= deltatime * this.speed * this.up[2]; 215 | } 216 | 217 | 218 | 219 | 220 | 221 | this.yaw += this.deltaRot[0] * smoothness; 222 | this.pitch -= this.deltaRot[1] * smoothness; 223 | 224 | this.deltaRot[0] -= this.deltaRot[0] * smoothness; 225 | this.deltaRot[1] -= this.deltaRot[1] * smoothness; 226 | 227 | if(this.pitch > 3.13/2) this.pitch = 3.13/2; 228 | if(this.pitch < -3.13/2) this.pitch = -3.13/2; 229 | 230 | this.front[0] = Math.cos(this.yaw) * Math.cos(this.pitch); 231 | this.front[1] = Math.sin(this.pitch); 232 | this.front[2] = Math.sin(this.yaw) * Math.cos(this.pitch); 233 | vec3.normalize(this.front, this.front); 234 | 235 | 236 | 237 | 238 | 239 | 240 | if(Math.abs(this.deltazoom) > 0) 241 | { 242 | var increment = this.deltazoom * this.zoom_smoothness; 243 | if(this.deltazoom < 0) this.deltazoom = this.deltazoom < -0.01 ? 244 | this.deltazoom - increment : 0; 245 | 246 | if(this.deltazoom > 0) this.deltazoom = this.deltazoom > +0.01 ? 247 | this.deltazoom - increment : 0; 248 | 249 | zoom += increment; 250 | if(zoom < 44.5) zoom = 44.5; 251 | if(zoom > this.startingZoom) zoom = this.startingZoom; 252 | } 253 | 254 | 255 | 256 | 257 | 258 | this.dir[0] = this.pos[0] + this.front[0]; 259 | this.dir[1] = this.pos[1] + this.front[1]; 260 | this.dir[2] = this.pos[2] + this.front[2]; 261 | mat4.lookAt(this.lookAt, this.pos, this.dir, this.up); 262 | return this.lookAt; 263 | } 264 | 265 | function camera_keydown(e) 266 | { 267 | switch(e.keyCode) { 268 | case 87: 269 | this.pressedKeys.w = true; 270 | break; 271 | case 65: 272 | this.pressedKeys.a = true; 273 | break; 274 | case 83: 275 | this.pressedKeys.s = true; 276 | break; 277 | case 68: 278 | this.pressedKeys.d = true; 279 | break; 280 | case 32: 281 | this.pressedKeys.space = true; 282 | break; 283 | case 16: 284 | this.pressedKeys.shift = true; 285 | break; 286 | case 37: 287 | this.pressedKeys.la = true; 288 | break; 289 | case 38: 290 | this.pressedKeys.ua = true; 291 | break; 292 | case 39: 293 | this.pressedKeys.ra = true; 294 | break; 295 | case 40: 296 | this.pressedKeys.da = true; 297 | break; 298 | } 299 | } 300 | 301 | function camera_keyup(e) 302 | { 303 | switch(e.keyCode) { 304 | case 87: 305 | this.pressedKeys.w = false; 306 | break; 307 | case 65: 308 | this.pressedKeys.a = false; 309 | break; 310 | case 83: 311 | this.pressedKeys.s = false; 312 | break; 313 | case 68: 314 | this.pressedKeys.d = false; 315 | break; 316 | case 32: 317 | this.pressedKeys.space = false; 318 | break; 319 | case 16: 320 | this.pressedKeys.shift = false; 321 | break; 322 | case 37: 323 | this.pressedKeys.la = false; 324 | break; 325 | case 38: 326 | this.pressedKeys.ua = false; 327 | break; 328 | case 39: 329 | this.pressedKeys.ra = false; 330 | break; 331 | case 40: 332 | this.pressedKeys.da = false; 333 | break; 334 | } 335 | } 336 | 337 | function camera_mousemove(e) 338 | { 339 | if(!this.dragging) return; 340 | 341 | //sta telecamera va fatta col click, non è un fps 342 | this.deltaRot[0] += (e.clientX - this.lastPos[0]) * this.rotationSensitivity; 343 | this.deltaRot[1] += (e.clientY - this.lastPos[1]) * this.rotationSensitivity; 344 | 345 | 346 | this.lastPos[0] = e.clientX; 347 | this.lastPos[1] = e.clientY; 348 | } 349 | 350 | function camera_touchmove(e) 351 | { 352 | if(!this.dragging) return; 353 | 354 | //sta telecamera va fatta col click, non è un fps 355 | this.deltaRot[0] += (e.touches[0].clientX - this.lastPos[0]) * this.rotationSensitivity; 356 | this.deltaRot[1] += (e.touches[0].clientY - this.lastPos[1]) * this.rotationSensitivity; 357 | 358 | 359 | this.lastPos[0] = e.touches[0].clientX; 360 | this.lastPos[1] = e.touches[0].clientY; 361 | } 362 | 363 | 364 | function camera_mousedown(e) 365 | { 366 | if(e.which != 1) return; 367 | this.lastPos[0] = e.clientX; 368 | this.lastPos[1] = e.clientY; 369 | this.dragging = true; 370 | } 371 | 372 | function camera_mouseup(e) 373 | { 374 | this.dragging = false; 375 | } 376 | 377 | function camera_touchdown(e) 378 | { 379 | this.lastPos[0] = e.touches[0].clientX; 380 | this.lastPos[1] = e.touches[0].clientY; 381 | this.dragging = true; 382 | } 383 | 384 | function camera_touchup(e) 385 | { 386 | this.dragging = false; 387 | } 388 | 389 | 390 | function camera_zoom(e) 391 | { 392 | var delta = e.wheelDelta ? e.wheelDelta : -e.detail; 393 | 394 | if(delta > 0) 395 | this.deltazoom += -0.15; 396 | else 397 | this.deltazoom += +0.15; 398 | } 399 | 400 | 401 | function camera_getAutocenteredViewMatrix(deltatime, smoothness, radius) 402 | { 403 | this.yaw += this.deltaRot[0] * smoothness; 404 | this.pitch -= this.deltaRot[1] * smoothness; 405 | 406 | if(this.autoRotate) 407 | { 408 | this.yaw += (this.autoRotateSpeed / 180 * Math.PI) * deltatime; 409 | } 410 | 411 | 412 | this.deltaRot[0] -= this.deltaRot[0] * smoothness; 413 | this.deltaRot[1] -= this.deltaRot[1] * smoothness; 414 | 415 | if(this.pitch > 3.13/2) this.pitch = 3.13/2; 416 | if(this.pitch < -3.13/2) this.pitch = -3.13/2; 417 | 418 | 419 | if(Math.abs(this.deltazoom) > 0) 420 | { 421 | var increment = this.deltazoom * this.zoom_smoothness; 422 | if(this.deltazoom < 0) this.deltazoom = this.deltazoom < -0.01 ? 423 | this.deltazoom - increment : 0; 424 | 425 | if(this.deltazoom > 0) this.deltazoom = this.deltazoom > +0.01 ? 426 | this.deltazoom - increment : 0; 427 | 428 | zoom += increment; 429 | if(zoom < 44.5) zoom = 44.5; 430 | if(zoom > this.startingZoom) zoom = this.startingZoom; 431 | } 432 | 433 | 434 | 435 | var xpos = Math.cos(this.yaw) * Math.cos(this.pitch) * radius; 436 | var zpos = Math.sin(this.yaw) * Math.cos(this.pitch) * radius; 437 | var ypos = Math.sin(this.pitch) * radius; 438 | 439 | 440 | this.pos[0] = xpos + this.look[0]; 441 | this.pos[1] = ypos + this.look[1]; 442 | this.pos[2] = -zpos + this.look[2]; 443 | 444 | 445 | mat4.lookAt(this.lookAt, this.pos, this.look, this.up); 446 | 447 | 448 | 449 | 450 | if(this.depth_of_field_transform_count != 0) { 451 | 452 | 453 | var degree = 6.28 * this.depth_of_field_transform_count / 10; 454 | 455 | var yaw = this.yaw + Math.cos(degree) / 150; 456 | var pitch = this.pitch + Math.sin(degree) / 150; 457 | 458 | /*var yaw = this.yaw// + 459 | this.depth_of_field_transform_count / 1500 - 460 | 5 / 1500; 461 | 462 | var pitch = this.pitch + 463 | this.depth_of_field_transform_count / 1600 - 464 | 5 / 1600;*/ 465 | 466 | var xpos = Math.cos(yaw) * Math.cos(pitch) * radius; 467 | var zpos = Math.sin(yaw) * Math.cos(pitch) * radius; 468 | var ypos = Math.sin(pitch) * radius; 469 | 470 | 471 | this.pos[0] = xpos + this.look[0]; 472 | this.pos[1] = ypos + this.look[1]; 473 | this.pos[2] = -zpos + this.look[2]; 474 | 475 | mat4.lookAt(this.lookAt, this.pos, this.look, this.up); 476 | } 477 | 478 | 479 | return this.lookAt; 480 | } 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | //v1.00 - basic functions 489 | //v1.02 - autocentered Camera 490 | //v1.03 - basic autoRotate 491 | //v1.04 - getAutoCenteredViewMatrix has depth of field capabilities 492 | //v1.05 - works on cellphones -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', pageInit); 2 | 3 | var projection = mat4.create(); 4 | var model = mat4.create(); 5 | var view = mat4.create(); 6 | var gl; 7 | var zoom = 45; 8 | 9 | function pageInit() { 10 | "use strict"; 11 | 12 | var names = ["webgl", "experimental-webgl"]; 13 | 14 | var canvas = document.querySelector('canvas'); 15 | canvas.width = innerWidth; 16 | canvas.height = innerHeight; 17 | 18 | for (var i in names) { 19 | try { 20 | gl = canvas.getContext(names[i], {}); 21 | 22 | if (gl && typeof gl.getParameter == "function") { 23 | // WebGL is enabled 24 | break; 25 | } 26 | } catch (e) { } 27 | } 28 | 29 | if (gl === null) 30 | alert("could not initialize WebGL"); 31 | 32 | 33 | 34 | mat4.perspective(projection, 45, innerWidth / innerHeight, 0.1, 100); 35 | window.camera = new createCamera(); 36 | camera.pos = [0, 0, 30]; 37 | camera.autoCentered = true; 38 | camera.radius = 30; 39 | 40 | initGui(); 41 | createMainProgram(); 42 | render(0); 43 | } 44 | 45 | function createMainProgram() { 46 | "use strict"; 47 | 48 | var vertex_shader = 49 | "attribute vec3 aPos;" + 50 | "attribute vec3 aPrevPos;" + 51 | "attribute vec3 aNextPos;" + 52 | "attribute float aId;" + 53 | "" + 54 | "uniform mat4 uProjection;" + 55 | "uniform mat4 uView;" + 56 | "uniform float uRatio;" + 57 | 58 | "uniform float uTime;" + 59 | "" + 60 | "void main() {" + 61 | 62 | " vec3 T = normalize(normalize(aPos - aPrevPos) + normalize(aNextPos - aPos));" + 63 | " vec3 N = vec3(-T.y, T.x, 0.0);" + 64 | 65 | " vec3 lineNormal = vec3(0.0);" + 66 | " vec3 lineVector = vec3(0.0);" + 67 | " if(aId == 1.0) {" + 68 | " lineVector = normalize(aNextPos - aPos);" + 69 | " lineNormal = -vec3(-lineVector.y, lineVector.x, 0.0);" + 70 | " }" + 71 | " if(aId == 2.0) {" + 72 | " lineVector = normalize(aNextPos - aPos);" + 73 | " lineNormal = vec3(-lineVector.y, lineVector.x, 0.0);" + 74 | " }" + 75 | " if(aId == 3.0) {" + 76 | " lineVector = normalize(aPos - aPrevPos);" + 77 | " lineNormal = -vec3(-lineVector.y, lineVector.x, 0.0);" + 78 | " }" + 79 | " if(aId > 3.0) {" + 80 | " lineVector = normalize(aPos - aPrevPos);" + 81 | " lineNormal = vec3(-lineVector.y, lineVector.x, 0.0);" + 82 | " }" + 83 | 84 | 85 | " float mult = dot(lineNormal, N);" + 86 | " N *= 1.0 / mult;" + 87 | 88 | 89 | " vec4 ndcpos; " + 90 | " if(abs(mult) > 0.4) " + 91 | " ndcpos = uProjection * uView * vec4(aPos + N * 0.07, 1.0);" + 92 | " else if(aId < 5.0) {" + 93 | " ndcpos = uProjection * uView * vec4(aPos + lineNormal * 0.07, 1.0);" + 94 | " } else {" + 95 | " vec3 L = normalize(aPos - aPrevPos);" + 96 | " vec3 L2 = normalize(aNextPos - aPos); " + 97 | " vec3 LN = vec3(-L.y, L.x, 0.0);" + 98 | " float leftorright = dot(LN, L2);" + 99 | " if(leftorright < 0.0) {" + 100 | " if(aId == 5.0) {" + 101 | " ndcpos = uProjection * uView * vec4(aPos - N * 0.07, 1.0);" + 102 | " }" + 103 | " if(aId == 6.0) {" + 104 | " ndcpos = uProjection * uView * vec4(aPos + lineNormal * 0.07, 1.0);" + 105 | " }" + 106 | " if(aId == 7.0) {" + 107 | //next line normal 108 | " vec3 NLN = normalize(vec3(aNextPos - aPos));" + 109 | " NLN = vec3(-NLN.y, NLN.x, 0.0);" + 110 | " ndcpos = uProjection * uView * vec4(aPos + NLN * 0.07, 1.0);" + 111 | " }" + 112 | " }" + 113 | 114 | " if(leftorright >= 0.0) {" + 115 | " if(aId == 5.0) {" + 116 | " ndcpos = uProjection * uView * vec4(aPos + N * 0.07, 1.0);" + 117 | " }" + 118 | " if(aId == 6.0) {" + 119 | " ndcpos = uProjection * uView * vec4(aPos - lineNormal * 0.07, 1.0);" + 120 | " }" + 121 | " if(aId == 7.0) {" + 122 | " vec3 NLN = normalize(vec3(aNextPos - aPos));" + 123 | " NLN = vec3(-NLN.y, NLN.x, 0.0);" + 124 | " ndcpos = uProjection * uView * vec4(aPos - NLN * 0.07, 1.0);" + 125 | " }" + 126 | " }" + 127 | " }" + 128 | 129 | " gl_Position = ndcpos;" + 130 | "}"; 131 | 132 | var screen_space_vertex_shader = 133 | "precision highp float;" + 134 | 135 | "attribute vec3 aPos;" + 136 | "attribute vec3 aPrevPos;" + 137 | "attribute vec3 aNextPos;" + 138 | "attribute float aId;" + 139 | "" + 140 | "uniform mat4 uProjection;" + 141 | "uniform mat4 uView;" + 142 | "uniform float uRatio;" + 143 | "uniform float uTime;" + 144 | 145 | 146 | "varying vec3 Color;" + 147 | 148 | 149 | "" + 150 | "void main() {" + 151 | 152 | " float expansion = 0.025; " + 153 | 154 | " vec4 ndcpos = uProjection * uView * vec4(aPos, 1.0);" + 155 | " vec2 ssaPos = vec2(uProjection * uView * vec4(aPos, 1.0));" + 156 | " vec2 ssaPrevPos = vec2(uProjection * uView * vec4(aPrevPos, 1.0));" + 157 | " vec2 ssaNextPos = vec2(uProjection * uView * vec4(aNextPos, 1.0));" + 158 | 159 | " ssaPos.xy /= (uProjection * uView * vec4(aPos, 1.0)).w; " + 160 | " ssaPrevPos.xy /= (uProjection * uView * vec4(aPrevPos, 1.0)).w; " + 161 | " ssaNextPos.xy /= (uProjection * uView * vec4(aNextPos, 1.0)).w; " + 162 | 163 | " ssaPos.x *= uRatio;" + 164 | " ssaPrevPos.x *= uRatio;" + 165 | " ssaNextPos.x *= uRatio;" + 166 | 167 | 168 | " vec2 T = normalize(normalize(ssaPos - ssaPrevPos) + normalize(ssaNextPos - ssaPos));" + 169 | " vec2 N = vec2(-T.y, T.x);" + 170 | 171 | " vec2 lineNormal = vec2(0.0);" + 172 | " vec2 lineVector = vec2(0.0);" + 173 | " if(aId == 1.0) {" + 174 | " lineVector = normalize(ssaNextPos - ssaPos);" + 175 | " lineNormal = -vec2(-lineVector.y, lineVector.x);" + 176 | " }" + 177 | " if(aId == 2.0) {" + 178 | " lineVector = normalize(ssaNextPos - ssaPos);" + 179 | " lineNormal = vec2(-lineVector.y, lineVector.x);" + 180 | " }" + 181 | " if(aId == 3.0) {" + 182 | " lineVector = normalize(ssaPos - ssaPrevPos);" + 183 | " lineNormal = -vec2(-lineVector.y, lineVector.x);" + 184 | " }" + 185 | " if(aId > 3.0) {" + 186 | " lineVector = normalize(ssaPos - ssaPrevPos);" + 187 | " lineNormal = vec2(-lineVector.y, lineVector.x);" + 188 | " }" + 189 | 190 | 191 | " float mult = dot(lineNormal, N);" + 192 | " N *= 1.0 / mult;" + 193 | 194 | 195 | " if(abs(mult) > 0.1) " + 196 | " ssaPos = (ssaPos + N * expansion);" + 197 | " else if(aId < 5.0) {" + 198 | " ssaPos = ssaPos + lineNormal * expansion;" + 199 | " } else {" + 200 | " vec2 L = normalize(ssaPos - ssaPrevPos);" + 201 | " vec2 L2 = normalize(ssaNextPos - ssaPos); " + 202 | " vec2 LN = vec2(-L.y, L.x);" + 203 | " float leftorright = dot(LN, L2);" + 204 | 205 | " if(leftorright < 0.0) {" + 206 | " if(aId == 5.0) {" + 207 | // will be fixed at the intersection point of the two rectangles 208 | " }" + 209 | " if(aId == 6.0) {" + 210 | " ssaPos = ssaPos + lineNormal * expansion;" + 211 | " }" + 212 | " if(aId == 7.0) {" + 213 | //next line normal 214 | " vec2 NLN = normalize(vec2(ssaNextPos - ssaPos));" + 215 | " NLN = vec2(-NLN.y, NLN.x);" + 216 | " ssaPos = ssaPos + NLN * expansion;" + 217 | " }" + 218 | " }" + 219 | 220 | " if(leftorright >= 0.0) {" + 221 | " if(aId == 5.0) {" + 222 | // will be fixed at the intersection point of the two rectangles 223 | " }" + 224 | " if(aId == 6.0) {" + 225 | " ssaPos = ssaPos - lineNormal * expansion;" + 226 | " }" + 227 | " if(aId == 7.0) {" + 228 | " vec2 NLN = normalize(ssaNextPos - ssaPos);" + 229 | " NLN = vec2(-NLN.y, NLN.x);" + 230 | " ssaPos = ssaPos - NLN * expansion;" + 231 | " }" + 232 | " }" + 233 | " }" + 234 | 235 | 236 | 237 | " ndcpos.x = (1.0 / uRatio) * ssaPos.x;" + 238 | " ndcpos.y = ssaPos.y;" + 239 | " ndcpos.z = ndcpos.z / ndcpos.w;" + 240 | " ndcpos.w = 1.0;" + 241 | " gl_Position = ndcpos;" + 242 | 243 | 244 | 245 | " Color = vec3(fract(aPos.x * 45678.0), fract(aPos.y * 45678.0), fract(aPos.z * 45678.0));" + 246 | 247 | "}"; 248 | 249 | 250 | 251 | var screen_space_animated_vertex_shader = 252 | "precision highp float;" + 253 | 254 | "attribute vec3 aPos;" + 255 | "attribute vec3 aPrevPos;" + 256 | "attribute vec3 aNextPos;" + 257 | "attribute float aId;" + 258 | "" + 259 | "uniform mat4 uProjection;" + 260 | "uniform mat4 uView;" + 261 | "uniform float uRatio;" + 262 | "uniform float uTime;" + 263 | "uniform float uExpansion;" + 264 | "uniform float uDegMultiplier;" + 265 | 266 | 267 | "varying vec3 Color;" + 268 | 269 | 270 | "" + 271 | "void main() {" + 272 | 273 | 274 | " float deg1 = sin(uTime) * aPos.y * uDegMultiplier;" + 275 | " float deg2 = sin(uTime) * aPrevPos.y * uDegMultiplier;" + 276 | " float deg3 = sin(uTime) * aNextPos.y * uDegMultiplier;" + 277 | 278 | 279 | 280 | " mat4 rotMatrix1 = mat4(cos(deg1), 0, -sin(deg1), 0," + 281 | " 0, 1, 0, 0," + 282 | " sin(deg1), 0, cos(deg1), 0," + 283 | " 0, 0, 0, 1);" + 284 | " mat4 rotMatrix2 = mat4(cos(deg2), 0, -sin(deg2), 0," + 285 | " 0, 1, 0, 0," + 286 | " sin(deg2), 0, cos(deg2), 0," + 287 | " 0, 0, 0, 1);" + 288 | " mat4 rotMatrix3 = mat4(cos(deg3), 0, -sin(deg3), 0," + 289 | " 0, 1, 0, 0," + 290 | " sin(deg3), 0, cos(deg3), 0," + 291 | " 0, 0, 0, 1);" + 292 | 293 | 294 | 295 | " vec4 ndcpos = uProjection * uView * rotMatrix1 * vec4(aPos, 1.0);" + 296 | " vec2 ssaPos = vec2(uProjection * uView * rotMatrix1 * vec4(aPos, 1.0));" + 297 | " vec2 ssaPrevPos = vec2(uProjection * uView * rotMatrix2 * vec4(aPrevPos, 1.0));" + 298 | " vec2 ssaNextPos = vec2(uProjection * uView * rotMatrix3 * vec4(aNextPos, 1.0));" + 299 | 300 | " ssaPos.xy /= (uProjection * uView * vec4(aPos, 1.0)).w; " + 301 | " ssaPrevPos.xy /= (uProjection * uView * vec4(aPrevPos, 1.0)).w; " + 302 | " ssaNextPos.xy /= (uProjection * uView * vec4(aNextPos, 1.0)).w; " + 303 | 304 | " ssaPos.x *= uRatio;" + 305 | " ssaPrevPos.x *= uRatio;" + 306 | " ssaNextPos.x *= uRatio;" + 307 | 308 | 309 | 310 | 311 | " vec2 T = normalize(normalize(ssaPos - ssaPrevPos) + normalize(ssaNextPos - ssaPos));" + 312 | " vec2 N = vec2(-T.y, T.x);" + 313 | 314 | " vec2 lineNormal = vec2(0.0);" + 315 | " vec2 lineVector = vec2(0.0);" + 316 | " if(aId == 1.0) {" + 317 | " lineVector = normalize(ssaNextPos - ssaPos);" + 318 | " lineNormal = -vec2(-lineVector.y, lineVector.x);" + 319 | " }" + 320 | " if(aId == 2.0) {" + 321 | " lineVector = normalize(ssaNextPos - ssaPos);" + 322 | " lineNormal = vec2(-lineVector.y, lineVector.x);" + 323 | " }" + 324 | " if(aId == 3.0) {" + 325 | " lineVector = normalize(ssaPos - ssaPrevPos);" + 326 | " lineNormal = -vec2(-lineVector.y, lineVector.x);" + 327 | " }" + 328 | " if(aId > 3.0) {" + 329 | " lineVector = normalize(ssaPos - ssaPrevPos);" + 330 | " lineNormal = vec2(-lineVector.y, lineVector.x);" + 331 | " }" + 332 | 333 | 334 | " float mult = dot(lineNormal, N);" + 335 | " N *= 1.0 / mult;" + 336 | 337 | 338 | " if(abs(mult) > 200000000000000000000000000000000.0) " + 339 | " ssaPos = (ssaPos + N * uExpansion);" + 340 | " else if(aId < 5.0) {" + 341 | " ssaPos = ssaPos + lineNormal * uExpansion;" + 342 | " } else {" + 343 | " vec2 L = normalize(ssaPos - ssaPrevPos);" + 344 | " vec2 L2 = normalize(ssaNextPos - ssaPos); " + 345 | " vec2 LN = vec2(-L.y, L.x);" + 346 | " float leftorright = dot(LN, L2);" + 347 | 348 | " if(leftorright < 0.0) {" + 349 | " if(aId == 5.0) {" + 350 | // will be fixed at the intersection point of the two rectangles 351 | " }" + 352 | " if(aId == 6.0) {" + 353 | " ssaPos = ssaPos + lineNormal * uExpansion;" + 354 | " }" + 355 | " if(aId == 7.0) {" + 356 | // NLN = next line normal 357 | " vec2 NLN = normalize(vec2(ssaNextPos - ssaPos));" + 358 | " NLN = vec2(-NLN.y, NLN.x);" + 359 | " ssaPos = ssaPos + NLN * uExpansion;" + 360 | " }" + 361 | " }" + 362 | 363 | " if(leftorright >= 0.0) {" + 364 | " if(aId == 5.0) {" + 365 | // will be fixed at the intersection point of the two rectangles 366 | " }" + 367 | " if(aId == 6.0) {" + 368 | " ssaPos = ssaPos - lineNormal * uExpansion;" + 369 | " }" + 370 | " if(aId == 7.0) {" + 371 | " vec2 NLN = normalize(ssaNextPos - ssaPos);" + 372 | " NLN = vec2(-NLN.y, NLN.x);" + 373 | " ssaPos = ssaPos - NLN * uExpansion;" + 374 | " }" + 375 | " }" + 376 | " }" + 377 | 378 | 379 | 380 | " ndcpos.x = (1.0 / uRatio) * ssaPos.x;" + 381 | " ndcpos.y = ssaPos.y;" + 382 | " ndcpos.z = ndcpos.z / ndcpos.w;" + 383 | " ndcpos.w = 1.0;" + 384 | " gl_Position = ndcpos;" + 385 | 386 | 387 | " Color = vec3(0.2 + (aPos.x * 0.03 + 0.6), 0.4, 1.0);" + 388 | 389 | "}"; 390 | 391 | 392 | 393 | var fragment_shader = 394 | "precision mediump float;" + 395 | "varying vec3 Color;" + 396 | "" + 397 | "void main() {" + 398 | " gl_FragColor = vec4(Color, 1.0);" + 399 | "}"; 400 | 401 | var Program = createProgramFromSource(screen_space_animated_vertex_shader, fragment_shader, gl); 402 | Program.aId = gl.getAttribLocation(Program, "aId"); 403 | Program.aPos = gl.getAttribLocation(Program, "aPos"); 404 | Program.aPrevPos = gl.getAttribLocation(Program, "aPrevPos"); 405 | Program.aNextPos = gl.getAttribLocation(Program, "aNextPos"); 406 | 407 | Program.uProjection = gl.getUniformLocation(Program, "uProjection"); 408 | Program.uView = gl.getUniformLocation(Program, "uView"); 409 | 410 | Program.uRatio = gl.getUniformLocation(Program, "uRatio"); 411 | Program.uTime = gl.getUniformLocation(Program, "uTime"); 412 | Program.uExpansion = gl.getUniformLocation(Program, "uExpansion"); 413 | Program.uDegMultiplier = gl.getUniformLocation(Program, "uDegMultiplier"); 414 | 415 | Program.buffer = gl.createBuffer(); 416 | var vertices = []; 417 | 418 | 419 | 420 | window.MainProgram = Program; 421 | // we need main program defined before calling this function 422 | animateBufferData(0); 423 | } 424 | 425 | var then = 0; 426 | var step = Float32Array.BYTES_PER_ELEMENT; 427 | var zRotSpeed = 0; 428 | var waveIncreaserSpeed = 0; 429 | function render(now) { 430 | "use strict"; 431 | 432 | requestAnimationFrame(render); 433 | 434 | now *= 0.001; 435 | var deltatime = now - then; 436 | then = now; 437 | 438 | zRotSpeed += deltatime * effectController.zRotSpeed; 439 | waveIncreaserSpeed += deltatime * effectController.nWaveIncreaserSpeed; 440 | 441 | gl.useProgram(window.MainProgram); 442 | gl.clearColor(0.1, 0.1, 0.1, 1); 443 | gl.clear(gl.COLOR_BUFFER_BIT); 444 | gl.enable(gl.DEPTH_TEST); 445 | 446 | gl.bindBuffer(gl.ARRAY_BUFFER, window.MainProgram.buffer); 447 | gl.enableVertexAttribArray(MainProgram.aPos); 448 | gl.enableVertexAttribArray(MainProgram.aPrevPos); 449 | gl.enableVertexAttribArray(MainProgram.aNextPos); 450 | gl.enableVertexAttribArray(MainProgram.aId); 451 | 452 | gl.vertexAttribPointer(MainProgram.aPos, 3, gl.FLOAT, false, step * 10, step * 0); 453 | gl.vertexAttribPointer(MainProgram.aPrevPos, 3, gl.FLOAT, false, step * 10, step * 3); 454 | gl.vertexAttribPointer(MainProgram.aNextPos, 3, gl.FLOAT, false, step * 10, step * 6); 455 | gl.vertexAttribPointer(MainProgram.aId, 1, gl.FLOAT, false, step * 10, step * 9); 456 | 457 | gl.uniformMatrix4fv(MainProgram.uProjection, false, projection); 458 | gl.uniformMatrix4fv(MainProgram.uView, false, camera.getViewMatrix(deltatime, 0.3)); 459 | 460 | gl.uniform1f(MainProgram.uRatio, innerWidth / innerHeight); 461 | gl.uniform1f(MainProgram.uTime, zRotSpeed); 462 | gl.uniform1f(MainProgram.uExpansion, effectController.lineSize); 463 | gl.uniform1f(MainProgram.uDegMultiplier, effectController.degreeMultiplier); 464 | 465 | 466 | 467 | 468 | animateBufferData(waveIncreaserSpeed); 469 | 470 | gl.drawArrays(gl.TRIANGLES, 0, window.nverts); 471 | } 472 | 473 | 474 | function animateBufferData(now) { 475 | "use strict"; 476 | 477 | 478 | // if this doesn't look messy to you I don't know what will, just know we're animating the fancy circle you see on screen 479 | // yeah yeah I know this thing should need a crazy code refactor but life is short and I need to learn other stuff too 480 | var vertices = []; 481 | var steps = Math.floor(effectController.lineNumber); 482 | var size = 10; 483 | for (var i = 0; i < steps; i++) { 484 | var deg1 = i / steps * (Math.PI * 2); 485 | var deg2 = (i + 1) / steps * (Math.PI * 2); 486 | 487 | var deg3 = i / steps * (Math.PI * effectController.nWaves * (Math.sin(now) * 0.5 + 0.5)); 488 | var deg4 = (i + 1) / steps * (Math.PI * effectController.nWaves * (Math.sin(now) * 0.5 + 0.5)); 489 | var mult1 = Math.sin(deg3) * 0.15; 490 | var mult2 = Math.sin(deg4) * 0.15; 491 | 492 | var y1 = Math.sin(deg1) * (size + (size * mult1)); 493 | var x1 = Math.cos(deg1) * (size + (size * mult1)); 494 | var z1 = 0.0; 495 | 496 | var y2 = Math.sin(deg2) * (size + (size * mult2)); 497 | var x2 = Math.cos(deg2) * (size + (size * mult2)); 498 | var z2 = 0.0; 499 | 500 | if (i === steps - 1) { 501 | // last vertex of the circle will be joined to the first to close the path 502 | x2 = vertices[0]; 503 | y2 = vertices[1]; 504 | z2 = vertices[2]; 505 | } 506 | 507 | vertices.push(x1, y1, z1, x2, y2, z2); 508 | } 509 | 510 | 511 | gl.bindBuffer(gl.ARRAY_BUFFER, MainProgram.buffer); 512 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangulateLines(vertices)), gl.STATIC_DRAW); 513 | } 514 | 515 | 516 | function createProgramFromSource(vertexSource, fragmentSource, ctx) { 517 | var vs = createShaderFromSource(vertexSource, "vert", ctx); 518 | var fs = createShaderFromSource(fragmentSource, "frag", ctx); 519 | 520 | var Program = ctx.createProgram(); 521 | 522 | ctx.attachShader(Program, vs); 523 | ctx.attachShader(Program, fs); 524 | ctx.linkProgram(Program); 525 | 526 | 527 | if (!ctx.getProgramParameter(Program, ctx.LINK_STATUS)) { 528 | alert("Could not initialise shaders"); 529 | return null; 530 | } 531 | 532 | return Program; 533 | } 534 | function createShaderFromSource(source, type, ctx) { 535 | var shader; 536 | if (type == "frag") { 537 | shader = ctx.createShader(ctx.FRAGMENT_SHADER); 538 | } else if (type == "vert") { 539 | shader = ctx.createShader(ctx.VERTEX_SHADER); 540 | } else { 541 | return null; 542 | } 543 | ctx.shaderSource(shader, source); 544 | ctx.compileShader(shader); 545 | if (!ctx.getShaderParameter(shader, ctx.COMPILE_STATUS)) { 546 | alert(ctx.getShaderInfoLog(shader) + " " + type); 547 | return null; 548 | } 549 | return shader; 550 | } 551 | 552 | function initGui() { 553 | "use strict"; 554 | 555 | var gui = new dat.GUI(); 556 | 557 | window.effectController = { 558 | lineNumber: 180, 559 | lineSize: 0.025, 560 | degreeMultiplier: 0.5, 561 | zRotSpeed: 1, 562 | nWaves: 10, 563 | nWaveIncreaserSpeed: 1 564 | }; 565 | 566 | gui.add(effectController, "lineNumber", 0, 1000).onChange(fromGui); 567 | gui.add(effectController, "lineSize", 0.001, 0.15).onChange(fromGui); 568 | gui.add(effectController, "zRotSpeed", 0.0, 5.0).onChange(fromGui); 569 | gui.add(effectController, "degreeMultiplier", 0.0, 1.5).onChange(fromGui); 570 | gui.add(effectController, "nWaves", 0, 50).onChange(fromGui); 571 | gui.add(effectController, "nWaveIncreaserSpeed", 0.0, 5.0).onChange(fromGui); 572 | 573 | function fromGui() { 574 | animateBufferData(); 575 | } 576 | } 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | var reusableBuffer = [0, 0, 0]; 590 | /** every line is going to generate 3 triangles, 2 of them will form an expanded quad enclosing the line itself, 591 | * the third triangle will be used to create the bevel join. 592 | * Keep in mind the third triangle is applied/positioned "at the end" of the line 593 | * Triangulation could be summarized as follows: 594 | * ______________ 595 | * | |\ 596 | * |______________|_\ 597 | * 598 | * the rectangle is formed from the first two triangles, and the rightmost triangle will create a bevel join 599 | * 600 | * */ 601 | function triangulateLines(lines) { 602 | "use strict"; 603 | 604 | var buf = []; 605 | 606 | var length = lines.length / 6; 607 | 608 | // iterating over every line 609 | for (var i = 0; i < length; i++) { 610 | // first line vertex 611 | var v1x = lines[i * 6 + 0]; 612 | var v1y = lines[i * 6 + 1]; 613 | var v1z = lines[i * 6 + 2]; 614 | 615 | // second line vertex 616 | var v2x = lines[i * 6 + 3]; 617 | var v2y = lines[i * 6 + 4]; 618 | var v2z = lines[i * 6 + 5]; 619 | 620 | var v3x, v3y, v3z, v4x, v4y, v4z; 621 | 622 | // prev line vertex 623 | if (i === 0) { 624 | // extending along 1% of the line's length 625 | reusableBuffer[0] = v1x + (v1x - v2x) * 0.01; 626 | reusableBuffer[1] = v1y + (v1y - v2y) * 0.01; 627 | reusableBuffer[2] = v1z + (v1z - v2z) * 0.01; 628 | v3x = reusableBuffer[0]; 629 | v3y = reusableBuffer[1]; 630 | v3z = reusableBuffer[2]; 631 | } else { 632 | v3x = lines[(i - 1) * 6 + 0]; 633 | v3y = lines[(i - 1) * 6 + 1]; 634 | v3z = lines[(i - 1) * 6 + 2]; 635 | } 636 | 637 | // next line vertex 638 | if (i == length - 1) { 639 | // // extending along 1% of the line's length 640 | // reusableBuffer[0] = v2x + (v2x - v1x) * 0.01; 641 | // reusableBuffer[1] = v2y + (v2y - v1y) * 0.01; 642 | // reusableBuffer[2] = v2z + (v2z - v1z) * 0.01; 643 | // v4x = reusableBuffer[0]; 644 | // v4y = reusableBuffer[1]; 645 | // v4z = reusableBuffer[2]; 646 | 647 | // assigning to the first vertex to close the path 648 | v4x = lines[3]; 649 | v4y = lines[4]; 650 | v4z = lines[5]; 651 | } else { 652 | v4x = lines[(i + 1) * 6 + 3]; 653 | v4y = lines[(i + 1) * 6 + 4]; 654 | v4z = lines[(i + 1) * 6 + 5]; 655 | } 656 | 657 | 658 | constructTriangles(v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z, v4x, v4y, v4z, buf); 659 | } 660 | 661 | // how many triangles in buffer ? 662 | window.nverts = buf.length / 10; 663 | return buf; 664 | } 665 | 666 | 667 | function constructTriangles(v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z, v4x, v4y, v4z, buffer) { 668 | "use strict"; 669 | 670 | // structure of a vertex is as follow: 671 | 672 | // current vertex: 3 floats - prev vertex: 3 floats - next vertex: 3 floats - ID: 1 float 673 | /* 674 | 2 ______________ 4 675 | | | 676 | |______________| 677 | 1 3 678 | */ 679 | 680 | // triangle 1 681 | // vertex 1 682 | buffer.push(v1x, v1y, v1z, v3x, v3y, v3z, v2x, v2y, v2z, 1); 683 | // vertex 2 684 | buffer.push(v1x, v1y, v1z, v3x, v3y, v3z, v2x, v2y, v2z, 2); 685 | // vertex 3 686 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 3); 687 | 688 | 689 | // triangle 2 690 | // vertex 3 691 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 3); 692 | // vertex 2 693 | buffer.push(v1x, v1y, v1z, v3x, v3y, v3z, v2x, v2y, v2z, 2); 694 | // vertex 4 695 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 4); 696 | 697 | 698 | // third triangle, possible miter join. Vertices are: 3, 4, 4 699 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 5); 700 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 6); 701 | buffer.push(v2x, v2y, v2z, v1x, v1y, v1z, v4x, v4y, v4z, 7); 702 | } -------------------------------------------------------------------------------- /gl-matrix-min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview gl-matrix - High performance matrix and vector operations 3 | * @author Brandon Jones 4 | * @author Colin MacKenzie IV 5 | * @version 2.3.2 6 | */ 7 | 8 | /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. */ 27 | 28 | !function(t,a){if("object"==typeof exports&&"object"==typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define(a);else{var n=a();for(var r in n)("object"==typeof exports?exports:t)[r]=n[r]}}(this,function(){return function(t){function a(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,a),o.loaded=!0,o.exports}var n={};return a.m=t,a.c=n,a.p="",a(0)}([function(t,a,n){a.glMatrix=n(1),a.mat2=n(2),a.mat2d=n(3),a.mat3=n(4),a.mat4=n(5),a.quat=n(6),a.vec2=n(9),a.vec3=n(7),a.vec4=n(8)},function(t,a){var n={};n.EPSILON=1e-6,n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,n.RANDOM=Math.random,n.ENABLE_SIMD=!1,n.SIMD_AVAILABLE=n.ARRAY_TYPE===Float32Array&&"SIMD"in this,n.USE_SIMD=n.ENABLE_SIMD&&n.SIMD_AVAILABLE,n.setMatrixArrayType=function(t){n.ARRAY_TYPE=t};var r=Math.PI/180;n.toRadian=function(t){return t*r},t.exports=n},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},o.clone=function(t){var a=new r.ARRAY_TYPE(4);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},o.transpose=function(t,a){if(t===a){var n=a[1];t[1]=a[2],t[2]=n}else t[0]=a[0],t[1]=a[2],t[2]=a[1],t[3]=a[3];return t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=n*l-o*r;return u?(u=1/u,t[0]=l*u,t[1]=-r*u,t[2]=-o*u,t[3]=n*u,t):null},o.adjoint=function(t,a){var n=a[0];return t[0]=a[3],t[1]=-a[1],t[2]=-a[2],t[3]=n,t},o.determinant=function(t){return t[0]*t[3]-t[2]*t[1]},o.multiply=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=n[0],M=n[1],i=n[2],s=n[3];return t[0]=r*e+l*M,t[1]=o*e+u*M,t[2]=r*i+l*s,t[3]=o*i+u*s,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+l*e,t[1]=o*M+u*e,t[2]=r*-e+l*M,t[3]=o*-e+u*M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=n[0],M=n[1];return t[0]=r*e,t[1]=o*e,t[2]=l*M,t[3]=u*M,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=-n,t[3]=r,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=a[1],t},o.str=function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2))},o.LDU=function(t,a,n,r){return t[2]=r[2]/r[0],n[0]=r[0],n[1]=r[1],n[3]=r[3]-t[2]*n[1],[t,a,n]},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(6);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(6);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=n*l-r*o;return M?(M=1/M,t[0]=l*M,t[1]=-r*M,t[2]=-o*M,t[3]=n*M,t[4]=(o*e-l*u)*M,t[5]=(r*u-n*e)*M,t):null},o.determinant=function(t){return t[0]*t[3]-t[1]*t[2]},o.multiply=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=n[0],s=n[1],c=n[2],D=n[3],S=n[4],I=n[5];return t[0]=r*i+l*s,t[1]=o*i+u*s,t[2]=r*c+l*D,t[3]=o*c+u*D,t[4]=r*S+l*I+e,t[5]=o*S+u*I+M,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=Math.sin(n),s=Math.cos(n);return t[0]=r*s+l*i,t[1]=o*s+u*i,t[2]=r*-i+l*s,t[3]=o*-i+u*s,t[4]=e,t[5]=M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=n[0],s=n[1];return t[0]=r*i,t[1]=o*i,t[2]=l*s,t[3]=u*s,t[4]=e,t[5]=M,t},o.translate=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=n[0],s=n[1];return t[0]=r,t[1]=o,t[2]=l,t[3]=u,t[4]=r*i+l*s+e,t[5]=o*i+u*s+M,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=-n,t[3]=r,t[4]=0,t[5]=0,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=a[1],t[4]=0,t[5]=0,t},o.fromTranslation=function(t,a){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=a[0],t[5]=a[1],t},o.str=function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+1)},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromMat4=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[4],t[4]=a[5],t[5]=a[6],t[6]=a[8],t[7]=a[9],t[8]=a[10],t},o.clone=function(t){var a=new r.ARRAY_TYPE(9);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a[6]=t[6],a[7]=t[7],a[8]=t[8],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.transpose=function(t,a){if(t===a){var n=a[1],r=a[2],o=a[5];t[1]=a[3],t[2]=a[6],t[3]=n,t[5]=a[7],t[6]=r,t[7]=o}else t[0]=a[0],t[1]=a[3],t[2]=a[6],t[3]=a[1],t[4]=a[4],t[5]=a[7],t[6]=a[2],t[7]=a[5],t[8]=a[8];return t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=a[6],i=a[7],s=a[8],c=s*u-e*i,D=-s*l+e*M,S=i*l-u*M,I=n*c+r*D+o*S;return I?(I=1/I,t[0]=c*I,t[1]=(-s*r+o*i)*I,t[2]=(e*r-o*u)*I,t[3]=D*I,t[4]=(s*n-o*M)*I,t[5]=(-e*n+o*l)*I,t[6]=S*I,t[7]=(-i*n+r*M)*I,t[8]=(u*n-r*l)*I,t):null},o.adjoint=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=a[6],i=a[7],s=a[8];return t[0]=u*s-e*i,t[1]=o*i-r*s,t[2]=r*e-o*u,t[3]=e*M-l*s,t[4]=n*s-o*M,t[5]=o*l-n*e,t[6]=l*i-u*M,t[7]=r*M-n*i,t[8]=n*u-r*l,t},o.determinant=function(t){var a=t[0],n=t[1],r=t[2],o=t[3],l=t[4],u=t[5],e=t[6],M=t[7],i=t[8];return a*(i*l-u*M)+n*(-i*o+u*e)+r*(M*o-l*e)},o.multiply=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=a[6],s=a[7],c=a[8],D=n[0],S=n[1],I=n[2],x=n[3],f=n[4],F=n[5],m=n[6],h=n[7],d=n[8];return t[0]=D*r+S*u+I*i,t[1]=D*o+S*e+I*s,t[2]=D*l+S*M+I*c,t[3]=x*r+f*u+F*i,t[4]=x*o+f*e+F*s,t[5]=x*l+f*M+F*c,t[6]=m*r+h*u+d*i,t[7]=m*o+h*e+d*s,t[8]=m*l+h*M+d*c,t},o.mul=o.multiply,o.translate=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=a[6],s=a[7],c=a[8],D=n[0],S=n[1];return t[0]=r,t[1]=o,t[2]=l,t[3]=u,t[4]=e,t[5]=M,t[6]=D*r+S*u+i,t[7]=D*o+S*e+s,t[8]=D*l+S*M+c,t},o.rotate=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=a[6],s=a[7],c=a[8],D=Math.sin(n),S=Math.cos(n);return t[0]=S*r+D*u,t[1]=S*o+D*e,t[2]=S*l+D*M,t[3]=S*u-D*r,t[4]=S*e-D*o,t[5]=S*M-D*l,t[6]=i,t[7]=s,t[8]=c,t},o.scale=function(t,a,n){var r=n[0],o=n[1];return t[0]=r*a[0],t[1]=r*a[1],t[2]=r*a[2],t[3]=o*a[3],t[4]=o*a[4],t[5]=o*a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t},o.fromTranslation=function(t,a){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=a[0],t[7]=a[1],t[8]=1,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=0,t[3]=-n,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=0,t[4]=a[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromMat2d=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=0,t[3]=a[2],t[4]=a[3],t[5]=0,t[6]=a[4],t[7]=a[5],t[8]=1,t},o.fromQuat=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=n+n,e=r+r,M=o+o,i=n*u,s=r*u,c=r*e,D=o*u,S=o*e,I=o*M,x=l*u,f=l*e,F=l*M;return t[0]=1-c-I,t[3]=s-F,t[6]=D+f,t[1]=s+F,t[4]=1-i-I,t[7]=S-x,t[2]=D-f,t[5]=S+x,t[8]=1-i-c,t},o.normalFromMat4=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=a[6],i=a[7],s=a[8],c=a[9],D=a[10],S=a[11],I=a[12],x=a[13],f=a[14],F=a[15],m=n*e-r*u,h=n*M-o*u,d=n*i-l*u,v=r*M-o*e,z=r*i-l*e,p=o*i-l*M,w=s*x-c*I,A=s*f-D*I,R=s*F-S*I,b=c*f-D*x,Y=c*F-S*x,q=D*F-S*f,y=m*q-h*Y+d*b+v*R-z*A+p*w;return y?(y=1/y,t[0]=(e*q-M*Y+i*b)*y,t[1]=(M*R-u*q-i*A)*y,t[2]=(u*Y-e*R+i*w)*y,t[3]=(o*Y-r*q-l*b)*y,t[4]=(n*q-o*R+l*A)*y,t[5]=(r*R-n*Y-l*w)*y,t[6]=(x*p-f*z+F*v)*y,t[7]=(f*d-I*p-F*h)*y,t[8]=(I*z-x*d+F*m)*y,t):null},o.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},t.exports=o},function(t,a,n){var r=n(1),o={scalar:{},SIMD:{}};o.create=function(){var t=new r.ARRAY_TYPE(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.clone=function(t){var a=new r.ARRAY_TYPE(16);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a[6]=t[6],a[7]=t[7],a[8]=t[8],a[9]=t[9],a[10]=t[10],a[11]=t[11],a[12]=t[12],a[13]=t[13],a[14]=t[14],a[15]=t[15],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t[9]=a[9],t[10]=a[10],t[11]=a[11],t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.scalar.transpose=function(t,a){if(t===a){var n=a[1],r=a[2],o=a[3],l=a[6],u=a[7],e=a[11];t[1]=a[4],t[2]=a[8],t[3]=a[12],t[4]=n,t[6]=a[9],t[7]=a[13],t[8]=r,t[9]=l,t[11]=a[14],t[12]=o,t[13]=u,t[14]=e}else t[0]=a[0],t[1]=a[4],t[2]=a[8],t[3]=a[12],t[4]=a[1],t[5]=a[5],t[6]=a[9],t[7]=a[13],t[8]=a[2],t[9]=a[6],t[10]=a[10],t[11]=a[14],t[12]=a[3],t[13]=a[7],t[14]=a[11],t[15]=a[15];return t},o.SIMD.transpose=function(t,a){var n,r,o,l,u,e,M,i,s,c;return n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),l=SIMD.Float32x4.load(a,12),u=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,l,0,1,4,5),M=SIMD.Float32x4.shuffle(u,e,0,2,4,6),i=SIMD.Float32x4.shuffle(u,e,1,3,5,7),SIMD.Float32x4.store(t,0,M),SIMD.Float32x4.store(t,4,i),u=SIMD.Float32x4.shuffle(n,r,2,3,6,7),e=SIMD.Float32x4.shuffle(o,l,2,3,6,7),s=SIMD.Float32x4.shuffle(u,e,0,2,4,6),c=SIMD.Float32x4.shuffle(u,e,1,3,5,7),SIMD.Float32x4.store(t,8,s),SIMD.Float32x4.store(t,12,c),t},o.transpose=r.USE_SIMD?o.SIMD.transpose:o.scalar.transpose,o.scalar.invert=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=a[6],i=a[7],s=a[8],c=a[9],D=a[10],S=a[11],I=a[12],x=a[13],f=a[14],F=a[15],m=n*e-r*u,h=n*M-o*u,d=n*i-l*u,v=r*M-o*e,z=r*i-l*e,p=o*i-l*M,w=s*x-c*I,A=s*f-D*I,R=s*F-S*I,b=c*f-D*x,Y=c*F-S*x,q=D*F-S*f,y=m*q-h*Y+d*b+v*R-z*A+p*w;return y?(y=1/y,t[0]=(e*q-M*Y+i*b)*y,t[1]=(o*Y-r*q-l*b)*y,t[2]=(x*p-f*z+F*v)*y,t[3]=(D*z-c*p-S*v)*y,t[4]=(M*R-u*q-i*A)*y,t[5]=(n*q-o*R+l*A)*y,t[6]=(f*d-I*p-F*h)*y,t[7]=(s*p-D*d+S*h)*y,t[8]=(u*Y-e*R+i*w)*y,t[9]=(r*R-n*Y-l*w)*y,t[10]=(I*z-x*d+F*m)*y,t[11]=(c*d-s*z-S*m)*y,t[12]=(e*A-u*b-M*w)*y,t[13]=(n*b-r*A+o*w)*y,t[14]=(x*h-I*v-f*m)*y,t[15]=(s*v-c*h+D*m)*y,t):null},o.SIMD.invert=function(t,a){var n,r,o,l,u,e,M,i,s,c,D=SIMD.Float32x4.load(a,0),S=SIMD.Float32x4.load(a,4),I=SIMD.Float32x4.load(a,8),x=SIMD.Float32x4.load(a,12);return u=SIMD.Float32x4.shuffle(D,S,0,1,4,5),r=SIMD.Float32x4.shuffle(I,x,0,1,4,5),n=SIMD.Float32x4.shuffle(u,r,0,2,4,6),r=SIMD.Float32x4.shuffle(r,u,1,3,5,7),u=SIMD.Float32x4.shuffle(D,S,2,3,6,7),l=SIMD.Float32x4.shuffle(I,x,2,3,6,7),o=SIMD.Float32x4.shuffle(u,l,0,2,4,6),l=SIMD.Float32x4.shuffle(l,u,1,3,5,7),u=SIMD.Float32x4.mul(o,l),u=SIMD.Float32x4.swizzle(u,1,0,3,2),e=SIMD.Float32x4.mul(r,u),M=SIMD.Float32x4.mul(n,u),u=SIMD.Float32x4.swizzle(u,2,3,0,1),e=SIMD.Float32x4.sub(SIMD.Float32x4.mul(r,u),e),M=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,u),M),M=SIMD.Float32x4.swizzle(M,2,3,0,1),u=SIMD.Float32x4.mul(r,o),u=SIMD.Float32x4.swizzle(u,1,0,3,2),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(l,u),e),s=SIMD.Float32x4.mul(n,u),u=SIMD.Float32x4.swizzle(u,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(l,u)),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,u),s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),u=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(r,2,3,0,1),l),u=SIMD.Float32x4.swizzle(u,1,0,3,2),o=SIMD.Float32x4.swizzle(o,2,3,0,1),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,u),e),i=SIMD.Float32x4.mul(n,u),u=SIMD.Float32x4.swizzle(u,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(o,u)),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,u),i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),u=SIMD.Float32x4.mul(n,r),u=SIMD.Float32x4.swizzle(u,1,0,3,2),i=SIMD.Float32x4.add(SIMD.Float32x4.mul(l,u),i),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(o,u),s),u=SIMD.Float32x4.swizzle(u,2,3,0,1),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,u),i),s=SIMD.Float32x4.sub(s,SIMD.Float32x4.mul(o,u)),u=SIMD.Float32x4.mul(n,l),u=SIMD.Float32x4.swizzle(u,1,0,3,2),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(o,u)),i=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,u),i),u=SIMD.Float32x4.swizzle(u,2,3,0,1),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,u),M),i=SIMD.Float32x4.sub(i,SIMD.Float32x4.mul(r,u)),u=SIMD.Float32x4.mul(n,o),u=SIMD.Float32x4.swizzle(u,1,0,3,2),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(l,u),M),s=SIMD.Float32x4.sub(s,SIMD.Float32x4.mul(r,u)),u=SIMD.Float32x4.swizzle(u,2,3,0,1),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(l,u)),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,u),s),c=SIMD.Float32x4.mul(n,e),c=SIMD.Float32x4.add(SIMD.Float32x4.swizzle(c,2,3,0,1),c),c=SIMD.Float32x4.add(SIMD.Float32x4.swizzle(c,1,0,3,2),c),u=SIMD.Float32x4.reciprocalApproximation(c),c=SIMD.Float32x4.sub(SIMD.Float32x4.add(u,u),SIMD.Float32x4.mul(c,SIMD.Float32x4.mul(u,u))),(c=SIMD.Float32x4.swizzle(c,0,0,0,0))?(SIMD.Float32x4.store(t,0,SIMD.Float32x4.mul(c,e)),SIMD.Float32x4.store(t,4,SIMD.Float32x4.mul(c,M)),SIMD.Float32x4.store(t,8,SIMD.Float32x4.mul(c,i)),SIMD.Float32x4.store(t,12,SIMD.Float32x4.mul(c,s)),t):null},o.invert=r.USE_SIMD?o.SIMD.invert:o.scalar.invert,o.scalar.adjoint=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=a[4],e=a[5],M=a[6],i=a[7],s=a[8],c=a[9],D=a[10],S=a[11],I=a[12],x=a[13],f=a[14],F=a[15];return t[0]=e*(D*F-S*f)-c*(M*F-i*f)+x*(M*S-i*D),t[1]=-(r*(D*F-S*f)-c*(o*F-l*f)+x*(o*S-l*D)),t[2]=r*(M*F-i*f)-e*(o*F-l*f)+x*(o*i-l*M),t[3]=-(r*(M*S-i*D)-e*(o*S-l*D)+c*(o*i-l*M)),t[4]=-(u*(D*F-S*f)-s*(M*F-i*f)+I*(M*S-i*D)),t[5]=n*(D*F-S*f)-s*(o*F-l*f)+I*(o*S-l*D),t[6]=-(n*(M*F-i*f)-u*(o*F-l*f)+I*(o*i-l*M)),t[7]=n*(M*S-i*D)-u*(o*S-l*D)+s*(o*i-l*M),t[8]=u*(c*F-S*x)-s*(e*F-i*x)+I*(e*S-i*c),t[9]=-(n*(c*F-S*x)-s*(r*F-l*x)+I*(r*S-l*c)),t[10]=n*(e*F-i*x)-u*(r*F-l*x)+I*(r*i-l*e),t[11]=-(n*(e*S-i*c)-u*(r*S-l*c)+s*(r*i-l*e)),t[12]=-(u*(c*f-D*x)-s*(e*f-M*x)+I*(e*D-M*c)),t[13]=n*(c*f-D*x)-s*(r*f-o*x)+I*(r*D-o*c),t[14]=-(n*(e*f-M*x)-u*(r*f-o*x)+I*(r*M-o*e)),t[15]=n*(e*D-M*c)-u*(r*D-o*c)+s*(r*M-o*e),t},o.SIMD.adjoint=function(t,a){var n,r,o,l,u,e,M,i,s,c,D,S,I,n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),l=SIMD.Float32x4.load(a,12);return s=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,l,0,1,4,5),u=SIMD.Float32x4.shuffle(s,e,0,2,4,6),e=SIMD.Float32x4.shuffle(e,s,1,3,5,7),s=SIMD.Float32x4.shuffle(n,r,2,3,6,7),i=SIMD.Float32x4.shuffle(o,l,2,3,6,7),M=SIMD.Float32x4.shuffle(s,i,0,2,4,6),i=SIMD.Float32x4.shuffle(i,s,1,3,5,7),s=SIMD.Float32x4.mul(M,i),s=SIMD.Float32x4.swizzle(s,1,0,3,2),c=SIMD.Float32x4.mul(e,s),D=SIMD.Float32x4.mul(u,s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),c=SIMD.Float32x4.sub(SIMD.Float32x4.mul(e,s),c),D=SIMD.Float32x4.sub(SIMD.Float32x4.mul(u,s),D),D=SIMD.Float32x4.swizzle(D,2,3,0,1),s=SIMD.Float32x4.mul(e,M),s=SIMD.Float32x4.swizzle(s,1,0,3,2),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(i,s),c),I=SIMD.Float32x4.mul(u,s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(i,s)),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(u,s),I),I=SIMD.Float32x4.swizzle(I,2,3,0,1),s=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,2,3,0,1),i),s=SIMD.Float32x4.swizzle(s,1,0,3,2),M=SIMD.Float32x4.swizzle(M,2,3,0,1),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,s),c),S=SIMD.Float32x4.mul(u,s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(M,s)),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(u,s),S),S=SIMD.Float32x4.swizzle(S,2,3,0,1),s=SIMD.Float32x4.mul(u,e),s=SIMD.Float32x4.swizzle(s,1,0,3,2),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(i,s),S),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(M,s),I),s=SIMD.Float32x4.swizzle(s,2,3,0,1),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(i,s),S),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(M,s)),s=SIMD.Float32x4.mul(u,i),s=SIMD.Float32x4.swizzle(s,1,0,3,2),D=SIMD.Float32x4.sub(D,SIMD.Float32x4.mul(M,s)),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,s),S),s=SIMD.Float32x4.swizzle(s,2,3,0,1),D=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,s),D),S=SIMD.Float32x4.sub(S,SIMD.Float32x4.mul(e,s)),s=SIMD.Float32x4.mul(u,M),s=SIMD.Float32x4.swizzle(s,1,0,3,2),D=SIMD.Float32x4.add(SIMD.Float32x4.mul(i,s),D),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(e,s)),s=SIMD.Float32x4.swizzle(s,2,3,0,1),D=SIMD.Float32x4.sub(D,SIMD.Float32x4.mul(i,s)),I=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,s),I),SIMD.Float32x4.store(t,0,c),SIMD.Float32x4.store(t,4,D),SIMD.Float32x4.store(t,8,S),SIMD.Float32x4.store(t,12,I),t},o.adjoint=r.USE_SIMD?o.SIMD.adjoint:o.scalar.adjoint,o.determinant=function(t){var a=t[0],n=t[1],r=t[2],o=t[3],l=t[4],u=t[5],e=t[6],M=t[7],i=t[8],s=t[9],c=t[10],D=t[11],S=t[12],I=t[13],x=t[14],f=t[15],F=a*u-n*l,m=a*e-r*l,h=a*M-o*l,d=n*e-r*u,v=n*M-o*u,z=r*M-o*e,p=i*I-s*S,w=i*x-c*S,A=i*f-D*S,R=s*x-c*I,b=s*f-D*I,Y=c*f-D*x;return F*Y-m*b+h*R+d*A-v*w+z*p},o.SIMD.multiply=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),l=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12),e=SIMD.Float32x4.load(n,0),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,2,2,2,2),l),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,3,3,3,3),u))));SIMD.Float32x4.store(t,0,M);var i=SIMD.Float32x4.load(n,4),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(i,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(i,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(i,2,2,2,2),l),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(i,3,3,3,3),u))));SIMD.Float32x4.store(t,4,s);var c=SIMD.Float32x4.load(n,8),D=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,2,2,2,2),l),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,3,3,3,3),u))));SIMD.Float32x4.store(t,8,D);var S=SIMD.Float32x4.load(n,12),I=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,2,2,2,2),l),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,3,3,3,3),u))));return SIMD.Float32x4.store(t,12,I),t},o.scalar.multiply=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=a[6],s=a[7],c=a[8],D=a[9],S=a[10],I=a[11],x=a[12],f=a[13],F=a[14],m=a[15],h=n[0],d=n[1],v=n[2],z=n[3];return t[0]=h*r+d*e+v*c+z*x,t[1]=h*o+d*M+v*D+z*f,t[2]=h*l+d*i+v*S+z*F,t[3]=h*u+d*s+v*I+z*m,h=n[4],d=n[5],v=n[6],z=n[7],t[4]=h*r+d*e+v*c+z*x,t[5]=h*o+d*M+v*D+z*f,t[6]=h*l+d*i+v*S+z*F,t[7]=h*u+d*s+v*I+z*m,h=n[8],d=n[9],v=n[10],z=n[11],t[8]=h*r+d*e+v*c+z*x,t[9]=h*o+d*M+v*D+z*f,t[10]=h*l+d*i+v*S+z*F,t[11]=h*u+d*s+v*I+z*m,h=n[12],d=n[13],v=n[14],z=n[15],t[12]=h*r+d*e+v*c+z*x,t[13]=h*o+d*M+v*D+z*f,t[14]=h*l+d*i+v*S+z*F,t[15]=h*u+d*s+v*I+z*m,t},o.multiply=r.USE_SIMD?o.SIMD.multiply:o.scalar.multiply,o.mul=o.multiply,o.scalar.translate=function(t,a,n){var r,o,l,u,e,M,i,s,c,D,S,I,x=n[0],f=n[1],F=n[2];return a===t?(t[12]=a[0]*x+a[4]*f+a[8]*F+a[12],t[13]=a[1]*x+a[5]*f+a[9]*F+a[13],t[14]=a[2]*x+a[6]*f+a[10]*F+a[14],t[15]=a[3]*x+a[7]*f+a[11]*F+a[15]):(r=a[0],o=a[1],l=a[2],u=a[3],e=a[4],M=a[5],i=a[6],s=a[7],c=a[8],D=a[9],S=a[10],I=a[11],t[0]=r,t[1]=o,t[2]=l,t[3]=u,t[4]=e,t[5]=M,t[6]=i,t[7]=s,t[8]=c,t[9]=D,t[10]=S,t[11]=I,t[12]=r*x+e*f+c*F+a[12],t[13]=o*x+M*f+D*F+a[13],t[14]=l*x+i*f+S*F+a[14],t[15]=u*x+s*f+I*F+a[15]),t},o.SIMD.translate=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),l=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12),e=SIMD.Float32x4(n[0],n[1],n[2],0);a!==t&&(t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t[9]=a[9],t[10]=a[10],t[11]=a[11]),r=SIMD.Float32x4.mul(r,SIMD.Float32x4.swizzle(e,0,0,0,0)),o=SIMD.Float32x4.mul(o,SIMD.Float32x4.swizzle(e,1,1,1,1)),l=SIMD.Float32x4.mul(l,SIMD.Float32x4.swizzle(e,2,2,2,2));var M=SIMD.Float32x4.add(r,SIMD.Float32x4.add(o,SIMD.Float32x4.add(l,u)));return SIMD.Float32x4.store(t,12,M),t},o.translate=r.USE_SIMD?o.SIMD.translate:o.scalar.translate,o.scalar.scale=function(t,a,n){var r=n[0],o=n[1],l=n[2];return t[0]=a[0]*r,t[1]=a[1]*r,t[2]=a[2]*r,t[3]=a[3]*r,t[4]=a[4]*o,t[5]=a[5]*o,t[6]=a[6]*o,t[7]=a[7]*o,t[8]=a[8]*l,t[9]=a[9]*l,t[10]=a[10]*l,t[11]=a[11]*l,t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.SIMD.scale=function(t,a,n){var r,o,l,u=SIMD.Float32x4(n[0],n[1],n[2],0);return r=SIMD.Float32x4.load(a,0),SIMD.Float32x4.store(t,0,SIMD.Float32x4.mul(r,SIMD.Float32x4.swizzle(u,0,0,0,0))),o=SIMD.Float32x4.load(a,4),SIMD.Float32x4.store(t,4,SIMD.Float32x4.mul(o,SIMD.Float32x4.swizzle(u,1,1,1,1))),l=SIMD.Float32x4.load(a,8),SIMD.Float32x4.store(t,8,SIMD.Float32x4.mul(l,SIMD.Float32x4.swizzle(u,2,2,2,2))),t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.scale=r.USE_SIMD?o.SIMD.scale:o.scalar.scale,o.rotate=function(t,a,n,o){var l,u,e,M,i,s,c,D,S,I,x,f,F,m,h,d,v,z,p,w,A,R,b,Y,q=o[0],y=o[1],E=o[2],g=Math.sqrt(q*q+y*y+E*E);return Math.abs(g)M?(l.cross(t,a,o),l.length(t)<1e-6&&l.cross(t,n,o),l.normalize(t,t),e.setAxisAngle(r,t,Math.PI),r):M>.999999?(r[0]=0,r[1]=0,r[2]=0,r[3]=1,r):(l.cross(t,o,u),r[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=1+M,e.normalize(r,r))}}(),e.setAxes=function(){var t=o.create();return function(a,n,r,o){return t[0]=r[0],t[3]=r[1],t[6]=r[2],t[1]=o[0],t[4]=o[1],t[7]=o[2],t[2]=-n[0],t[5]=-n[1],t[8]=-n[2],e.normalize(a,e.fromMat3(a,t))}}(),e.clone=u.clone,e.fromValues=u.fromValues,e.copy=u.copy,e.set=u.set,e.identity=function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},e.setAxisAngle=function(t,a,n){n=.5*n;var r=Math.sin(n);return t[0]=r*a[0],t[1]=r*a[1],t[2]=r*a[2],t[3]=Math.cos(n),t},e.add=u.add,e.multiply=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3],e=n[0],M=n[1],i=n[2],s=n[3];return t[0]=r*s+u*e+o*i-l*M,t[1]=o*s+u*M+l*e-r*i,t[2]=l*s+u*i+r*M-o*e,t[3]=u*s-r*e-o*M-l*i,t},e.mul=e.multiply,e.scale=u.scale,e.rotateX=function(t,a,n){n*=.5;var r=a[0],o=a[1],l=a[2],u=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+u*e,t[1]=o*M+l*e,t[2]=l*M-o*e,t[3]=u*M-r*e,t},e.rotateY=function(t,a,n){n*=.5;var r=a[0],o=a[1],l=a[2],u=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M-l*e,t[1]=o*M+u*e,t[2]=l*M+r*e,t[3]=u*M-o*e,t},e.rotateZ=function(t,a,n){n*=.5;var r=a[0],o=a[1],l=a[2],u=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+o*e,t[1]=o*M-r*e,t[2]=l*M+u*e,t[3]=u*M-l*e,t},e.calculateW=function(t,a){var n=a[0],r=a[1],o=a[2];return t[0]=n,t[1]=r,t[2]=o,t[3]=Math.sqrt(Math.abs(1-n*n-r*r-o*o)),t},e.dot=u.dot,e.lerp=u.lerp,e.slerp=function(t,a,n,r){var o,l,u,e,M,i=a[0],s=a[1],c=a[2],D=a[3],S=n[0],I=n[1],x=n[2],f=n[3];return l=i*S+s*I+c*x+D*f,0>l&&(l=-l,S=-S,I=-I,x=-x,f=-f),1-l>1e-6?(o=Math.acos(l),u=Math.sin(o),e=Math.sin((1-r)*o)/u,M=Math.sin(r*o)/u):(e=1-r,M=r),t[0]=e*i+M*S,t[1]=e*s+M*I,t[2]=e*c+M*x,t[3]=e*D+M*f,t},e.sqlerp=function(){var t=e.create(),a=e.create();return function(n,r,o,l,u,M){return e.slerp(t,r,u,M),e.slerp(a,o,l,M),e.slerp(n,t,a,2*M*(1-M)),n}}(),e.invert=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=n*n+r*r+o*o+l*l,e=u?1/u:0; 29 | return t[0]=-n*e,t[1]=-r*e,t[2]=-o*e,t[3]=l*e,t},e.conjugate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t[3]=a[3],t},e.length=u.length,e.len=e.length,e.squaredLength=u.squaredLength,e.sqrLen=e.squaredLength,e.normalize=u.normalize,e.fromMat3=function(t,a){var n,r=a[0]+a[4]+a[8];if(r>0)n=Math.sqrt(r+1),t[3]=.5*n,n=.5/n,t[0]=(a[5]-a[7])*n,t[1]=(a[6]-a[2])*n,t[2]=(a[1]-a[3])*n;else{var o=0;a[4]>a[0]&&(o=1),a[8]>a[3*o+o]&&(o=2);var l=(o+1)%3,u=(o+2)%3;n=Math.sqrt(a[3*o+o]-a[3*l+l]-a[3*u+u]+1),t[o]=.5*n,n=.5/n,t[3]=(a[3*l+u]-a[3*u+l])*n,t[l]=(a[3*l+o]+a[3*o+l])*n,t[u]=(a[3*u+o]+a[3*o+u])*n}return t},e.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=e},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(3);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a},o.fromValues=function(t,a,n){var o=new r.ARRAY_TYPE(3);return o[0]=t,o[1]=a,o[2]=n,o},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t},o.set=function(t,a,n,r){return t[0]=a,t[1]=n,t[2]=r,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t[2]=a[2]*n[2],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t[2]=a[2]/n[2],t},o.div=o.divide,o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t[2]=Math.min(a[2],n[2]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t[2]=Math.max(a[2],n[2]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2];return Math.sqrt(n*n+r*r+o*o)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2];return n*n+r*r+o*o},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1],r=t[2];return Math.sqrt(a*a+n*n+r*r)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1],r=t[2];return a*a+n*n+r*r},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t[2]=1/a[2],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=a[2],l=n*n+r*r+o*o;return l>0&&(l=1/Math.sqrt(l),t[0]=a[0]*l,t[1]=a[1]*l,t[2]=a[2]*l),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]+t[2]*a[2]},o.cross=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=n[0],e=n[1],M=n[2];return t[0]=o*M-l*e,t[1]=l*u-r*M,t[2]=r*e-o*u,t},o.lerp=function(t,a,n,r){var o=a[0],l=a[1],u=a[2];return t[0]=o+r*(n[0]-o),t[1]=l+r*(n[1]-l),t[2]=u+r*(n[2]-u),t},o.hermite=function(t,a,n,r,o,l){var u=l*l,e=u*(2*l-3)+1,M=u*(l-2)+l,i=u*(l-1),s=u*(3-2*l);return t[0]=a[0]*e+n[0]*M+r[0]*i+o[0]*s,t[1]=a[1]*e+n[1]*M+r[1]*i+o[1]*s,t[2]=a[2]*e+n[2]*M+r[2]*i+o[2]*s,t},o.bezier=function(t,a,n,r,o,l){var u=1-l,e=u*u,M=l*l,i=e*u,s=3*l*e,c=3*M*u,D=M*l;return t[0]=a[0]*i+n[0]*s+r[0]*c+o[0]*D,t[1]=a[1]*i+n[1]*s+r[1]*c+o[1]*D,t[2]=a[2]*i+n[2]*s+r[2]*c+o[2]*D,t},o.random=function(t,a){a=a||1;var n=2*r.RANDOM()*Math.PI,o=2*r.RANDOM()-1,l=Math.sqrt(1-o*o)*a;return t[0]=Math.cos(n)*l,t[1]=Math.sin(n)*l,t[2]=o*a,t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=n[3]*r+n[7]*o+n[11]*l+n[15];return u=u||1,t[0]=(n[0]*r+n[4]*o+n[8]*l+n[12])/u,t[1]=(n[1]*r+n[5]*o+n[9]*l+n[13])/u,t[2]=(n[2]*r+n[6]*o+n[10]*l+n[14])/u,t},o.transformMat3=function(t,a,n){var r=a[0],o=a[1],l=a[2];return t[0]=r*n[0]+o*n[3]+l*n[6],t[1]=r*n[1]+o*n[4]+l*n[7],t[2]=r*n[2]+o*n[5]+l*n[8],t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=n[0],e=n[1],M=n[2],i=n[3],s=i*r+e*l-M*o,c=i*o+M*r-u*l,D=i*l+u*o-e*r,S=-u*r-e*o-M*l;return t[0]=s*i+S*-u+c*-M-D*-e,t[1]=c*i+S*-e+D*-u-s*-M,t[2]=D*i+S*-M+s*-e-c*-u,t},o.rotateX=function(t,a,n,r){var o=[],l=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],l[0]=o[0],l[1]=o[1]*Math.cos(r)-o[2]*Math.sin(r),l[2]=o[1]*Math.sin(r)+o[2]*Math.cos(r),t[0]=l[0]+n[0],t[1]=l[1]+n[1],t[2]=l[2]+n[2],t},o.rotateY=function(t,a,n,r){var o=[],l=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],l[0]=o[2]*Math.sin(r)+o[0]*Math.cos(r),l[1]=o[1],l[2]=o[2]*Math.cos(r)-o[0]*Math.sin(r),t[0]=l[0]+n[0],t[1]=l[1]+n[1],t[2]=l[2]+n[2],t},o.rotateZ=function(t,a,n,r){var o=[],l=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],l[0]=o[0]*Math.cos(r)-o[1]*Math.sin(r),l[1]=o[0]*Math.sin(r)+o[1]*Math.cos(r),l[2]=o[2],t[0]=l[0]+n[0],t[1]=l[1]+n[1],t[2]=l[2]+n[2],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,l,u){var e,M;for(n||(n=3),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],t[2]=a[e+2],l(t,t,u),a[e]=t[0],a[e+1]=t[1],a[e+2]=t[2];return a}}(),o.angle=function(t,a){var n=o.fromValues(t[0],t[1],t[2]),r=o.fromValues(a[0],a[1],a[2]);o.normalize(n,n),o.normalize(r,r);var l=o.dot(n,r);return l>1?0:Math.acos(l)},o.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(4);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a},o.fromValues=function(t,a,n,o){var l=new r.ARRAY_TYPE(4);return l[0]=t,l[1]=a,l[2]=n,l[3]=o,l},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t},o.set=function(t,a,n,r,o){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t[3]=a[3]+n[3],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t[3]=a[3]-n[3],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t[2]=a[2]*n[2],t[3]=a[3]*n[3],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t[2]=a[2]/n[2],t[3]=a[3]/n[3],t},o.div=o.divide,o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t[2]=Math.min(a[2],n[2]),t[3]=Math.min(a[3],n[3]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t[2]=Math.max(a[2],n[2]),t[3]=Math.max(a[3],n[3]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t[3]=a[3]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t[3]=a[3]+n[3]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2],l=a[3]-t[3];return Math.sqrt(n*n+r*r+o*o+l*l)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2],l=a[3]-t[3];return n*n+r*r+o*o+l*l},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1],r=t[2],o=t[3];return Math.sqrt(a*a+n*n+r*r+o*o)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1],r=t[2],o=t[3];return a*a+n*n+r*r+o*o},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t[3]=-a[3],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t[2]=1/a[2],t[3]=1/a[3],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=a[2],l=a[3],u=n*n+r*r+o*o+l*l;return u>0&&(u=1/Math.sqrt(u),t[0]=n*u,t[1]=r*u,t[2]=o*u,t[3]=l*u),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]+t[2]*a[2]+t[3]*a[3]},o.lerp=function(t,a,n,r){var o=a[0],l=a[1],u=a[2],e=a[3];return t[0]=o+r*(n[0]-o),t[1]=l+r*(n[1]-l),t[2]=u+r*(n[2]-u),t[3]=e+r*(n[3]-e),t},o.random=function(t,a){return a=a||1,t[0]=r.RANDOM(),t[1]=r.RANDOM(),t[2]=r.RANDOM(),t[3]=r.RANDOM(),o.normalize(t,t),o.scale(t,t,a),t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=a[3];return t[0]=n[0]*r+n[4]*o+n[8]*l+n[12]*u,t[1]=n[1]*r+n[5]*o+n[9]*l+n[13]*u,t[2]=n[2]*r+n[6]*o+n[10]*l+n[14]*u,t[3]=n[3]*r+n[7]*o+n[11]*l+n[15]*u,t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],l=a[2],u=n[0],e=n[1],M=n[2],i=n[3],s=i*r+e*l-M*o,c=i*o+M*r-u*l,D=i*l+u*o-e*r,S=-u*r-e*o-M*l;return t[0]=s*i+S*-u+c*-M-D*-e,t[1]=c*i+S*-e+D*-u-s*-M,t[2]=D*i+S*-M+s*-e-c*-u,t[3]=a[3],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,l,u){var e,M;for(n||(n=4),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],t[2]=a[e+2],t[3]=a[e+3],l(t,t,u),a[e]=t[0],a[e+1]=t[1],a[e+2]=t[2],a[e+3]=t[3];return a}}(),o.str=function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(2);return a[0]=t[0],a[1]=t[1],a},o.fromValues=function(t,a){var n=new r.ARRAY_TYPE(2);return n[0]=t,n[1]=a,n},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t},o.set=function(t,a,n){return t[0]=a,t[1]=n,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t},o.div=o.divide,o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1];return Math.sqrt(n*n+r*r)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1];return n*n+r*r},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1];return Math.sqrt(a*a+n*n)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1];return a*a+n*n},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=n*n+r*r;return o>0&&(o=1/Math.sqrt(o),t[0]=a[0]*o,t[1]=a[1]*o),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]},o.cross=function(t,a,n){var r=a[0]*n[1]-a[1]*n[0];return t[0]=t[1]=0,t[2]=r,t},o.lerp=function(t,a,n,r){var o=a[0],l=a[1];return t[0]=o+r*(n[0]-o),t[1]=l+r*(n[1]-l),t},o.random=function(t,a){a=a||1;var n=2*r.RANDOM()*Math.PI;return t[0]=Math.cos(n)*a,t[1]=Math.sin(n)*a,t},o.transformMat2=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[2]*o,t[1]=n[1]*r+n[3]*o,t},o.transformMat2d=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[2]*o+n[4],t[1]=n[1]*r+n[3]*o+n[5],t},o.transformMat3=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[3]*o+n[6],t[1]=n[1]*r+n[4]*o+n[7],t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[4]*o+n[12],t[1]=n[1]*r+n[5]*o+n[13],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,l,u){var e,M;for(n||(n=2),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],l(t,t,u),a[e]=t[0],a[e+1]=t[1];return a}}(),o.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},t.exports=o}])}); -------------------------------------------------------------------------------- /dat.gui.min.js: -------------------------------------------------------------------------------- 1 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){a=a||document;var b=a.createElement("link");b.type="text/css";b.rel="stylesheet";b.href=e;a.getElementsByTagName("head")[0].appendChild(b)},inject:function(e,a){a=a||document;var b=document.createElement("style");b.type="text/css";b.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(b)}}}(); 2 | dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(b){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(b[f]=a[f])},this);return b},defaults:function(b){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(b[f])&&(b[f]=a[f])},this);return b},compose:function(){var b=a.call(arguments);return function(){for(var d=a.call(arguments),f=b.length-1;0<=f;f--)d=[b[f].apply(this,d)];return d[0]}}, 3 | each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var c=0,p=a.length;cthis.__max&&(a=this.__max);void 0!==this.__step&&0!=a%this.__step&&(a=Math.round(a/this.__step)*this.__step);return b.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return b}(dat.controllers.Controller,dat.utils.common); 17 | dat.controllers.NumberControllerBox=function(e,a,b){var d=function(f,c,e){function k(){var a=parseFloat(n.__input.value);b.isNaN(a)||n.setValue(a)}function l(a){var c=r-a.clientY;n.setValue(n.getValue()+c*n.__impliedStep);r=a.clientY}function q(){a.unbind(window,"mousemove",l);a.unbind(window,"mouseup",q)}this.__truncationSuspended=!1;d.superclass.call(this,f,c,e);var n=this,r;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",k);a.bind(this.__input, 18 | "blur",function(){k();n.__onFinishChange&&n.__onFinishChange.call(n,n.getValue())});a.bind(this.__input,"mousedown",function(c){a.bind(window,"mousemove",l);a.bind(window,"mouseup",q);r=c.clientY});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&(n.__truncationSuspended=!0,this.blur(),n.__truncationSuspended=!1)});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;b.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input,c;if(this.__truncationSuspended)c= 19 | this.getValue();else{c=this.getValue();var b=Math.pow(10,this.__precision);c=Math.round(c*b)/b}a.value=c;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); 20 | dat.controllers.NumberControllerSlider=function(e,a,b,d,f){function c(a,c,d,b,f){return b+(a-c)/(d-c)*(f-b)}var p=function(d,b,f,e,r){function y(d){d.preventDefault();var b=a.getOffset(h.__background),f=a.getWidth(h.__background);h.setValue(c(d.clientX,b.left,b.left+f,h.__min,h.__max));return!1}function g(){a.unbind(window,"mousemove",y);a.unbind(window,"mouseup",g);h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())}p.superclass.call(this,d,b,{min:f,max:e,step:r});var h=this;this.__background= 21 | document.createElement("div");this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(c){a.bind(window,"mousemove",y);a.bind(window,"mouseup",g);y(c)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};p.superclass=e;p.useDefaultStyles=function(){b.inject(f)};d.extend(p.prototype,e.prototype,{updateDisplay:function(){var a= 22 | (this.getValue()-this.__min)/(this.__max-this.__min);this.__foreground.style.width=100*a+"%";return p.superclass.prototype.updateDisplay.call(this)}});return p}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); 23 | dat.controllers.FunctionController=function(e,a,b){var d=function(b,c,e){d.superclass.call(this,b,c);var k=this;this.__button=document.createElement("div");this.__button.innerHTML=void 0===e?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();k.fire();return!1});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;b.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, 24 | this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 25 | dat.controllers.BooleanController=function(e,a,b){var d=function(b,c){d.superclass.call(this,b,c);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},!1);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;b.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& 26 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){!0===this.getValue()?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=!0):this.__checkbox.checked=!1;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); 27 | dat.color.toString=function(e){return function(a){if(1==a.a||e.isUndefined(a.a)){for(a=a.hex.toString(16);6>a.length;)a="0"+a;return"#"+a}return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); 28 | dat.color.interpret=function(e,a){var b,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); 29 | return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return 3!= 30 | a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return 4!=a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(c){return a.isNumber(c.r)&&a.isNumber(c.g)&&a.isNumber(c.b)&&a.isNumber(c.a)?{space:"RGB",r:c.r,g:c.g,b:c.b,a:c.a}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(c){return a.isNumber(c.r)&& 31 | a.isNumber(c.g)&&a.isNumber(c.b)?{space:"RGB",r:c.r,g:c.g,b:c.b}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(c){return a.isNumber(c.h)&&a.isNumber(c.s)&&a.isNumber(c.v)&&a.isNumber(c.a)?{space:"HSV",h:c.h,s:c.s,v:c.v,a:c.a}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(d){return a.isNumber(d.h)&&a.isNumber(d.s)&&a.isNumber(d.v)?{space:"HSV",h:d.h,s:d.s,v:d.v}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d=!1; 32 | var c=1\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n', 59 | ".dg {\n /** Clear list styles */\n /* Auto-place container */\n /* Auto-placed GUI's */\n /* Line items that don't contain folders. */\n /** Folder names */\n /** Hides closed items */\n /** Controller row */\n /** Name-half (left) */\n /** Controller-half (right) */\n /** Controller placement */\n /** Shorter number boxes when slider is present. */\n /** Ensure the entire boolean and function row shows a hand */ }\n .dg ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n clear: both; }\n .dg.ac {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 0;\n z-index: 0; }\n .dg:not(.ac) .main {\n /** Exclude mains in ac so that we don't hide close button */\n overflow: hidden; }\n .dg.main {\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear; }\n .dg.main.taller-than-window {\n overflow-y: auto; }\n .dg.main.taller-than-window .close-button {\n opacity: 1;\n /* TODO, these are style notes */\n margin-top: -1px;\n border-top: 1px solid #2c2c2c; }\n .dg.main ul.closed .close-button {\n opacity: 1 !important; }\n .dg.main:hover .close-button,\n .dg.main .close-button.drag {\n opacity: 1; }\n .dg.main .close-button {\n /*opacity: 0;*/\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear;\n border: 0;\n position: absolute;\n line-height: 19px;\n height: 20px;\n /* TODO, these are style notes */\n cursor: pointer;\n text-align: center;\n background-color: #000; }\n .dg.main .close-button:hover {\n background-color: #111; }\n .dg.a {\n float: right;\n margin-right: 15px;\n overflow-x: hidden; }\n .dg.a.has-save > ul {\n margin-top: 27px; }\n .dg.a.has-save > ul.closed {\n margin-top: 0; }\n .dg.a .save-row {\n position: fixed;\n top: 0;\n z-index: 1002; }\n .dg li {\n -webkit-transition: height 0.1s ease-out;\n -o-transition: height 0.1s ease-out;\n -moz-transition: height 0.1s ease-out;\n transition: height 0.1s ease-out; }\n .dg li:not(.folder) {\n cursor: auto;\n height: 27px;\n line-height: 27px;\n overflow: hidden;\n padding: 0 4px 0 5px; }\n .dg li.folder {\n padding: 0;\n border-left: 4px solid rgba(0, 0, 0, 0); }\n .dg li.title {\n cursor: pointer;\n margin-left: -4px; }\n .dg .closed li:not(.title),\n .dg .closed ul li,\n .dg .closed ul li > * {\n height: 0;\n overflow: hidden;\n border: 0; }\n .dg .cr {\n clear: both;\n padding-left: 3px;\n height: 27px; }\n .dg .property-name {\n cursor: default;\n float: left;\n clear: left;\n width: 40%;\n overflow: hidden;\n text-overflow: ellipsis; }\n .dg .c {\n float: left;\n width: 60%; }\n .dg .c input[type=text] {\n border: 0;\n margin-top: 4px;\n padding: 3px;\n width: 100%;\n float: right; }\n .dg .has-slider input[type=text] {\n width: 30%;\n /*display: none;*/\n margin-left: 0; }\n .dg .slider {\n float: left;\n width: 66%;\n margin-left: -5px;\n margin-right: 0;\n height: 19px;\n margin-top: 4px; }\n .dg .slider-fg {\n height: 100%; }\n .dg .c input[type=checkbox] {\n margin-top: 9px; }\n .dg .c select {\n margin-top: 5px; }\n .dg .cr.function,\n .dg .cr.function .property-name,\n .dg .cr.function *,\n .dg .cr.boolean,\n .dg .cr.boolean * {\n cursor: pointer; }\n .dg .selector {\n display: none;\n position: absolute;\n margin-left: -9px;\n margin-top: 23px;\n z-index: 10; }\n .dg .c:hover .selector,\n .dg .selector.drag {\n display: block; }\n .dg li.save-row {\n padding: 0; }\n .dg li.save-row .button {\n display: inline-block;\n padding: 0px 6px; }\n .dg.dialogue {\n background-color: #222;\n width: 460px;\n padding: 15px;\n font-size: 13px;\n line-height: 15px; }\n\n/* TODO Separate style and structure */\n#dg-new-constructor {\n padding: 10px;\n color: #222;\n font-family: Monaco, monospace;\n font-size: 10px;\n border: 0;\n resize: none;\n box-shadow: inset 1px 1px 1px #888;\n word-wrap: break-word;\n margin: 12px 0;\n display: block;\n width: 440px;\n overflow-y: scroll;\n height: 100px;\n position: relative; }\n\n#dg-local-explain {\n display: none;\n font-size: 11px;\n line-height: 17px;\n border-radius: 3px;\n background-color: #333;\n padding: 8px;\n margin-top: 10px; }\n #dg-local-explain code {\n font-size: 10px; }\n\n#dat-gui-save-locally {\n display: none; }\n\n/** Main type */\n.dg {\n color: #eee;\n font: 11px 'Lucida Grande', sans-serif;\n text-shadow: 0 -1px 0 #111;\n /** Auto place */\n /* Controller row,
  • */\n /** Controllers */ }\n .dg.main {\n /** Scrollbar */ }\n .dg.main::-webkit-scrollbar {\n width: 5px;\n background: #1a1a1a; }\n .dg.main::-webkit-scrollbar-corner {\n height: 0;\n display: none; }\n .dg.main::-webkit-scrollbar-thumb {\n border-radius: 5px;\n background: #676767; }\n .dg li:not(.folder) {\n background: #1a1a1a;\n border-bottom: 1px solid #2c2c2c; }\n .dg li.save-row {\n line-height: 25px;\n background: #dad5cb;\n border: 0; }\n .dg li.save-row select {\n margin-left: 5px;\n width: 108px; }\n .dg li.save-row .button {\n margin-left: 5px;\n margin-top: 1px;\n border-radius: 2px;\n font-size: 9px;\n line-height: 7px;\n padding: 4px 4px 5px 4px;\n background: #c5bdad;\n color: #fff;\n text-shadow: 0 1px 0 #b0a58f;\n box-shadow: 0 -1px 0 #b0a58f;\n cursor: pointer; }\n .dg li.save-row .button.gears {\n background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;\n height: 7px;\n width: 8px; }\n .dg li.save-row .button:hover {\n background-color: #bab19e;\n box-shadow: 0 -1px 0 #b0a58f; }\n .dg li.folder {\n border-bottom: 0; }\n .dg li.title {\n padding-left: 16px;\n background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;\n cursor: pointer;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2); }\n .dg .closed li.title {\n background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }\n .dg .cr.boolean {\n border-left: 3px solid #806787; }\n .dg .cr.function {\n border-left: 3px solid #e61d5f; }\n .dg .cr.number {\n border-left: 3px solid #2fa1d6; }\n .dg .cr.number input[type=text] {\n color: #2fa1d6; }\n .dg .cr.string {\n border-left: 3px solid #1ed36f; }\n .dg .cr.string input[type=text] {\n color: #1ed36f; }\n .dg .cr.function:hover, .dg .cr.boolean:hover {\n background: #111; }\n .dg .c input[type=text] {\n background: #303030;\n outline: none; }\n .dg .c input[type=text]:hover {\n background: #3c3c3c; }\n .dg .c input[type=text]:focus {\n background: #494949;\n color: #fff; }\n .dg .c .slider {\n background: #303030;\n cursor: ew-resize; }\n .dg .c .slider-fg {\n background: #2fa1d6; }\n .dg .c .slider:hover {\n background: #3c3c3c; }\n .dg .c .slider:hover .slider-fg {\n background: #44abda; }\n", 60 | dat.controllers.factory=function(e,a,b,d,f,c,p){return function(k,l,q,n){var r=k[l];if(p.isArray(q)||p.isObject(q))return new e(k,l,q);if(p.isNumber(r))return p.isNumber(q)&&p.isNumber(n)?new b(k,l,q,n):new a(k,l,{min:q,max:n});if(p.isString(r))return new d(k,l);if(p.isFunction(r))return new f(k,l,"");if(p.isBoolean(r))return new c(k,l)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,b){var d= 61 | function(b,c){function e(){k.setValue(k.__input.value)}d.superclass.call(this,b,c);var k=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){k.__onFinishChange&&k.__onFinishChange.call(k,k.getValue())});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;b.extend(d.prototype, 62 | e.prototype,{updateDisplay:function(){a.isActive(this.__input)||(this.__input.value=this.getValue());return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, 63 | dat.controllers.ColorController=function(e,a,b,d,f){function c(a,b,d,c){a.style.background="";f.each(l,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+d+" 0%, "+c+" 100%); "})}function p(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; 64 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var k=function(e,n){function r(b){t(b);a.bind(window,"mousemove",t);a.bind(window, 65 | "mouseup",l)}function l(){a.unbind(window,"mousemove",t);a.unbind(window,"mouseup",l)}function g(){var a=d(this.value);!1!==a?(s.__color.__state=a,s.setValue(s.__color.toOriginal())):this.value=s.__color.toString()}function h(){a.unbind(window,"mousemove",u);a.unbind(window,"mouseup",h)}function t(b){b.preventDefault();var d=a.getWidth(s.__saturation_field),c=a.getOffset(s.__saturation_field),e=(b.clientX-c.left+document.body.scrollLeft)/d;b=1-(b.clientY-c.top+document.body.scrollTop)/d;1 66 | b&&(b=0);1e&&(e=0);s.__color.v=b;s.__color.s=e;s.setValue(s.__color.toOriginal());return!1}function u(b){b.preventDefault();var d=a.getHeight(s.__hue_field),c=a.getOffset(s.__hue_field);b=1-(b.clientY-c.top+document.body.scrollTop)/d;1b&&(b=0);s.__color.h=360*b;s.setValue(s.__color.toOriginal());return!1}k.superclass.call(this,e,n);this.__color=new b(this.getValue());this.__temp=new b(0);var s=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,!1); 67 | this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=document.createElement("input"); 68 | this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){13===a.keyCode&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(b){a.addClass(this,"drag").bind(window,"mouseup",function(b){a.removeClass(s.__selector,"drag")})});var v=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});f.extend(this.__field_knob.style, 69 | {position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(0.5>this.__color.v?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(v.style,{width:"100%",height:"100%", 70 | background:"none"});c(v,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});p(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",r);a.bind(this.__field_knob,"mousedown",r);a.bind(this.__hue_field,"mousedown",function(b){u(b);a.bind(window, 71 | "mousemove",u);a.bind(window,"mouseup",h)});this.__saturation_field.appendChild(v);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};k.superclass=e;f.extend(k.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue());if(!1!==a){var e=!1; 72 | f.each(b.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=!0,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var k=0.5>this.__color.v||0.5a&&(a+=1);return{h:360*a,s:e/c,v:c/255}},rgb_to_hex:function(a,b,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,b);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,b){return a>>8*b&255},hex_with_component:function(a,b,d){return d<<(e=8*b)|a&~(255<