├── LICENSE ├── README.md ├── Week10 └── Demo0 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Week11 ├── Demo0 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js └── Demo1 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Week2 ├── Demo0 │ ├── demo.html │ └── demo.js ├── Demo1 │ ├── demo.html │ └── demo.js ├── Demo2 │ ├── demo.html │ └── demo.js └── Demo3 │ ├── demo.html │ └── demo.js ├── Week3 ├── Demo0 │ ├── demo.html │ └── demo.js ├── Demo1 │ ├── demo.html │ └── demo.js └── Demo2 │ ├── demo.html │ └── demo.js ├── Week4 ├── Demo0 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Demo0a │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Demo0b │ ├── demo.html │ ├── demo.js │ └── twgl-full.min.js └── Demo1 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Week5 ├── Demo0 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Demo1 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js └── Demo2 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Week6 ├── Demo0 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js ├── Demo1 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js └── Demo2 │ ├── demo.html │ ├── demo.js │ └── gl-matrix-min.js └── Week7 ├── Demo0 ├── demo.html ├── demo.js └── gl-matrix-min.js ├── Demo1 ├── demo.html ├── demo.js └── gl-matrix-min.js ├── Demo2 ├── demo.html ├── demo.js └── gl-matrix-min.js ├── Demo3 ├── demo.html ├── demo.js └── gl-matrix-min.js └── Demo4 ├── demo.html ├── demo.js └── gl-matrix-min.js /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020-21, Eftychios Sifakis 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CS559F21_Demos 2 | Software artifacts and Demos for CS559 (Fall 2021) "Computer Graphics" 3 | -------------------------------------------------------------------------------- /Week10/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebGL cube drawn with indexed vertex list 5 | 6 | 7 | 8 | 19 | 20 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Week10/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function start() { 2 | 3 | // Get canvas, WebGL context 4 | var canvas = document.getElementById("mycanvas"); 5 | var gl = canvas.getContext("webgl"); 6 | 7 | // Sliders at center 8 | var slider1 = document.getElementById('slider1'); 9 | slider1.value = 0; 10 | var slider2 = document.getElementById('slider2'); 11 | slider2.value = 0; 12 | 13 | // Read shader source 14 | var vertexSource = document.getElementById("vertexShader").text; 15 | var fragmentSource = document.getElementById("fragmentShader").text; 16 | 17 | // Compile vertex shader 18 | var vertexShader = gl.createShader(gl.VERTEX_SHADER); 19 | gl.shaderSource(vertexShader,vertexSource); 20 | gl.compileShader(vertexShader); 21 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 22 | alert(gl.getShaderInfoLog(vertexShader)); return null; } 23 | 24 | // Compile fragment shader 25 | var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 26 | gl.shaderSource(fragmentShader,fragmentSource); 27 | gl.compileShader(fragmentShader); 28 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 29 | alert(gl.getShaderInfoLog(fragmentShader)); return null; } 30 | 31 | // Attach the shaders and link 32 | var shaderProgram = gl.createProgram(); 33 | gl.attachShader(shaderProgram, vertexShader); 34 | gl.attachShader(shaderProgram, fragmentShader); 35 | gl.linkProgram(shaderProgram); 36 | if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 37 | alert("Could not initialize shaders"); } 38 | gl.useProgram(shaderProgram); 39 | 40 | // with the vertex shader, we need to pass it positions 41 | // as an attribute - so set up that communication 42 | shaderProgram.PositionAttribute = gl.getAttribLocation(shaderProgram, "vPosition"); 43 | gl.enableVertexAttribArray(shaderProgram.PositionAttribute); 44 | 45 | shaderProgram.ColorAttribute = gl.getAttribLocation(shaderProgram, "vColor"); 46 | gl.enableVertexAttribArray(shaderProgram.ColorAttribute); 47 | 48 | // this gives us access to the matrix uniform 49 | shaderProgram.MVPmatrix = gl.getUniformLocation(shaderProgram,"uMVP"); 50 | 51 | // Data ... 52 | 53 | // vertex positions 54 | var vertexPos = new Float32Array( 55 | [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, 56 | 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, 57 | 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, 58 | -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, 59 | -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, 60 | 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ]); 61 | 62 | // vertex colors 63 | var vertexColors = new Float32Array( 64 | [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 65 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 66 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 67 | 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 68 | 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 69 | 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1 ]); 70 | 71 | // element index array 72 | var triangleIndices = new Uint8Array( 73 | [ 0, 1, 2, 0, 2, 3, // front 74 | 4, 5, 6, 4, 6, 7, // right 75 | 8, 9,10, 8,10,11, // top 76 | 12,13,14, 12,14,15, // left 77 | 16,17,18, 16,18,19, // bottom 78 | 20,21,22, 20,22,23 ]); // back 79 | 80 | // we need to put the vertices into a buffer so we can 81 | // block transfer them to the graphics hardware 82 | var trianglePosBuffer = gl.createBuffer(); 83 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 84 | gl.bufferData(gl.ARRAY_BUFFER, vertexPos, gl.STATIC_DRAW); 85 | trianglePosBuffer.itemSize = 3; 86 | trianglePosBuffer.numItems = 24; 87 | 88 | // a buffer for colors 89 | var colorBuffer = gl.createBuffer(); 90 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 91 | gl.bufferData(gl.ARRAY_BUFFER, vertexColors, gl.STATIC_DRAW); 92 | colorBuffer.itemSize = 3; 93 | colorBuffer.numItems = 24; 94 | 95 | // a buffer for indices 96 | var indexBuffer = gl.createBuffer(); 97 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 98 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, triangleIndices, gl.STATIC_DRAW); 99 | 100 | // Scene (re-)draw routine 101 | function draw() { 102 | 103 | // Translate slider values to angles in the [-pi,pi] interval 104 | var angle1 = slider1.value*0.01*Math.PI; 105 | var angle2 = slider2.value*0.01*Math.PI; 106 | 107 | // Circle around the y-axis 108 | var eye = [400*Math.sin(angle1),150.0,400.0*Math.cos(angle1)]; 109 | var target = [0,0,0]; 110 | var up = [0,1,0]; 111 | 112 | var tModel = mat4.create(); 113 | mat4.fromScaling(tModel,[100,100,100]); 114 | mat4.rotate(tModel,tModel,angle2,[1,1,1]); 115 | 116 | var tCamera = mat4.create(); 117 | mat4.lookAt(tCamera, eye, target, up); 118 | 119 | var tProjection = mat4.create(); 120 | mat4.perspective(tProjection,Math.PI/4,1,10,1000); 121 | 122 | var tMVP = mat4.create(); 123 | mat4.multiply(tMVP,tCamera,tModel); // "modelView" matrix 124 | mat4.multiply(tMVP,tProjection,tMVP); 125 | 126 | // Clear screen, prepare for rendering 127 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 128 | gl.enable(gl.DEPTH_TEST); 129 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 130 | 131 | // Set up uniforms & attributes 132 | gl.uniformMatrix4fv(shaderProgram.MVPmatrix,false,tMVP); 133 | 134 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 135 | gl.vertexAttribPointer(shaderProgram.ColorAttribute, colorBuffer.itemSize, 136 | gl.FLOAT,false, 0, 0); 137 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 138 | gl.vertexAttribPointer(shaderProgram.PositionAttribute, trianglePosBuffer.itemSize, 139 | gl.FLOAT, false, 0, 0); 140 | 141 | // Do the drawing 142 | gl.drawElements(gl.TRIANGLES, triangleIndices.length, gl.UNSIGNED_BYTE, 0); 143 | 144 | } 145 | 146 | slider1.addEventListener("input",draw); 147 | slider2.addEventListener("input",draw); 148 | draw(); 149 | } 150 | 151 | window.onload=start; 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /Week10/Demo0/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},n.equals=function(t,a){return Math.abs(t-a)<=n.EPSILON*Math.max(1,Math.abs(t),Math.abs(a))},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.fromValues=function(t,a,n,o){var u=new r.ARRAY_TYPE(4);return u[0]=t,u[1]=a,u[2]=n,u[3]=o,u},o.set=function(t,a,n,r,o){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,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],u=a[3],l=n*u-o*r;return l?(l=1/l,t[0]=u*l,t[1]=-r*l,t[2]=-o*l,t[3]=n*l,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],u=a[2],l=a[3],e=n[0],M=n[1],s=n[2],i=n[3];return t[0]=r*e+u*M,t[1]=o*e+l*M,t[2]=r*s+u*i,t[3]=o*s+l*i,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=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]=r*-e+u*M,t[3]=o*-e+l*M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=n[0],M=n[1];return t[0]=r*e,t[1]=o*e,t[2]=u*M,t[3]=l*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]},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.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=a[0],M=a[1],s=a[2],i=a[3];return Math.abs(n-e)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(e))&&Math.abs(o-M)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(M))&&Math.abs(u-s)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(l-i)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(i))},o.multiplyScalar=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.multiplyScalarAndAdd=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},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.fromValues=function(t,a,n,o,u,l){var e=new r.ARRAY_TYPE(6);return e[0]=t,e[1]=a,e[2]=n,e[3]=o,e[4]=u,e[5]=l,e},o.set=function(t,a,n,r,o,u,l){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=n*u-r*o;return M?(M=1/M,t[0]=u*M,t[1]=-r*M,t[2]=-o*M,t[3]=n*M,t[4]=(o*e-u*l)*M,t[5]=(r*l-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],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1],c=n[2],h=n[3],S=n[4],I=n[5];return t[0]=r*s+u*i,t[1]=o*s+l*i,t[2]=r*c+u*h,t[3]=o*c+l*h,t[4]=r*S+u*I+e,t[5]=o*S+l*I+M,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=Math.sin(n),i=Math.cos(n);return t[0]=r*i+u*s,t[1]=o*i+l*s,t[2]=r*-s+u*i,t[3]=o*-s+l*i,t[4]=e,t[5]=M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1];return t[0]=r*s,t[1]=o*s,t[2]=u*i,t[3]=l*i,t[4]=e,t[5]=M,t},o.translate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1];return t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=r*s+u*i+e,t[5]=o*s+l*i+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)},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[4]=a[4]+n[4],t[5]=a[5]+n[5],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[4]=a[4]-n[4],t[5]=a[5]-n[5],t},o.sub=o.subtract,o.multiplyScalar=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[4]=a[4]*n,t[5]=a[5]*n,t},o.multiplyScalarAndAdd=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[4]=a[4]+n[4]*r,t[5]=a[5]+n[5]*r,t},o.exactEquals=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]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=t[4],M=t[5],s=a[0],i=a[1],c=a[2],h=a[3],S=a[4],I=a[5];return Math.abs(n-s)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(s))&&Math.abs(o-i)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(i))&&Math.abs(u-c)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(l-h)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(h))&&Math.abs(e-S)<=r.EPSILON*Math.max(1,Math.abs(e),Math.abs(S))&&Math.abs(M-I)<=r.EPSILON*Math.max(1,Math.abs(M),Math.abs(I))},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.fromValues=function(t,a,n,o,u,l,e,M,s){var i=new r.ARRAY_TYPE(9);return i[0]=t,i[1]=a,i[2]=n,i[3]=o,i[4]=u,i[5]=l,i[6]=e,i[7]=M,i[8]=s,i},o.set=function(t,a,n,r,o,u,l,e,M,s){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t[6]=e,t[7]=M,t[8]=s,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],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=i*l-e*s,h=-i*u+e*M,S=s*u-l*M,I=n*c+r*h+o*S;return I?(I=1/I,t[0]=c*I,t[1]=(-i*r+o*s)*I,t[2]=(e*r-o*l)*I,t[3]=h*I,t[4]=(i*n-o*M)*I,t[5]=(-e*n+o*u)*I,t[6]=S*I,t[7]=(-s*n+r*M)*I,t[8]=(l*n-r*u)*I,t):null},o.adjoint=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8];return t[0]=l*i-e*s,t[1]=o*s-r*i,t[2]=r*e-o*l,t[3]=e*M-u*i,t[4]=n*i-o*M,t[5]=o*u-n*e,t[6]=u*s-l*M,t[7]=r*M-n*s,t[8]=n*l-r*u,t},o.determinant=function(t){var a=t[0],n=t[1],r=t[2],o=t[3],u=t[4],l=t[5],e=t[6],M=t[7],s=t[8];return a*(s*u-l*M)+n*(-s*o+l*e)+r*(M*o-u*e)},o.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=n[0],S=n[1],I=n[2],f=n[3],x=n[4],D=n[5],F=n[6],m=n[7],d=n[8];return t[0]=h*r+S*l+I*s,t[1]=h*o+S*e+I*i,t[2]=h*u+S*M+I*c,t[3]=f*r+x*l+D*s,t[4]=f*o+x*e+D*i,t[5]=f*u+x*M+D*c,t[6]=F*r+m*l+d*s,t[7]=F*o+m*e+d*i,t[8]=F*u+m*M+d*c,t},o.mul=o.multiply,o.translate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=n[0],S=n[1];return t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=e,t[5]=M,t[6]=h*r+S*l+s,t[7]=h*o+S*e+i,t[8]=h*u+S*M+c,t},o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=Math.sin(n),S=Math.cos(n);return t[0]=S*r+h*l,t[1]=S*o+h*e,t[2]=S*u+h*M,t[3]=S*l-h*r,t[4]=S*e-h*o,t[5]=S*M-h*u,t[6]=s,t[7]=i,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],u=a[3],l=n+n,e=r+r,M=o+o,s=n*l,i=r*l,c=r*e,h=o*l,S=o*e,I=o*M,f=u*l,x=u*e,D=u*M;return t[0]=1-c-I,t[3]=i-D,t[6]=h+x,t[1]=i+D,t[4]=1-s-I,t[7]=S-f,t[2]=h-x,t[5]=S+f,t[8]=1-s-c,t},o.normalFromMat4=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15],F=n*e-r*l,m=n*M-o*l,d=n*s-u*l,b=r*M-o*e,v=r*s-u*e,z=o*s-u*M,p=i*f-c*I,w=i*x-h*I,E=i*D-S*I,A=c*x-h*f,P=c*D-S*f,L=h*D-S*x,q=F*L-m*P+d*A+b*E-v*w+z*p;return q?(q=1/q,t[0]=(e*L-M*P+s*A)*q,t[1]=(M*E-l*L-s*w)*q,t[2]=(l*P-e*E+s*p)*q,t[3]=(o*P-r*L-u*A)*q,t[4]=(n*L-o*E+u*w)*q,t[5]=(r*E-n*P-u*p)*q,t[6]=(f*z-x*v+D*b)*q,t[7]=(x*d-I*z-D*m)*q,t[8]=(I*v-f*d+D*F)*q,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))},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[4]=a[4]+n[4],t[5]=a[5]+n[5],t[6]=a[6]+n[6],t[7]=a[7]+n[7],t[8]=a[8]+n[8],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[4]=a[4]-n[4],t[5]=a[5]-n[5],t[6]=a[6]-n[6],t[7]=a[7]-n[7],t[8]=a[8]-n[8],t},o.sub=o.subtract,o.multiplyScalar=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[4]=a[4]*n,t[5]=a[5]*n,t[6]=a[6]*n,t[7]=a[7]*n,t[8]=a[8]*n,t},o.multiplyScalarAndAdd=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[4]=a[4]+n[4]*r,t[5]=a[5]+n[5]*r,t[6]=a[6]+n[6]*r,t[7]=a[7]+n[7]*r,t[8]=a[8]+n[8]*r,t},o.exactEquals=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]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=t[4],M=t[5],s=t[6],i=t[7],c=t[8],h=a[0],S=a[1],I=a[2],f=a[3],x=a[4],D=a[5],F=t[6],m=a[7],d=a[8];return Math.abs(n-h)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(h))&&Math.abs(o-S)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(S))&&Math.abs(u-I)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(I))&&Math.abs(l-f)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(f))&&Math.abs(e-x)<=r.EPSILON*Math.max(1,Math.abs(e),Math.abs(x))&&Math.abs(M-D)<=r.EPSILON*Math.max(1,Math.abs(M),Math.abs(D))&&Math.abs(s-F)<=r.EPSILON*Math.max(1,Math.abs(s),Math.abs(F))&&Math.abs(i-m)<=r.EPSILON*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(c-d)<=r.EPSILON*Math.max(1,Math.abs(c),Math.abs(d))},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.fromValues=function(t,a,n,o,u,l,e,M,s,i,c,h,S,I,f,x){var D=new r.ARRAY_TYPE(16);return D[0]=t,D[1]=a,D[2]=n,D[3]=o,D[4]=u,D[5]=l,D[6]=e,D[7]=M,D[8]=s,D[9]=i,D[10]=c,D[11]=h,D[12]=S,D[13]=I,D[14]=f,D[15]=x,D},o.set=function(t,a,n,r,o,u,l,e,M,s,i,c,h,S,I,f,x){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t[6]=e,t[7]=M,t[8]=s,t[9]=i,t[10]=c,t[11]=h,t[12]=S,t[13]=I,t[14]=f,t[15]=x,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],u=a[6],l=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]=u,t[11]=a[14],t[12]=o,t[13]=l,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,u,l,e,M,s,i,c;return n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12),l=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,u,0,1,4,5),M=SIMD.Float32x4.shuffle(l,e,0,2,4,6),s=SIMD.Float32x4.shuffle(l,e,1,3,5,7),SIMD.Float32x4.store(t,0,M),SIMD.Float32x4.store(t,4,s),l=SIMD.Float32x4.shuffle(n,r,2,3,6,7),e=SIMD.Float32x4.shuffle(o,u,2,3,6,7),i=SIMD.Float32x4.shuffle(l,e,0,2,4,6),c=SIMD.Float32x4.shuffle(l,e,1,3,5,7),SIMD.Float32x4.store(t,8,i),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],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15],F=n*e-r*l,m=n*M-o*l,d=n*s-u*l,b=r*M-o*e,v=r*s-u*e,z=o*s-u*M,p=i*f-c*I,w=i*x-h*I,E=i*D-S*I,A=c*x-h*f,P=c*D-S*f,L=h*D-S*x,q=F*L-m*P+d*A+b*E-v*w+z*p;return q?(q=1/q,t[0]=(e*L-M*P+s*A)*q,t[1]=(o*P-r*L-u*A)*q,t[2]=(f*z-x*v+D*b)*q,t[3]=(h*v-c*z-S*b)*q,t[4]=(M*E-l*L-s*w)*q,t[5]=(n*L-o*E+u*w)*q,t[6]=(x*d-I*z-D*m)*q,t[7]=(i*z-h*d+S*m)*q,t[8]=(l*P-e*E+s*p)*q,t[9]=(r*E-n*P-u*p)*q,t[10]=(I*v-f*d+D*F)*q,t[11]=(c*d-i*v-S*F)*q,t[12]=(e*w-l*A-M*p)*q,t[13]=(n*A-r*w+o*p)*q,t[14]=(f*m-I*b-x*F)*q,t[15]=(i*b-c*m+h*F)*q,t):null},o.SIMD.invert=function(t,a){var n,r,o,u,l,e,M,s,i,c,h=SIMD.Float32x4.load(a,0),S=SIMD.Float32x4.load(a,4),I=SIMD.Float32x4.load(a,8),f=SIMD.Float32x4.load(a,12);return l=SIMD.Float32x4.shuffle(h,S,0,1,4,5),r=SIMD.Float32x4.shuffle(I,f,0,1,4,5),n=SIMD.Float32x4.shuffle(l,r,0,2,4,6),r=SIMD.Float32x4.shuffle(r,l,1,3,5,7),l=SIMD.Float32x4.shuffle(h,S,2,3,6,7),u=SIMD.Float32x4.shuffle(I,f,2,3,6,7),o=SIMD.Float32x4.shuffle(l,u,0,2,4,6),u=SIMD.Float32x4.shuffle(u,l,1,3,5,7),l=SIMD.Float32x4.mul(o,u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),e=SIMD.Float32x4.mul(r,l),M=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(SIMD.Float32x4.mul(r,l),e),M=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),M),M=SIMD.Float32x4.swizzle(M,2,3,0,1),l=SIMD.Float32x4.mul(r,o),l=SIMD.Float32x4.swizzle(l,1,0,3,2),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),e),i=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(u,l)),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),l=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(r,2,3,0,1),u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),o=SIMD.Float32x4.swizzle(o,2,3,0,1),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,l),e),s=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(o,l)),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),l=SIMD.Float32x4.mul(n,r),l=SIMD.Float32x4.swizzle(l,1,0,3,2),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),s),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(o,l),i),l=SIMD.Float32x4.swizzle(l,2,3,0,1),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(u,l),s),i=SIMD.Float32x4.sub(i,SIMD.Float32x4.mul(o,l)),l=SIMD.Float32x4.mul(n,u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(o,l)),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,l),s),l=SIMD.Float32x4.swizzle(l,2,3,0,1),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,l),M),s=SIMD.Float32x4.sub(s,SIMD.Float32x4.mul(r,l)),l=SIMD.Float32x4.mul(n,o),l=SIMD.Float32x4.swizzle(l,1,0,3,2),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),M),i=SIMD.Float32x4.sub(i,SIMD.Float32x4.mul(r,l)),l=SIMD.Float32x4.swizzle(l,2,3,0,1),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(u,l)),i=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,l),i),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),l=SIMD.Float32x4.reciprocalApproximation(c),c=SIMD.Float32x4.sub(SIMD.Float32x4.add(l,l),SIMD.Float32x4.mul(c,SIMD.Float32x4.mul(l,l))),(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,s)),SIMD.Float32x4.store(t,12,SIMD.Float32x4.mul(c,i)),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],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15];return t[0]=e*(h*D-S*x)-c*(M*D-s*x)+f*(M*S-s*h),t[1]=-(r*(h*D-S*x)-c*(o*D-u*x)+f*(o*S-u*h)),t[2]=r*(M*D-s*x)-e*(o*D-u*x)+f*(o*s-u*M),t[3]=-(r*(M*S-s*h)-e*(o*S-u*h)+c*(o*s-u*M)),t[4]=-(l*(h*D-S*x)-i*(M*D-s*x)+I*(M*S-s*h)),t[5]=n*(h*D-S*x)-i*(o*D-u*x)+I*(o*S-u*h),t[6]=-(n*(M*D-s*x)-l*(o*D-u*x)+I*(o*s-u*M)),t[7]=n*(M*S-s*h)-l*(o*S-u*h)+i*(o*s-u*M),t[8]=l*(c*D-S*f)-i*(e*D-s*f)+I*(e*S-s*c),t[9]=-(n*(c*D-S*f)-i*(r*D-u*f)+I*(r*S-u*c)),t[10]=n*(e*D-s*f)-l*(r*D-u*f)+I*(r*s-u*e),t[11]=-(n*(e*S-s*c)-l*(r*S-u*c)+i*(r*s-u*e)),t[12]=-(l*(c*x-h*f)-i*(e*x-M*f)+I*(e*h-M*c)),t[13]=n*(c*x-h*f)-i*(r*x-o*f)+I*(r*h-o*c),t[14]=-(n*(e*x-M*f)-l*(r*x-o*f)+I*(r*M-o*e)),t[15]=n*(e*h-M*c)-l*(r*h-o*c)+i*(r*M-o*e),t},o.SIMD.adjoint=function(t,a){var n,r,o,u,l,e,M,s,i,c,h,S,I,n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12);return i=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,u,0,1,4,5),l=SIMD.Float32x4.shuffle(i,e,0,2,4,6),e=SIMD.Float32x4.shuffle(e,i,1,3,5,7),i=SIMD.Float32x4.shuffle(n,r,2,3,6,7),s=SIMD.Float32x4.shuffle(o,u,2,3,6,7),M=SIMD.Float32x4.shuffle(i,s,0,2,4,6),s=SIMD.Float32x4.shuffle(s,i,1,3,5,7),i=SIMD.Float32x4.mul(M,s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),c=SIMD.Float32x4.mul(e,i),h=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(SIMD.Float32x4.mul(e,i),c),h=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),h),h=SIMD.Float32x4.swizzle(h,2,3,0,1),i=SIMD.Float32x4.mul(e,M),i=SIMD.Float32x4.swizzle(i,1,0,3,2),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),c),I=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(s,i)),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),I),I=SIMD.Float32x4.swizzle(I,2,3,0,1),i=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,2,3,0,1),s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),M=SIMD.Float32x4.swizzle(M,2,3,0,1),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,i),c),S=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(M,i)),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),S),S=SIMD.Float32x4.swizzle(S,2,3,0,1),i=SIMD.Float32x4.mul(l,e),i=SIMD.Float32x4.swizzle(i,1,0,3,2),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),S),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(M,i),I),i=SIMD.Float32x4.swizzle(i,2,3,0,1),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(s,i),S),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(M,i)),i=SIMD.Float32x4.mul(l,s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),h=SIMD.Float32x4.sub(h,SIMD.Float32x4.mul(M,i)),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,i),S),i=SIMD.Float32x4.swizzle(i,2,3,0,1),h=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,i),h),S=SIMD.Float32x4.sub(S,SIMD.Float32x4.mul(e,i)),i=SIMD.Float32x4.mul(l,M),i=SIMD.Float32x4.swizzle(i,1,0,3,2),h=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),h),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(e,i)),i=SIMD.Float32x4.swizzle(i,2,3,0,1),h=SIMD.Float32x4.sub(h,SIMD.Float32x4.mul(s,i)),I=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,i),I),SIMD.Float32x4.store(t,0,c),SIMD.Float32x4.store(t,4,h),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],u=t[4],l=t[5],e=t[6],M=t[7],s=t[8],i=t[9],c=t[10],h=t[11],S=t[12],I=t[13],f=t[14],x=t[15],D=a*l-n*u,F=a*e-r*u,m=a*M-o*u,d=n*e-r*l,b=n*M-o*l,v=r*M-o*e,z=s*I-i*S,p=s*f-c*S,w=s*x-h*S,E=i*f-c*I,A=i*x-h*I,P=c*x-h*f;return D*P-F*A+m*E+d*w-b*p+v*z},o.SIMD.multiply=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),u=SIMD.Float32x4.load(a,8),l=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),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,3,3,3,3),l))));SIMD.Float32x4.store(t,0,M);var s=SIMD.Float32x4.load(n,4),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),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s,3,3,3,3),l))));SIMD.Float32x4.store(t,4,i);var c=SIMD.Float32x4.load(n,8),h=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),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,3,3,3,3),l))));SIMD.Float32x4.store(t,8,h);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),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,3,3,3,3),l))));return SIMD.Float32x4.store(t,12,I),t},o.scalar.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=a[9],S=a[10],I=a[11],f=a[12],x=a[13],D=a[14],F=a[15],m=n[0],d=n[1],b=n[2],v=n[3];return t[0]=m*r+d*e+b*c+v*f,t[1]=m*o+d*M+b*h+v*x,t[2]=m*u+d*s+b*S+v*D,t[3]=m*l+d*i+b*I+v*F,m=n[4],d=n[5],b=n[6],v=n[7],t[4]=m*r+d*e+b*c+v*f,t[5]=m*o+d*M+b*h+v*x,t[6]=m*u+d*s+b*S+v*D,t[7]=m*l+d*i+b*I+v*F,m=n[8],d=n[9],b=n[10],v=n[11],t[8]=m*r+d*e+b*c+v*f,t[9]=m*o+d*M+b*h+v*x,t[10]=m*u+d*s+b*S+v*D,t[11]=m*l+d*i+b*I+v*F,m=n[12],d=n[13],b=n[14],v=n[15],t[12]=m*r+d*e+b*c+v*f,t[13]=m*o+d*M+b*h+v*x,t[14]=m*u+d*s+b*S+v*D,t[15]=m*l+d*i+b*I+v*F,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,u,l,e,M,s,i,c,h,S,I,f=n[0],x=n[1],D=n[2];return a===t?(t[12]=a[0]*f+a[4]*x+a[8]*D+a[12],t[13]=a[1]*f+a[5]*x+a[9]*D+a[13],t[14]=a[2]*f+a[6]*x+a[10]*D+a[14],t[15]=a[3]*f+a[7]*x+a[11]*D+a[15]):(r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=a[9],S=a[10],I=a[11],t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=e,t[5]=M,t[6]=s,t[7]=i,t[8]=c,t[9]=h,t[10]=S,t[11]=I,t[12]=r*f+e*x+c*D+a[12],t[13]=o*f+M*x+h*D+a[13],t[14]=u*f+s*x+S*D+a[14],t[15]=l*f+i*x+I*D+a[15]),t},o.SIMD.translate=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),u=SIMD.Float32x4.load(a,8),l=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)),u=SIMD.Float32x4.mul(u,SIMD.Float32x4.swizzle(e,2,2,2,2));var M=SIMD.Float32x4.add(r,SIMD.Float32x4.add(o,SIMD.Float32x4.add(u,l)));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],u=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]*u,t[9]=a[9]*u,t[10]=a[10]*u,t[11]=a[11]*u,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,u,l=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(l,0,0,0,0))),o=SIMD.Float32x4.load(a,4),SIMD.Float32x4.store(t,4,SIMD.Float32x4.mul(o,SIMD.Float32x4.swizzle(l,1,1,1,1))),u=SIMD.Float32x4.load(a,8),SIMD.Float32x4.store(t,8,SIMD.Float32x4.mul(u,SIMD.Float32x4.swizzle(l,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 u,l,e,M,s,i,c,h,S,I,f,x,D,F,m,d,b,v,z,p,w,E,A,P,L=o[0],q=o[1],R=o[2],N=Math.sqrt(L*L+q*q+R*R);return Math.abs(N)0?(r=2*Math.sqrt(n+1),t[3]=.25*r,t[0]=(a[6]-a[9])/r,t[1]=(a[8]-a[2])/r,t[2]=(a[1]-a[4])/r):a[0]>a[5]&a[0]>a[10]?(r=2*Math.sqrt(1+a[0]-a[5]-a[10]),t[3]=(a[6]-a[9])/r,t[0]=.25*r,t[1]=(a[1]+a[4])/r,t[2]=(a[8]+a[2])/r):a[5]>a[10]?(r=2*Math.sqrt(1+a[5]-a[0]-a[10]),t[3]=(a[8]-a[2])/r,t[0]=(a[1]+a[4])/r,t[1]=.25*r,t[2]=(a[6]+a[9])/r):(r=2*Math.sqrt(1+a[10]-a[0]-a[5]),t[3]=(a[1]-a[4])/r,t[0]=(a[8]+a[2])/r,t[1]=(a[6]+a[9])/r,t[2]=.25*r),t},o.fromRotationTranslationScale=function(t,a,n,r){var o=a[0],u=a[1],l=a[2],e=a[3],M=o+o,s=u+u,i=l+l,c=o*M,h=o*s,S=o*i,I=u*s,f=u*i,x=l*i,D=e*M,F=e*s,m=e*i,d=r[0],b=r[1],v=r[2];return t[0]=(1-(I+x))*d,t[1]=(h+m)*d,t[2]=(S-F)*d,t[3]=0,t[4]=(h-m)*b,t[5]=(1-(c+x))*b,t[6]=(f+D)*b,t[7]=0,t[8]=(S+F)*v,t[9]=(f-D)*v,t[10]=(1-(c+I))*v,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t},o.fromRotationTranslationScaleOrigin=function(t,a,n,r,o){ 29 | var u=a[0],l=a[1],e=a[2],M=a[3],s=u+u,i=l+l,c=e+e,h=u*s,S=u*i,I=u*c,f=l*i,x=l*c,D=e*c,F=M*s,m=M*i,d=M*c,b=r[0],v=r[1],z=r[2],p=o[0],w=o[1],E=o[2];return t[0]=(1-(f+D))*b,t[1]=(S+d)*b,t[2]=(I-m)*b,t[3]=0,t[4]=(S-d)*v,t[5]=(1-(h+D))*v,t[6]=(x+F)*v,t[7]=0,t[8]=(I+m)*z,t[9]=(x-F)*z,t[10]=(1-(h+f))*z,t[11]=0,t[12]=n[0]+p-(t[0]*p+t[4]*w+t[8]*E),t[13]=n[1]+w-(t[1]*p+t[5]*w+t[9]*E),t[14]=n[2]+E-(t[2]*p+t[6]*w+t[10]*E),t[15]=1,t},o.fromQuat=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n+n,e=r+r,M=o+o,s=n*l,i=r*l,c=r*e,h=o*l,S=o*e,I=o*M,f=u*l,x=u*e,D=u*M;return t[0]=1-c-I,t[1]=i+D,t[2]=h-x,t[3]=0,t[4]=i-D,t[5]=1-s-I,t[6]=S+f,t[7]=0,t[8]=h+x,t[9]=S-f,t[10]=1-s-c,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.frustum=function(t,a,n,r,o,u,l){var e=1/(n-a),M=1/(o-r),s=1/(u-l);return t[0]=2*u*e,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*M,t[6]=0,t[7]=0,t[8]=(n+a)*e,t[9]=(o+r)*M,t[10]=(l+u)*s,t[11]=-1,t[12]=0,t[13]=0,t[14]=l*u*2*s,t[15]=0,t},o.perspective=function(t,a,n,r,o){var u=1/Math.tan(a/2),l=1/(r-o);return t[0]=u/n,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(o+r)*l,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*o*r*l,t[15]=0,t},o.perspectiveFromFieldOfView=function(t,a,n,r){var o=Math.tan(a.upDegrees*Math.PI/180),u=Math.tan(a.downDegrees*Math.PI/180),l=Math.tan(a.leftDegrees*Math.PI/180),e=Math.tan(a.rightDegrees*Math.PI/180),M=2/(l+e),s=2/(o+u);return t[0]=M,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=s,t[6]=0,t[7]=0,t[8]=-((l-e)*M*.5),t[9]=(o-u)*s*.5,t[10]=r/(n-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*n/(n-r),t[15]=0,t},o.ortho=function(t,a,n,r,o,u,l){var e=1/(a-n),M=1/(r-o),s=1/(u-l);return t[0]=-2*e,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*M,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*s,t[11]=0,t[12]=(a+n)*e,t[13]=(o+r)*M,t[14]=(l+u)*s,t[15]=1,t},o.lookAt=function(t,a,n,u){var l,e,M,s,i,c,h,S,I,f,x=a[0],D=a[1],F=a[2],m=u[0],d=u[1],b=u[2],v=n[0],z=n[1],p=n[2];return Math.abs(x-v)M?(u.cross(t,a,o),u.length(t)<1e-6&&u.cross(t,n,o),u.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):(u.cross(t,o,l),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=l.clone,e.fromValues=l.fromValues,e.copy=l.copy,e.set=l.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.getAxisAngle=function(t,a){var n=2*Math.acos(a[3]),r=Math.sin(n/2);return 0!=r?(t[0]=a[0]/r,t[1]=a[1]/r,t[2]=a[2]/r):(t[0]=1,t[1]=0,t[2]=0),n},e.add=l.add,e.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=n[0],M=n[1],s=n[2],i=n[3];return t[0]=r*i+l*e+o*s-u*M,t[1]=o*i+l*M+u*e-r*s,t[2]=u*i+l*s+r*M-o*e,t[3]=l*i-r*e-o*M-u*s,t},e.mul=e.multiply,e.scale=l.scale,e.rotateX=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=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]=u*M-o*e,t[3]=l*M-r*e,t},e.rotateY=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=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]=u*M+r*e,t[3]=l*M-o*e,t},e.rotateZ=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=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]=u*M+l*e,t[3]=l*M-u*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=l.dot,e.lerp=l.lerp,e.slerp=function(t,a,n,r){var o,u,l,e,M,s=a[0],i=a[1],c=a[2],h=a[3],S=n[0],I=n[1],f=n[2],x=n[3];return u=s*S+i*I+c*f+h*x,0>u&&(u=-u,S=-S,I=-I,f=-f,x=-x),1-u>1e-6?(o=Math.acos(u),l=Math.sin(o),e=Math.sin((1-r)*o)/l,M=Math.sin(r*o)/l):(e=1-r,M=r),t[0]=e*s+M*S,t[1]=e*i+M*I,t[2]=e*c+M*f,t[3]=e*h+M*x,t},e.sqlerp=function(){var t=e.create(),a=e.create();return function(n,r,o,u,l,M){return e.slerp(t,r,l,M),e.slerp(a,o,u,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],u=a[3],l=n*n+r*r+o*o+u*u,e=l?1/l:0;return t[0]=-n*e,t[1]=-r*e,t[2]=-o*e,t[3]=u*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=l.length,e.len=e.length,e.squaredLength=l.squaredLength,e.sqrLen=e.squaredLength,e.normalize=l.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 u=(o+1)%3,l=(o+2)%3;n=Math.sqrt(a[3*o+o]-a[3*u+u]-a[3*l+l]+1),t[o]=.5*n,n=.5/n,t[3]=(a[3*u+l]-a[3*l+u])*n,t[u]=(a[3*u+o]+a[3*o+u])*n,t[l]=(a[3*l+o]+a[3*o+l])*n}return t},e.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},e.exactEquals=l.exactEquals,e.equals=l.equals,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.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t[2]=Math.ceil(a[2]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t[2]=Math.floor(a[2]),t},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.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[1]),t[2]=Math.round(a[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],u=n*n+r*r+o*o;return u>0&&(u=1/Math.sqrt(u),t[0]=a[0]*u,t[1]=a[1]*u,t[2]=a[2]*u),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],u=a[2],l=n[0],e=n[1],M=n[2];return t[0]=o*M-u*e,t[1]=u*l-r*M,t[2]=r*e-o*l,t},o.lerp=function(t,a,n,r){var o=a[0],u=a[1],l=a[2];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),t[2]=l+r*(n[2]-l),t},o.hermite=function(t,a,n,r,o,u){var l=u*u,e=l*(2*u-3)+1,M=l*(u-2)+u,s=l*(u-1),i=l*(3-2*u);return t[0]=a[0]*e+n[0]*M+r[0]*s+o[0]*i,t[1]=a[1]*e+n[1]*M+r[1]*s+o[1]*i,t[2]=a[2]*e+n[2]*M+r[2]*s+o[2]*i,t},o.bezier=function(t,a,n,r,o,u){var l=1-u,e=l*l,M=u*u,s=e*l,i=3*u*e,c=3*M*l,h=M*u;return t[0]=a[0]*s+n[0]*i+r[0]*c+o[0]*h,t[1]=a[1]*s+n[1]*i+r[1]*c+o[1]*h,t[2]=a[2]*s+n[2]*i+r[2]*c+o[2]*h,t},o.random=function(t,a){a=a||1;var n=2*r.RANDOM()*Math.PI,o=2*r.RANDOM()-1,u=Math.sqrt(1-o*o)*a;return t[0]=Math.cos(n)*u,t[1]=Math.sin(n)*u,t[2]=o*a,t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[3]*r+n[7]*o+n[11]*u+n[15];return l=l||1,t[0]=(n[0]*r+n[4]*o+n[8]*u+n[12])/l,t[1]=(n[1]*r+n[5]*o+n[9]*u+n[13])/l,t[2]=(n[2]*r+n[6]*o+n[10]*u+n[14])/l,t},o.transformMat3=function(t,a,n){var r=a[0],o=a[1],u=a[2];return t[0]=r*n[0]+o*n[3]+u*n[6],t[1]=r*n[1]+o*n[4]+u*n[7],t[2]=r*n[2]+o*n[5]+u*n[8],t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[0],e=n[1],M=n[2],s=n[3],i=s*r+e*u-M*o,c=s*o+M*r-l*u,h=s*u+l*o-e*r,S=-l*r-e*o-M*u;return t[0]=i*s+S*-l+c*-M-h*-e,t[1]=c*s+S*-e+h*-l-i*-M,t[2]=h*s+S*-M+i*-e-c*-l,t},o.rotateX=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[0],u[1]=o[1]*Math.cos(r)-o[2]*Math.sin(r),u[2]=o[1]*Math.sin(r)+o[2]*Math.cos(r),t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.rotateY=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[2]*Math.sin(r)+o[0]*Math.cos(r),u[1]=o[1],u[2]=o[2]*Math.cos(r)-o[0]*Math.sin(r),t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.rotateZ=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[0]*Math.cos(r)-o[1]*Math.sin(r),u[1]=o[0]*Math.sin(r)+o[1]*Math.cos(r),u[2]=o[2],t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,u,l){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],u(t,t,l),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 u=o.dot(n,r);return u>1?0:Math.acos(u)},o.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=a[0],e=a[1],M=a[2];return Math.abs(n-l)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(l))&&Math.abs(o-e)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(e))&&Math.abs(u-M)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(M))},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 u=new r.ARRAY_TYPE(4);return u[0]=t,u[1]=a,u[2]=n,u[3]=o,u},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.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t[2]=Math.ceil(a[2]),t[3]=Math.ceil(a[3]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t[2]=Math.floor(a[2]),t[3]=Math.floor(a[3]),t},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.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[1]),t[2]=Math.round(a[2]),t[3]=Math.round(a[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],u=a[3]-t[3];return Math.sqrt(n*n+r*r+o*o+u*u)},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],u=a[3]-t[3];return n*n+r*r+o*o+u*u},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],u=a[3],l=n*n+r*r+o*o+u*u;return l>0&&(l=1/Math.sqrt(l),t[0]=n*l,t[1]=r*l,t[2]=o*l,t[3]=u*l),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],u=a[1],l=a[2],e=a[3];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),t[2]=l+r*(n[2]-l),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],u=a[2],l=a[3];return t[0]=n[0]*r+n[4]*o+n[8]*u+n[12]*l,t[1]=n[1]*r+n[5]*o+n[9]*u+n[13]*l,t[2]=n[2]*r+n[6]*o+n[10]*u+n[14]*l,t[3]=n[3]*r+n[7]*o+n[11]*u+n[15]*l,t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[0],e=n[1],M=n[2],s=n[3],i=s*r+e*u-M*o,c=s*o+M*r-l*u,h=s*u+l*o-e*r,S=-l*r-e*o-M*u;return t[0]=i*s+S*-l+c*-M-h*-e,t[1]=c*s+S*-e+h*-l-i*-M,t[2]=h*s+S*-M+i*-e-c*-l,t[3]=a[3],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,u,l){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],u(t,t,l),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]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=a[0],M=a[1],s=a[2],i=a[3];return Math.abs(n-e)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(e))&&Math.abs(o-M)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(M))&&Math.abs(u-s)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(l-i)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(i))},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.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t},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.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[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],u=a[1];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),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,u,l){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],u(t,t,l),a[e]=t[0],a[e+1]=t[1];return a}}(),o.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]},o.equals=function(t,a){var n=t[0],o=t[1],u=a[0],l=a[1];return Math.abs(n-u)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(u))&&Math.abs(o-l)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(l))},t.exports=o}])}); -------------------------------------------------------------------------------- /Week11/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebGL cube drawn with indexed vertex list 5 | 6 | 7 | 8 | 25 | 26 | 59 | 60 | 61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Week11/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function start() { 2 | 3 | // Get canvas, WebGL context, twgl.m4 4 | var canvas = document.getElementById("mycanvas"); 5 | var gl = canvas.getContext("webgl"); 6 | 7 | // Sliders at center 8 | var slider1 = document.getElementById('slider1'); 9 | slider1.value = 0; 10 | var slider2 = document.getElementById('slider2'); 11 | slider2.value = 0; 12 | 13 | // Read shader source 14 | var vertexSource = document.getElementById("vertexShader").text; 15 | var fragmentSource = document.getElementById("fragmentShader").text; 16 | 17 | // Compile vertex shader 18 | var vertexShader = gl.createShader(gl.VERTEX_SHADER); 19 | gl.shaderSource(vertexShader,vertexSource); 20 | gl.compileShader(vertexShader); 21 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 22 | alert(gl.getShaderInfoLog(vertexShader)); return null; } 23 | 24 | // Compile fragment shader 25 | var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 26 | gl.shaderSource(fragmentShader,fragmentSource); 27 | gl.compileShader(fragmentShader); 28 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 29 | alert(gl.getShaderInfoLog(fragmentShader)); return null; } 30 | 31 | // Attach the shaders and link 32 | var shaderProgram = gl.createProgram(); 33 | gl.attachShader(shaderProgram, vertexShader); 34 | gl.attachShader(shaderProgram, fragmentShader); 35 | gl.linkProgram(shaderProgram); 36 | if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 37 | alert("Could not initialize shaders"); } 38 | gl.useProgram(shaderProgram); 39 | 40 | // with the vertex shader, we need to pass it positions 41 | // as an attribute - so set up that communication 42 | shaderProgram.PositionAttribute = gl.getAttribLocation(shaderProgram, "vPosition"); 43 | gl.enableVertexAttribArray(shaderProgram.PositionAttribute); 44 | 45 | shaderProgram.NormalAttribute = gl.getAttribLocation(shaderProgram, "vNormal"); 46 | gl.enableVertexAttribArray(shaderProgram.NormalAttribute); 47 | 48 | shaderProgram.ColorAttribute = gl.getAttribLocation(shaderProgram, "vColor"); 49 | gl.enableVertexAttribArray(shaderProgram.ColorAttribute); 50 | 51 | shaderProgram.texcoordAttribute = gl.getAttribLocation(shaderProgram, "vTexCoord"); 52 | gl.enableVertexAttribArray(shaderProgram.texcoordAttribute); 53 | 54 | // this gives us access to the matrix uniform 55 | shaderProgram.MVmatrix = gl.getUniformLocation(shaderProgram,"uMV"); 56 | shaderProgram.MVNormalmatrix = gl.getUniformLocation(shaderProgram,"uMVn"); 57 | shaderProgram.MVPmatrix = gl.getUniformLocation(shaderProgram,"uMVP"); 58 | 59 | // Data ... 60 | 61 | // vertex positions 62 | var vertexPos = new Float32Array( 63 | [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, 64 | 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, 65 | 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, 66 | -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, 67 | -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, 68 | 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ]); 69 | 70 | // vertex normals 71 | var vertexNormals = new Float32Array( 72 | [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 73 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 74 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 75 | -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 76 | 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 77 | 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 ]); 78 | 79 | // vertex colors 80 | var vertexColors = new Float32Array( 81 | [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 82 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 83 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 84 | 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 85 | 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 86 | 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1 ]); 87 | 88 | // element index array 89 | var triangleIndices = new Uint8Array( 90 | [ 0, 1, 2, 0, 2, 3, // front 91 | 4, 5, 6, 4, 6, 7, // right 92 | 8, 9,10, 8,10,11, // top 93 | 12,13,14, 12,14,15, // left 94 | 16,17,18, 16,18,19, // bottom 95 | 20,21,22, 20,22,23 ]); // back 96 | 97 | // we need to put the vertices into a buffer so we can 98 | // block transfer them to the graphics hardware 99 | var trianglePosBuffer = gl.createBuffer(); 100 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 101 | gl.bufferData(gl.ARRAY_BUFFER, vertexPos, gl.STATIC_DRAW); 102 | trianglePosBuffer.itemSize = 3; 103 | trianglePosBuffer.numItems = 24; 104 | 105 | // a buffer for normals 106 | var triangleNormalBuffer = gl.createBuffer(); 107 | gl.bindBuffer(gl.ARRAY_BUFFER, triangleNormalBuffer); 108 | gl.bufferData(gl.ARRAY_BUFFER, vertexNormals, gl.STATIC_DRAW); 109 | triangleNormalBuffer.itemSize = 3; 110 | triangleNormalBuffer.numItems = 24; 111 | 112 | // a buffer for colors 113 | var colorBuffer = gl.createBuffer(); 114 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 115 | gl.bufferData(gl.ARRAY_BUFFER, vertexColors, gl.STATIC_DRAW); 116 | colorBuffer.itemSize = 3; 117 | colorBuffer.numItems = 24; 118 | 119 | // a buffer for indices 120 | var indexBuffer = gl.createBuffer(); 121 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 122 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, triangleIndices, gl.STATIC_DRAW); 123 | 124 | // Scene (re-)draw routine 125 | function draw() { 126 | 127 | // Translate slider values to angles in the [-pi,pi] interval 128 | var angle1 = slider1.value*0.01*Math.PI; 129 | var angle2 = slider2.value*0.01*Math.PI; 130 | 131 | // Circle around the y-axis 132 | var eye = [400*Math.sin(angle1),150.0,400.0*Math.cos(angle1)]; 133 | var target = [0,0,0]; 134 | var up = [0,1,0]; 135 | 136 | var tModel = mat4.create(); 137 | mat4.fromScaling(tModel,[100,100,100]); 138 | mat4.rotate(tModel,tModel,angle2,[1,1,1]); 139 | 140 | var tCamera = mat4.create(); 141 | mat4.lookAt(tCamera, eye, target, up); 142 | 143 | var tProjection = mat4.create(); 144 | mat4.perspective(tProjection,Math.PI/4,1,10,1000); 145 | 146 | var tMV = mat4.create(); 147 | var tMVn = mat3.create(); 148 | var tMVP = mat4.create(); 149 | mat4.multiply(tMV,tCamera,tModel); // "modelView" matrix 150 | mat3.normalFromMat4(tMVn,tMV); 151 | mat4.multiply(tMVP,tProjection,tMV); 152 | 153 | // Clear screen, prepare for rendering 154 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 155 | gl.enable(gl.DEPTH_TEST); 156 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 157 | 158 | // Set up uniforms & attributes 159 | gl.uniformMatrix4fv(shaderProgram.MVmatrix,false,tMV); 160 | gl.uniformMatrix3fv(shaderProgram.MVNormalmatrix,false,tMVn); 161 | gl.uniformMatrix4fv(shaderProgram.MVPmatrix,false,tMVP); 162 | 163 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 164 | gl.vertexAttribPointer(shaderProgram.PositionAttribute, trianglePosBuffer.itemSize, 165 | gl.FLOAT, false, 0, 0); 166 | gl.bindBuffer(gl.ARRAY_BUFFER, triangleNormalBuffer); 167 | gl.vertexAttribPointer(shaderProgram.NormalAttribute, triangleNormalBuffer.itemSize, 168 | gl.FLOAT, false, 0, 0); 169 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 170 | gl.vertexAttribPointer(shaderProgram.ColorAttribute, colorBuffer.itemSize, 171 | gl.FLOAT,false, 0, 0); 172 | 173 | // Do the drawing 174 | gl.drawElements(gl.TRIANGLES, triangleIndices.length, gl.UNSIGNED_BYTE, 0); 175 | 176 | } 177 | 178 | slider1.addEventListener("input",draw); 179 | slider2.addEventListener("input",draw); 180 | draw(); 181 | } 182 | 183 | window.onload=start; 184 | -------------------------------------------------------------------------------- /Week11/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebGL cube drawn with indexed vertex list 5 | 6 | 7 | 8 | 28 | 29 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Week11/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function start() { 2 | 3 | // Get canvas, WebGL context, twgl.m4 4 | var canvas = document.getElementById("mycanvas"); 5 | var gl = canvas.getContext("webgl"); 6 | 7 | // Sliders at center 8 | var slider1 = document.getElementById('slider1'); 9 | slider1.value = 0; 10 | var slider2 = document.getElementById('slider2'); 11 | slider2.value = 0; 12 | 13 | // Read shader source 14 | var vertexSource = document.getElementById("vertexShader").text; 15 | var fragmentSource = document.getElementById("fragmentShader").text; 16 | 17 | // Compile vertex shader 18 | var vertexShader = gl.createShader(gl.VERTEX_SHADER); 19 | gl.shaderSource(vertexShader,vertexSource); 20 | gl.compileShader(vertexShader); 21 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 22 | alert(gl.getShaderInfoLog(vertexShader)); return null; } 23 | 24 | // Compile fragment shader 25 | var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 26 | gl.shaderSource(fragmentShader,fragmentSource); 27 | gl.compileShader(fragmentShader); 28 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 29 | alert(gl.getShaderInfoLog(fragmentShader)); return null; } 30 | 31 | // Attach the shaders and link 32 | var shaderProgram = gl.createProgram(); 33 | gl.attachShader(shaderProgram, vertexShader); 34 | gl.attachShader(shaderProgram, fragmentShader); 35 | gl.linkProgram(shaderProgram); 36 | if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 37 | alert("Could not initialize shaders"); } 38 | gl.useProgram(shaderProgram); 39 | 40 | // with the vertex shader, we need to pass it positions 41 | // as an attribute - so set up that communication 42 | shaderProgram.PositionAttribute = gl.getAttribLocation(shaderProgram, "vPosition"); 43 | gl.enableVertexAttribArray(shaderProgram.PositionAttribute); 44 | 45 | shaderProgram.NormalAttribute = gl.getAttribLocation(shaderProgram, "vNormal"); 46 | gl.enableVertexAttribArray(shaderProgram.NormalAttribute); 47 | 48 | shaderProgram.ColorAttribute = gl.getAttribLocation(shaderProgram, "vColor"); 49 | gl.enableVertexAttribArray(shaderProgram.ColorAttribute); 50 | 51 | shaderProgram.texcoordAttribute = gl.getAttribLocation(shaderProgram, "vTexCoord"); 52 | gl.enableVertexAttribArray(shaderProgram.texcoordAttribute); 53 | 54 | // this gives us access to the matrix uniform 55 | shaderProgram.MVmatrix = gl.getUniformLocation(shaderProgram,"uMV"); 56 | shaderProgram.MVNormalmatrix = gl.getUniformLocation(shaderProgram,"uMVn"); 57 | shaderProgram.MVPmatrix = gl.getUniformLocation(shaderProgram,"uMVP"); 58 | 59 | // Attach samplers to texture units 60 | shaderProgram.texSampler1 = gl.getUniformLocation(shaderProgram, "texSampler1"); 61 | gl.uniform1i(shaderProgram.texSampler1, 0); 62 | shaderProgram.texSampler2 = gl.getUniformLocation(shaderProgram, "texSampler2"); 63 | gl.uniform1i(shaderProgram.texSampler2, 1); 64 | 65 | // Data ... 66 | 67 | // vertex positions 68 | var vertexPos = new Float32Array( 69 | [ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, 70 | 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, 71 | 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, 72 | -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, 73 | -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, 74 | 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 ]); 75 | 76 | // vertex normals 77 | var vertexNormals = new Float32Array( 78 | [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 79 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 80 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 81 | -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 82 | 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 83 | 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 ]); 84 | 85 | // vertex colors 86 | var vertexColors = new Float32Array( 87 | [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 88 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 89 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 90 | 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 91 | 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 92 | 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1 ]); 93 | 94 | // vertex texture coordinates 95 | var vertexTextureCoords = new Float32Array( 96 | [ 0, 0, 1, 0, 1, 1, 0, 1, 97 | 1, 0, 1, 1, 0, 1, 0, 0, 98 | 0, 1, 0, 0, 1, 0, 1, 1, 99 | 0, 0, 1, 0, 1, 1, 0, 1, 100 | 1, 1, 0, 1, 0, 0, 1, 0, 101 | 1, 1, 0, 1, 0, 0, 1, 0 ]); 102 | 103 | // element index array 104 | var triangleIndices = new Uint8Array( 105 | [ 0, 1, 2, 0, 2, 3, // front 106 | 4, 5, 6, 4, 6, 7, // right 107 | 8, 9,10, 8,10,11, // top 108 | 12,13,14, 12,14,15, // left 109 | 16,17,18, 16,18,19, // bottom 110 | 20,21,22, 20,22,23 ]); // back 111 | 112 | // we need to put the vertices into a buffer so we can 113 | // block transfer them to the graphics hardware 114 | var trianglePosBuffer = gl.createBuffer(); 115 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 116 | gl.bufferData(gl.ARRAY_BUFFER, vertexPos, gl.STATIC_DRAW); 117 | trianglePosBuffer.itemSize = 3; 118 | trianglePosBuffer.numItems = 24; 119 | 120 | // a buffer for normals 121 | var triangleNormalBuffer = gl.createBuffer(); 122 | gl.bindBuffer(gl.ARRAY_BUFFER, triangleNormalBuffer); 123 | gl.bufferData(gl.ARRAY_BUFFER, vertexNormals, gl.STATIC_DRAW); 124 | triangleNormalBuffer.itemSize = 3; 125 | triangleNormalBuffer.numItems = 24; 126 | 127 | // a buffer for colors 128 | var colorBuffer = gl.createBuffer(); 129 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 130 | gl.bufferData(gl.ARRAY_BUFFER, vertexColors, gl.STATIC_DRAW); 131 | colorBuffer.itemSize = 3; 132 | colorBuffer.numItems = 24; 133 | 134 | // a buffer for textures 135 | var textureBuffer = gl.createBuffer(); 136 | gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer); 137 | gl.bufferData(gl.ARRAY_BUFFER, vertexTextureCoords, gl.STATIC_DRAW); 138 | textureBuffer.itemSize = 2; 139 | textureBuffer.numItems = 24; 140 | 141 | // a buffer for indices 142 | var indexBuffer = gl.createBuffer(); 143 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 144 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, triangleIndices, gl.STATIC_DRAW); 145 | 146 | // Set up texture 147 | var texture1 = gl.createTexture(); 148 | gl.activeTexture(gl.TEXTURE0); 149 | gl.bindTexture(gl.TEXTURE_2D, texture1); 150 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 151 | var image1 = new Image(); 152 | 153 | var texture2 = gl.createTexture(); 154 | gl.activeTexture(gl.TEXTURE1); 155 | gl.bindTexture(gl.TEXTURE_2D, texture2); 156 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 157 | var image2 = new Image(); 158 | 159 | function initTextureThenDraw() 160 | { 161 | image1.onload = function() { loadTexture(image1,texture1); }; 162 | image1.crossOrigin = "anonymous"; 163 | image1.src = "https://farm6.staticflickr.com/5564/30725680942_e3bfe50e5e_b.jpg"; 164 | 165 | image2.onload = function() { loadTexture(image2,texture2); }; 166 | image2.crossOrigin = "anonymous"; 167 | image2.src = "https://farm6.staticflickr.com/5726/30206830053_87e9530b48_b.jpg"; 168 | 169 | window.setTimeout(draw,200); 170 | } 171 | 172 | function loadTexture(image,texture) 173 | { 174 | gl.bindTexture(gl.TEXTURE_2D, texture); 175 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 176 | 177 | // Option 1 : Use mipmap, select interpolation mode 178 | gl.generateMipmap(gl.TEXTURE_2D); 179 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); 180 | 181 | // Option 2: At least use linear filters 182 | // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 183 | // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 184 | 185 | // Optional ... if your shader & texture coordinates go outside the [0,1] range 186 | // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 187 | // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 188 | } 189 | // Scene (re-)draw routine 190 | function draw() { 191 | 192 | // Translate slider values to angles in the [-pi,pi] interval 193 | var angle1 = slider1.value*0.01*Math.PI; 194 | var angle2 = slider2.value*0.01*Math.PI; 195 | 196 | // Circle around the y-axis 197 | var eye = [400*Math.sin(angle1),150.0,400.0*Math.cos(angle1)]; 198 | var target = [0,0,0]; 199 | var up = [0,1,0]; 200 | 201 | var tModel = mat4.create(); 202 | mat4.fromScaling(tModel,[100,100,100]); 203 | mat4.rotate(tModel,tModel,angle2,[1,1,1]); 204 | 205 | var tCamera = mat4.create(); 206 | mat4.lookAt(tCamera, eye, target, up); 207 | 208 | var tProjection = mat4.create(); 209 | mat4.perspective(tProjection,Math.PI/4,1,10,1000); 210 | 211 | var tMV = mat4.create(); 212 | var tMVn = mat3.create(); 213 | var tMVP = mat4.create(); 214 | mat4.multiply(tMV,tCamera,tModel); // "modelView" matrix 215 | mat3.normalFromMat4(tMVn,tMV); 216 | mat4.multiply(tMVP,tProjection,tMV); 217 | 218 | // Clear screen, prepare for rendering 219 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 220 | gl.enable(gl.DEPTH_TEST); 221 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 222 | 223 | // Set up uniforms & attributes 224 | gl.uniformMatrix4fv(shaderProgram.MVmatrix,false,tMV); 225 | gl.uniformMatrix3fv(shaderProgram.MVNormalmatrix,false,tMVn); 226 | gl.uniformMatrix4fv(shaderProgram.MVPmatrix,false,tMVP); 227 | 228 | gl.bindBuffer(gl.ARRAY_BUFFER, trianglePosBuffer); 229 | gl.vertexAttribPointer(shaderProgram.PositionAttribute, trianglePosBuffer.itemSize, 230 | gl.FLOAT, false, 0, 0); 231 | gl.bindBuffer(gl.ARRAY_BUFFER, triangleNormalBuffer); 232 | gl.vertexAttribPointer(shaderProgram.NormalAttribute, triangleNormalBuffer.itemSize, 233 | gl.FLOAT, false, 0, 0); 234 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 235 | gl.vertexAttribPointer(shaderProgram.ColorAttribute, colorBuffer.itemSize, 236 | gl.FLOAT,false, 0, 0); 237 | gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer); 238 | gl.vertexAttribPointer(shaderProgram.texcoordAttribute, textureBuffer.itemSize, 239 | gl.FLOAT, false, 0, 0); 240 | 241 | // Bind texture 242 | gl.activeTexture(gl.TEXTURE0); 243 | gl.bindTexture(gl.TEXTURE_2D, texture1); 244 | gl.activeTexture(gl.TEXTURE1); 245 | gl.bindTexture(gl.TEXTURE_2D, texture2); 246 | 247 | // Do the drawing 248 | gl.drawElements(gl.TRIANGLES, triangleIndices.length, gl.UNSIGNED_BYTE, 0); 249 | 250 | } 251 | 252 | slider1.addEventListener("input",draw); 253 | slider2.addEventListener("input",draw); 254 | initTextureThenDraw(); 255 | } 256 | 257 | window.onload=start; 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /Week2/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A simple drawing demo 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week2/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | var canvas = document.getElementById('myCanvas'); 2 | var context = canvas.getContext('2d'); 3 | 4 | // a thick red line 5 | context.lineWidth = 5; 6 | context.strokeStyle = "red"; 7 | 8 | // the actual line 9 | context.beginPath(); 10 | context.moveTo(50,50); 11 | context.lineTo(100,100); 12 | context.stroke(); 13 | -------------------------------------------------------------------------------- /Week2/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Coordinate axes and a filled shape 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Week2/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | var canvas = document.getElementById('myCanvas'); 2 | 3 | function draw() { 4 | var context = canvas.getContext('2d'); 5 | 6 | function DrawLshape(color) { 7 | context.beginPath(); 8 | context.fillStyle = color; 9 | context.moveTo(50,25); 10 | context.lineTo(150,25); 11 | context.lineTo(150,75); 12 | context.lineTo(100,75); 13 | context.lineTo(100,175); 14 | context.lineTo(50,175); 15 | context.closePath(); 16 | context.fill(); 17 | } 18 | 19 | function DrawAxes(color) { 20 | context.strokeStyle=color; 21 | context.beginPath(); 22 | // Axes 23 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 24 | // Arrowheads 25 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 26 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 27 | // X-label 28 | context.moveTo(130,0);context.lineTo(140,10); 29 | context.moveTo(130,10);context.lineTo(140,0); 30 | // Y-label 31 | context.moveTo(0,130);context.lineTo(5,135);context.lineTo(10,130); 32 | context.moveTo(5,135);context.lineTo(5,142); 33 | 34 | context.stroke(); 35 | } 36 | 37 | // make sure you understand these 38 | 39 | DrawAxes("green"); 40 | DrawLshape("green"); 41 | 42 | } 43 | 44 | draw(); 45 | 46 | -------------------------------------------------------------------------------- /Week2/Demo2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple demonstration of slider interface 5 | 6 | 7 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Week2/Demo2/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { "use strict"; 2 | var canvas = document.getElementById('myCanvas'); 3 | var slider1 = document.getElementById('slider1'); 4 | slider1.value = 0; 5 | var slider2 = document.getElementById('slider2'); 6 | slider2.value = 0; 7 | function draw() { 8 | var context = canvas.getContext('2d'); 9 | canvas.width = canvas.width; 10 | // use the sliders to get various parameters 11 | var dx = slider1.value; 12 | var dy = slider2.value; 13 | 14 | function DrawLshape(color) { 15 | context.beginPath(); 16 | context.fillStyle = color; 17 | context.moveTo(50,25); 18 | context.lineTo(150,25); 19 | context.lineTo(150,75); 20 | context.lineTo(100,75); 21 | context.lineTo(100,175); 22 | context.lineTo(50,175); 23 | context.closePath(); 24 | context.fill(); 25 | } 26 | 27 | function DrawAxes(color) { 28 | context.strokeStyle=color; 29 | context.beginPath(); 30 | // Axes 31 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 32 | // Arrowheads 33 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 34 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 35 | // X-label 36 | context.moveTo(130,0);context.lineTo(140,10); 37 | context.moveTo(130,10);context.lineTo(140,0); 38 | // Y-label 39 | context.moveTo(0,130);context.lineTo(5,135);context.lineTo(10,130); 40 | context.moveTo(5,135);context.lineTo(5,142); 41 | 42 | context.stroke(); 43 | } 44 | 45 | // make sure you understand these 46 | 47 | DrawAxes("black"); 48 | context.save(); 49 | context.translate(dx,dy); 50 | DrawAxes("green"); 51 | DrawLshape("green"); 52 | context.restore(); 53 | 54 | } 55 | slider1.addEventListener("input",draw); 56 | slider2.addEventListener("input",draw); 57 | draw(); 58 | } 59 | window.onload = setup; 60 | 61 | 62 | -------------------------------------------------------------------------------- /Week2/Demo3/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A few static shapes 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Week2/Demo3/demo.js: -------------------------------------------------------------------------------- 1 | // function draw() { 2 | window.onload = function() { 3 | var canvas = document.getElementById('myCanvas'); 4 | var context = canvas.getContext('2d'); 5 | context.beginPath(); 6 | context.rect(25,25,50,50); 7 | context.fill(); 8 | 9 | context.beginPath(); 10 | context.rect(125,25,50,50); 11 | context.fillStyle = "#800"; 12 | context.fill(); 13 | 14 | context.beginPath(); 15 | context.rect(25,125,50,50); 16 | context.strokeStyle = "#800"; 17 | context.lineWidth = 4; 18 | context.stroke(); 19 | 20 | context.beginPath(); 21 | context.moveTo(150,125); 22 | context.lineTo(125,175); 23 | context.lineTo(175,175); 24 | context.closePath(); 25 | context.fillStyle="#EE0"; 26 | context.fill(); 27 | context.stroke(); 28 | }; 29 | // window.onload = draw; 30 | 31 | -------------------------------------------------------------------------------- /Week3/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple (non-branching) robotic arm example 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Week3/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | 3 | var canvas = document.getElementById('myCanvas'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = -25; 8 | function draw() { 9 | var context = canvas.getContext('2d'); 10 | canvas.width = canvas.width; 11 | // use the sliders to get the angles 12 | var theta1 = slider1.value*0.005*Math.PI; 13 | var phi1 = slider2.value*0.005*Math.PI; 14 | 15 | // note that this only changes the y 16 | // X just stays the same 17 | // the coordinate systems will move 18 | function linkage(color) { 19 | 20 | context.beginPath(); 21 | context.fillStyle = color; 22 | context.moveTo(0,0); 23 | context.lineTo(10,5); 24 | context.lineTo(90,5); 25 | context.lineTo(100,0); 26 | context.lineTo(90,-5); 27 | context.lineTo(10,-5); 28 | context.closePath(); 29 | context.fill(); 30 | 31 | axes(color); 32 | } 33 | 34 | function axes(color) { 35 | context.strokeStyle=color; 36 | context.beginPath(); 37 | // Axes 38 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 39 | // Arrowheads 40 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 41 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 42 | // X-label 43 | context.moveTo(130,-5);context.lineTo(140,5); 44 | context.moveTo(130,5);context.lineTo(140,-5); 45 | // Y-label 46 | context.moveTo(-5,130);context.lineTo(0,135);context.lineTo(5,130); 47 | context.moveTo(0,135);context.lineTo(0,142); 48 | 49 | context.stroke(); 50 | } 51 | 52 | // make sure you understand these 53 | axes("black"); 54 | context.translate(50,150); 55 | linkage("blue"); 56 | context.translate(100,0); 57 | context.rotate(theta1); 58 | linkage("green"); 59 | context.translate(100,0); 60 | context.rotate(phi1); 61 | context.scale(0.5,1); 62 | linkage("red"); 63 | } 64 | 65 | slider1.addEventListener("input",draw); 66 | slider2.addEventListener("input",draw); 67 | draw(); 68 | } 69 | window.onload = setup; 70 | -------------------------------------------------------------------------------- /Week3/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A slightly more complex (branching) robotic arm example 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Week3/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var slider1 = document.getElementById('slider1'); 4 | slider1.value = -25; 5 | var slider2 = document.getElementById('slider2'); 6 | slider2.value = 50; 7 | var slider3 = document.getElementById('slider3'); 8 | slider3.value = -50; 9 | var slider4 = document.getElementById('slider4'); 10 | slider4.value = 25; 11 | 12 | function draw() { 13 | var context = canvas.getContext('2d'); 14 | canvas.width = canvas.width; 15 | // use the sliders to get the angles 16 | var theta1 = slider1.value*0.005*Math.PI; 17 | var phi1 = slider2.value*0.005*Math.PI; 18 | var phi2 = slider3.value*0.005*Math.PI; 19 | var theta2 = slider4.value*0.005*Math.PI; 20 | 21 | // note that this only changes the y 22 | // X just stays the same 23 | // the coordinate systems will move 24 | function linkage(color) { 25 | context.beginPath(); 26 | context.fillStyle = color; 27 | context.moveTo(0,0); 28 | context.lineTo(10,5); 29 | context.lineTo(90,5); 30 | context.lineTo(100,0); 31 | context.lineTo(90,-5); 32 | context.lineTo(10,-5); 33 | context.closePath(); 34 | context.fill(); 35 | 36 | axes(color); 37 | } 38 | 39 | function axes(color) { 40 | context.strokeStyle=color; 41 | context.beginPath(); 42 | // Axes 43 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 44 | // Arrowheads 45 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 46 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 47 | // X-label 48 | context.moveTo(130,-5);context.lineTo(140,5); 49 | context.moveTo(130,5);context.lineTo(140,-5); 50 | // Y-label 51 | context.moveTo(-5,130);context.lineTo(0,135);context.lineTo(5,130); 52 | context.moveTo(0,135);context.lineTo(0,142); 53 | 54 | context.stroke(); 55 | } 56 | 57 | // make sure you understand these 58 | context.translate(50,150); 59 | context.save(); 60 | linkage("blue"); 61 | context.translate(100,0); 62 | context.save(); 63 | context.rotate(theta1); 64 | linkage("green"); 65 | context.translate(100,0); 66 | context.save(); 67 | context.rotate(phi1); 68 | context.scale(0.5,1); 69 | linkage("red"); 70 | context.restore(); 71 | context.save(); 72 | context.rotate(phi2); 73 | context.scale(0.5,1); 74 | linkage("orange"); 75 | context.restore(); 76 | context.restore(); 77 | context.save(); 78 | context.rotate(theta2); 79 | linkage("brown"); 80 | context.restore(); 81 | context.restore(); 82 | } 83 | 84 | slider1.addEventListener("input",draw); 85 | slider2.addEventListener("input",draw); 86 | slider3.addEventListener("input",draw); 87 | slider4.addEventListener("input",draw); 88 | draw(); 89 | } 90 | window.onload = setup; 91 | 92 | -------------------------------------------------------------------------------- /Week3/Demo2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A slightly more complex (branching) robotic arm example 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Week3/Demo2/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var slider1 = document.getElementById('slider1'); 4 | slider1.value = -25; 5 | var slider2 = document.getElementById('slider2'); 6 | slider2.value = 50; 7 | var slider3 = document.getElementById('slider3'); 8 | slider3.value = -50; 9 | var slider4 = document.getElementById('slider4'); 10 | slider4.value = 25; 11 | function draw() { 12 | var context = canvas.getContext('2d'); 13 | canvas.width = canvas.width; 14 | // use the sliders to get the angles 15 | var theta1 = slider1.value*0.005*Math.PI; 16 | var phi1 = slider2.value*0.005*Math.PI; 17 | var phi2 = slider3.value*0.005*Math.PI; 18 | var theta2 = slider4.value*0.005*Math.PI; 19 | 20 | // note that this only changes the y 21 | // X just stays the same 22 | // the coordinate systems will move 23 | function linkage(color) { 24 | 25 | context.beginPath(); 26 | context.fillStyle = color; 27 | context.moveTo(0,0); 28 | context.lineTo(10,5); 29 | context.lineTo(90,5); 30 | context.lineTo(100,0); 31 | context.lineTo(90,-5); 32 | context.lineTo(10,-5); 33 | context.closePath(); 34 | context.fill(); 35 | 36 | axes(color); 37 | } 38 | 39 | function axes(color) { 40 | context.strokeStyle=color; 41 | context.beginPath(); 42 | // Axes 43 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 44 | // Arrowheads 45 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 46 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 47 | // X-label 48 | context.moveTo(130,-5);context.lineTo(140,5); 49 | context.moveTo(130,5);context.lineTo(140,-5); 50 | // Y-label 51 | context.moveTo(-5,130);context.lineTo(0,135);context.lineTo(5,130); 52 | context.moveTo(0,135);context.lineTo(0,142); 53 | 54 | context.stroke(); 55 | } 56 | 57 | // make sure you understand these 58 | 59 | context.translate(50,150); // Transform from Canvas coordinate system -> Blue coordinate system 60 | // Stack is now : Blue -> Canvas (top) 61 | linkage("blue"); 62 | context.save(); // Stack is now : Blue -> Canvas (top) 63 | // Blue -> Canvas 64 | context.translate(100,0); 65 | context.rotate(theta1); // Transform Green -> Blue is prefixed to top of stack 66 | // Stack is now : Green -> Blue -> Canvas (top) 67 | // Blue -> Canvas 68 | 69 | linkage("green"); 70 | context.save(); // Stack is now : Green -> Blue -> Canvas (top) 71 | // Green -> Blue -> Canvas 72 | // Blue -> Canvas 73 | context.translate(100,0); 74 | context.rotate(phi1); 75 | context.scale(0.5,1); // Transform Red -> Green is prefixed to top of stack 76 | // Stack is now : Red -> Green -> Blue -> Canvas (top) 77 | // Green -> Blue -> Canvas 78 | // Blue -> Canvas 79 | linkage("red"); 80 | context.restore(); // We "pop" the Red transform (top of stack) 81 | // Stack is now : Green -> Blue -> Canvas 82 | // Blue -> Canvas 83 | 84 | context.save(); // Stack is now : Green -> Blue -> Canvas (top) 85 | // Green -> Blue -> Canvas 86 | // Blue -> Canvas 87 | context.translate(100,0); 88 | context.rotate(phi2); 89 | context.scale(0.5,1); // Transform Orange -> Green is prefixed to top of stack 90 | // Stack is now : Orange -> Green -> Blue -> Canvas (top) 91 | // Green -> Blue -> Canvas 92 | // Blue -> Canvas 93 | linkage("orange"); 94 | context.restore(); // Pop Stack twice -- essentially undo the Orange -> Green -> Blue transforms 95 | context.restore(); // Stack is now : Blue -> Canvas (top) 96 | 97 | context.save(); // Stack is now : Blue -> Canvas (top) 98 | // Blue -> Canvas 99 | context.translate(100,0); 100 | context.rotate(theta2); // Transform Brown -> Blue is prefixed to top of stack 101 | // Stack is now : Brown -> Blue -> Canvas (top) 102 | // Blue -> Canvas 103 | linkage("brown"); 104 | context.restore(); // Stack is now : Blue -> Canvas (top) 105 | } 106 | 107 | slider1.addEventListener("input",draw); 108 | slider2.addEventListener("input",draw); 109 | slider3.addEventListener("input",draw); 110 | slider4.addEventListener("input",draw); 111 | draw(); 112 | } 113 | window.onload = setup; 114 | 115 | -------------------------------------------------------------------------------- /Week4/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hierarchical model using glmatrix implementation of transforms (no stack) 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Week4/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 50; 8 | var slider3 = document.getElementById('slider3'); 9 | slider3.value = -50; 10 | var slider4 = document.getElementById('slider4'); 11 | slider4.value = 25; 12 | 13 | function draw() { 14 | canvas.width = canvas.width; 15 | // use the sliders to get the angles 16 | var theta1 = slider1.value*0.005*Math.PI; 17 | var phi1 = slider2.value*0.005*Math.PI; 18 | var phi2 = slider3.value*0.005*Math.PI; 19 | var theta2 = slider4.value*0.005*Math.PI; 20 | 21 | function moveToTx(x,y,Tx) 22 | {var res=vec2.create(); vec2.transformMat3(res,[x,y],Tx); context.moveTo(res[0],res[1]);} 23 | 24 | function lineToTx(x,y,Tx) 25 | {var res=vec2.create(); vec2.transformMat3(res,[x,y],Tx); context.lineTo(res[0],res[1]);} 26 | 27 | function linkage(color,Tx) { 28 | context.beginPath(); 29 | context.fillStyle = color; 30 | moveToTx(0,0,Tx); 31 | lineToTx(10,5,Tx); 32 | lineToTx(90,5,Tx); 33 | lineToTx(100,0,Tx); 34 | lineToTx(90,-5,Tx); 35 | lineToTx(10,-5,Tx); 36 | context.closePath(); 37 | context.fill(); 38 | axes(color,Tx); 39 | } 40 | 41 | function axes(color,Tx) { 42 | context.strokeStyle=color; 43 | context.beginPath(); 44 | // Axes 45 | moveToTx(120,0,Tx);lineToTx(0,0,Tx);lineToTx(0,120,Tx); 46 | // Arrowheads 47 | moveToTx(110,5,Tx);lineToTx(120,0,Tx);lineToTx(110,-5,Tx); 48 | moveToTx(5,110,Tx);lineToTx(0,120,Tx);lineToTx(-5,110,Tx); 49 | // X-label 50 | moveToTx(130,-5,Tx);lineToTx(140,5,Tx); 51 | moveToTx(130,5,Tx);lineToTx(140,-5,Tx); 52 | // Y-label 53 | moveToTx(-5,130,Tx);lineToTx(0,135,Tx);lineToTx(5,130,Tx); 54 | moveToTx(0,135,Tx);lineToTx(0,142,Tx); 55 | context.stroke(); 56 | } 57 | 58 | // make sure you understand these 59 | 60 | var Tblue_to_canvas = mat3.create(); 61 | mat3.fromTranslation(Tblue_to_canvas,[50,150]); 62 | linkage("blue",Tblue_to_canvas); 63 | 64 | var Tgreen_to_blue = mat3.create(); 65 | mat3.fromTranslation(Tgreen_to_blue,[100,0]); 66 | mat3.rotate(Tgreen_to_blue,Tgreen_to_blue,theta1); 67 | var Tgreen_to_canvas = mat3.create(); 68 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 69 | linkage("green",Tgreen_to_canvas); 70 | 71 | var Tred_to_green = mat3.create(); 72 | mat3.fromTranslation(Tred_to_green,[100,0]); 73 | mat3.rotate(Tred_to_green,Tred_to_green,phi1); 74 | mat3.scale(Tred_to_green,Tred_to_green,[0.5,1]); 75 | var Tred_to_canvas = mat3.create(); 76 | mat3.multiply(Tred_to_canvas,Tgreen_to_canvas,Tred_to_green); 77 | linkage("red",Tred_to_canvas); 78 | 79 | var Torange_to_green = mat3.create(); 80 | mat3.fromTranslation(Torange_to_green,[100,0]); 81 | mat3.rotate(Torange_to_green,Torange_to_green,phi2); 82 | mat3.scale(Torange_to_green,Torange_to_green,[0.5,1]); 83 | var Torange_to_canvas = mat3.create(); 84 | mat3.multiply(Torange_to_canvas,Tgreen_to_canvas,Torange_to_green); 85 | linkage("orange",Torange_to_canvas); 86 | 87 | var Tbrown_to_blue = mat3.create(); 88 | mat3.fromTranslation(Tbrown_to_blue,[100,0]); 89 | mat3.rotate(Tbrown_to_blue,Tbrown_to_blue,theta2); 90 | var Tbrown_to_canvas = mat3.create(); 91 | mat3.multiply(Tbrown_to_canvas, Tblue_to_canvas, Tbrown_to_blue); 92 | linkage("brown",Tbrown_to_canvas); 93 | } 94 | 95 | slider1.addEventListener("input",draw); 96 | slider2.addEventListener("input",draw); 97 | slider3.addEventListener("input",draw); 98 | slider4.addEventListener("input",draw); 99 | draw(); 100 | } 101 | window.onload = setup; 102 | -------------------------------------------------------------------------------- /Week4/Demo0a/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hierarchical model using glmatrix implementation of transforms (no stack) 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Week4/Demo0a/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 50; 8 | var slider3 = document.getElementById('slider3'); 9 | slider3.value = -50; 10 | var slider4 = document.getElementById('slider4'); 11 | slider4.value = 25; 12 | 13 | function draw() { 14 | canvas.width = canvas.width; 15 | // use the sliders to get the angles 16 | var theta1 = slider1.value*0.005*Math.PI; 17 | var phi1 = slider2.value*0.005*Math.PI; 18 | var phi2 = slider3.value*0.005*Math.PI; 19 | var theta2 = slider4.value*0.005*Math.PI; 20 | 21 | function setCanvasTransform(Tx) { 22 | context.setTransform(Tx[0],Tx[1],Tx[3],Tx[4],Tx[6],Tx[7]); 23 | } 24 | 25 | function linkage(color) { 26 | context.beginPath(); 27 | context.fillStyle = color; 28 | context.moveTo(0,0); 29 | context.lineTo(10,5); 30 | context.lineTo(90,5); 31 | context.lineTo(100,0); 32 | context.lineTo(90,-5); 33 | context.lineTo(10,-5); 34 | context.closePath(); 35 | context.fill(); 36 | 37 | axes(color); 38 | } 39 | 40 | function axes(color) { 41 | context.strokeStyle=color; 42 | context.beginPath(); 43 | // Axes 44 | context.moveTo(120,0);context.lineTo(0,0);context.lineTo(0,120); 45 | // Arrowheads 46 | context.moveTo(110,5);context.lineTo(120,0);context.lineTo(110,-5); 47 | context.moveTo(5,110);context.lineTo(0,120);context.lineTo(-5,110); 48 | // X-label 49 | context.moveTo(130,-5);context.lineTo(140,5); 50 | context.moveTo(130,5);context.lineTo(140,-5); 51 | // Y-label 52 | context.moveTo(-5,130);context.lineTo(0,135);context.lineTo(5,130); 53 | context.moveTo(0,135);context.lineTo(0,142); 54 | context.stroke(); 55 | } 56 | 57 | // make sure you understand these 58 | 59 | var Tblue_to_canvas = mat3.create(); 60 | mat3.fromTranslation(Tblue_to_canvas,[50,150]); 61 | setCanvasTransform(Tblue_to_canvas); 62 | linkage("blue"); 63 | 64 | var Tgreen_to_blue = mat3.create(); 65 | mat3.fromTranslation(Tgreen_to_blue,[100,0]); 66 | mat3.rotate(Tgreen_to_blue,Tgreen_to_blue,theta1); 67 | var Tgreen_to_canvas = mat3.create(); 68 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 69 | setCanvasTransform(Tgreen_to_canvas); 70 | linkage("green"); 71 | 72 | var Tred_to_green = mat3.create(); 73 | mat3.fromTranslation(Tred_to_green,[100,0]); 74 | mat3.rotate(Tred_to_green,Tred_to_green,phi1); 75 | mat3.scale(Tred_to_green,Tred_to_green,[0.5,1]); 76 | var Tred_to_canvas = mat3.create(); 77 | mat3.multiply(Tred_to_canvas,Tgreen_to_canvas,Tred_to_green); 78 | setCanvasTransform(Tred_to_canvas); 79 | linkage("red"); 80 | 81 | var Torange_to_green = mat3.create(); 82 | mat3.fromTranslation(Torange_to_green,[100,0]); 83 | mat3.rotate(Torange_to_green,Torange_to_green,phi2); 84 | mat3.scale(Torange_to_green,Torange_to_green,[0.5,1]); 85 | var Torange_to_canvas = mat3.create(); 86 | mat3.multiply(Torange_to_canvas,Tgreen_to_canvas,Torange_to_green); 87 | setCanvasTransform(Torange_to_canvas); 88 | linkage("orange"); 89 | 90 | var Tbrown_to_blue = mat3.create(); 91 | mat3.fromTranslation(Tbrown_to_blue,[100,0]); 92 | mat3.rotate(Tbrown_to_blue,Tbrown_to_blue,theta2); 93 | var Tbrown_to_canvas = mat3.create(); 94 | mat3.multiply(Tbrown_to_canvas, Tblue_to_canvas, Tbrown_to_blue); 95 | setCanvasTransform(Tbrown_to_canvas); 96 | linkage("brown"); 97 | } 98 | 99 | slider1.addEventListener("input",draw); 100 | slider2.addEventListener("input",draw); 101 | slider3.addEventListener("input",draw); 102 | slider4.addEventListener("input",draw); 103 | draw(); 104 | } 105 | window.onload = setup; 106 | -------------------------------------------------------------------------------- /Week4/Demo0b/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hierarchical model using glmatrix implementation of transforms (no stack) 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Week4/Demo0b/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { "use strict"; 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var m4 = twgl.m4; 5 | var slider1 = document.getElementById('slider1'); 6 | slider1.value = -25; 7 | var slider2 = document.getElementById('slider2'); 8 | slider2.value = 50; 9 | var slider3 = document.getElementById('slider3'); 10 | slider3.value = -50; 11 | var slider4 = document.getElementById('slider4'); 12 | slider4.value = 25; 13 | 14 | function draw() { 15 | canvas.width = canvas.width; 16 | // use the sliders to get the angles 17 | var theta1 = slider1.value*0.005*Math.PI; 18 | var phi1 = slider2.value*0.005*Math.PI; 19 | var phi2 = slider3.value*0.005*Math.PI; 20 | var theta2 = slider4.value*0.005*Math.PI; 21 | 22 | function moveToTx(x,y,Tx) 23 | {var pt_in=[x,y,0]; var pt_out=m4.transformPoint(Tx,pt_in); context.moveTo(pt_out[0],pt_out[1]);} 24 | 25 | function lineToTx(x,y,Tx) 26 | {var pt_in=[x,y,0]; var pt_out=m4.transformPoint(Tx,pt_in); context.lineTo(pt_out[0],pt_out[1]);} 27 | 28 | function linkage(color,Tx) { 29 | 30 | context.beginPath(); 31 | context.fillStyle = color; 32 | moveToTx(0,0,Tx); 33 | lineToTx(10,5,Tx); 34 | lineToTx(90,5,Tx); 35 | lineToTx(100,0,Tx); 36 | lineToTx(90,-5,Tx); 37 | lineToTx(10,-5,Tx); 38 | context.closePath(); 39 | context.fill(); 40 | 41 | axes(color,Tx); 42 | } 43 | 44 | function axes(color,Tx) { 45 | context.strokeStyle=color; 46 | context.beginPath(); 47 | // Axes 48 | moveToTx(120,0,Tx);lineToTx(0,0,Tx);lineToTx(0,120,Tx); 49 | // Arrowheads 50 | moveToTx(110,5,Tx);lineToTx(120,0,Tx);lineToTx(110,-5,Tx); 51 | moveToTx(5,110,Tx);lineToTx(0,120,Tx);lineToTx(-5,110,Tx); 52 | // X-label 53 | moveToTx(130,-5,Tx);lineToTx(140,5,Tx); 54 | moveToTx(130,5,Tx);lineToTx(140,-5,Tx); 55 | // Y-label 56 | moveToTx(-5,130,Tx);lineToTx(0,135,Tx);lineToTx(5,130,Tx); 57 | moveToTx(0,135,Tx);lineToTx(0,142,Tx); 58 | 59 | context.stroke(); 60 | } 61 | 62 | // make sure you understand these 63 | 64 | var Tblue_to_canvas = m4.translation([50,150,0]); 65 | linkage("blue",Tblue_to_canvas); 66 | 67 | var Tgreen_to_blue = m4.multiply(m4.rotationZ(theta1),m4.translation([100,0,0])); 68 | var Tgreen_to_canvas = m4.multiply(Tgreen_to_blue,Tblue_to_canvas); 69 | linkage("green",Tgreen_to_canvas); 70 | 71 | 72 | var Tred_to_green = m4.multiply(m4.scaling([0.5,1,1]), 73 | m4.multiply(m4.rotationZ(phi1), 74 | m4.translation([100,0,0]))); 75 | var Tred_to_canvas = m4.multiply(Tred_to_green,Tgreen_to_canvas); 76 | linkage("red",Tred_to_canvas); 77 | 78 | var Torange_to_green = m4.multiply(m4.scaling([0.5,1,1]), 79 | m4.multiply(m4.rotationZ(phi2), 80 | m4.translation([100,0,0]))); 81 | var Torange_to_canvas = m4.multiply(Torange_to_green,Tgreen_to_canvas); 82 | linkage("orange",Torange_to_canvas); 83 | 84 | var Tbrown_to_blue = m4.multiply(m4.rotationZ(theta2),m4.translation([100,0,0])); 85 | var Tbrown_to_canvas = m4.multiply(Tbrown_to_blue,Tblue_to_canvas); 86 | linkage("brown",Tbrown_to_canvas); 87 | 88 | } 89 | slider1.addEventListener("input",draw); 90 | slider2.addEventListener("input",draw); 91 | slider3.addEventListener("input",draw); 92 | slider4.addEventListener("input",draw); 93 | draw(); 94 | } 95 | window.onload = setup; 96 | -------------------------------------------------------------------------------- /Week4/Demo0b/twgl-full.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license twgl.js 0.0.25 Copyright (c) 2015, Gregg Tavares All Rights Reserved. 3 | * Available via the MIT license. 4 | * see: http://github.com/greggman/twgl.js for details 5 | */ 6 | /** 7 | * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. 8 | * Available via the MIT or new BSD license. 9 | * see: http://github.com/jrburke/almond for details 10 | */ 11 | !function(a,b){"function"==typeof define&&define.amd?define([],b):a.twgl=b()}(this,function(){var a,b,c;return function(d){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.slice(0,n.length-1).concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,b){return function(){var c=v.call(arguments,0);return"string"!=typeof c[0]&&1===c.length&&c.push(null),n.apply(d,c.concat([a,b]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var b=r[a];delete r[a],t[a]=!0,m.apply(d,b)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,b,c,f){var h,k,l,m,n,s,u=[],v=typeof c;if(f=f||a,"undefined"===v||"function"===v){for(b=!b.length&&c.length?["require","exports","module"]:b,n=0;n1&&"[0]"===c.name.substr(-3);if(f===a.FLOAT&&g)return function(b){a.uniform1fv(e,b)};if(f===a.FLOAT)return function(b){a.uniform1f(e,b)};if(f===a.FLOAT_VEC2)return function(b){a.uniform2fv(e,b)};if(f===a.FLOAT_VEC3)return function(b){a.uniform3fv(e,b)};if(f===a.FLOAT_VEC4)return function(b){a.uniform4fv(e,b)};if(f===a.INT&&g)return function(b){a.uniform1iv(e,b)};if(f===a.INT)return function(b){a.uniform1i(e,b)};if(f===a.INT_VEC2)return function(b){a.uniform2iv(e,b)};if(f===a.INT_VEC3)return function(b){a.uniform3iv(e,b)};if(f===a.INT_VEC4)return function(b){a.uniform4iv(e,b)};if(f===a.BOOL)return function(b){a.uniform1iv(e,b)};if(f===a.BOOL_VEC2)return function(b){a.uniform2iv(e,b)};if(f===a.BOOL_VEC3)return function(b){a.uniform3iv(e,b)};if(f===a.BOOL_VEC4)return function(b){a.uniform4iv(e,b)};if(f===a.FLOAT_MAT2)return function(b){a.uniformMatrix2fv(e,!1,b)};if(f===a.FLOAT_MAT3)return function(b){a.uniformMatrix3fv(e,!1,b)};if(f===a.FLOAT_MAT4)return function(b){a.uniformMatrix4fv(e,!1,b)};if((f===a.SAMPLER_2D||f===a.SAMPLER_CUBE)&&g){for(var h=[],i=0;ig;++g){var h=a.getActiveUniform(b,g);if(!h)break;var i=h.name;"[0]"===i.substr(-3)&&(i=i.substr(0,i.length-3));var j=c(b,h);e[i]=j}return e}function m(a,b){a=a.uniformSetters||a;for(var c=arguments.length,d=1;c>d;++d){var e=arguments[d];if(Array.isArray(e))for(var f=e.length,g=0;f>g;++g)m(a,e[g]);else for(var h in e){var i=a[h];i&&i(e[h])}}}function n(a,b){function c(b){return function(c){a.bindBuffer(a.ARRAY_BUFFER,c.buffer),a.enableVertexAttribArray(b),a.vertexAttribPointer(b,c.numComponents||c.size,c.type||a.FLOAT,c.normalize||!1,c.stride||0,c.offset||0)}}for(var d={},e=a.getProgramParameter(b,a.ACTIVE_ATTRIBUTES),f=0;e>f;++f){var g=a.getActiveAttrib(b,f);if(!g)break;var h=a.getAttribLocation(b,g.name);d[g.name]=c(h)}return d}function o(a,b){for(var c in b){var d=a[c];d&&d(b[c])}}function p(a,b,c){o(b.attribSetters||b,c.attribs),c.indices&&a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,c.indices)}function q(a,b,c,d,e){b=b.map(function(a){var b=document.getElementById(a);return b?b.text:a});var f=j(a,b,c,d,e);if(!f)return null;var g=l(a,f),h=n(a,f);return{program:f,uniformSetters:g,attribSetters:h}}function r(a,b){b=b||1,b=Math.max(1,b);var c=a.clientWidth*b|0,d=a.clientHeight*b|0;return a.width!==c||a.height!==d?(a.width=c,a.height=d,!0):!1}function s(a,b,c,d){if(b instanceof WebGLBuffer)return b;c=c||a.ARRAY_BUFFER;var e=a.createBuffer();return a.bindBuffer(c,e),a.bufferData(c,b,d||a.STATIC_DRAW),e}function t(a){return"indices"===a}function u(a){if(a instanceof Int8Array)return ga;if(a instanceof Uint8Array)return ha;if(a instanceof Int16Array)return ia;if(a instanceof Uint16Array)return ja;if(a instanceof Int32Array)return ka;if(a instanceof Uint32Array)return la;if(a instanceof Float32Array)return ma;throw"unsupported typed array type"}function v(a,b){switch(b){case a.BYTE:return Int8Array;case a.UNSIGNED_BYTE:return Uint8Array;case a.SHORT:return Int16Array;case a.UNSIGNED_SHORT:return Uint16Array;case a.INT:return Int32Array;case a.UNSIGNED_INT:return Uint32Array;case a.FLOAT:return Float32Array;default:throw"unknown gl type"}}function w(a){return a instanceof Int8Array?!0:a instanceof Uint8Array?!0:!1}function x(a){return a&&a.buffer&&a.buffer instanceof ArrayBuffer}function y(a,b){var c;if(c=a.indexOf("coord")>=0?2:a.indexOf("color")>=0?4:3,b%c>0)throw"can not guess numComponents. You should specify it.";return c}function z(a,b){if(x(a))return a;if(x(a.data))return a.data;Array.isArray(a)&&(a={data:a});var c=a.type;return c||(c="indices"===b?Uint16Array:Float32Array),new c(a.data)}function A(a,b){var c={};return Object.keys(b).forEach(function(d){if(!t(d)){var e=b[d],f=e.attrib||e.name||e.attribName||da+d,g=z(e,d);c[f]={buffer:s(a,g,void 0,e.drawType),numComponents:e.numComponents||e.size||y(d),type:u(g),normalize:void 0!==e.normalize?e.normalize:w(g),stride:e.stride||0,offset:e.offset||0}}}),c}function B(a,b){var c={attribs:A(a,b)},d=b.indices;return d?(d=z(d,"indices"),c.indices=s(a,d,a.ELEMENT_ARRAY_BUFFER),c.numElements=d.length,c.elementType=d instanceof Uint32Array?a.UNSIGNED_INT:a.UNSIGNED_SHORT):c.numElements=Ia(b),c}function C(a,b){var c={};return Object.keys(b).forEach(function(d){var e="indices"===d?a.ELEMENT_ARRAY_BUFFER:a.ARRAY_BUFFER,f=z(b[d],d);c[d]=s(a,f,e)}),c}function D(a,b,c,d,e){var f=c.indices,g=void 0===d?c.numElements:d;e=void 0===e?0:e,f?a.drawElements(b,g,void 0===c.elementType?a.UNSIGNED_SHORT:c.elementType,e):a.drawArrays(b,e,g)}function E(a,b){var c=null,d=null;b.forEach(function(b){if(b.active!==!1){var e=b.programInfo,f=b.bufferInfo,g=!1;e!==c&&(c=e,a.useProgram(e.program),g=!0),(g||f!==d)&&(d=f,p(a,e,f)),m(e,b.uniforms),D(a,b.type||a.TRIANGLES,f,b.count,b.offset)}})}function F(a,b){void 0!==b.colorspaceConversion&&(Ja.colorSpaceConversion=a.getParameter(a.UNPACK_COLORSPACE_CONVERSION_WEBGL)),void 0!==b.premultiplyAlpha&&(Ja.premultiplyAlpha=a.getParameter(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL)),void 0!==b.flipY&&(Ja.flipY=a.getParameter(a.UNPACK_FLIP_Y_WEBGL))}function G(a,b){void 0!==b.colorspaceConversion&&a.pixelStorei(a.UNPACK_COLORSPACE_CONVERSION_WEBGL,Ja.colorSpaceConversion),void 0!==b.premultiplyAlpha&&a.pixelStorei(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL,Ja.premultiplyAlpha),void 0!==b.flipY&&a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,Ja.flipY)}function H(a,b,c){var d=c.target||a.TEXTURE_2D;a.bindTexture(d,b),c.min&&a.texParameteri(d,a.TEXTURE_MIN_FILTER,c.min),c.mag&&a.texParameteri(d,a.TEXTURE_MAG_FILTER,c.mag),c.wrap&&(a.texParameteri(d,a.TEXTURE_WRAP_S,c.wrap),a.texParameteri(d,a.TEXTURE_WRAP_T,c.wrap)),c.wrapS&&a.texParameteri(d,a.TEXTURE_WRAP_S,c.wrapS),c.wrapT&&a.texParameteri(d,a.TEXTURE_WRAP_T,c.wrapT)}function I(a){return a=a||ea,x(a)?a:new Uint8Array([255*a[0],255*a[1],255*a[2],255*a[3]])}function J(a){return 0===(a&a-1)}function K(a,b,c,d,e){c=c||fa;var f=c.target||a.TEXTURE_2D;d=d||c.width,e=e||c.height,a.bindTexture(f,b),J(d)&&J(e)?a.generateMipmap(f):(a.texParameteri(f,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(f,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(f,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE))}function L(a,b){return b=b||{},b.cubeFaceOrder||[a.TEXTURE_CUBE_MAP_POSITIVE_X,a.TEXTURE_CUBE_MAP_NEGATIVE_X,a.TEXTURE_CUBE_MAP_POSITIVE_Y,a.TEXTURE_CUBE_MAP_NEGATIVE_Y,a.TEXTURE_CUBE_MAP_POSITIVE_Z,a.TEXTURE_CUBE_MAP_NEGATIVE_Z]}function M(a,b){var c=L(a,b),d=c.map(function(a,b){return{face:a,ndx:b}});return d.sort(function(a,b){return a.face-b.face}),d}function N(a){var b={};return Object.keys(a).forEach(function(c){b[c]=a[c]}),b}function O(a,b){var c=new Image;return c.onerror=function(){var d="couldn't load image: "+a;ca(d),b(d,c)},c.onload=function(){b(null,c)},c.src=a,c}function P(a,b,c){c=c||fa;var d=c.target||a.TEXTURE_2D;if(a.bindTexture(d,b),c.color!==!1){var e=I(c.color);if(d===a.TEXTURE_CUBE_MAP)for(var f=0;6>f;++f)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,a.RGBA,1,1,0,a.RGBA,a.UNSIGNED_BYTE,e);else a.texImage2D(d,0,a.RGBA,1,1,0,a.RGBA,a.UNSIGNED_BYTE,e)}}function Q(a,b,c,d){c=c||fa,P(a,b,c),c=N(c);var e=O(c.src,function(e,f){e?d(e,b,f):(Ka(a,b,f,c),d(null,b,f))});return e}function R(a,b,c,d){function e(e){return function(f,m){--k,f?l.push(f):m.width!==m.height?l.push("cubemap face img is not a square: "+m.src):(F(a,c),a.bindTexture(i,b),5===k?L(a).forEach(function(b){a.texImage2D(b,0,g,g,h,m)}):a.texImage2D(e,0,g,g,h,m),G(a,c),a.generateMipmap(i)),0===k&&d&&d(l.length?l:void 0,j,b)}}var f=c.src;if(6!==f.length)throw"there must be 6 urls for a cubemap";var g=c.format||a.RGBA,h=c.type||a.UNSIGNED_BYTE,i=c.target||a.TEXTURE_2D;if(i!==a.TEXTURE_CUBE_MAP)throw"target must be TEXTURE_CUBE_MAP";P(a,b,c),c=N(c);var j,k=6,l=[],m=L(a,c);j=f.map(function(a,b){return O(a,e(m[b]))})}function S(a){switch(a){case oa:case ra:return 1;case sa:return 2;case pa:return 3;case qa:return 4;default:throw"unknown type: "+a}}function T(a,b){return x(b)?u(b):a.UNSIGNED_BYTE}function U(a,b,c,d){d=d||fa;var e=d.target||a.TEXTURE_2D,f=d.width,g=d.height,h=d.format||a.RGBA,i=d.type||T(a,c),j=S(h),k=c.length/j;if(k%1)throw"length wrong size of format: "+Ga(a,h);if(f||g){if(g){if(!f&&(f=k/g,f%1))throw"can't guess width"}else if(g=k/f,g%1)throw"can't guess height"}else{var l=Math.sqrt(k/(e===a.TEXTURE_CUBE_MAP?6:1));l%1===0?(f=l,g=l):(f=k,g=1)}if(!x(c)){var m=v(a,i);c=new m(c)}if(a.pixelStorei(a.UNPACK_ALIGNMENT,d.unpackAlignment||1),F(a,d),e===a.TEXTURE_CUBE_MAP){var n=k/6*j;M(a,d).forEach(function(b){var d=n*b.ndx,e=c.subarray(d,d+n);a.texImage2D(b.face,0,h,f,g,0,h,i,e)})}else a.texImage2D(e,0,h,f,g,0,h,i,c);return G(a,d),{width:f,height:g}}function V(a,b,c){var d=c.target||a.TEXTURE_2D;a.bindTexture(d,b);var e=c.format||a.RGBA,f=c.type||a.UNSIGNED_BYTE;if(F(a,c),d===a.TEXTURE_CUBE_MAP)for(var g=0;6>g;++g)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,e,c.width,c.height,0,e,f,null);else a.texImage2D(d,0,e,c.width,c.height,0,e,f,null)}function W(a,b,c){b=b||fa;var d=a.createTexture(),e=b.target||a.TEXTURE_2D,f=b.width||1,g=b.height||1;a.bindTexture(e,d),e===a.TEXTURE_CUBE_MAP&&(a.texParameteri(e,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(e,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE));var h=b.src;if(h)if("function"==typeof h&&(h=h(a,b)),"string"==typeof h)Q(a,d,b,c);else if(x(h)||Array.isArray(h)&&("number"==typeof h[0]||Array.isArray(h[0])||x(h[0]))){var i=U(a,d,h,b);f=i.width,g=i.height}else if(Array.isArray(h)&&"string"==typeof h[0])R(a,d,b,c);else{if(!(h instanceof HTMLElement))throw"unsupported src type";Ka(a,d,h,b),f=h.width,g=h.height}else V(a,d,b);return b.auto!==!1&&K(a,d,b,f,g),H(a,d,b),d}function X(a,b,c,d,e){d=d||c.width,e=e||c.height;var f=c.target||a.TEXTURE_2D;a.bindTexture(f,b);var g,h=c.format||a.RGBA,i=c.src;if(g=i&&(x(i)||Array.isArray(i)&&"number"==typeof i[0])?c.type||T(a,i):c.type||a.UNSIGNED_BYTE,f===a.TEXTURE_CUBE_MAP)for(var j=0;6>j;++j)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+j,0,h,d,e,0,h,g,null);else a.texImage2D(f,0,h,d,e,0,h,g,null)}function Y(a){return"string"==typeof a||Array.isArray(a)&&"string"==typeof a[0]}function Z(a,b,c){function d(){0===f&&c&&setTimeout(function(){c(g.length?g:void 0,b)},0)}function e(a){--f,a&&g.push(a),d()}var f=0,g=[],h={};return Object.keys(b).forEach(function(c){var d=b[c],g=void 0;Y(d.src)&&(g=e,++f),h[c]=W(a,d,g)}),d(),h}function $(a){return Ma[a]}function _(a){return Na[a]}function aa(a,b,c,d){var e=a.FRAMEBUFFER,f=a.createFramebuffer();a.bindFramebuffer(e,f),c=c||a.drawingBufferWidth,d=d||a.drawingBufferHeight,b=b||La;var g=0,h={framebuffer:f,attachments:[]};return b.forEach(function(b){var f=b.attachment,i=b.format,j=$(i);if(j||(j=Aa+g++),!f)if(_(i))f=a.createRenderbuffer(),a.bindRenderbuffer(a.RENDERBUFFER,f),a.renderbufferStorage(a.RENDERBUFFER,i,c,d);else{var k=N(b);k.width=c,k.height=d,k.auto=void 0===b.auto?!1:b.auto,f=W(a,k)}if(f instanceof WebGLRenderbuffer)a.framebufferRenderbuffer(e,j,a.RENDERBUFFER,f);else{if(!(f instanceof WebGLTexture))throw"unknown attachment type";a.framebufferTexture2D(e,j,b.texTarget||a.TEXTURE_2D,f,b.level||0)}h.attachments.push(f)}),h}function ba(a,b,c,d,e){d=d||a.drawingBufferWidth,e=e||a.drawingBufferHeight,c=c||La,c.forEach(function(c,f){var g=b.attachments[f],h=c.format;if(g instanceof WebGLRenderbuffer)a.bindRenderbuffer(a.RENDERBUFFER,g),a.renderbufferStorage(a.RENDERBUFFER,h,d,e);else{if(!(g instanceof WebGLTexture))throw"unknown attachment type";X(a,g,c,d,e)}})}var ca=window.console&&window.console.error?window.console.error.bind(window.console):function(){},da="",ea=new Uint8Array([128,192,255,255]),fa={},ga=5120,ha=5121,ia=5122,ja=5123,ka=5124,la=5125,ma=5126,na=6402,oa=6406,pa=6407,qa=6408,ra=6409,sa=6410,ta=32854,ua=32855,va=36194,wa=33189,xa=6401,ya=36168,za=34041,Aa=36064,Ba=36096,Ca=36128,Da=33306,Ea=33071,Fa=9729,Ga=function(){function a(a){b||(b={},Object.keys(a).forEach(function(c){"number"==typeof a[c]&&(b[a[c]]=c)}))}var b;return function(c,d){return a(),b[d]||"0x"+d.toString(16)}}(),Ha=["VERTEX_SHADER","FRAGMENT_SHADER"],Ia=function(){var a=["position","positions","a_position"];return function(b){for(var c,d=0;d0)throw"numComponents "+g+" not correct for length "+f;return h}}(),Ja={},Ka=function(){var a=document.createElement("canvas").getContext("2d");return function(b,c,d,e){e=e||fa;var f=e.target||b.TEXTURE_2D,g=d.width,h=d.height,i=e.format||b.RGBA,j=e.type||b.UNSIGNED_BYTE;if(F(b,e),b.bindTexture(f,c),f===b.TEXTURE_CUBE_MAP){var k,l,m=d.width,n=d.height;if(m/6===n)k=n,l=[0,0,1,0,2,0,3,0,4,0,5,0];else if(n/6===m)k=m,l=[0,0,0,1,0,2,0,3,0,4,0,5];else if(m/3===n/2)k=m/3,l=[0,0,1,0,2,0,0,1,1,1,2,1];else{if(m/2!==n/3)throw"can't figure out cube map from element: "+(d.src?d.src:d.nodeName);k=m/2,l=[0,0,1,0,0,1,1,1,0,2,1,2]}a.canvas.width=k,a.canvas.height=k,g=k,h=k,M(b,e).forEach(function(c){var e=l[2*c.ndx+0]*k,f=l[2*c.ndx+1]*k;a.drawImage(d,e,f,k,k,0,0,k,k),b.texImage2D(c.face,0,i,i,j,a.canvas)}),a.canvas.width=1,a.canvas.height=1}else b.texImage2D(f,0,i,i,j,d);G(b,e),e.auto!==!1&&K(b,c,e,g,h),H(b,c,e)}}(),La=[{format:qa,type:ha,min:Fa,wrap:Ea},{format:za}],Ma={};Ma[za]=Da,Ma[xa]=Ca,Ma[ya]=Ca,Ma[na]=Ba,Ma[wa]=Ba;var Na={};return Na[ta]=!0,Na[ua]=!0,Na[va]=!0,Na[za]=!0,Na[wa]=!0,Na[xa]=!0,Na[ya]=!0,{createAttribsFromArrays:A,createBuffersFromArrays:C,createBufferInfoFromArrays:B,createAttributeSetters:n,createProgram:g,createProgramFromScripts:i,createProgramFromSources:j,createProgramInfo:q,createUniformSetters:l,drawBufferInfo:D,drawObjectList:E,getWebGLContext:d,resizeCanvasToDisplaySize:r,setAttributes:o,setAttributePrefix:b,setBuffersAndAttributes:p,setUniforms:m,createTexture:W,setEmptyTexture:V,setTextureFromArray:U,loadTextureFromUrl:Q,setTextureFromElement:Ka,setTextureFilteringForSize:K,setTextureParameters:H,setDefaultTextureColor:a,createTextures:Z,resizeTexture:X,createFramebufferInfo:aa,resizeFramebufferInfo:ba}}),c("twgl/v3",[],function(){function a(a){q=a}function b(){return new q(3)}function c(a,b,c){return c=c||new q(3),c[0]=a[0]+b[0],c[1]=a[1]+b[1],c[2]=a[2]+b[2],c}function d(a,b,c){return c=c||new q(3),c[0]=a[0]-b[0],c[1]=a[1]-b[1],c[2]=a[2]-b[2],c}function e(a,b,c,d){return d=d||new q(3),d[0]=(1-c)*a[0]+c*b[0],d[1]=(1-c)*a[1]+c*b[1],d[2]=(1-c)*a[2]+c*b[2],d}function f(a,b,c){return c=c||new q(3),c[0]=a[0]*b,c[1]=a[1]*b,c[2]=a[2]*b,c}function g(a,b,c){return c=c||new q(3),c[0]=a[0]/b,c[1]=a[1]/b,c[2]=a[2]/b,c}function h(a,b,c){return c=c||new q(3),c[0]=a[1]*b[2]-a[2]*b[1],c[1]=a[2]*b[0]-a[0]*b[2],c[2]=a[0]*b[1]-a[1]*b[0],c}function i(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]}function j(a){return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])}function k(a){return a[0]*a[0]+a[1]*a[1]+a[2]*a[2]}function l(a,b){b=b||new q(3);var c=a[0]*a[0]+a[1]*a[1]+a[2]*a[2],d=Math.sqrt(c);return d>1e-5?(b[0]=a[0]/d,b[1]=a[1]/d,b[2]=a[2]/d):(b[0]=0,b[1]=0,b[2]=0),b}function m(a,b){return b=b||new q(3),b[0]=-a[0],b[1]=-a[1],b[2]=-a[2],b}function n(a,b){return b=b||new q(3),b[0]=a[0],b[1]=a[1],b[2]=a[2],b}function o(a,b,c){return c=c||new q(3),c[0]=a[0]*b[0],c[1]=a[1]*b[1],c[2]=a[2]*b[2],c}function p(a,b,c){return c=c||new q(3),c[0]=a[0]/b[0],c[1]=a[1]/b[1],c[2]=a[2]/b[2],c}var q=Float32Array;return{add:c,copy:n,create:b,cross:h,divide:p,divScalar:g,dot:i,lerp:e,length:j,lengthSq:k,mulScalar:f,multiply:o,negate:m,normalize:l,setDefaultType:a,subtract:d}}),c("twgl/m4",["./v3"],function(a){function b(a){VecType=a}function c(a,b){return b=b||new E(16),b[0]=-a[0],b[1]=-a[1],b[2]=-a[2],b[3]=-a[3],b[4]=-a[4],b[5]=-a[5],b[6]=-a[6],b[7]=-a[7],b[8]=-a[8],b[9]=-a[9],b[10]=-a[10],b[11]=-a[11],b[12]=-a[12],b[13]=-a[13],b[14]=-a[14],b[15]=-a[15],b}function d(a,b){return b=b||new E(16),b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b[9]=a[9],b[10]=a[10],b[11]=a[11],b[12]=a[12],b[13]=a[13],b[14]=a[14],b[15]=a[15],b}function e(a){return a=a||new E(16),a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a}function f(a,b){if(b=b||new E(16),b===a){var c;return c=a[1],a[1]=a[4],a[4]=c,c=a[2],a[2]=a[8],a[8]=c,c=a[3],a[3]=a[12],a[12]=c,c=a[6],a[6]=a[9],a[9]=c,c=a[7],a[7]=a[13],a[13]=c,c=a[11],a[11]=a[14],a[14]=c,b}var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15];return b[0]=d,b[1]=h,b[2]=l,b[3]=p,b[4]=e,b[5]=i,b[6]=m,b[7]=q,b[8]=f,b[9]=j,b[10]=n,b[11]=r,b[12]=g,b[13]=k,b[14]=o,b[15]=s,b}function g(a,b){b=b||new E(16);var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],i=a[6],j=a[7],k=a[8],l=a[9],m=a[10],n=a[11],o=a[12],p=a[13],q=a[14],r=a[15],s=m*r,t=q*n,u=i*r,v=q*j,w=i*n,x=m*j,y=e*r,z=q*f,A=e*n,B=m*f,C=e*j,D=i*f,F=k*p,G=o*l,H=g*p,I=o*h,J=g*l,K=k*h,L=c*p,M=o*d,N=c*l,O=k*d,P=c*h,Q=g*d,R=s*h+v*l+w*p-(t*h+u*l+x*p),S=t*d+y*l+B*p-(s*d+z*l+A*p),T=u*d+z*h+C*p-(v*d+y*h+D*p),U=x*d+A*h+D*l-(w*d+B*h+C*l),V=1/(c*R+g*S+k*T+o*U);return b[0]=V*R,b[1]=V*S,b[2]=V*T,b[3]=V*U,b[4]=V*(t*g+u*k+x*o-(s*g+v*k+w*o)),b[5]=V*(s*c+z*k+A*o-(t*c+y*k+B*o)),b[6]=V*(v*c+y*g+D*o-(u*c+z*g+C*o)),b[7]=V*(w*c+B*g+C*k-(x*c+A*g+D*k)),b[8]=V*(F*j+I*n+J*r-(G*j+H*n+K*r)),b[9]=V*(G*f+L*n+O*r-(F*f+M*n+N*r)),b[10]=V*(H*f+M*j+P*r-(I*f+L*j+Q*r)),b[11]=V*(K*f+N*j+Q*n-(J*f+O*j+P*n)),b[12]=V*(H*m+K*q+G*i-(J*q+F*i+I*m)),b[13]=V*(N*q+F*e+M*m-(L*m+O*q+G*e)),b[14]=V*(L*i+Q*q+I*e-(P*q+H*e+M*i)),b[15]=V*(P*m+J*e+O*i-(N*i+Q*m+K*e)),b}function h(a,b,c){c=c||new E(16);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3],x=b[4],y=b[5],z=b[6],A=b[7],B=b[8],C=b[9],D=b[10],F=b[11],G=b[12],H=b[13],I=b[14],J=b[15];return c[0]=d*t+e*x+f*B+g*G,c[1]=d*u+e*y+f*C+g*H,c[2]=d*v+e*z+f*D+g*I,c[3]=d*w+e*A+f*F+g*J,c[4]=h*t+i*x+j*B+k*G,c[5]=h*u+i*y+j*C+k*H,c[6]=h*v+i*z+j*D+k*I,c[7]=h*w+i*A+j*F+k*J,c[8]=l*t+m*x+n*B+o*G,c[9]=l*u+m*y+n*C+o*H,c[10]=l*v+m*z+n*D+o*I,c[11]=l*w+m*A+n*F+o*J,c[12]=p*t+q*x+r*B+s*G,c[13]=p*u+q*y+r*C+s*H,c[14]=p*v+q*z+r*D+s*I,c[15]=p*w+q*A+r*F+s*J,c}function i(a,b,c){return c=c||e(),a!==c&&(c[0]=a[0],c[1]=a[1],c[2]=a[2],c[3]=a[3],c[4]=a[4],c[5]=a[5],c[6]=a[6],c[7]=a[7],c[8]=a[8],c[9]=a[9],c[10]=a[10],c[11]=a[11]),c[12]=b[0],c[13]=b[1],c[14]=b[2],c[15]=1,c}function j(b,c){return c=c||a.create(),c[0]=b[12],c[1]=b[13],c[2]=b[14],c}function k(b,c,d){d=d||a.create();var e=4*c;return d[0]=b[e+0],d[1]=b[e+1],d[2]=b[e+2],d}function l(a,b,c,d,e){e=e||new E(16);var f=Math.tan(.5*Math.PI-.5*a),g=1/(c-d);return e[0]=f/b,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=f,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=(c+d)*g,e[11]=-1,e[12]=0,e[13]=0,e[14]=c*d*g*2,e[15]=0,e}function m(a,b,c,d,e,f,g){return g=g||new E(16),g[0]=2/(b-a),g[1]=0,g[2]=0,g[3]=0,g[4]=0,g[5]=2/(d-c),g[6]=0,g[7]=0,g[8]=0,g[9]=0,g[10]=-1/(f-e),g[11]=0,g[12]=(b+a)/(a-b),g[13]=(d+c)/(c-d),g[14]=-e/(e-f),g[15]=1,g}function n(a,b,c,d,e,f,g){g=g||new E(16);var h=b-a,i=d-c,j=e-f;return g[0]=2*e/h,g[1]=0,g[2]=0,g[3]=0,g[4]=0,g[5]=2*e/i,g[6]=0,g[7]=0,g[8]=(a+b)/h,g[9]=(d+c)/i,g[10]=f/j,g[11]=-1,g[12]=0,g[13]=0,g[14]=e*f/j,g[15]=0,g}function o(b,c,d,e){e=e||new E(16);var f=F,g=G,h=H;return a.normalize(a.subtract(b,c,h),h),a.normalize(a.cross(d,h,f),f),a.normalize(a.cross(h,f,g),g),e[0]=f[0],e[1]=f[1],e[2]=f[2],e[3]=0,e[4]=g[0],e[5]=g[1],e[6]=g[2],e[7]=0,e[8]=h[0],e[9]=h[1],e[10]=h[2],e[11]=0,e[12]=b[0],e[13]=b[1],e[14]=b[2],e[15]=1,e}function p(a,b){return b=b||new E(16),b[0]=1,b[1]=0,b[2]=0,b[3]=0,b[4]=0,b[5]=1,b[6]=0,b[7]=0,b[8]=0,b[9]=0,b[10]=1,b[11]=0,b[12]=a[0],b[13]=a[1],b[14]=a[2],b[15]=1,b}function q(a,b,c){c=c||new E(16);var d=b[0],e=b[1],f=b[2],g=a[0],h=a[1],i=a[2],j=a[3],k=a[4],l=a[5],m=a[6],n=a[7],o=a[8],p=a[9],q=a[10],r=a[11],s=a[12],t=a[13],u=a[14],v=a[15];return a!==c&&(c[0]=g,c[1]=h,c[2]=i,c[3]=j,c[4]=k,c[5]=l,c[6]=m,c[7]=n,c[8]=o,c[9]=p,c[10]=q,c[11]=r),c[12]=g*d+k*e+o*f+s,c[13]=h*d+l*e+p*f+t,c[14]=i*d+m*e+q*f+u,c[15]=j*d+n*e+r*f+v,c}function r(a,b){b=b||new E(16);var c=Math.cos(a),d=Math.sin(a);return b[0]=1,b[1]=0,b[2]=0,b[3]=0,b[4]=0,b[5]=c,b[6]=d,b[7]=0,b[8]=0,b[9]=-d,b[10]=c,b[11]=0,b[12]=0,b[13]=0,b[14]=0,b[15]=1,b}function s(a,b,c){c=c||new E(16);var d=a[4],e=a[5],f=a[6],g=a[7],h=a[8],i=a[9],j=a[10],k=a[11],l=Math.cos(b),m=Math.sin(b);return c[4]=l*d+m*h,c[5]=l*e+m*i,c[6]=l*f+m*j,c[7]=l*g+m*k,c[8]=l*h-m*d,c[9]=l*i-m*e,c[10]=l*j-m*f,c[11]=l*k-m*g,a!==c&&(c[0]=a[0],c[1]=a[1],c[2]=a[2],c[3]=a[3],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]),c}function t(a,b){b=b||new E(16);var c=Math.cos(a),d=Math.sin(a);return b[0]=c,b[1]=0,b[2]=-d,b[3]=0,b[4]=0,b[5]=1,b[6]=0,b[7]=0,b[8]=d,b[9]=0,b[10]=c,b[11]=0,b[12]=0,b[13]=0,b[14]=0,b[15]=1,b}function u(a,b,c){c=c||new E(16);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[8],i=a[9],j=a[10],k=a[11],l=Math.cos(b),m=Math.sin(b);return c[0]=l*d-m*h,c[1]=l*e-m*i,c[2]=l*f-m*j,c[3]=l*g-m*k,c[8]=l*h+m*d,c[9]=l*i+m*e,c[10]=l*j+m*f,c[11]=l*k+m*g,a!==c&&(c[4]=a[4],c[5]=a[5],c[6]=a[6],c[7]=a[7],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]),c}function v(a,b){b=b||new E(16);var c=Math.cos(a),d=Math.sin(a);return b[0]=c,b[1]=d,b[2]=0,b[3]=0,b[4]=-d,b[5]=c,b[6]=0,b[7]=0,b[8]=0,b[9]=0,b[10]=1,b[11]=0,b[12]=0,b[13]=0,b[14]=0,b[15]=1,b}function w(a,b,c){c=c||new E(16);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=Math.cos(b),m=Math.sin(b);return c[0]=l*d+m*h,c[1]=l*e+m*i,c[2]=l*f+m*j,c[3]=l*g+m*k,c[4]=l*h-m*d,c[5]=l*i-m*e,c[6]=l*j-m*f,c[7]=l*k-m*g,a!==c&&(c[8]=a[8],c[9]=a[9],c[10]=a[10],c[11]=a[11],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]),c}function x(a,b,c){c=c||new E(16);var d=a[0],e=a[1],f=a[2],g=Math.sqrt(d*d+e*e+f*f);d/=g,e/=g,f/=g;var h=d*d,i=e*e,j=f*f,k=Math.cos(b),l=Math.sin(b),m=1-k;return c[0]=h+(1-h)*k,c[1]=d*e*m+f*l,c[2]=d*f*m-e*l,c[3]=0,c[4]=d*e*m-f*l,c[5]=i+(1-i)*k,c[6]=e*f*m+d*l,c[7]=0,c[8]=d*f*m+e*l,c[9]=e*f*m-d*l,c[10]=j+(1-j)*k,c[11]=0,c[12]=0,c[13]=0,c[14]=0,c[15]=1,c}function y(a,b,c,d){d=d||new E(16);var e=b[0],f=b[1],g=b[2],h=Math.sqrt(e*e+f*f+g*g);e/=h,f/=h,g/=h;var i=e*e,j=f*f,k=g*g,l=Math.cos(c),m=Math.sin(c),n=1-l,o=i+(1-i)*l,p=e*f*n+g*m,q=e*g*n-f*m,r=e*f*n-g*m,s=j+(1-j)*l,t=f*g*n+e*m,u=e*g*n+f*m,v=f*g*n-e*m,w=k+(1-k)*l,x=a[0],y=a[1],z=a[2],A=a[3],B=a[4],C=a[5],D=a[6],F=a[7],G=a[8],H=a[9],I=a[10],J=a[11];return d[0]=o*x+p*B+q*G,d[1]=o*y+p*C+q*H,d[2]=o*z+p*D+q*I,d[3]=o*A+p*F+q*J,d[4]=r*x+s*B+t*G,d[5]=r*y+s*C+t*H,d[6]=r*z+s*D+t*I,d[7]=r*A+s*F+t*J,d[8]=u*x+v*B+w*G,d[9]=u*y+v*C+w*H,d[10]=u*z+v*D+w*I,d[11]=u*A+v*F+w*J,a!==d&&(d[12]=a[12],d[13]=a[13],d[14]=a[14],d[15]=a[15]),d}function z(a,b){return b=b||new E(16),b[0]=a[0],b[1]=0,b[2]=0,b[3]=0,b[4]=0,b[5]=a[1],b[6]=0,b[7]=0,b[8]=0,b[9]=0,b[10]=a[2],b[11]=0,b[12]=0,b[13]=0,b[14]=0,b[15]=1,b}function A(a,b,c){c=c||new E(16);var d=b[0],e=b[1],f=b[2];return c[0]=d*a[0],c[1]=d*a[1],c[2]=d*a[2],c[3]=d*a[3],c[4]=e*a[4],c[5]=e*a[5],c[6]=e*a[6],c[7]=e*a[7],c[8]=f*a[8],c[9]=f*a[9],c[10]=f*a[10],c[11]=f*a[11],a!==c&&(c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]),a}function B(b,c,d){d=d||a.create();var e=c[0],f=c[1],g=c[2],h=e*b[3]+f*b[7]+g*b[11]+b[15];return d[0]=(e*b[0]+f*b[4]+g*b[8]+b[12])/h,d[1]=(e*b[1]+f*b[5]+g*b[9]+b[13])/h,d[2]=(e*b[2]+f*b[6]+g*b[10]+b[14])/h,d}function C(b,c,d){d=d||a.create();var e=c[0],f=c[1],g=c[2];return d[0]=e*b[0]+f*b[4]+g*b[8],d[1]=e*b[1]+f*b[5]+g*b[9],d[2]=e*b[2]+f*b[6]+g*b[10],d}function D(b,c,d){d=d||a.create();var e=g(b),f=c[0],h=c[1],i=c[2];return d[0]=f*e[0]+h*e[1]+i*e[2],d[1]=f*e[4]+h*e[5]+i*e[6],d[2]=f*e[8]+h*e[9]+i*e[10],d}var E=Float32Array,F=a.create(),G=a.create(),H=a.create();return{axisRotate:y,axisRotation:x,create:e,copy:d,frustum:n,getAxis:k,getTranslation:j,identity:e,inverse:g,lookAt:o,multiply:h,negate:c,ortho:m,perspective:l,rotateX:s,rotateY:u,rotateZ:w,rotationX:r,rotationY:t,rotationZ:v,scale:A,scaling:z,setDefaultType:b,setTranslation:i,transformDirection:C,transformNormal:D,transformPoint:B,translate:q,translation:p,transpose:f}}),c("twgl/primitives",["./twgl","./m4","./v3"],function(a,b,c){function d(a,b){var c=0;return a.push=function(){for(var b=0;bj;++j)for(var k=c[j],l=k*h,m=0;h>m;++m)i.push(f[l+m]);d[b]=i}var c=a.indices,d={},g=c.length;return Object.keys(a).filter(f).forEach(b),d}function h(a){if(a.indices)throw"can't flatten normals of indexed vertices. deindex them first";for(var b=a.normal,c=b.length,d=0;c>d;d+=9){var e=b[d+0],f=b[d+1],g=b[d+2],h=b[d+3],i=b[d+4],j=b[d+5],k=b[d+6],l=b[d+7],m=b[d+8],n=e+h+k,o=f+i+l,p=g+j+m,q=Math.sqrt(n*n+o*o+p*p);n/=q,o/=q,p/=q,b[d+0]=n,b[d+1]=o,b[d+2]=p,b[d+3]=n,b[d+4]=o,b[d+5]=p,b[d+6]=n,b[d+7]=o,b[d+8]=p}return a}function i(a,b,c){for(var d=a.length,e=new Float32Array(3),f=0;d>f;f+=3)c(b,[a[f],a[f+1],a[f+2]],e),a[f]=e[0],a[f+1]=e[1],a[f+2]=e[2]}function j(a,b,d){d=d||c.create();var e=b[0],f=b[1],g=b[2];return d[0]=e*a[0]+f*a[1]+g*a[2],d[1]=e*a[4]+f*a[5]+g*a[6],d[2]=e*a[8]+f*a[9]+g*a[10],d}function k(a,c){return i(a,c,b.transformDirection),a}function l(a,c){return i(a,b.inverse(c),j),a}function m(a,c){return i(a,c,b.transformPoint),a}function n(a,b){return Object.keys(a).forEach(function(c){var d=a[c];c.indexOf("pos")>=0?m(d,b):c.indexOf("tan")>=0||c.indexOf("binorm")>=0?k(d,b):c.indexOf("norm")>=0&&l(d,b)}),a}function o(a,b,c){return a=a||2,b=b||0,c=c||0,a*=.5,{position:{numComponents:2,data:[b+-1*a,c+-1*a,b+1*a,c+-1*a,b+-1*a,c+1*a,b+1*a,c+1*a]},normal:[0,0,1,0,0,1,0,0,1,0,0,1],texcoord:[0,0,1,0,0,1,1,1],indices:[0,1,2,2,1,3]}}function p(a,c,d,f,g){a=a||1,c=c||1,d=d||1,f=f||1,g=g||b.identity();for(var h=(d+1)*(f+1),i=e(3,h),j=e(3,h),k=e(2,h),l=0;f>=l;l++)for(var m=0;d>=m;m++){var o=m/d,p=l/f;i.push(a*o-.5*a,0,c*p-.5*c),j.push(0,1,0),k.push(o,p)}for(var q=d+1,r=e(3,d*f*2,Uint16Array),l=0;f>l;l++)for(var m=0;d>m;m++)r.push((l+0)*q+m,(l+1)*q+m,(l+0)*q+m+1),r.push((l+1)*q+m,(l+1)*q+m+1,(l+0)*q+m+1);var s=n({position:i,normal:j,texcoord:k,indices:r},g);return s}function q(a,b,c,d,f,g,h){if(0>=b||0>=c)throw Error("subdivisionAxis and subdivisionHeight must be > 0");d=d||0,f=f||Math.PI,g=g||0,h=h||2*Math.PI;for(var i=f-d,j=h-g,k=(b+1)*(c+1),l=e(3,k),m=e(3,k),n=e(2,k),o=0;c>=o;o++)for(var p=0;b>=p;p++){var q=p/b,r=o/c,s=j*q,t=i*r,u=Math.sin(s),v=Math.cos(s),w=Math.sin(t),x=Math.cos(t),y=v*w,z=x,A=u*w;l.push(a*y,a*z,a*A),m.push(y,z,A),n.push(1-q,r)}for(var B=b+1,C=e(3,b*c*2,Uint16Array),p=0;b>p;p++)for(var o=0;c>o;o++)C.push((o+0)*B+p,(o+0)*B+p+1,(o+1)*B+p),C.push((o+1)*B+p,(o+0)*B+p+1,(o+1)*B+p+1);return{position:l,normal:m,texcoord:n,indices:C}}function r(a){a=a||1;for(var b=a/2,c=[[-b,-b,-b],[+b,-b,-b],[-b,+b,-b],[+b,+b,-b],[-b,-b,+b],[+b,-b,+b],[-b,+b,+b],[+b,+b,+b]],d=[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]],f=[[1,0],[0,0],[0,1],[1,1]],g=24,h=e(3,g),i=e(3,g),j=e(2,g),k=e(3,12,Uint16Array),l=0;6>l;++l){ 12 | for(var m=D[l],n=0;4>n;++n){var o=c[m[n]],p=d[l],q=f[n];h.push(o),i.push(p),j.push(q)}var r=4*l;k.push(r+0,r+1,r+2),k.push(r+0,r+2,r+3)}return{position:h,normal:i,texcoord:j,indices:k}}function s(a,b,c,d,f,g,h){if(3>d)throw Error("radialSubdivisions must be 3 or greater");if(1>f)throw Error("verticalSubdivisions must be 1 or greater");for(var i=void 0===g?!0:g,j=void 0===h?!0:h,k=(i?2:0)+(j?2:0),l=(d+1)*(f+1+k),m=e(3,l),n=e(3,l),o=e(2,l),p=e(3,d*(f+k)*2,Uint16Array),q=d+1,r=Math.atan2(a-b,c),s=Math.cos(r),t=Math.sin(r),u=i?-2:0,v=f+(j?2:0),w=u;v>=w;++w){var x,y=w/f,z=c*y;0>w?(z=0,y=1,x=a):w>f?(z=c,y=1,x=b):x=a+(b-a)*(w/f),(-2===w||w===f+2)&&(x=0,y=0),z-=c/2;for(var A=0;q>A;++A){var B=Math.sin(A*Math.PI*2/d),C=Math.cos(A*Math.PI*2/d);m.push(B*x,z,C*x),n.push(0>w||w>f?0:B*s,0>w?-1:w>f?1:t,0>w||w>f?0:C*s),o.push(A/d,1-y)}}for(var w=0;f+k>w;++w)for(var A=0;d>A;++A)p.push(q*(w+0)+0+A,q*(w+0)+1+A,q*(w+1)+1+A),p.push(q*(w+0)+0+A,q*(w+1)+1+A,q*(w+1)+0+A);return{position:m,normal:n,texcoord:o,indices:p}}function t(a,b){b=b||[];for(var c=[],d=0;dg;++g)c.push.apply(c,f)}return c}function u(){var a=[0,0,0,0,150,0,30,0,0,0,150,0,30,150,0,30,0,0,30,0,0,30,30,0,100,0,0,30,30,0,100,30,0,100,0,0,30,60,0,30,90,0,67,60,0,30,90,0,67,90,0,67,60,0,0,0,30,30,0,30,0,150,30,0,150,30,30,0,30,30,150,30,30,0,30,100,0,30,30,30,30,30,30,30,100,0,30,100,30,30,30,60,30,67,60,30,30,90,30,30,90,30,67,60,30,67,90,30,0,0,0,100,0,0,100,0,30,0,0,0,100,0,30,0,0,30,100,0,0,100,30,0,100,30,30,100,0,0,100,30,30,100,0,30,30,30,0,30,30,30,100,30,30,30,30,0,100,30,30,100,30,0,30,30,0,30,60,30,30,30,30,30,30,0,30,60,0,30,60,30,30,60,0,67,60,30,30,60,30,30,60,0,67,60,0,67,60,30,67,60,0,67,90,30,67,60,30,67,60,0,67,90,0,67,90,30,30,90,0,30,90,30,67,90,30,30,90,0,67,90,30,67,90,0,30,90,0,30,150,30,30,90,30,30,90,0,30,150,0,30,150,30,0,150,0,0,150,30,30,150,30,0,150,0,30,150,30,30,150,0,0,0,0,0,0,30,0,150,30,0,0,0,0,150,30,0,150,0],b=[.22,.19,.22,.79,.34,.19,.22,.79,.34,.79,.34,.19,.34,.19,.34,.31,.62,.19,.34,.31,.62,.31,.62,.19,.34,.43,.34,.55,.49,.43,.34,.55,.49,.55,.49,.43,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1,1,0],c=t([18,0,0,1,18,0,0,-1,6,0,1,0,6,1,0,0,6,0,-1,0,6,1,0,0,6,0,1,0,6,1,0,0,6,0,-1,0,6,1,0,0,6,0,-1,0,6,-1,0,0]),d=t([18,200,70,120,18,80,70,200,6,70,200,210,6,200,200,70,6,210,100,70,6,210,160,70,6,70,180,210,6,100,70,210,6,76,210,100,6,140,210,80,6,90,130,110,6,160,160,220],[255]),f=a.length/3,g={position:e(3,f),texcoord:e(2,f),normal:e(3,f),color:e(4,f,Uint8Array),indices:e(3,f/3,Uint16Array)};g.position.push(a),g.texcoord.push(b),g.normal.push(c),g.color.push(d);for(var h=0;f>h;++h)g.indices.push(h);return g}function v(a,b,d,f,g,h,i){function j(a,b,c){return a+(b-a)*c}function k(b,d,e,i,k,l){for(var o=0;g>=o;o++){var s=d/(m-1),t=o/g,u=2*(s-.5),v=(h+t*n)*Math.PI,w=Math.sin(v),x=Math.cos(v),y=j(a,b,w),z=u*f,A=x*a,B=w*y;p.push(z,A,B);var C=c.add(c.multiply([0,w,x],e),i);q.push(C),r.push(s*k+l,t)}}function l(a,b){for(var c=0;g>c;++c)u.push(a+c+0,a+c+1,b+c+0),u.push(a+c+1,b+c+1,b+c+0)}if(0>=g)throw Error("subdivisionDown must be > 0");h=h||0,i=i||1;for(var m=2,n=i-h,o=2*(g+1)*(2+m),p=e(3,o),q=e(3,o),r=e(2,o),s=0;m>s;s++){var t=2*(s/(m-1)-.5);k(b,s,[1,1,1],[0,0,0],1,0),k(b,s,[0,0,0],[t,0,0],0,0),k(d,s,[1,1,1],[0,0,0],1,0),k(d,s,[0,0,0],[t,0,0],0,1)}var u=e(3,2*g*(2+m),Uint16Array),v=g+1;return l(0*v,4*v),l(5*v,7*v),l(6*v,2*v),l(3*v,1*v),{position:p,normal:q,texcoord:r,indices:u}}function w(a,b,c,d,e,f){return s(a,a,b,c,d,e,f)}function x(a,b,c,d,f,g){if(3>c)throw Error("radialSubdivisions must be 3 or greater");if(3>d)throw Error("verticalSubdivisions must be 3 or greater");f=f||0,g=g||2*Math.PI,range=g-f;for(var h=c+1,i=d+1,j=h*i,k=e(3,j),l=e(3,j),m=e(2,j),n=e(3,c*d*2,Uint16Array),o=0;i>o;++o)for(var p=o/d,q=p*Math.PI*2,r=Math.sin(q),s=a+r*b,t=Math.cos(q),u=t*b,v=0;h>v;++v){var w=v/c,x=f+w*range,y=Math.sin(x),z=Math.cos(x),A=y*s,B=z*s,C=y*r,D=z*r;k.push(A,u,B),l.push(C,t,D),m.push(w,1-p)}for(var o=0;d>o;++o)for(var v=0;c>v;++v){var E=1+v,F=1+o;n.push(h*o+v,h*F+v,h*o+E),n.push(h*F+v,h*F+E,h*o+E)}return{position:k,normal:l,texcoord:m,indices:n}}function y(a,b,c,d,f){if(3>b)throw Error("divisions must be at least 3");c=c?c:1,f=f?f:1,d=d?d:0;for(var g=(b+1)*(c+1),h=e(3,g),i=e(3,g),j=e(2,g),k=e(3,c*b*2,Uint16Array),l=0,m=a-d,n=0;c>=n;++n){for(var o=d+m*Math.pow(n/c,f),p=0;b>=p;++p){var q=2*Math.PI*p/b,r=o*Math.cos(q),s=o*Math.sin(q);if(h.push(r,0,s),i.push(0,1,0),j.push(1-p/b,n/c),n>0&&p!==b){var t=l+(p+1),u=l+p,v=l+p-b,w=l+(p+1)-b;k.push(t,u,v),k.push(t,v,w)}}l+=b+1}return{position:h,normal:i,texcoord:j,indices:k}}function z(a){return Math.random()*a|0}function A(a,b){b=b||{};var c=a.position.numElements,d=e(4,c,Uint8Array),f=b.rand||function(a,b){return 3>b?z(256):255};if(a.color=d,a.indices)for(var g=0;c>g;++g)d.push(f(g,0),f(g,1),f(g,2),f(g,3));else for(var h=b.vertsPerColor||3,i=c/h,g=0;i>g;++g)for(var j=[f(g,0),f(g,1),f(g,2),f(g,3)],k=0;h>k;++k)d.push(j);return a}function B(b){return function(c){var d=b.apply(this,Array.prototype.slice.call(arguments,1));return a.createBuffersFromArrays(c,d)}}function C(b){return function(c){var d=b.apply(null,Array.prototype.slice.call(arguments,1));return a.createBufferInfoFromArrays(c,d)}}var D=[[3,7,5,1],[6,2,0,4],[6,7,3,2],[0,1,5,4],[7,6,4,5],[2,3,1,0]];return{create3DFBufferInfo:C(u),create3DFBuffers:B(u),create3DFVertices:u,createAugmentedTypedArray:e,createCubeBufferInfo:C(r),createCubeBuffers:B(r),createCubeVertices:r,createPlaneBufferInfo:C(p),createPlaneBuffers:B(p),createPlaneVertices:p,createSphereBufferInfo:C(q),createSphereBuffers:B(q),createSphereVertices:q,createTruncatedConeBufferInfo:C(s),createTruncatedConeBuffers:B(s),createTruncatedConeVertices:s,createXYQuadBufferInfo:C(o),createXYQuadBuffers:B(o),createXYQuadVertices:o,createCresentBufferInfo:C(v),createCresentBuffers:B(v),createCresentVertices:v,createCylinderBufferInfo:C(w),createCylinderBuffers:B(w),createCylinderVertices:w,createTorusBufferInfo:C(x),createTorusBuffers:B(x),createTorusVertices:x,createDiscBufferInfo:C(y),createDiscBuffers:B(y),createDiscVertices:y,deindexVertices:g,flattenNormals:h,makeRandomVertexColors:A,reorientDirections:k,reorientNormals:l,reorientPositions:m,reorientVertices:n}}),c("main",["twgl/twgl","twgl/m4","twgl/v3","twgl/primitives"],function(a,b,c,d){return a.m4=b,a.v3=c,a.primitives=d,a}),b(["main"],function(a){return a},void 0,!0),c("build/js/twgl-includer-full",function(){}),b("main")}); -------------------------------------------------------------------------------- /Week4/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hierarchical model using glmatrix implementation of transforms (no stack) 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Week4/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 50; 8 | var slider3 = document.getElementById('slider3'); 9 | slider3.value = -50; 10 | var slider4 = document.getElementById('slider4'); 11 | slider4.value = 25; 12 | 13 | function draw() { 14 | canvas.width = canvas.width; 15 | // use the sliders to get the angles 16 | var theta1 = slider1.value*0.005*Math.PI; 17 | var phi1 = slider2.value*0.005*Math.PI; 18 | var phi2 = slider3.value*0.005*Math.PI; 19 | var theta2 = slider4.value*0.005*Math.PI; 20 | 21 | var stack = [ mat3.create() ]; // Initialize stack with identity on top 22 | 23 | function moveToTx(x,y) 24 | {var res=vec2.create(); vec2.transformMat3(res,[x,y],stack[0]); context.moveTo(res[0],res[1]);} 25 | 26 | function lineToTx(x,y) 27 | {var res=vec2.create(); vec2.transformMat3(res,[x,y],stack[0]); context.lineTo(res[0],res[1]);} 28 | 29 | function linkage(color) { 30 | context.beginPath(); 31 | context.fillStyle = color; 32 | moveToTx(0,0); 33 | lineToTx(10,5); 34 | lineToTx(90,5); 35 | lineToTx(100,0); 36 | lineToTx(90,-5); 37 | lineToTx(10,-5); 38 | context.closePath(); 39 | context.fill(); 40 | axes(color); 41 | } 42 | 43 | function axes(color) { 44 | context.strokeStyle=color; 45 | context.beginPath(); 46 | // Axes 47 | moveToTx(120,0);lineToTx(0,0);lineToTx(0,120); 48 | // Arrowheads 49 | moveToTx(110,5);lineToTx(120,0);lineToTx(110,-5); 50 | moveToTx(5,110);lineToTx(0,120);lineToTx(-5,110); 51 | // X-label 52 | moveToTx(130,-5);lineToTx(140,5); 53 | moveToTx(130,5);lineToTx(140,-5); 54 | // Y-label 55 | moveToTx(-5,130);lineToTx(0,135);lineToTx(5,130); 56 | moveToTx(0,135);lineToTx(0,142); 57 | context.stroke(); 58 | } 59 | 60 | // make sure you understand these 61 | 62 | var Tblue_to_canvas = mat3.create(); 63 | mat3.fromTranslation(Tblue_to_canvas,[50,150]); 64 | mat3.multiply(stack[0],stack[0],Tblue_to_canvas); 65 | linkage("blue"); 66 | 67 | stack.unshift(mat3.clone(stack[0])); // "save" (note: you *need* to clone) 68 | var Tgreen_to_blue = mat3.create(); 69 | mat3.fromTranslation(Tgreen_to_blue,[100,0]); 70 | mat3.rotate(Tgreen_to_blue,Tgreen_to_blue,theta1); 71 | mat3.multiply(stack[0],stack[0],Tgreen_to_blue); 72 | linkage("green"); 73 | 74 | stack.unshift(mat3.clone(stack[0])); // "save" 75 | var Tred_to_green = mat3.create(); 76 | mat3.fromTranslation(Tred_to_green,[100,0]); 77 | mat3.rotate(Tred_to_green,Tred_to_green,phi1); 78 | mat3.scale(Tred_to_green,Tred_to_green,[0.5,1]); 79 | mat3.multiply(stack[0],stack[0],Tred_to_green); 80 | linkage("red"); 81 | stack.shift(); // "restore" 82 | 83 | stack.unshift(mat3.clone(stack[0])); // "save" 84 | var Torange_to_green = mat3.create(); 85 | mat3.fromTranslation(Torange_to_green,[100,0]); 86 | mat3.rotate(Torange_to_green,Torange_to_green,phi2); 87 | mat3.scale(Torange_to_green,Torange_to_green,[0.5,1]); 88 | mat3.multiply(stack[0],stack[0],Torange_to_green); 89 | linkage("orange"); 90 | stack.shift(); // "restore" 91 | stack.shift(); // "restore" 92 | 93 | stack.unshift(mat3.clone(stack[0])); // "save" 94 | var Tbrown_to_blue = mat3.create(); 95 | mat3.fromTranslation(Tbrown_to_blue,[100,0]); 96 | mat3.rotate(Tbrown_to_blue,Tbrown_to_blue,theta2); 97 | mat3.multiply(stack[0],stack[0],Tbrown_to_blue); 98 | linkage("brown"); 99 | stack.shift(); // "restore" 100 | } 101 | 102 | slider1.addEventListener("input",draw); 103 | slider2.addEventListener("input",draw); 104 | slider3.addEventListener("input",draw); 105 | slider4.addEventListener("input",draw); 106 | draw(); 107 | } 108 | window.onload = setup; 109 | 110 | -------------------------------------------------------------------------------- /Week5/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week5/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-5,-5],Tx); 22 | lineToTx([-5,5],Tx); 23 | lineToTx([5,5],Tx); 24 | lineToTx([5,-5],Tx); 25 | context.closePath(); 26 | context.fill(); 27 | } 28 | 29 | function drawAxes(color,Tx) { 30 | context.strokeStyle=color; 31 | context.beginPath(); 32 | // Axes 33 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 34 | // Arrowheads 35 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 36 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 37 | // X-label 38 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 39 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 40 | context.stroke(); 41 | } 42 | 43 | var Rstart = 50.0; 44 | var Rslope = 25.0; 45 | var Cspiral = function(t) { 46 | var R = Rslope * t + Rstart; 47 | var x = R * Math.cos(2.0 * Math.PI * t); 48 | var y = R * Math.sin(2.0 * Math.PI * t); 49 | return [x,y]; 50 | } 51 | 52 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 53 | context.strokeStyle=color; 54 | context.beginPath(); 55 | moveToTx(C(t_begin),Tx); 56 | for(var i=1;i<=intervals;i++){ 57 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 58 | lineToTx(C(t),Tx); 59 | } 60 | context.stroke(); 61 | } 62 | 63 | // make sure you understand these 64 | 65 | drawAxes("black", mat3.create()); 66 | 67 | var Tblue_to_canvas = mat3.create(); 68 | mat3.fromTranslation(Tblue_to_canvas,[150,150]); 69 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[1,-1]); // Flip the Y-axis 70 | drawAxes("blue",Tblue_to_canvas); 71 | 72 | drawTrajectory(0.0,2.0,100,Cspiral,Tblue_to_canvas,"brown"); 73 | var Tgreen_to_blue = mat3.create(); 74 | mat3.fromTranslation(Tgreen_to_blue,Cspiral(tParam)); 75 | var Tgreen_to_canvas = mat3.create(); 76 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 77 | drawObject("green",Tgreen_to_canvas); 78 | } 79 | 80 | slider1.addEventListener("input",draw); 81 | draw(); 82 | } 83 | window.onload = setup; 84 | -------------------------------------------------------------------------------- /Week5/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week5/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = 0; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-5,-5],Tx); 22 | lineToTx([-5,5],Tx); 23 | lineToTx([5,5],Tx); 24 | lineToTx([10,0],Tx); 25 | lineToTx([5,-5],Tx); 26 | context.closePath(); 27 | context.fill(); 28 | } 29 | 30 | function drawAxes(color,Tx) { 31 | context.strokeStyle=color; 32 | context.beginPath(); 33 | // Axes 34 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 35 | // Arrowheads 36 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 37 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 38 | // X-label 39 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 40 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 41 | context.stroke(); 42 | } 43 | 44 | var Rstart = 50.0; 45 | var Rslope = 25.0; 46 | var Cspiral = function(t) { 47 | var R = Rslope * t + Rstart; 48 | var x = R * Math.cos(2.0 * Math.PI * t); 49 | var y = R * Math.sin(2.0 * Math.PI * t); 50 | return [x,y]; 51 | } 52 | var Cspiral_tangent = function(t) { 53 | var R = Rslope * t + Rstart; 54 | var Rprime = Rslope; 55 | var x = Rprime * Math.cos(2.0 * Math.PI * t) 56 | - R * 2.0 * Math.PI * Math.sin(2.0 * Math.PI * t); 57 | var y = Rprime * Math.sin(2.0 * Math.PI * t) 58 | + R * 2.0 * Math.PI * Math.cos(2.0 * Math.PI * t); 59 | return [x,y]; 60 | } 61 | 62 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 63 | context.strokeStyle=color; 64 | context.beginPath(); 65 | moveToTx(C(t_begin),Tx); 66 | for(var i=1;i<=intervals;i++){ 67 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 68 | lineToTx(C(t),Tx); 69 | } 70 | context.stroke(); 71 | } 72 | 73 | // make sure you understand these 74 | 75 | drawAxes("black", mat3.create()); 76 | 77 | var Tred_to_canvas = mat3.create(); 78 | mat3.fromTranslation(Tred_to_canvas,[25,25]); 79 | drawAxes("red",Tred_to_canvas); 80 | drawObject("red",Tred_to_canvas); 81 | 82 | var Tblue_to_canvas = mat3.create(); 83 | mat3.fromTranslation(Tblue_to_canvas,[150,175]); 84 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[1,-1]); // Flip the Y-axis 85 | drawAxes("blue",Tblue_to_canvas); 86 | 87 | drawTrajectory(0.0,2.0,100,Cspiral,Tblue_to_canvas,"brown"); 88 | var Tgreen_to_blue = mat3.create(); 89 | mat3.fromTranslation(Tgreen_to_blue,Cspiral(tParam)); 90 | var tangent = Cspiral_tangent(tParam); 91 | var angle = Math.atan2(tangent[1],tangent[0]); 92 | mat3.rotate(Tgreen_to_blue,Tgreen_to_blue,angle); 93 | var Tgreen_to_canvas = mat3.create(); 94 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 95 | // drawAxes("green",Tgreen_to_canvas); // Un-comment this to view axes 96 | drawObject("green",Tgreen_to_canvas); 97 | } 98 | 99 | slider1.addEventListener("input",draw); 100 | draw(); 101 | } 102 | window.onload = setup; 103 | -------------------------------------------------------------------------------- /Week5/Demo2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Composite curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week5/Demo2/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-.05,-.05],Tx); 22 | lineToTx([-.05,.05],Tx); 23 | lineToTx([.05,.05],Tx); 24 | lineToTx([.05,-.05],Tx); 25 | context.closePath(); 26 | context.fill(); 27 | } 28 | 29 | function drawAxes100unit(color,Tx) { 30 | context.strokeStyle=color; 31 | context.beginPath(); 32 | // Axes 33 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 34 | // Arrowheads 35 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 36 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 37 | // X-label 38 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 39 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 40 | context.stroke(); 41 | } 42 | 43 | function drawAxes1unit(color,Tx) { 44 | context.strokeStyle=color; 45 | context.beginPath(); 46 | // Axes 47 | moveToTx([1.20,0],Tx);lineToTx([0,0],Tx);lineToTx([0,1.20],Tx); 48 | // Arrowheads 49 | moveToTx([1.10,.05],Tx);lineToTx([1.20,0],Tx);lineToTx([1.10,-.05],Tx); 50 | moveToTx([.05,1.10],Tx);lineToTx([0,1.20],Tx);lineToTx([-.05,1.10],Tx); 51 | // X-label 52 | moveToTx([1.30,0],Tx);lineToTx([1.40,.10],Tx); 53 | moveToTx([1.30,.10],Tx);lineToTx([1.40,0],Tx); 54 | context.stroke(); 55 | } 56 | 57 | 58 | var C0 = function(t) { 59 | var x = t; 60 | var y = t*t; 61 | return [x,y]; 62 | } 63 | 64 | var C1a = function(t) { // discontinuity at t=1 65 | var x = t*(t-1); 66 | var y = t; 67 | return [x,y]; 68 | } 69 | 70 | var C1b = function(t) { // C0 continuity at t=1 71 | var x = t*t-3*t+3; 72 | var y = t; 73 | return [x,y]; 74 | } 75 | 76 | var C1c = function(t) { // C1 continuity at t=1 77 | var x = t; 78 | var y = -t*t+4*t-2; 79 | return [x,y]; 80 | } 81 | 82 | var C1d = function(t) { // G1 continuity at t=1 83 | var x = 0.25*(t+3); 84 | var y = -0.0625*(t+3)*(t+3)+(t+3)-2; 85 | return [x,y]; 86 | } 87 | 88 | var C1e = function(t) { // C2 continuity at t=1 89 | var x = t; 90 | var y = t*t-2*(t-1)*(t-1)*(t-1); 91 | return [x,y]; 92 | } 93 | 94 | var C1 = C1e; 95 | 96 | var Ccomp = function(t) { 97 | if(t<1) { 98 | return C0(t); 99 | }else{ 100 | return C1(t); 101 | } 102 | } 103 | 104 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 105 | context.strokeStyle=color; 106 | context.beginPath(); 107 | moveToTx(C(t_begin),Tx); 108 | for(var i=1;i<=intervals;i++){ 109 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 110 | lineToTx(C(t),Tx); 111 | } 112 | context.stroke(); 113 | } 114 | 115 | // make sure you understand these 116 | 117 | drawAxes100unit("black", mat3.create()); 118 | 119 | var Tblue_to_canvas = mat3.create(); 120 | mat3.fromTranslation(Tblue_to_canvas,[50,350]); 121 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[150,-150]); // Flip the Y-axis 122 | drawAxes1unit("grey",Tblue_to_canvas); 123 | 124 | drawTrajectory(0.0,1.0,100,C0,Tblue_to_canvas,"red"); 125 | drawTrajectory(1.0,2.0,100,C1,Tblue_to_canvas,"blue"); 126 | var Tgreen_to_blue = mat3.create(); 127 | mat3.fromTranslation(Tgreen_to_blue,Ccomp(tParam)); 128 | var Tgreen_to_canvas = mat3.create(); 129 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 130 | drawObject("green",Tgreen_to_canvas); 131 | } 132 | 133 | slider1.addEventListener("input",draw); 134 | draw(); 135 | } 136 | window.onload = setup; 137 | -------------------------------------------------------------------------------- /Week6/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Composite curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week6/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-.05,-.05],Tx); 22 | lineToTx([-.05,.05],Tx); 23 | lineToTx([.05,.05],Tx); 24 | lineToTx([.05,-.05],Tx); 25 | context.closePath(); 26 | context.fill(); 27 | } 28 | 29 | function drawAxes100unit(color,Tx) { 30 | context.strokeStyle=color; 31 | context.beginPath(); 32 | // Axes 33 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 34 | // Arrowheads 35 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 36 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 37 | // X-label 38 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 39 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 40 | context.stroke(); 41 | } 42 | 43 | function drawAxes1unit(color,Tx) { 44 | context.strokeStyle=color; 45 | context.beginPath(); 46 | // Axes 47 | moveToTx([1.20,0],Tx);lineToTx([0,0],Tx);lineToTx([0,1.20],Tx); 48 | // Arrowheads 49 | moveToTx([1.10,.05],Tx);lineToTx([1.20,0],Tx);lineToTx([1.10,-.05],Tx); 50 | moveToTx([.05,1.10],Tx);lineToTx([0,1.20],Tx);lineToTx([-.05,1.10],Tx); 51 | // X-label 52 | moveToTx([1.30,0],Tx);lineToTx([1.40,.10],Tx); 53 | moveToTx([1.30,.10],Tx);lineToTx([1.40,0],Tx); 54 | context.stroke(); 55 | } 56 | 57 | 58 | var Hermite = function(t) { 59 | return [ 60 | 2*t*t*t-3*t*t+1, 61 | t*t*t-2*t*t+t, 62 | -2*t*t*t+3*t*t, 63 | t*t*t-t*t 64 | ]; 65 | } 66 | 67 | function Cubic(basis,P,t){ 68 | var b = basis(t); 69 | var result=vec2.create(); 70 | vec2.scale(result,P[0],b[0]); 71 | vec2.scaleAndAdd(result,result,P[1],b[1]); 72 | vec2.scaleAndAdd(result,result,P[2],b[2]); 73 | vec2.scaleAndAdd(result,result,P[3],b[3]); 74 | return result; 75 | } 76 | 77 | var p0=[0,0]; 78 | var d0=[1,3]; 79 | var p1=[1,1]; 80 | var d1=[-1,3]; 81 | var p2=[2,2]; 82 | var d2=[0,3]; 83 | 84 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 85 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 86 | 87 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 88 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 89 | 90 | var Ccomp = function(t) { 91 | if (t<1){ 92 | var u = t; 93 | return C0(u); 94 | } else { 95 | var u = t-1.0; 96 | return C1(u); 97 | } 98 | } 99 | 100 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 101 | context.strokeStyle=color; 102 | context.beginPath(); 103 | moveToTx(C(t_begin),Tx); 104 | for(var i=1;i<=intervals;i++){ 105 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 106 | lineToTx(C(t),Tx); 107 | } 108 | context.stroke(); 109 | } 110 | 111 | // make sure you understand these 112 | 113 | drawAxes100unit("black", mat3.create()); 114 | 115 | var Tblue_to_canvas = mat3.create(); 116 | mat3.fromTranslation(Tblue_to_canvas,[50,350]); 117 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[150,-150]); // Flip the Y-axis 118 | drawAxes1unit("grey",Tblue_to_canvas); 119 | 120 | drawTrajectory(0.0,1.0,100,C0,Tblue_to_canvas,"red"); 121 | drawTrajectory(0.0,1.0,100,C1,Tblue_to_canvas,"blue"); 122 | var Tgreen_to_blue = mat3.create(); 123 | mat3.fromTranslation(Tgreen_to_blue,Ccomp(tParam)); 124 | var Tgreen_to_canvas = mat3.create(); 125 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 126 | drawObject("green",Tgreen_to_canvas); 127 | } 128 | 129 | 130 | slider1.addEventListener("input",draw); 131 | draw(); 132 | } 133 | window.onload = setup; 134 | -------------------------------------------------------------------------------- /Week6/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Composite curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week6/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-.05,-.05],Tx); 22 | lineToTx([-.05,.05],Tx); 23 | lineToTx([.05,.05],Tx); 24 | lineToTx([.1,0],Tx); 25 | lineToTx([.05,-.05],Tx); 26 | context.closePath(); 27 | context.fill(); 28 | } 29 | 30 | function drawAxes100unit(color,Tx) { 31 | context.strokeStyle=color; 32 | context.beginPath(); 33 | // Axes 34 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 35 | // Arrowheads 36 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 37 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 38 | // X-label 39 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 40 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 41 | context.stroke(); 42 | } 43 | 44 | function drawAxes1unit(color,Tx) { 45 | context.strokeStyle=color; 46 | context.beginPath(); 47 | // Axes 48 | moveToTx([1.20,0],Tx);lineToTx([0,0],Tx);lineToTx([0,1.20],Tx); 49 | // Arrowheads 50 | moveToTx([1.10,.05],Tx);lineToTx([1.20,0],Tx);lineToTx([1.10,-.05],Tx); 51 | moveToTx([.05,1.10],Tx);lineToTx([0,1.20],Tx);lineToTx([-.05,1.10],Tx); 52 | // X-label 53 | moveToTx([1.30,0],Tx);lineToTx([1.40,.10],Tx); 54 | moveToTx([1.30,.10],Tx);lineToTx([1.40,0],Tx); 55 | context.stroke(); 56 | } 57 | 58 | 59 | var Hermite = function(t) { 60 | return [ 61 | 2*t*t*t-3*t*t+1, 62 | t*t*t-2*t*t+t, 63 | -2*t*t*t+3*t*t, 64 | t*t*t-t*t 65 | ]; 66 | } 67 | 68 | var HermiteDerivative = function(t) { 69 | return [ 70 | 6*t*t-6*t, 71 | 3*t*t-4*t+1, 72 | -6*t*t+6*t, 73 | 3*t*t-2*t 74 | ]; 75 | } 76 | 77 | function Cubic(basis,P,t){ 78 | var b = basis(t); 79 | var result=vec2.create(); 80 | vec2.scale(result,P[0],b[0]); 81 | vec2.scaleAndAdd(result,result,P[1],b[1]); 82 | vec2.scaleAndAdd(result,result,P[2],b[2]); 83 | vec2.scaleAndAdd(result,result,P[3],b[3]); 84 | return result; 85 | } 86 | 87 | var p0=[0,0]; 88 | var d0=[1,3]; 89 | var p1=[1,1]; 90 | var d1=[-1,3]; 91 | var p2=[2,2]; 92 | var d2=[0,3]; 93 | 94 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 95 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 96 | 97 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 98 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 99 | 100 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 101 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 102 | 103 | var Ccomp = function(t) { 104 | if (t<1){ 105 | var u = t; 106 | return C0(u); 107 | } else { 108 | var u = t-1.0; 109 | return C1(u); 110 | } 111 | } 112 | 113 | var Ccomp_tangent = function(t) { 114 | if (t<1){ 115 | var u = t; 116 | return C0prime(u); 117 | } else { 118 | var u = t-1.0; 119 | return C1prime(u); 120 | } 121 | } 122 | 123 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 124 | context.strokeStyle=color; 125 | context.beginPath(); 126 | moveToTx(C(t_begin),Tx); 127 | for(var i=1;i<=intervals;i++){ 128 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 129 | lineToTx(C(t),Tx); 130 | } 131 | context.stroke(); 132 | } 133 | 134 | // make sure you understand these 135 | 136 | drawAxes100unit("black", mat3.create()); 137 | 138 | var Tblue_to_canvas = mat3.create(); 139 | mat3.fromTranslation(Tblue_to_canvas,[50,350]); 140 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[150,-150]); // Flip the Y-axis 141 | drawAxes1unit("grey",Tblue_to_canvas); 142 | 143 | drawTrajectory(0.0,1.0,100,C0,Tblue_to_canvas,"red"); 144 | drawTrajectory(0.0,1.0,100,C1,Tblue_to_canvas,"blue"); 145 | var Tgreen_to_blue = mat3.create(); 146 | mat3.fromTranslation(Tgreen_to_blue,Ccomp(tParam)); 147 | var Tgreen_to_canvas = mat3.create(); 148 | var tangent = Ccomp_tangent(tParam); 149 | var angle = Math.atan2(tangent[1],tangent[0]); 150 | mat3.rotate(Tgreen_to_blue,Tgreen_to_blue,angle); 151 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 152 | drawObject("green",Tgreen_to_canvas); 153 | } 154 | 155 | slider1.addEventListener("input",draw); 156 | draw(); 157 | } 158 | window.onload = setup; 159 | 160 | -------------------------------------------------------------------------------- /Week6/Demo2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Composite curve drawing (with motion) example 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week6/Demo2/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec2.create(); vec2.transformMat3(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawPoint(color,pos,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-.03+pos[0],-.03+pos[1]],Tx); 22 | lineToTx([-.03+pos[0],.03+pos[1]],Tx); 23 | lineToTx([.03+pos[0],.03+pos[1]],Tx); 24 | lineToTx([.03+pos[0],-.03+pos[1]],Tx); 25 | context.closePath(); 26 | context.fill(); 27 | } 28 | 29 | function drawObject(color,Tx) { 30 | context.beginPath(); 31 | context.fillStyle = color; 32 | moveToTx([-.05,-.05],Tx); 33 | lineToTx([-.05,.05],Tx); 34 | lineToTx([.05,.05],Tx); 35 | lineToTx([.05,-.05],Tx); 36 | context.closePath(); 37 | context.fill(); 38 | } 39 | 40 | function drawAxes100unit(color,Tx) { 41 | context.strokeStyle=color; 42 | context.beginPath(); 43 | // Axes 44 | moveToTx([120,0],Tx);lineToTx([0,0],Tx);lineToTx([0,120],Tx); 45 | // Arrowheads 46 | moveToTx([110,5],Tx);lineToTx([120,0],Tx);lineToTx([110,-5],Tx); 47 | moveToTx([5,110],Tx);lineToTx([0,120],Tx);lineToTx([-5,110],Tx); 48 | // X-label 49 | moveToTx([130,0],Tx);lineToTx([140,10],Tx); 50 | moveToTx([130,10],Tx);lineToTx([140,0],Tx); 51 | context.stroke(); 52 | } 53 | 54 | function drawAxes1unit(color,Tx) { 55 | context.strokeStyle=color; 56 | context.beginPath(); 57 | // Axes 58 | moveToTx([1.20,0],Tx);lineToTx([0,0],Tx);lineToTx([0,1.20],Tx); 59 | // Arrowheads 60 | moveToTx([1.10,.05],Tx);lineToTx([1.20,0],Tx);lineToTx([1.10,-.05],Tx); 61 | moveToTx([.05,1.10],Tx);lineToTx([0,1.20],Tx);lineToTx([-.05,1.10],Tx); 62 | // X-label 63 | moveToTx([1.30,0],Tx);lineToTx([1.40,.10],Tx); 64 | moveToTx([1.30,.10],Tx);lineToTx([1.40,0],Tx); 65 | context.stroke(); 66 | } 67 | 68 | 69 | var Bspline = function(t) { 70 | return [ 71 | (1./6.)*(-t*t*t+3*t*t-3*t+1), 72 | (1./6.)*(3*t*t*t-6*t*t+4), 73 | (1./6.)*(-3*t*t*t+3*t*t+3*t+1), 74 | (1./6.)*t*t*t 75 | ]; 76 | } 77 | 78 | function Cubic(basis,P,t){ 79 | var b = basis(t); 80 | var result=vec2.create(); 81 | vec2.scale(result,P[0],b[0]); 82 | vec2.scaleAndAdd(result,result,P[1],b[1]); 83 | vec2.scaleAndAdd(result,result,P[2],b[2]); 84 | vec2.scaleAndAdd(result,result,P[3],b[3]); 85 | return result; 86 | } 87 | 88 | var p0=[1+Math.cos(5.*Math.PI/5.),Math.sin(5.*Math.PI/5.)]; 89 | var p1=[1+Math.cos(4.*Math.PI/5.),Math.sin(4.*Math.PI/5.)]; 90 | var p2=[1+Math.cos(3.*Math.PI/5.),Math.sin(3.*Math.PI/5.)]; 91 | var p3=[1+Math.cos(2.*Math.PI/5.),Math.sin(2.*Math.PI/5.)]; 92 | var p4=[1+Math.cos(1.*Math.PI/5.),Math.sin(1.*Math.PI/5.)]; 93 | var p5=[1+Math.cos(0.*Math.PI/5.),Math.sin(0.*Math.PI/5.)]; 94 | 95 | var P0 = [p0,p1,p2,p3]; 96 | var P1 = [p1,p2,p3,p4]; 97 | var P2 = [p2,p3,p4,p5]; 98 | 99 | var C0 = function(t_) {return Cubic(Bspline,P0,t_);}; 100 | var C1 = function(t_) {return Cubic(Bspline,P1,t_);}; 101 | var C2 = function(t_) {return Cubic(Bspline,P2,t_);}; 102 | 103 | var Ccomp = function(t) { 104 | if (t<1){ 105 | var u = t; 106 | return C0(u); 107 | } else if (t<2){ 108 | var u = t-1.0; 109 | return C1(u); 110 | } else { 111 | var u = t-2.0; 112 | return C2(u); 113 | } 114 | } 115 | 116 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 117 | context.strokeStyle=color; 118 | context.beginPath(); 119 | moveToTx(C(t_begin),Tx); 120 | for(var i=1;i<=intervals;i++){ 121 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 122 | lineToTx(C(t),Tx); 123 | } 124 | context.stroke(); 125 | } 126 | 127 | // make sure you understand these 128 | 129 | drawAxes100unit("black", mat3.create()); 130 | 131 | var Tblue_to_canvas = mat3.create(); 132 | mat3.fromTranslation(Tblue_to_canvas,[50,350]); 133 | mat3.scale(Tblue_to_canvas,Tblue_to_canvas,[150,-150]); // Flip the Y-axis 134 | drawAxes1unit("grey",Tblue_to_canvas); 135 | 136 | drawPoint("grey",p0,Tblue_to_canvas); 137 | drawPoint("grey",p1,Tblue_to_canvas); 138 | drawPoint("grey",p2,Tblue_to_canvas); 139 | drawPoint("grey",p3,Tblue_to_canvas); 140 | drawPoint("grey",p4,Tblue_to_canvas); 141 | drawPoint("grey",p5,Tblue_to_canvas); 142 | 143 | drawTrajectory(0.0,1.0,100,C0,Tblue_to_canvas,"red"); 144 | drawTrajectory(0.0,1.0,100,C1,Tblue_to_canvas,"blue"); 145 | drawTrajectory(0.0,1.0,100,C2,Tblue_to_canvas,"brown"); 146 | 147 | var Tgreen_to_blue = mat3.create(); 148 | mat3.fromTranslation(Tgreen_to_blue,Ccomp(tParam)); 149 | var Tgreen_to_canvas = mat3.create(); 150 | mat3.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 151 | drawObject("green",Tgreen_to_canvas); 152 | } 153 | 154 | slider1.addEventListener("input",draw); 155 | draw(); 156 | } 157 | window.onload = setup; 158 | 159 | 160 | -------------------------------------------------------------------------------- /Week7/Demo0/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Introductory demos on 3D viewing and drawing 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Week7/Demo0/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = -25; 6 | 7 | function draw() { 8 | canvas.width = canvas.width; 9 | // use the sliders to get the angles 10 | var tParam = slider1.value*0.01; 11 | 12 | function moveToTx(loc,Tx) 13 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.moveTo(res[0],res[1]);} 14 | 15 | function lineToTx(loc,Tx) 16 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.lineTo(res[0],res[1]);} 17 | 18 | function drawObject(color,Tx) { 19 | context.beginPath(); 20 | context.fillStyle = color; 21 | moveToTx([-5,-5,0],Tx); 22 | lineToTx([-5,5,0],Tx); 23 | lineToTx([5,5,0],Tx); 24 | lineToTx([10,0,0],Tx); 25 | lineToTx([5,-5,0],Tx); 26 | context.closePath(); 27 | context.fill(); 28 | } 29 | 30 | function drawAxes(color,Tx) { 31 | context.strokeStyle=color; 32 | context.beginPath(); 33 | // Axes 34 | moveToTx([120,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,120,0],Tx); 35 | // Arrowheads 36 | moveToTx([110,5,0],Tx);lineToTx([120,0,0],Tx);lineToTx([110,-5,0],Tx); 37 | moveToTx([5,110,0],Tx);lineToTx([0,120,0],Tx);lineToTx([-5,110,0],Tx); 38 | // X-label 39 | moveToTx([130,0,0],Tx);lineToTx([140,10,0],Tx); 40 | moveToTx([130,10,0],Tx);lineToTx([140,0,0],Tx); 41 | context.stroke(); 42 | } 43 | 44 | var Hermite = function(t) { 45 | return [ 46 | 2*t*t*t-3*t*t+1, 47 | t*t*t-2*t*t+t, 48 | -2*t*t*t+3*t*t, 49 | t*t*t-t*t 50 | ]; 51 | } 52 | 53 | var HermiteDerivative = function(t) { 54 | return [ 55 | 6*t*t-6*t, 56 | 3*t*t-4*t+1, 57 | -6*t*t+6*t, 58 | 3*t*t-2*t 59 | ]; 60 | } 61 | 62 | function Cubic(basis,P,t){ 63 | var b = basis(t); 64 | var result=vec3.create(); 65 | vec3.scale(result,P[0],b[0]); 66 | vec3.scaleAndAdd(result,result,P[1],b[1]); 67 | vec3.scaleAndAdd(result,result,P[2],b[2]); 68 | vec3.scaleAndAdd(result,result,P[3],b[3]); 69 | return result; 70 | } 71 | 72 | var p0=[0,0,0]; 73 | var d0=[100,300,0]; 74 | var p1=[100,100,0]; 75 | var d1=[-100,300,0]; 76 | var p2=[200,200,0]; 77 | var d2=[0,300,0]; 78 | 79 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 80 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 81 | 82 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 83 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 84 | 85 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 86 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 87 | 88 | var Ccomp = function(t) { 89 | if (t<1){ 90 | var u = t; 91 | return C0(u); 92 | } else { 93 | var u = t-1.0; 94 | return C1(u); 95 | } 96 | } 97 | 98 | var Ccomp_tangent = function(t) { 99 | if (t<1){ 100 | var u = t; 101 | return C0prime(u); 102 | } else { 103 | var u = t-1.0; 104 | return C1prime(u); 105 | } 106 | } 107 | 108 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 109 | context.strokeStyle=color; 110 | context.beginPath(); 111 | moveToTx(C(t_begin),Tx); 112 | for(var i=1;i<=intervals;i++){ 113 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 114 | lineToTx(C(t),Tx); 115 | } 116 | context.stroke(); 117 | } 118 | 119 | // make sure you understand these 120 | 121 | drawAxes("black", mat4.create()); 122 | 123 | var Tblue_to_canvas = mat4.create(); 124 | mat4.fromTranslation(Tblue_to_canvas,[200,300,0]); 125 | mat4.scale(Tblue_to_canvas,Tblue_to_canvas,[1,-1,-1]); // Flip the Y-axis 126 | drawAxes("grey",Tblue_to_canvas); 127 | 128 | drawTrajectory(0.0,1.0,100,C0,Tblue_to_canvas,"red"); 129 | drawTrajectory(0.0,1.0,100,C1,Tblue_to_canvas,"blue"); 130 | 131 | var Tgreen_to_blue = mat4.create(); 132 | mat4.fromTranslation(Tgreen_to_blue,Ccomp(tParam)); 133 | var Tgreen_to_canvas = mat4.create(); 134 | var tangent = Ccomp_tangent(tParam); 135 | var angle = Math.atan2(tangent[1],tangent[0]); 136 | mat4.rotateZ(Tgreen_to_blue,Tgreen_to_blue,angle); 137 | mat4.multiply(Tgreen_to_canvas, Tblue_to_canvas, Tgreen_to_blue); 138 | drawObject("green",Tgreen_to_canvas); 139 | } 140 | 141 | slider1.addEventListener("input",draw); 142 | draw(); 143 | } 144 | window.onload = setup; 145 | -------------------------------------------------------------------------------- /Week7/Demo1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Introductory demos on 3D viewing and drawing 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Week7/Demo1/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = 0; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 0; 8 | 9 | function draw() { 10 | canvas.width = canvas.width; 11 | 12 | // use the sliders to get the angles 13 | var tParam = slider1.value*0.01; 14 | 15 | var viewAngle = slider2.value*0.02*Math.PI; 16 | var locCamera = vec3.create(); 17 | var distCamera = 400.0; 18 | locCamera[0] = distCamera*Math.sin(viewAngle); 19 | locCamera[1] = 100; 20 | locCamera[2] = distCamera*Math.cos(viewAngle); 21 | var TlookAt = mat4.create(); 22 | mat4.lookAt(TlookAt, locCamera, [0,0,0], [0,1,0]); 23 | 24 | function moveToTx(loc,Tx) 25 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.moveTo(res[0],res[1]);} 26 | 27 | function lineToTx(loc,Tx) 28 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.lineTo(res[0],res[1]);} 29 | 30 | function drawObject(color,Tx) { 31 | context.beginPath(); 32 | context.fillStyle = color; 33 | moveToTx([-5,-5,0],Tx); 34 | lineToTx([-5,5,0],Tx); 35 | lineToTx([5,5,0],Tx); 36 | lineToTx([10,0,0],Tx); 37 | lineToTx([5,-5,0],Tx); 38 | context.closePath(); 39 | context.fill(); 40 | } 41 | 42 | function drawAxes(color,Tx) { 43 | context.strokeStyle=color; 44 | context.beginPath(); 45 | // Axes 46 | moveToTx([120,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,120,0],Tx); 47 | // Arrowheads 48 | moveToTx([110,5,0],Tx);lineToTx([120,0,0],Tx);lineToTx([110,-5,0],Tx); 49 | moveToTx([5,110,0],Tx);lineToTx([0,120,0],Tx);lineToTx([-5,110,0],Tx); 50 | // X-label 51 | moveToTx([130,0,0],Tx);lineToTx([140,10,0],Tx); 52 | moveToTx([130,10,0],Tx);lineToTx([140,0,0],Tx); 53 | context.stroke(); 54 | } 55 | 56 | var Hermite = function(t) { 57 | return [ 58 | 2*t*t*t-3*t*t+1, 59 | t*t*t-2*t*t+t, 60 | -2*t*t*t+3*t*t, 61 | t*t*t-t*t 62 | ]; 63 | } 64 | 65 | var HermiteDerivative = function(t) { 66 | return [ 67 | 6*t*t-6*t, 68 | 3*t*t-4*t+1, 69 | -6*t*t+6*t, 70 | 3*t*t-2*t 71 | ]; 72 | } 73 | 74 | function Cubic(basis,P,t){ 75 | var b = basis(t); 76 | var result=vec3.create(); 77 | vec3.scale(result,P[0],b[0]); 78 | vec3.scaleAndAdd(result,result,P[1],b[1]); 79 | vec3.scaleAndAdd(result,result,P[2],b[2]); 80 | vec3.scaleAndAdd(result,result,P[3],b[3]); 81 | return result; 82 | } 83 | 84 | var p0=[0,0,0]; 85 | var d0=[100,300,0]; 86 | var p1=[100,100,0]; 87 | var d1=[-100,300,0]; 88 | var p2=[200,200,0]; 89 | var d2=[0,300,0]; 90 | 91 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 92 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 93 | 94 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 95 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 96 | 97 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 98 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 99 | 100 | var Ccomp = function(t) { 101 | if (t<1){ 102 | var u = t; 103 | return C0(u); 104 | } else { 105 | var u = t-1.0; 106 | return C1(u); 107 | } 108 | } 109 | 110 | var Ccomp_tangent = function(t) { 111 | if (t<1){ 112 | var u = t; 113 | return C0prime(u); 114 | } else { 115 | var u = t-1.0; 116 | return C1prime(u); 117 | } 118 | } 119 | 120 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 121 | context.strokeStyle=color; 122 | context.beginPath(); 123 | moveToTx(C(t_begin),Tx); 124 | for(var i=1;i<=intervals;i++){ 125 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 126 | lineToTx(C(t),Tx); 127 | } 128 | context.stroke(); 129 | } 130 | 131 | // make sure you understand these 132 | 133 | drawAxes("black", mat4.create()); 134 | 135 | 136 | var Tgrey_to_canvas = mat4.create(); 137 | mat4.fromTranslation(Tgrey_to_canvas,[200,300,0]); 138 | mat4.scale(Tgrey_to_canvas,Tgrey_to_canvas,[1,-1,-1]); // Flip the Y-axis 139 | mat4.multiply(Tgrey_to_canvas,Tgrey_to_canvas,TlookAt); 140 | drawAxes("grey",Tgrey_to_canvas); 141 | 142 | drawTrajectory(0.0,1.0,100,C0,Tgrey_to_canvas,"red"); 143 | drawTrajectory(0.0,1.0,100,C1,Tgrey_to_canvas,"blue"); 144 | 145 | var Tgreen_to_grey = mat4.create(); 146 | mat4.fromTranslation(Tgreen_to_grey,Ccomp(tParam)); 147 | var Tgreen_to_canvas = mat4.create(); 148 | var tangent = Ccomp_tangent(tParam); 149 | var angle = Math.atan2(tangent[1],tangent[0]); 150 | mat4.rotateZ(Tgreen_to_grey,Tgreen_to_grey,angle); 151 | mat4.multiply(Tgreen_to_canvas, Tgrey_to_canvas, Tgreen_to_grey); 152 | drawObject("green",Tgreen_to_canvas); 153 | } 154 | 155 | slider1.addEventListener("input",draw); 156 | slider2.addEventListener("input",draw); 157 | draw(); 158 | } 159 | window.onload = setup; 160 | 161 | -------------------------------------------------------------------------------- /Week7/Demo2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Introductory demos on 3D viewing and drawing 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Week7/Demo2/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = 0; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 0; 8 | 9 | function draw() { 10 | canvas.width = canvas.width; 11 | 12 | // use the sliders to get the angles 13 | var tParam = slider1.value*0.01; 14 | var viewAngle = slider2.value*0.02*Math.PI; 15 | 16 | 17 | function moveToTx(loc,Tx) 18 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.moveTo(res[0],res[1]);} 19 | 20 | function lineToTx(loc,Tx) 21 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.lineTo(res[0],res[1]);} 22 | 23 | function drawObject(color,Tx) { 24 | context.beginPath(); 25 | context.fillStyle = color; 26 | moveToTx([-.05,-.05,0],Tx); 27 | lineToTx([-.05,.05,0],Tx); 28 | lineToTx([.05,.05,0],Tx); 29 | lineToTx([.1,0,0],Tx); 30 | lineToTx([.05,-.05,0],Tx); 31 | context.closePath(); 32 | context.fill(); 33 | } 34 | 35 | function draw3DAxes(color,Tx) { 36 | context.strokeStyle=color; 37 | context.beginPath(); 38 | // Axes 39 | moveToTx([1.2,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,1.2,0],Tx); 40 | moveToTx([0,0,0],Tx);lineToTx([0,0,1.2],Tx); 41 | // Arrowheads 42 | moveToTx([1.1,.05,0],Tx);lineToTx([1.2,0,0],Tx);lineToTx([1.1,-.05,0],Tx); 43 | moveToTx([.05,1.1,0],Tx);lineToTx([0,1.2,0],Tx);lineToTx([-.05,1.1,0],Tx); 44 | moveToTx([.05,0,1.1],Tx);lineToTx([0,0,1.2],Tx);lineToTx([-.05,0,1.1],Tx); 45 | // X-label 46 | moveToTx([1.3,0,0],Tx);lineToTx([1.4,.1,0],Tx); 47 | moveToTx([1.3,.1,0],Tx);lineToTx([1.4,0,0],Tx); 48 | // Y-label 49 | moveToTx([0,1.35,0],Tx);lineToTx([.05,1.3,0],Tx);lineToTx([.1,1.35,0],Tx); 50 | moveToTx([.05,1.3,0],Tx);lineToTx([.05,1.23,0],Tx); 51 | 52 | context.stroke(); 53 | } 54 | 55 | function draw2DAxes(color,Tx) { 56 | context.strokeStyle=color; 57 | context.beginPath(); 58 | // Axes 59 | moveToTx([120,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,120,0],Tx); 60 | // Arrowheads 61 | moveToTx([110,5,0],Tx);lineToTx([120,0,0],Tx);lineToTx([110,-5,0],Tx); 62 | moveToTx([5,110,0],Tx);lineToTx([0,120,0],Tx);lineToTx([-5,110,0],Tx); 63 | // X-label 64 | moveToTx([130,0,0],Tx);lineToTx([140,10,0],Tx); 65 | moveToTx([130,10,0],Tx);lineToTx([140,0,0],Tx); 66 | context.stroke(); 67 | } 68 | 69 | var Hermite = function(t) { 70 | return [ 71 | 2*t*t*t-3*t*t+1, 72 | t*t*t-2*t*t+t, 73 | -2*t*t*t+3*t*t, 74 | t*t*t-t*t 75 | ]; 76 | } 77 | 78 | var HermiteDerivative = function(t) { 79 | return [ 80 | 6*t*t-6*t, 81 | 3*t*t-4*t+1, 82 | -6*t*t+6*t, 83 | 3*t*t-2*t 84 | ]; 85 | } 86 | 87 | function Cubic(basis,P,t){ 88 | var b = basis(t); 89 | var result=vec3.create(); 90 | vec3.scale(result,P[0],b[0]); 91 | vec3.scaleAndAdd(result,result,P[1],b[1]); 92 | vec3.scaleAndAdd(result,result,P[2],b[2]); 93 | vec3.scaleAndAdd(result,result,P[3],b[3]); 94 | return result; 95 | } 96 | 97 | var p0=[0,0,0]; 98 | var d0=[1,3,0]; 99 | var p1=[1,1,0]; 100 | var d1=[-1,3,0]; 101 | var p2=[2,2,0]; 102 | var d2=[0,3,0]; 103 | 104 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 105 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 106 | 107 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 108 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 109 | 110 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 111 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 112 | 113 | var Ccomp = function(t) { 114 | if (t<1){ 115 | var u = t; 116 | return C0(u); 117 | } else { 118 | var u = t-1.0; 119 | return C1(u); 120 | } 121 | } 122 | 123 | var Ccomp_tangent = function(t) { 124 | if (t<1){ 125 | var u = t; 126 | return C0prime(u); 127 | } else { 128 | var u = t-1.0; 129 | return C1prime(u); 130 | } 131 | } 132 | 133 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 134 | context.strokeStyle=color; 135 | context.beginPath(); 136 | moveToTx(C(t_begin),Tx); 137 | for(var i=1;i<=intervals;i++){ 138 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 139 | lineToTx(C(t),Tx); 140 | } 141 | context.stroke(); 142 | } 143 | 144 | // make sure you understand these 145 | 146 | draw2DAxes("black", mat4.create()); 147 | 148 | // Create ViewPort transform 149 | var Tviewport = mat4.create(); 150 | mat4.fromTranslation(Tviewport,[200,300,0]); // Move the center of the 151 | // "lookAt" transform (where 152 | // the camera points) to the 153 | // canvas coordinates (200,300) 154 | mat4.scale(Tviewport,Tviewport,[100,-100,1]); // Flip the Y-axis, 155 | // scale everything by 100x 156 | // draw3DAxes("brown",Tviewport); // Uncomment this to see the "camera" coords 157 | 158 | // Create Camera (lookAt) transform 159 | var locCamera = vec3.create(); 160 | var distCamera = 400.0; 161 | locCamera[0] = distCamera*Math.sin(viewAngle); 162 | locCamera[1] = 100; 163 | locCamera[2] = distCamera*Math.cos(viewAngle); 164 | var locTarget = vec3.fromValues(0,0,0); // Aim at the origin of the world coords 165 | var vecUp = vec3.fromValues(0,1,0); 166 | var TlookAt = mat4.create(); 167 | mat4.lookAt(TlookAt, locCamera, locTarget, vecUp); 168 | 169 | 170 | // Create transform t_VP_CAM that incorporates 171 | // Viewport and Camera transformations 172 | var tVP_CAM = mat4.create(); 173 | mat4.multiply(tVP_CAM,Tviewport,TlookAt); 174 | draw3DAxes("grey",tVP_CAM); 175 | 176 | drawTrajectory(0.0,1.0,100,C0,tVP_CAM,"red"); 177 | drawTrajectory(0.0,1.0,100,C1,tVP_CAM,"blue"); 178 | 179 | // Create model(ing) transform 180 | // (from moving object to world) 181 | var Tmodel = mat4.create(); 182 | mat4.fromTranslation(Tmodel,Ccomp(tParam)); 183 | var tangent = Ccomp_tangent(tParam); 184 | var angle = Math.atan2(tangent[1],tangent[0]); 185 | mat4.rotateZ(Tmodel,Tmodel,angle); 186 | 187 | // Create transform t_VP_CAM_MOD that incorporates 188 | // Viewport, camera, and modeling transform 189 | var tVP_CAM_MOD = mat4.create(); 190 | mat4.multiply(tVP_CAM_MOD, tVP_CAM, Tmodel); 191 | // draw3DAxes("green", tVP_CAM_MOD); // Uncomment to see "model" coords 192 | drawObject("green",tVP_CAM_MOD); 193 | } 194 | 195 | slider1.addEventListener("input",draw); 196 | slider2.addEventListener("input",draw); 197 | draw(); 198 | } 199 | window.onload = setup; 200 | 201 | 202 | -------------------------------------------------------------------------------- /Week7/Demo3/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Introductory demos on 3D viewing and drawing 5 | 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Week7/Demo3/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var canvas = document.getElementById('myCanvas'); 3 | var context = canvas.getContext('2d'); 4 | var slider1 = document.getElementById('slider1'); 5 | slider1.value = 0; 6 | var slider2 = document.getElementById('slider2'); 7 | slider2.value = 0; 8 | 9 | function draw() { 10 | canvas.width = canvas.width; 11 | 12 | // use the sliders to get the angles 13 | var tParam = slider1.value*0.01; 14 | var viewAngle = slider2.value*0.02*Math.PI; 15 | 16 | 17 | function moveToTx(loc,Tx) 18 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.moveTo(res[0],res[1]);} 19 | 20 | function lineToTx(loc,Tx) 21 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.lineTo(res[0],res[1]);} 22 | 23 | function drawObject(color,Tx) { 24 | context.beginPath(); 25 | context.fillStyle = color; 26 | moveToTx([-.5,-.5,0],Tx); 27 | lineToTx([-.5,.5,0],Tx); 28 | lineToTx([.5,.5,0],Tx); 29 | lineToTx([1,0,0],Tx); 30 | lineToTx([.5,-.5,0],Tx); 31 | context.closePath(); 32 | context.fill(); 33 | } 34 | 35 | function draw3DAxes(color,Tx) { 36 | context.strokeStyle=color; 37 | context.beginPath(); 38 | // Axes 39 | moveToTx([12,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,12,0],Tx); 40 | moveToTx([0,0,0],Tx);lineToTx([0,0,12],Tx); 41 | // Arrowheads 42 | moveToTx([11,.5,0],Tx);lineToTx([12,0,0],Tx);lineToTx([11,-.5,0],Tx); 43 | moveToTx([.5,11,0],Tx);lineToTx([0,12,0],Tx);lineToTx([-.5,11,0],Tx); 44 | moveToTx([.5,0,11],Tx);lineToTx([0,0,12],Tx);lineToTx([-.5,0,11],Tx); 45 | // X-label 46 | moveToTx([13,0,0],Tx);lineToTx([14,1,0],Tx); 47 | moveToTx([13,1,0],Tx);lineToTx([14,0,0],Tx); 48 | // Y-label 49 | moveToTx([0,13.5,0],Tx);lineToTx([.5,13,0],Tx);lineToTx([1,13.5,0],Tx); 50 | moveToTx([.5,13,0],Tx);lineToTx([.5,12.3,0],Tx); 51 | 52 | context.stroke(); 53 | } 54 | 55 | function draw2DAxes(color,Tx) { 56 | context.strokeStyle=color; 57 | context.beginPath(); 58 | // Axes 59 | moveToTx([120,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,120,0],Tx); 60 | // Arrowheads 61 | moveToTx([110,5,0],Tx);lineToTx([120,0,0],Tx);lineToTx([110,-5,0],Tx); 62 | moveToTx([5,110,0],Tx);lineToTx([0,120,0],Tx);lineToTx([-5,110,0],Tx); 63 | // X-label 64 | moveToTx([130,0,0],Tx);lineToTx([140,10,0],Tx); 65 | moveToTx([130,10,0],Tx);lineToTx([140,0,0],Tx); 66 | context.stroke(); 67 | } 68 | 69 | var Hermite = function(t) { 70 | return [ 71 | 2*t*t*t-3*t*t+1, 72 | t*t*t-2*t*t+t, 73 | -2*t*t*t+3*t*t, 74 | t*t*t-t*t 75 | ]; 76 | } 77 | 78 | var HermiteDerivative = function(t) { 79 | return [ 80 | 6*t*t-6*t, 81 | 3*t*t-4*t+1, 82 | -6*t*t+6*t, 83 | 3*t*t-2*t 84 | ]; 85 | } 86 | 87 | function Cubic(basis,P,t){ 88 | var b = basis(t); 89 | var result=vec3.create(); 90 | vec3.scale(result,P[0],b[0]); 91 | vec3.scaleAndAdd(result,result,P[1],b[1]); 92 | vec3.scaleAndAdd(result,result,P[2],b[2]); 93 | vec3.scaleAndAdd(result,result,P[3],b[3]); 94 | return result; 95 | } 96 | 97 | var p0=[0,0,0]; 98 | var d0=[10,30,0]; 99 | var p1=[10,10,0]; 100 | var d1=[-10,30,0]; 101 | var p2=[20,20,0]; 102 | var d2=[0,30,0]; 103 | 104 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 105 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 106 | 107 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 108 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 109 | 110 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 111 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 112 | 113 | var Ccomp = function(t) { 114 | if (t<1){ 115 | var u = t; 116 | return C0(u); 117 | } else { 118 | var u = t-1.0; 119 | return C1(u); 120 | } 121 | } 122 | 123 | var Ccomp_tangent = function(t) { 124 | if (t<1){ 125 | var u = t; 126 | return C0prime(u); 127 | } else { 128 | var u = t-1.0; 129 | return C1prime(u); 130 | } 131 | } 132 | 133 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 134 | context.strokeStyle=color; 135 | context.beginPath(); 136 | moveToTx(C(t_begin),Tx); 137 | for(var i=1;i<=intervals;i++){ 138 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 139 | lineToTx(C(t),Tx); 140 | } 141 | context.stroke(); 142 | } 143 | 144 | // make sure you understand these 145 | 146 | draw2DAxes("black", mat4.create()); 147 | 148 | // Create ViewPort transform 149 | var Tviewport = mat4.create(); 150 | mat4.fromTranslation(Tviewport,[200,300,0]); // Move the center of the 151 | // "lookAt" transform (where 152 | // the camera points) to the 153 | // canvas coordinates (200,300) 154 | mat4.scale(Tviewport,Tviewport,[100,-100,1]); // Flip the Y-axis, 155 | // scale everything by 100x 156 | 157 | // Create projection transform 158 | // (orthographic for now) 159 | var Tprojection = mat4.create(); 160 | mat4.ortho(Tprojection,-10,10,-10,10,-1,1); 161 | // mat4.perspective(Tprojection,Math.PI/5,1,-1,1); // Use for perspective teaser! 162 | 163 | // Combined transform for viewport and projection 164 | var tVP_PROJ = mat4.create(); 165 | mat4.multiply(tVP_PROJ,Tviewport,Tprojection); 166 | //draw3DAxes("brown",tVP_PROJ); // Uncomment this to see the "camera" coords 167 | 168 | // Create Camera (lookAt) transform 169 | var locCamera = vec3.create(); 170 | var distCamera = 40.0; 171 | locCamera[0] = distCamera*Math.sin(viewAngle); 172 | locCamera[1] = 10; 173 | locCamera[2] = distCamera*Math.cos(viewAngle); 174 | var locTarget = vec3.fromValues(0,0,0); // Aim at the origin of the world coords 175 | var vecUp = vec3.fromValues(0,1,0); 176 | var TlookAt = mat4.create(); 177 | mat4.lookAt(TlookAt, locCamera, locTarget, vecUp); 178 | 179 | 180 | // Create transform t_VP_CAM that incorporates 181 | // Viewport and Camera transformations 182 | var tVP_PROJ_CAM = mat4.create(); 183 | mat4.multiply(tVP_PROJ_CAM,tVP_PROJ,TlookAt); 184 | draw3DAxes("grey",tVP_PROJ_CAM); 185 | 186 | drawTrajectory(0.0,1.0,100,C0,tVP_PROJ_CAM,"red"); 187 | drawTrajectory(0.0,1.0,100,C1,tVP_PROJ_CAM,"blue"); 188 | 189 | // Create model(ing) transform 190 | // (from moving object to world) 191 | var Tmodel = mat4.create(); 192 | mat4.fromTranslation(Tmodel,Ccomp(tParam)); 193 | var tangent = Ccomp_tangent(tParam); 194 | var angle = Math.atan2(tangent[1],tangent[0]); 195 | mat4.rotateZ(Tmodel,Tmodel,angle); 196 | 197 | // Create transform t_VP_CAM_MOD that incorporates 198 | // Viewport, camera, and modeling transform 199 | var tVP_PROJ_CAM_MOD = mat4.create(); 200 | mat4.multiply(tVP_PROJ_CAM_MOD, tVP_PROJ_CAM, Tmodel); 201 | // draw3DAxes("green", tVP_PROJ_CAM_MOD); // Uncomment to see "model" coords 202 | drawObject("green",tVP_PROJ_CAM_MOD); 203 | } 204 | 205 | slider1.addEventListener("input",draw); 206 | slider2.addEventListener("input",draw); 207 | draw(); 208 | } 209 | window.onload = setup; 210 | 211 | -------------------------------------------------------------------------------- /Week7/Demo4/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Visualization of viewing transforms and associated coordinate systems 5 | 6 | 7 | [Left window] View by a remote external observer; [Right window] View from location of the camera
8 | 9 | 10 |
11 | Move object along curve 12 |
13 | Move camera around scene 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Week7/Demo4/demo.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | var observerCanvas = document.getElementById('observerCanvas'); 3 | var cameraCanvas = document.getElementById('cameraCanvas'); 4 | var observerContext = observerCanvas.getContext('2d'); 5 | var cameraContext = cameraCanvas.getContext('2d'); 6 | var slider1 = document.getElementById('slider1'); 7 | slider1.value = 0; 8 | var slider2 = document.getElementById('slider2'); 9 | slider2.value = 0; 10 | 11 | var context = cameraContext; // default to drawing in the camera window 12 | 13 | function draw() { 14 | 15 | // clear both canvas instances 16 | observerCanvas.width = observerCanvas.width; 17 | cameraCanvas.width = cameraCanvas.width; 18 | 19 | // use the sliders to get the angles 20 | var tParam = slider1.value*0.01; 21 | var viewAngle = slider2.value*0.02*Math.PI; 22 | 23 | function moveToTx(loc,Tx) 24 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.moveTo(res[0],res[1]);} 25 | 26 | function lineToTx(loc,Tx) 27 | {var res=vec3.create(); vec3.transformMat4(res,loc,Tx); context.lineTo(res[0],res[1]);} 28 | 29 | function drawObject(color,TxU,scale) { 30 | var Tx = mat4.clone(TxU); 31 | mat4.scale(Tx,Tx,[scale,scale,scale]); 32 | context.beginPath(); 33 | context.fillStyle = color; 34 | moveToTx([-.05,-.05,0],Tx); 35 | lineToTx([-.05,.05,0],Tx); 36 | lineToTx([.05,.05,0],Tx); 37 | lineToTx([.1,0,0],Tx); 38 | lineToTx([.05,-.05,0],Tx); 39 | context.closePath(); 40 | context.fill(); 41 | } 42 | 43 | function drawCamera(color,TxU,scale) { 44 | var Tx = mat4.clone(TxU); 45 | mat4.scale(Tx,Tx,[scale,scale,scale]); 46 | context.beginPath(); 47 | context.strokeStyle = color; 48 | // Twelve edges of a cropped pyramid 49 | moveToTx([-3,-3,-2],Tx);lineToTx([3,-3,-2],Tx); 50 | lineToTx([3,3,-2],Tx);lineToTx([-3,3,-2],Tx); 51 | moveToTx([3,-3,-2],Tx);lineToTx([2,-2,0],Tx); 52 | lineToTx([2,2,0],Tx);lineToTx([3,3,-2],Tx); 53 | moveToTx([2,-2,0],Tx);lineToTx([-2,-2,0],Tx); 54 | lineToTx([-2,2,0],Tx);lineToTx([2,2,0],Tx); 55 | moveToTx([-2,-2,0],Tx);lineToTx([-3,-3,-2],Tx); 56 | lineToTx([-3,3,-2],Tx);lineToTx([-2,2,0],Tx); 57 | context.stroke(); 58 | } 59 | 60 | function draw3DAxes(color,TxU,scale) { 61 | var Tx = mat4.clone(TxU); 62 | mat4.scale(Tx,Tx,[scale,scale,scale]); 63 | 64 | context.strokeStyle=color; 65 | context.beginPath(); 66 | // Axes 67 | moveToTx([1.2,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,1.2,0],Tx); 68 | moveToTx([0,0,0],Tx);lineToTx([0,0,1.2],Tx); 69 | // Arrowheads 70 | moveToTx([1.1,.05,0],Tx);lineToTx([1.2,0,0],Tx);lineToTx([1.1,-.05,0],Tx); 71 | moveToTx([.05,1.1,0],Tx);lineToTx([0,1.2,0],Tx);lineToTx([-.05,1.1,0],Tx); 72 | moveToTx([.05,0,1.1],Tx);lineToTx([0,0,1.2],Tx);lineToTx([-.05,0,1.1],Tx); 73 | // X-label 74 | moveToTx([1.3,-.05,0],Tx);lineToTx([1.4,.05,0],Tx); 75 | moveToTx([1.3,.05,0],Tx);lineToTx([1.4,-.05,0],Tx); 76 | // Y-label 77 | moveToTx([-.05,1.4,0],Tx);lineToTx([0,1.35,0],Tx);lineToTx([.05,1.4,0],Tx); 78 | moveToTx([0,1.35,0],Tx);lineToTx([0,1.28,0],Tx); 79 | // Z-label 80 | moveToTx([-.05,0,1.3],Tx); 81 | lineToTx([.05,0,1.3],Tx); 82 | lineToTx([-.05,0,1.4],Tx); 83 | lineToTx([.05,0,1.4],Tx); 84 | 85 | context.stroke(); 86 | } 87 | 88 | function drawUVWAxes(color,TxU,scale) { 89 | var Tx = mat4.clone(TxU); 90 | mat4.scale(Tx,Tx,[scale,scale,scale]); 91 | 92 | context.strokeStyle=color; 93 | context.beginPath(); 94 | // Axes 95 | moveToTx([1.2,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,1.2,0],Tx); 96 | moveToTx([0,0,0],Tx);lineToTx([0,0,1.2],Tx); 97 | // Arrowheads 98 | moveToTx([1.1,.05,0],Tx);lineToTx([1.2,0,0],Tx);lineToTx([1.1,-.05,0],Tx); 99 | moveToTx([.05,1.1,0],Tx);lineToTx([0,1.2,0],Tx);lineToTx([-.05,1.1,0],Tx); 100 | moveToTx([.05,0,1.1],Tx);lineToTx([0,0,1.2],Tx);lineToTx([-.05,0,1.1],Tx); 101 | // U-label 102 | moveToTx([1.3,.05,0],Tx);lineToTx([1.3,-.035,0],Tx);lineToTx([1.35,-.05,0],Tx); 103 | lineToTx([1.4,-.035,0],Tx);lineToTx([1.4,.05,0],Tx); 104 | // V-label 105 | moveToTx([-.05,1.4,0],Tx);lineToTx([0,1.3,0],Tx);lineToTx([.05,1.4,0],Tx); 106 | // W-label 107 | moveToTx([-.1,0,1.3],Tx);lineToTx([-.05,0,1.4],Tx);lineToTx([-0,0,1.3],Tx); 108 | lineToTx([.05,0,1.4],Tx);lineToTx([.1,0,1.3],Tx); 109 | 110 | context.stroke(); 111 | } 112 | 113 | function draw2DAxes(color,Tx) { 114 | context.strokeStyle=color; 115 | context.beginPath(); 116 | // Axes 117 | moveToTx([120,0,0],Tx);lineToTx([0,0,0],Tx);lineToTx([0,120,0],Tx); 118 | // Arrowheads 119 | moveToTx([110,5,0],Tx);lineToTx([120,0,0],Tx);lineToTx([110,-5,0],Tx); 120 | moveToTx([5,110,0],Tx);lineToTx([0,120,0],Tx);lineToTx([-5,110,0],Tx); 121 | // X-label 122 | moveToTx([130,0,0],Tx);lineToTx([140,10,0],Tx); 123 | moveToTx([130,10,0],Tx);lineToTx([140,0,0],Tx); 124 | // Y-label 125 | moveToTx([0,128,0],Tx);lineToTx([5,133,0],Tx);lineToTx([10,128,0],Tx); 126 | moveToTx([5,133,0],Tx);lineToTx([5,140,0],Tx); 127 | context.stroke(); 128 | } 129 | 130 | function drawUpVector(color,vecUp,Tx) { 131 | context.strokeStyle=color; 132 | context.beginPath(); 133 | // A single line segment in the "up" direction 134 | moveToTx([0,0,0],Tx); 135 | lineToTx(vecUp,Tx); 136 | context.stroke(); 137 | } 138 | var Hermite = function(t) { 139 | return [ 140 | 2*t*t*t-3*t*t+1, 141 | t*t*t-2*t*t+t, 142 | -2*t*t*t+3*t*t, 143 | t*t*t-t*t 144 | ]; 145 | } 146 | 147 | var HermiteDerivative = function(t) { 148 | return [ 149 | 6*t*t-6*t, 150 | 3*t*t-4*t+1, 151 | -6*t*t+6*t, 152 | 3*t*t-2*t 153 | ]; 154 | } 155 | 156 | function Cubic(basis,P,t){ 157 | var b = basis(t); 158 | var result=vec3.create(); 159 | vec3.scale(result,P[0],b[0]); 160 | vec3.scaleAndAdd(result,result,P[1],b[1]); 161 | vec3.scaleAndAdd(result,result,P[2],b[2]); 162 | vec3.scaleAndAdd(result,result,P[3],b[3]); 163 | return result; 164 | } 165 | 166 | var p0=[0,0,0]; 167 | var d0=[100,300,0]; 168 | var p1=[100,100,0]; 169 | var d1=[-100,300,0]; 170 | var p2=[200,200,0]; 171 | var d2=[0,300,0]; 172 | 173 | var P0 = [p0,d0,p1,d1]; // First two points and tangents 174 | var P1 = [p1,d1,p2,d2]; // Last two points and tangents 175 | 176 | var C0 = function(t_) {return Cubic(Hermite,P0,t_);}; 177 | var C1 = function(t_) {return Cubic(Hermite,P1,t_);}; 178 | 179 | var C0prime = function(t_) {return Cubic(HermiteDerivative,P0,t_);}; 180 | var C1prime = function(t_) {return Cubic(HermiteDerivative,P1,t_);}; 181 | 182 | var Ccomp = function(t) { 183 | if (t<1){ 184 | var u = t; 185 | return C0(u); 186 | } else { 187 | var u = t-1.0; 188 | return C1(u); 189 | } 190 | } 191 | 192 | var Ccomp_tangent = function(t) { 193 | if (t<1){ 194 | var u = t; 195 | return C0prime(u); 196 | } else { 197 | var u = t-1.0; 198 | return C1prime(u); 199 | } 200 | } 201 | 202 | var CameraCurve = function(angle) { 203 | var distance = 120.0; 204 | var eye = vec3.create(); 205 | eye[0] = distance*Math.sin(viewAngle); 206 | eye[1] = 100; 207 | eye[2] = distance*Math.cos(viewAngle); 208 | return [eye[0],eye[1],eye[2]]; 209 | } 210 | 211 | function drawTrajectory(t_begin,t_end,intervals,C,Tx,color) { 212 | context.strokeStyle=color; 213 | context.beginPath(); 214 | moveToTx(C(t_begin),Tx); 215 | for(var i=1;i<=intervals;i++){ 216 | var t=((intervals-i)/intervals)*t_begin+(i/intervals)*t_end; 217 | lineToTx(C(t),Tx); 218 | } 219 | context.stroke(); 220 | } 221 | 222 | // create two lookAt transforms; one for the camera 223 | // and one for the "external observer" 224 | 225 | // Create Camera (lookAt) transform 226 | var eyeCamera = CameraCurve(viewAngle); 227 | var targetCamera = vec3.fromValues(0,0,0); // Aim at the origin of the world coords 228 | var upCamera = vec3.fromValues(0,100,0); // Y-axis of world coords to be vertical 229 | var TlookAtCamera = mat4.create(); 230 | mat4.lookAt(TlookAtCamera, eyeCamera, targetCamera, upCamera); 231 | 232 | // Create Camera (lookAt) transform 233 | var eyeObserver = vec3.fromValues(500,300,500); 234 | var targetObserver = vec3.fromValues(0,50,0); // Observer still looks at origin 235 | var upObserver = vec3.fromValues(0,1,0); // Y-axis of world coords to be vertical 236 | var TlookAtObserver = mat4.create(); 237 | mat4.lookAt(TlookAtObserver, eyeObserver, targetObserver, upObserver); 238 | 239 | // Create ViewPort transform (assumed the same for both canvas instances) 240 | var Tviewport = mat4.create(); 241 | mat4.fromTranslation(Tviewport,[200,300,0]); // Move the center of the 242 | // "lookAt" transform (where 243 | // the camera points) to the 244 | // canvas coordinates (200,300) 245 | mat4.scale(Tviewport,Tviewport,[100,-100,1]); // Flip the Y-axis, 246 | // scale everything by 100x 247 | // make sure you understand these 248 | 249 | context = cameraContext; 250 | 251 | // Create Camera projection transform 252 | // (orthographic for now) 253 | var TprojectionCamera = mat4.create(); 254 | mat4.ortho(TprojectionCamera,-100,100,-100,100,-1,1); 255 | //mat4.perspective(TprojectionCamera,Math.PI/4,1,-1,1); // Use for perspective teaser! 256 | 257 | // Create Observer projection transform 258 | // (orthographic for now) 259 | var TprojectionObserver = mat4.create(); 260 | mat4.ortho(TprojectionObserver,-120,120,-120,120,-1,1); 261 | 262 | // Create transform t_VP_PROJ_CAM that incorporates 263 | // Viewport, projection and camera transforms 264 | var tVP_PROJ_VIEW_Camera = mat4.create(); 265 | mat4.multiply(tVP_PROJ_VIEW_Camera,Tviewport,TprojectionCamera); 266 | mat4.multiply(tVP_PROJ_VIEW_Camera,tVP_PROJ_VIEW_Camera,TlookAtCamera); 267 | var tVP_PROJ_VIEW_Observer = mat4.create(); 268 | mat4.multiply(tVP_PROJ_VIEW_Observer,Tviewport,TprojectionObserver); 269 | mat4.multiply(tVP_PROJ_VIEW_Observer,tVP_PROJ_VIEW_Observer,TlookAtObserver); 270 | 271 | // Create model(ing) transform 272 | // (from moving object to world) 273 | var Tmodel = mat4.create(); 274 | mat4.fromTranslation(Tmodel,Ccomp(tParam)); 275 | var tangent = Ccomp_tangent(tParam); 276 | var angle = Math.atan2(tangent[1],tangent[0]); 277 | mat4.rotateZ(Tmodel,Tmodel,angle); 278 | 279 | // Create transform t_VP_PROJ_VIEW_MOD that incorporates 280 | // Viewport, projection, camera, and modeling transform 281 | var tVP_PROJ_VIEW_MOD_Camera = mat4.create(); 282 | mat4.multiply(tVP_PROJ_VIEW_MOD_Camera, tVP_PROJ_VIEW_Camera, Tmodel); 283 | var tVP_PROJ_VIEW_MOD1_Observer = mat4.create(); 284 | mat4.multiply(tVP_PROJ_VIEW_MOD1_Observer, tVP_PROJ_VIEW_Observer, Tmodel); 285 | var tVP_PROJ_VIEW_MOD2_Observer = mat4.create(); 286 | mat4.translate(tVP_PROJ_VIEW_MOD2_Observer, tVP_PROJ_VIEW_Observer, eyeCamera); 287 | var TlookFromCamera = mat4.create(); 288 | mat4.invert(TlookFromCamera,TlookAtCamera); 289 | mat4.multiply(tVP_PROJ_VIEW_MOD2_Observer, tVP_PROJ_VIEW_MOD2_Observer, TlookFromCamera); 290 | 291 | // Draw the following in the Camera window 292 | context = cameraContext; 293 | draw2DAxes("black", mat4.create()); 294 | draw3DAxes("grey",tVP_PROJ_VIEW_Camera,100.0); 295 | // drawUpVector("orange",upCamera,tVP_PROJ_VIEW_Camera,1.0); 296 | drawTrajectory(0.0,1.0,100,C0,tVP_PROJ_VIEW_Camera,"red"); 297 | drawTrajectory(0.0,1.0,100,C1,tVP_PROJ_VIEW_Camera,"blue"); 298 | // draw3DAxes("green", tVP_PROJ_VIEW_MOD_Camera,100.0); // Uncomment to see "model" coords 299 | drawObject("green",tVP_PROJ_VIEW_MOD_Camera,100.0); 300 | 301 | // Draw the following in the Observer window 302 | context = observerContext; 303 | draw3DAxes("grey",tVP_PROJ_VIEW_Observer,100.0); 304 | // drawUpVector("orange",upCamera,tVP_PROJ_VIEW_Observer,1.0); 305 | drawTrajectory(0.0,1.0,100,C0,tVP_PROJ_VIEW_Observer,"red"); 306 | drawTrajectory(0.0,1.0,100,C1,tVP_PROJ_VIEW_Observer,"blue"); 307 | drawObject("green",tVP_PROJ_VIEW_MOD1_Observer,100.0); 308 | drawCamera("purple",tVP_PROJ_VIEW_MOD2_Observer,10.0); 309 | drawUVWAxes("purple",tVP_PROJ_VIEW_MOD2_Observer,100.0); 310 | } 311 | 312 | 313 | slider1.addEventListener("input",draw); 314 | slider2.addEventListener("input",draw); 315 | draw(); 316 | } 317 | window.onload = setup; 318 | --------------------------------------------------------------------------------