├── blank.cur ├── flotr ├── flotr-min.js ├── flotr.css ├── flotr.js └── lib │ ├── base64.js │ ├── canvas2image.js │ ├── canvastext.js │ ├── excanvas.js │ └── prototype.js ├── images ├── destroy.png └── tablesort │ ├── down.gif │ └── up.gif ├── js ├── rand.js └── test-helper.js ├── libs ├── CanvasMatrix │ ├── CanvasMatrix.html │ └── CanvasMatrix.js ├── EWGL_math │ ├── EWGL_math.html │ └── EWGL_math.js ├── Sylvester │ ├── Sylvester.html │ ├── benchmark.js │ └── sylvester.js ├── closure │ ├── closure.html │ └── goog │ │ ├── base.js │ │ ├── deps.js │ │ └── vec │ │ ├── float32array.js │ │ ├── mat3.js │ │ ├── mat4.js │ │ ├── matrix3.js │ │ ├── matrix4.js │ │ ├── quaternion.js │ │ ├── ray.js │ │ ├── vec.js │ │ ├── vec3.js │ │ └── vec4.js ├── glMatrix │ ├── gl-matrix.js │ └── glMatrix.html ├── mjs │ ├── mjs.html │ └── mjs.js └── tdl │ ├── tdl-fast.html │ ├── tdl-math.html │ └── tdl │ ├── base.js │ ├── fast.js │ ├── log.js │ ├── math.js │ └── string.js ├── matrix_benchmark.html ├── readme.md ├── sprintf.js └── table ├── fastinit.js ├── table.css └── tablesort.js /blank.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/blank.cur -------------------------------------------------------------------------------- /flotr/flotr-min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/flotr/flotr-min.js -------------------------------------------------------------------------------- /flotr/flotr.css: -------------------------------------------------------------------------------- 1 | 2 | .flotr-datagrid-container { 3 | border: 1px solid #999; 4 | border-bottom: none; 5 | background: #fff; 6 | } 7 | .flotr-datagrid { 8 | border-collapse: collapse; 9 | border-spacing: 0; 10 | } 11 | .flotr-datagrid td, .flotr-datagrid th { 12 | border: 1px solid #ccc; 13 | padding: 1px 3px; 14 | min-width: 2em; 15 | } 16 | .flotr-datagrid tr:hover, .flotr-datagrid col.hover { 17 | background: #f3f3f3; 18 | } 19 | .flotr-datagrid tr:hover th, .flotr-datagrid th.hover { 20 | background: #999; 21 | color: #fff; 22 | } 23 | .flotr-datagrid th { 24 | text-align: left; 25 | background: #e3e3e3; 26 | border: 2px outset #fff; 27 | } 28 | .flotr-datagrid-toolbar { 29 | padding: 1px; 30 | border-bottom: 1px solid #ccc; 31 | background: #f9f9f9; 32 | } 33 | .flotr-datagrid td:hover { 34 | background: #ccc; 35 | } 36 | .flotr-datagrid .first-row th { 37 | text-align: center; 38 | } 39 | .flotr-canvas { 40 | margin-bottom: -3px; 41 | padding-bottom: 1px; 42 | } 43 | .flotr-tabs-group { 44 | border-top: 1px solid #999; 45 | } 46 | .flotr-tab { 47 | border: 1px solid #666; 48 | border-top: none; 49 | margin: 0 3px; 50 | padding: 1px 4px; 51 | cursor: pointer; 52 | -moz-border-radius: 0 0 4px 4px; 53 | -webkit-border-bottom-left-radius: 4px; 54 | -webkit-border-bottom-right-radius: 4px; 55 | border-radius: 0 0 4px 4px; 56 | opacity: 0.5; 57 | -moz-opacity: 0.5; 58 | } 59 | .flotr-tab.selected { 60 | background: #ddd; 61 | opacity: 1; 62 | -moz-opacity: 1; 63 | } 64 | .flotr-tab:hover { 65 | background: #ccc; 66 | } -------------------------------------------------------------------------------- /flotr/flotr.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/flotr/flotr.js -------------------------------------------------------------------------------- /flotr/lib/base64.js: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Masanao Izumo 2 | * Version: 1.0 3 | * LastModified: Dec 25 1999 4 | * This library is free. You can redistribute it and/or modify it. 5 | */ 6 | 7 | /* 8 | * Interfaces: 9 | * b64 = base64encode(data); 10 | * data = base64decode(b64); 11 | */ 12 | 13 | (function() { 14 | 15 | var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 16 | var base64DecodeChars = [ 17 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 20 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 21 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 22 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 23 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 24 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; 25 | 26 | function base64encode(str) { 27 | var out, i, len; 28 | var c1, c2, c3; 29 | 30 | len = str.length; 31 | i = 0; 32 | out = ""; 33 | while(i < len) { 34 | c1 = str.charCodeAt(i++) & 0xff; 35 | if(i == len) 36 | { 37 | out += base64EncodeChars.charAt(c1 >> 2); 38 | out += base64EncodeChars.charAt((c1 & 0x3) << 4); 39 | out += "=="; 40 | break; 41 | } 42 | c2 = str.charCodeAt(i++); 43 | if(i == len) 44 | { 45 | out += base64EncodeChars.charAt(c1 >> 2); 46 | out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); 47 | out += base64EncodeChars.charAt((c2 & 0xF) << 2); 48 | out += "="; 49 | break; 50 | } 51 | c3 = str.charCodeAt(i++); 52 | out += base64EncodeChars.charAt(c1 >> 2); 53 | out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); 54 | out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)); 55 | out += base64EncodeChars.charAt(c3 & 0x3F); 56 | } 57 | return out; 58 | } 59 | 60 | function base64decode(str) { 61 | var c1, c2, c3, c4; 62 | var i, len, out; 63 | 64 | len = str.length; 65 | i = 0; 66 | out = ""; 67 | while(i < len) { 68 | /* c1 */ 69 | do { 70 | c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; 71 | } while(i < len && c1 == -1); 72 | if(c1 == -1) 73 | break; 74 | 75 | /* c2 */ 76 | do { 77 | c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; 78 | } while(i < len && c2 == -1); 79 | if(c2 == -1) 80 | break; 81 | 82 | out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); 83 | 84 | /* c3 */ 85 | do { 86 | c3 = str.charCodeAt(i++) & 0xff; 87 | if(c3 == 61) 88 | return out; 89 | c3 = base64DecodeChars[c3]; 90 | } while(i < len && c3 == -1); 91 | if(c3 == -1) 92 | break; 93 | 94 | out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); 95 | 96 | /* c4 */ 97 | do { 98 | c4 = str.charCodeAt(i++) & 0xff; 99 | if(c4 == 61) 100 | return out; 101 | c4 = base64DecodeChars[c4]; 102 | } while(i < len && c4 == -1); 103 | if(c4 == -1) 104 | break; 105 | out += String.fromCharCode(((c3 & 0x03) << 6) | c4); 106 | } 107 | return out; 108 | } 109 | 110 | if (!window.btoa) window.btoa = base64encode; 111 | if (!window.atob) window.atob = base64decode; 112 | 113 | })(); -------------------------------------------------------------------------------- /flotr/lib/canvas2image.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Canvas2Image v0.1 3 | * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com 4 | * MIT License [http://www.opensource.org/licenses/mit-license.php] 5 | */ 6 | 7 | var Canvas2Image = (function() { 8 | // check if we have canvas support 9 | var oCanvas = document.createElement("canvas"), 10 | sc = String.fromCharCode, 11 | strDownloadMime = "image/octet-stream", 12 | bReplaceDownloadMime = false; 13 | 14 | // no canvas, bail out. 15 | if (!oCanvas.getContext) { 16 | return { 17 | saveAsBMP : function(){}, 18 | saveAsPNG : function(){}, 19 | saveAsJPEG : function(){} 20 | } 21 | } 22 | 23 | var bHasImageData = !!(oCanvas.getContext("2d").getImageData), 24 | bHasDataURL = !!(oCanvas.toDataURL), 25 | bHasBase64 = !!(window.btoa); 26 | 27 | // ok, we're good 28 | var readCanvasData = function(oCanvas) { 29 | var iWidth = parseInt(oCanvas.width), 30 | iHeight = parseInt(oCanvas.height); 31 | return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight); 32 | } 33 | 34 | // base64 encodes either a string or an array of charcodes 35 | var encodeData = function(data) { 36 | var i, aData, strData = ""; 37 | 38 | if (typeof data == "string") { 39 | strData = data; 40 | } else { 41 | aData = data; 42 | for (i = 0; i < aData.length; i++) { 43 | strData += sc(aData[i]); 44 | } 45 | } 46 | return btoa(strData); 47 | } 48 | 49 | // creates a base64 encoded string containing BMP data takes an imagedata object as argument 50 | var createBMP = function(oData) { 51 | var strHeader = '', 52 | iWidth = oData.width, 53 | iHeight = oData.height; 54 | 55 | strHeader += 'BM'; 56 | 57 | var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes 58 | strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); 59 | strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); 60 | strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); 61 | strHeader += sc(iFileSize % 256); 62 | 63 | strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset 64 | strHeader += sc(40, 0, 0, 0); // info header size 65 | 66 | var iImageWidth = iWidth; 67 | strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); 68 | strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); 69 | strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); 70 | strHeader += sc(iImageWidth % 256); 71 | 72 | var iImageHeight = iHeight; 73 | strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); 74 | strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); 75 | strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); 76 | strHeader += sc(iImageHeight % 256); 77 | 78 | strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel 79 | strHeader += sc(0, 0, 0, 0); // compression = none 80 | 81 | var iDataSize = iWidth*iHeight*4; 82 | strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); 83 | strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); 84 | strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); 85 | strHeader += sc(iDataSize % 256); 86 | 87 | strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used 88 | 89 | var aImgData = oData.data, 90 | strPixelData = "", 91 | c, x, y = iHeight, 92 | iOffsetX, iOffsetY, strPixelRow; 93 | 94 | do { 95 | iOffsetY = iWidth*(y-1)*4; 96 | strPixelRow = ""; 97 | for (x = 0; x < iWidth; x++) { 98 | iOffsetX = 4*x; 99 | strPixelRow += sc( 100 | aImgData[iOffsetY + iOffsetX + 2], // B 101 | aImgData[iOffsetY + iOffsetX + 1], // G 102 | aImgData[iOffsetY + iOffsetX], // R 103 | aImgData[iOffsetY + iOffsetX + 3] // A 104 | ); 105 | } 106 | strPixelData += strPixelRow; 107 | } while (--y); 108 | 109 | return encodeData(strHeader + strPixelData); 110 | } 111 | 112 | // sends the generated file to the client 113 | var saveFile = function(strData) { 114 | if (!window.open(strData)) { 115 | document.location.href = strData; 116 | } 117 | } 118 | 119 | var makeDataURI = function(strData, strMime) { 120 | return "data:" + strMime + ";base64," + strData; 121 | } 122 | 123 | // generates a object containing the imagedata 124 | var makeImageObject = function(strSource) { 125 | var oImgElement = document.createElement("img"); 126 | oImgElement.src = strSource; 127 | return oImgElement; 128 | } 129 | 130 | var scaleCanvas = function(oCanvas, iWidth, iHeight) { 131 | if (iWidth && iHeight) { 132 | var oSaveCanvas = document.createElement("canvas"); 133 | 134 | oSaveCanvas.width = iWidth; 135 | oSaveCanvas.height = iHeight; 136 | oSaveCanvas.style.width = iWidth+"px"; 137 | oSaveCanvas.style.height = iHeight+"px"; 138 | 139 | var oSaveCtx = oSaveCanvas.getContext("2d"); 140 | 141 | oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth); 142 | 143 | return oSaveCanvas; 144 | } 145 | return oCanvas; 146 | } 147 | 148 | return { 149 | saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) { 150 | if (!bHasDataURL) return false; 151 | 152 | var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), 153 | strMime = "image/png", 154 | strData = oScaledCanvas.toDataURL(strMime); 155 | 156 | if (bReturnImg) { 157 | return makeImageObject(strData); 158 | } else { 159 | saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData); 160 | } 161 | return true; 162 | }, 163 | 164 | saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) { 165 | if (!bHasDataURL) return false; 166 | 167 | var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), 168 | strMime = "image/jpeg", 169 | strData = oScaledCanvas.toDataURL(strMime); 170 | 171 | // check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false 172 | if (strData.indexOf(strMime) != 5) return false; 173 | 174 | if (bReturnImg) { 175 | return makeImageObject(strData); 176 | } else { 177 | saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData); 178 | } 179 | return true; 180 | }, 181 | 182 | saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) { 183 | if (!(bHasDataURL && bHasImageData && bHasBase64)) return false; 184 | 185 | var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), 186 | strMime = "image/bmp", 187 | oData = readCanvasData(oScaledCanvas), 188 | strImgData = createBMP(oData); 189 | 190 | if (bReturnImg) { 191 | return makeImageObject(makeDataURI(strImgData, strMime)); 192 | } else { 193 | saveFile(makeDataURI(strImgData, strMime)); 194 | } 195 | return true; 196 | } 197 | }; 198 | })(); -------------------------------------------------------------------------------- /flotr/lib/canvastext.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/flotr/lib/canvastext.js -------------------------------------------------------------------------------- /images/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/images/destroy.png -------------------------------------------------------------------------------- /images/tablesort/down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/images/tablesort/down.gif -------------------------------------------------------------------------------- /images/tablesort/up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepheneb/webgl-matrix-benchmarks/428e8531590b323e46b656b9434df590f792b577/images/tablesort/up.gif -------------------------------------------------------------------------------- /js/rand.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | /** 3 | * A random seed for the pseudoRandom function. 4 | * @private 5 | * @type {number} 6 | */ 7 | var randomSeed = 0; 8 | 9 | /** 10 | * A constant for the pseudoRandom function 11 | * @private 12 | * @type {number} 13 | */ 14 | var RANDOM_RANGE = Math.pow(2, 32); 15 | var RANDOM_RANGE_PLUS_1 = RANDOM_RANGE + 1; 16 | 17 | /** 18 | * Returns a deterministic pseudorandom number between 0 and 1 19 | * @return {number} a random number between 0 and 1 20 | */ 21 | pseudoRandom = function() { 22 | return (randomSeed = 23 | (134775813 * randomSeed + 1) % 24 | RANDOM_RANGE) / RANDOM_RANGE_PLUS_1; 25 | }; 26 | 27 | /** 28 | * Resets the pseudoRandom function sequence. 29 | */ 30 | resetPseudoRandom = function() { 31 | randomSeed = 0; 32 | }; 33 | }()); 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /js/test-helper.js: -------------------------------------------------------------------------------- 1 | TestHelper = function() { 2 | 3 | var isInIFrame = (window.location != window.parent.location) ? true : false; 4 | 5 | function log(html) { 6 | var div = document.createElement('div'); 7 | div.innerHTML = html; 8 | document.body.appendChild(div); 9 | } 10 | 11 | function debuggerLog(obj) { 12 | if (window.console && window.console.log) { 13 | window.console.log(obj); 14 | } 15 | } 16 | 17 | function resetPseudoRandom() { 18 | if (window.resetPseudoRandom) { 19 | window.resetPseudoRandom(); 20 | } 21 | } 22 | 23 | function test(label, f) { 24 | // Repeats each benchmark multiple times to smooth out anomalies 25 | // Also tracks min and max times 26 | 27 | if(!f) { 28 | return { avg: null, min: null, max: null }; 29 | } 30 | 31 | var runCount = 10; 32 | var internalRunCount = 100; 33 | var totalIterations = 0; 34 | var minIterations = 0; 35 | var maxIterations = 0; 36 | var totalTime = 0; 37 | var minTime = 0; 38 | var maxTime = 0; 39 | var timePerRun = 30; 40 | resetPseudoRandom(); 41 | 42 | for(var i = 0; i < runCount; ++i) { 43 | var data = f(internalRunCount, -1, timePerRun); 44 | var iterations = internalRunCount * data.loopCount; 45 | var time = data.time; 46 | if(i == 0) { 47 | minIterations = iterations; 48 | maxIterations = iterations; 49 | minTime = time; 50 | maxTime = time; 51 | } else { 52 | if(minIterations > iterations) { 53 | minIterations = iterations; 54 | minTime = time; 55 | } 56 | if(maxIterations < iterations) { 57 | maxIterations = iterations; 58 | maxTime = time; 59 | } 60 | } 61 | totalIterations += iterations; 62 | totalTime += time; 63 | } 64 | 65 | var iterationsPerSecond = Math.floor(totalIterations / (totalTime * 0.001)); 66 | var minIterationsPerSecond = Math.floor(minIterations / (minTime * 0.001)); 67 | var maxIterationsPerSecond = Math.floor(maxIterations / (maxTime * 0.001)); 68 | 69 | return { avg: iterationsPerSecond, min: minIterationsPerSecond, max: maxIterationsPerSecond, result: data.result }; 70 | } 71 | 72 | function runTests(tests) { 73 | // Gather the test names 74 | var testNames = [] 75 | for (var testName in tests) { 76 | testNames.push(testName); 77 | } 78 | 79 | // Run each test 80 | function runNextTest() { 81 | if (testNames.length) { 82 | var testName = testNames.shift(); 83 | var testInfo = tests[testName]; 84 | var data = test(testName, testInfo.test); 85 | if (data.avg === null) { 86 | log('' + testName + ' Unsupported'); 87 | } else { 88 | log('' + label + ' - Avg: ' + data.avg + ' iterations per second, Min: ' + data.min + ' iterations per second, Max: ' + data.max + ' iterations per second'); 89 | } 90 | if (testNames.length) { 91 | setTimeout(runNextTest, 100); 92 | } 93 | } 94 | } 95 | runNextTest(); 96 | } 97 | 98 | function main() { 99 | var href = window.location.href; 100 | var slash = href.lastIndexOf('/'); 101 | var name = href.substr(slash + 1).replace('.html', ''); 102 | log('Test for: ' + name); 103 | log(''); 104 | 105 | if (!isInIFrame) { 106 | runTests(tests); 107 | } else { 108 | if (console && console.log) { 109 | debuggerLog("loaded: " + name); 110 | parent.childLoaded(); 111 | } 112 | } 113 | } 114 | 115 | return { 116 | main: main, 117 | test: test, 118 | resetPseudoRandom: resetPseudoRandom 119 | }; 120 | 121 | }(); 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /libs/CanvasMatrix/CanvasMatrix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /libs/EWGL_math/EWGL_math.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /libs/EWGL_math/EWGL_math.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var precision = 1e-6; 3 | var identitymatrix = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]; 4 | 5 | var matrix = function(els){ 6 | this.elements = new WebGLFloatArray( els || identitymatrix); 7 | //this.matrixstack = []; 8 | return this; 9 | }; 10 | 11 | matrix.prototype.I = matrix.prototype.identity = function(){ 12 | this.elements = identitymatrix; 13 | return this; 14 | }; 15 | 16 | 17 | matrix.prototype.e = function(i,j) { 18 | return this.elements[((i-1)*4)+(j-1)]; 19 | }; 20 | 21 | matrix.prototype.row = function(i){ 22 | var e = this.elements; 23 | return [e[i-1],e[3+i],e[7+i],e[11+i]]; 24 | }; 25 | 26 | matrix.prototype.col = function(i){ 27 | var e = this.elements; 28 | return [e[i*4-4],e[i*4-3],e[i*4-2],e[i*4-1]]; 29 | }; 30 | 31 | matrix.prototype.dimensions = function() { 32 | return {'rows':4,'cols':4}; 33 | }; 34 | 35 | matrix.prototype.rows = function() { 36 | return 4; 37 | }; 38 | 39 | matrix.prototype.cols = function() { 40 | return 4; 41 | }; 42 | 43 | matrix.prototype.eql = function(matrix) { 44 | var i = 16,e1 = this.elements,e2 = matrix.elements ; 45 | 46 | return Math.abs(e1[0] - e2[0]) < precision && 47 | Math.abs(e1[1] - e2[1]) < precision && 48 | Math.abs(e1[2] - e2[2]) < precision && 49 | Math.abs(e1[3] - e2[3]) < precision && 50 | Math.abs(e1[4] - e2[4]) < precision && 51 | Math.abs(e1[5] - e2[5]) < precision && 52 | Math.abs(e1[6] - e2[6]) < precision && 53 | Math.abs(e1[7] - e2[7]) < precision && 54 | Math.abs(e1[8] - e2[8]) < precision && 55 | Math.abs(e1[9] - e2[9]) < precision && 56 | Math.abs(e1[10] - e2[10]) < precision && 57 | Math.abs(e1[11] - e2[11]) < precision && 58 | Math.abs(e1[12] - e2[12]) < precision && 59 | Math.abs(e1[13] - e2[13]) < precision && 60 | Math.abs(e1[14] - e2[14]) < precision && 61 | Math.abs(e1[15] - e2[15]) < precision; 62 | }; 63 | 64 | matrix.prototype.setElements = function(els){ 65 | var e = this.elements; 66 | 67 | e[0] = els[0]; 68 | e[1] = els[1]; 69 | e[2] = els[2]; 70 | e[3] = els[3]; 71 | 72 | e[4] = els[4]; 73 | e[5] = els[5]; 74 | e[6] = els[6]; 75 | e[7] = els[7]; 76 | 77 | e[8] = els[8]; 78 | e[9] = els[9]; 79 | e[10] = els[10]; 80 | e[11] = els[11]; 81 | 82 | e[12] = els[12]; 83 | e[13] = els[13]; 84 | e[14] = els[14]; 85 | e[15] = els[15]; 86 | 87 | return this; 88 | }; 89 | 90 | matrix.prototype.dup = function(){ 91 | return (new matrix(this.elements)); 92 | }; 93 | 94 | matrix.prototype.map = function(fn) { 95 | var e = this.elements; 96 | 97 | e[0] = fn(e[0], 0, 0) 98 | e[1] = fn(e[1], 0, 1) 99 | e[2] = fn(e[2], 0, 2) 100 | e[3] = fn(e[3], 0, 3) 101 | 102 | e[4] = fn(e[4], 1, 0) 103 | e[5] = fn(e[5], 1, 1) 104 | e[6] = fn(e[6], 1, 2) 105 | e[7] = fn(e[7], 1, 3) 106 | 107 | e[8] = fn(e[8], 2, 0) 108 | e[9] = fn(e[9], 2, 1) 109 | e[10] = fn(e[10], 2, 2) 110 | e[11] = fn(e[11], 2, 3) 111 | 112 | e[12] = fn(e[12], 3, 0) 113 | e[13] = fn(e[13], 3, 1) 114 | e[14] = fn(e[14], 3, 2) 115 | e[15] = fn(e[15], 3, 3) 116 | 117 | return this; 118 | } 119 | 120 | matrix.prototype.add = function(matrix){ 121 | 122 | var els1 = this.elements, els2 = matrix.elements; 123 | 124 | els1[0] = els1[0]+els2[0]; 125 | els1[1] = els1[1]+els2[1]; 126 | els1[2] = els1[2]+els2[2]; 127 | els1[3] = els1[3]+els2[3]; 128 | els1[4] = els1[4]+els2[4]; 129 | els1[5] = els1[5]+els2[5]; 130 | els1[6] = els1[6]+els2[6]; 131 | els1[7] = els1[7]+els2[7]; 132 | els1[8] = els1[8]+els2[8]; 133 | els1[9] = els1[9]+els2[9]; 134 | els1[10] = els1[10]+els2[10]; 135 | els1[11] = els1[11]+els2[11]; 136 | els1[12] = els1[12]+els2[12]; 137 | els1[14] = els1[13]+els2[13]; 138 | els1[14] = els1[14]+els2[14]; 139 | els1[15] = els1[15]+els2[15]; 140 | 141 | return this; 142 | } 143 | 144 | matrix.prototype.substract =function(matrix){ 145 | 146 | var els1 = this.elements,els2 = matrix.elements; 147 | 148 | els1[0] = els1[0]-els2[0]; 149 | els1[1] = els1[1]-els2[1]; 150 | els1[2] = els1[2]-els2[2]; 151 | els1[3] = els1[3]-els2[3]; 152 | els1[4] = els1[4]-els2[4]; 153 | els1[5] = els1[5]-els2[5]; 154 | els1[6] = els1[6]-els2[6]; 155 | els1[7] = els1[7]-els2[7]; 156 | els1[8] = els1[8]-els2[8]; 157 | els1[9] = els1[9]-els2[9]; 158 | els1[10] = els1[10]-els2[10]; 159 | els1[11] = els1[11]-els2[11]; 160 | els1[12] = els1[12]-els2[12]; 161 | els1[14] = els1[13]-els2[13]; 162 | els1[14] = els1[14]-els2[14]; 163 | els1[15] = els1[15]-els2[15]; 164 | 165 | return this; 166 | } 167 | 168 | matrix.prototype.multiply = matrix.prototype.x = function(matrix) { 169 | var m1 = this.elements,m2 = matrix.elements || matrix, 170 | m10 = m1[0], m11 = m1[4], m12 = m1[8], m13 = m1[12], 171 | m14 = m1[1], m15 = m1[5], m16 = m1[9], m17 = m1[13], 172 | m18 = m1[2], m19 = m1[6], m110 = m1[10],m111 = m1[14], 173 | m112 = m1[3], m113 = m1[7], m114 = m1[11],m115 = m1[15], 174 | 175 | m20 = m2[0], m21 = m2[4], m22 = m2[8], m23 = m2[12], 176 | m24 = m2[1], m25 = m2[5], m26 = m2[9], m27 = m2[13], 177 | m28 = m2[2], m29 = m2[6], m210 = m2[10],m211 = m2[14], 178 | m212 = m2[3],m213 = m2[7],m214 = m2[11],m215 = m2[15]; 179 | 180 | 181 | 182 | m1[0] = m10 * m20 + m11 * m24 + m12 * m28 + m13 * m212; 183 | m1[1] = m14 * m20 + m15 * m24 + m16 * m28 + m17 * m212; 184 | m1[2] = m18 * m20 + m19 * m24 + m110 * m28 + m111 * m212; 185 | m1[3] = m112 * m20 + m113 * m24 + m114 * m28 + m115 * m212; 186 | 187 | m1[4] = m10 * m21 + m11 * m25 + m12 * m29 + m13 * m213; 188 | m1[5] = m14 * m21 + m15 * m25 + m16 * m29 + m17 * m213; 189 | m1[6] = m18 * m21 + m19 * m25 + m110 * m29 + m111 * m213; 190 | m1[7] = m112 * m21 + m113 * m25 + m114 * m29 + m115 * m213; 191 | 192 | m1[8] = m10 * m22 + m11 * m26 + m12 * m210 + m13 * m214; 193 | m1[9] = m14 * m22 + m15 * m26 + m16 * m210 + m17 * m214; 194 | m1[10] = m18 * m22 + m19 * m26 + m110 * m210 + m111 * m214; 195 | m1[11] = m112 * m22 + m113 * m26 + m114 * m210 + m115 * m214; 196 | 197 | m1[12] = m10 * m23 + m11 * m27 + m12 * m211 + m13 * m215; 198 | m1[13] = m14 * m23 + m15 * m27 + m16 * m211 + m17 * m215; 199 | m1[14] = m18 * m23 + m19 * m27 + m110 * m211 + m111 * m215; 200 | m1[15] = m112 * m23 + m113 * m27 + m114 * m211 + m115 * m215; 201 | 202 | return this; 203 | }; 204 | 205 | matrix.prototype.translate = function(vector) { 206 | var m1 = this.elements,v1 = vector.elements || vector, 207 | m10 = m1[0], m11 = m1[4], m12 = m1[8], m13 = m1[12], 208 | m14 = m1[1], m15 = m1[5], m16 = m1[9], m17 = m1[13], 209 | m18 = m1[2], m19 = m1[6], m110 = m1[10],m111 = m1[14], 210 | m112 = m1[3], m113 = m1[7], m114 = m1[11],m115 = m1[15], 211 | 212 | m23 = v1[0],m27 = v1[1],m211 = v1[2]; 213 | 214 | 215 | 216 | m1[0] = m10; 217 | m1[1] = m14; 218 | m1[2] = m18; 219 | m1[3] = m112; 220 | 221 | m1[4] = m11; 222 | m1[5] = m15; 223 | m1[6] = m19; 224 | m1[7] = m113; 225 | 226 | m1[8] = m12; 227 | m1[9] = m16; 228 | m1[10] = m110; 229 | m1[11] = m114; 230 | 231 | m1[12] = m10 * m23 + m11 * m27 + m12 * m211 + m13; 232 | m1[13] = m14 * m23 + m15 * m27 + m16 * m211 + m17; 233 | m1[14] = m18 * m23 + m19 * m27 + m110 * m211 + m111; 234 | m1[15] = m112 * m23 + m113 * m27 + m114 * m211 + m115; 235 | 236 | return this; 237 | }; 238 | 239 | matrix.prototype.rotate = function(theta,vector) 240 | { 241 | var v = vector.elements ? vector.elements : vector, 242 | m1 = this.elements, 243 | v0 = v[0],v1 = v[1],v2 = v[2], 244 | mod = Math.sqrt(v0*v0+v1*v1+v2*v2), 245 | x = v0/mod, y = v1/mod, z = v2/mod, 246 | s = Math.sin(theta), c = Math.cos(theta), t = 1 - c, 247 | 248 | m10 = m1[0], m11 = m1[4], m12 = m1[8], m13 = m1[12], 249 | m14 = m1[1], m15 = m1[5], m16 = m1[9], m17 = m1[13], 250 | m18 = m1[2], m19 = m1[6], m110 = m1[10],m111 = m1[14], 251 | m112 = m1[3], m113 = m1[7], m114 = m1[11],m115 = m1[15], 252 | 253 | m20 = t*x*x + c, m21 = t*x*y-s*z, m22 = t*x*z + s*y, 254 | m24 = t*x*y + s*z, m25 = t*y*y + c, m26 = t*y*z - s*x, 255 | m28 = t*x*z - s*y, m29 = t*y*z + s*x, m210 = t*z*z + c; 256 | 257 | m1[0] = m10 * m20 + m11 * m24 + m12 * m28; 258 | m1[1] = m14 * m20 + m15 * m24 + m16 * m28; 259 | m1[2] = m18 * m20 + m19 * m24 + m110 * m28; 260 | m1[3] = m112 * m20 + m113 * m24 + m114 * m28; 261 | 262 | m1[4] = m10 * m21 + m11 * m25 + m12 * m29; 263 | m1[5] = m14 * m21 + m15 * m25 + m16 * m29; 264 | m1[6] = m18 * m21 + m19 * m25 + m110 * m29; 265 | m1[7] = m112 * m21 + m113 * m25 + m114 * m29; 266 | 267 | m1[8] = m10 * m22 + m11 * m26 + m12 * m210; 268 | m1[9] = m14 * m22 + m15 * m26 + m16 * m210; 269 | m1[10] = m18 * m22 + m19 * m26 + m110 * m210; 270 | m1[11] = m112 * m22 + m113 * m26 + m114 * m210; 271 | 272 | m1[12] = m13; 273 | m1[13] = m17; 274 | m1[14] = m111; 275 | m1[15] = m115; 276 | 277 | return this; 278 | } 279 | 280 | matrix.prototype.scale = function(vector){ 281 | var s = vector.elements ? vector.elements : vector, 282 | m1 = this.elements, 283 | 284 | m10 = m1[0], m11 = m1[4], m12 = m1[8], m13 = m1[12], 285 | m14 = m1[1], m15 = m1[5], m16 = m1[9], m17 = m1[13], 286 | m18 = m1[2], m19 = m1[6], m110 = m1[10],m111 = m1[14], 287 | m112 = m1[3], m113 = m1[7], m114 = m1[11],m115 = m1[15], 288 | 289 | m20 = s[0], m25 = s[1], m210 = s[2]; 290 | 291 | m1[0] = m10 * m20; 292 | m1[1] = m14 * m20; 293 | m1[2] = m18 * m20; 294 | m1[3] = m112 * m20; 295 | 296 | m1[4] = m11 * m25; 297 | m1[5] = m15 * m25; 298 | m1[6] = m19 * m25; 299 | m1[7] = m113 * m25; 300 | 301 | m1[8] = m12 * m210; 302 | m1[9] = m16 * m210; 303 | m1[10] = m110 * m210; 304 | m1[11] = m114 * m210; 305 | 306 | m1[12] = m13; 307 | m1[13] = m17; 308 | m1[14] = m111; 309 | m1[15] = m115; 310 | 311 | return this; 312 | }; 313 | 314 | 315 | matrix.prototype.transpose = function(){ 316 | var e = this.elements, 317 | 318 | k = e[1]; 319 | e[1] = e[4]; 320 | e[4] = k; 321 | 322 | k = e[2]; 323 | e[2] = e[8]; 324 | e[8] = k; 325 | 326 | k = e[3]; 327 | e[3] = e[12]; 328 | e[12] = k; 329 | 330 | k = e[6]; 331 | e[6] = e[9]; 332 | e[9] = k; 333 | 334 | k = e[7]; 335 | e[7] = e[13]; 336 | e[13] = k; 337 | 338 | k = e[11]; 339 | e[11] = e[14]; 340 | e[14] = k; 341 | 342 | return this; 343 | }; 344 | 345 | matrix.prototype.max = function(){ 346 | var e = this.elements, m = e[0], j = e[1]; 347 | if (j > m) { m = j} 348 | j = e[2]; 349 | if (j > m) { m = j} 350 | j = e[3]; 351 | if (j > m) { m = j} 352 | j = e[4]; 353 | if (j > m) { m = j} 354 | j = e[5]; 355 | if (j > m) { m = j} 356 | j = e[6]; 357 | if (j > m) { m = j} 358 | j = e[7]; 359 | if (j > m) { m = j} 360 | j = e[8]; 361 | if (j > m) { m = j} 362 | j = e[9]; 363 | if (j > m) { m = j} 364 | j = e[10]; 365 | if (j > m) { m = j} 366 | j = e[12]; 367 | if (j > m) { m = j} 368 | j = e[13]; 369 | if (j > m) { m = j} 370 | j = e[14]; 371 | if (j > m) { m = j} 372 | j = e[15]; 373 | if (j > m) { return j} 374 | return m; 375 | }; 376 | 377 | matrix.prototype.min = function(){ 378 | 379 | var e = this.elements, m = e[0], j = e[1]; 380 | if (j < m) { m = j} 381 | j = e[2]; 382 | if (j < m) { m = j} 383 | j = e[3]; 384 | if (j < m) { m = j} 385 | j = e[4]; 386 | if (j < m) { m = j} 387 | j = e[5]; 388 | if (j < m) { m = j} 389 | j = e[6]; 390 | if (j < m) { m = j} 391 | j = e[7]; 392 | if (j < m) { m = j} 393 | j = e[8]; 394 | if (j < m) { m = j} 395 | j = e[9]; 396 | if (j > m) { m = j} 397 | j = e[10]; 398 | if (j < m) { m = j} 399 | j = e[12]; 400 | if (j < m) { m = j} 401 | j = e[13]; 402 | if (j < m) { m = j} 403 | j = e[14]; 404 | if (j < m) { m = j} 405 | j = e[15]; 406 | if (j < m) { return j} 407 | return m; 408 | }; 409 | 410 | matrix.prototype.indexOf = function(value){ 411 | e = this.elements; 412 | 413 | if (e[0] == value) { return new WebGLIntArray([0, 0])} 414 | if (e[1] == value) { return new WebGLIntArray([0, 1])} 415 | if (e[2] == value) { return new WebGLIntArray([0, 2])} 416 | if (e[3] == value) { return new WebGLIntArray([0, 3])} 417 | if (e[4] == value) { return new WebGLIntArray([1, 0])} 418 | if (e[5] == value) { return new WebGLIntArray([1, 1])} 419 | if (e[6] == value) { return new WebGLIntArray([1, 2])} 420 | if (e[7] == value) { return new WebGLIntArray([1, 3])} 421 | if (e[8] == value) { return new WebGLIntArray([2, 0])} 422 | if (e[9] == value) { return new WebGLIntArray([2, 1])} 423 | if (e[10] == value) { return new WebGLIntArray([2, 2])} 424 | if (e[11] == value) { return new WebGLIntArray([2, 3])} 425 | if (e[12] == value) { return new WebGLIntArray([3, 0])} 426 | if (e[13] == value) { return new WebGLIntArray([3, 1])} 427 | if (e[14] == value) { return new WebGLIntArray([3, 2])} 428 | if (e[15] == value) { return new WebGLIntArray([3, 3])} 429 | return null; 430 | }; 431 | 432 | matrix.prototype.diagonal = function(){ 433 | var els = this.elements; 434 | return [els[0],els[5],els[10],els[15]]; 435 | } 436 | 437 | matrix.prototype.determinant = matrix.prototype.det = function() { 438 | var m1 = this.elements, 439 | m00 = m1[0], m01 = m1[4], m02 = m1[8], m03 = m1[12], 440 | m10 = m1[1], m11 = m1[5], m12 = m1[9], m13 = m1[13], 441 | m20 = m1[2], m21 = m1[6], m22 = m1[10], m23 = m1[14], 442 | m30 = m1[3], m31 = m1[7], m32 = m1[11], m33 = m1[15]; 443 | 444 | return m03 * m12 * m21 * m30-m02 * m13 * m21 * m30-m03 * m11 * m22 * m30+m01 * m13 * m22 * m30+ 445 | m02 * m11 * m23 * m30-m01 * m12 * m23 * m30-m03 * m12 * m20 * m31+m02 * m13 * m20 * m31+ 446 | m03 * m10 * m22 * m31-m00 * m13 * m22 * m31-m02 * m10 * m23 * m31+m00 * m12 * m23 * m31+ 447 | m03 * m11 * m20 * m32-m01 * m13 * m20 * m32-m03 * m10 * m21 * m32+m00 * m13 * m21 * m32+ 448 | m01 * m10 * m23 * m32-m00 * m11 * m23 * m32-m02 * m11 * m20 * m33+m01 * m12 * m20 * m33+ 449 | m02 * m10 * m21 * m33-m00 * m12 * m21 * m33-m01 * m10 * m22 * m33+m00 * m11 * m22 * m33; 450 | } 451 | 452 | matrix.prototype.isSingular = function() { 453 | return (this.determinant() === 0); 454 | } 455 | 456 | matrix.prototype.trace = matrix.prototype.tr = function(){ 457 | var e = this.elements; 458 | return (e[0]+e[5]+e[10]+e[15]) 459 | } 460 | 461 | matrix.prototype.inverse = function(){ 462 | var m1 = this.elements,d = this.determinant(), 463 | m00 = m1[0], m01 = m1[4], m02 = m1[8], m03 = m1[12], 464 | m10 = m1[1], m11 = m1[5], m12 = m1[9], m13 = m1[13], 465 | m20 = m1[2], m21 = m1[6], m22 = m1[10], m23 = m1[14], 466 | m30 = m1[3], m31 = m1[7], m32 = m1[11], m33 = m1[15]; 467 | 468 | m1[0] = ( m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33)/d; 469 | m1[1] = ( m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33)/d; 470 | m1[2] = ( m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33)/d; 471 | m1[3] = ( m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32)/d; 472 | 473 | m1[4] = ( m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33)/d; 474 | m1[5] = ( m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33)/d; 475 | m1[6] = ( m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33)/d; 476 | m1[7] = ( m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32)/d; 477 | 478 | m1[8] = ( m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33)/d; 479 | m1[9] = ( m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33)/d; 480 | m1[10] = ( m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33)/d; 481 | m1[11] = ( m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32)/d; 482 | 483 | m1[12] = ( m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23)/d; 484 | m1[13] = ( m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23)/d; 485 | m1[14] = ( m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23)/d; 486 | m1[15] = ( m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22)/d; 487 | 488 | return this; 489 | } 490 | 491 | matrix.prototype.view = function(){ 492 | var e = this.elements; 493 | return "[ " + e[0] + " , " + e[4] + " , " + e[8] + " , " + e[12] + " ] \n " + 494 | "[ " + e[1] + " , " + e[5] + " , " + e[9] + " , " + e[13] + " ] \n " + 495 | "[ " + e[2] + " , " + e[6] + " , " + e[10] + " , " + e[14] + " ] \n " + 496 | "[ " + e[3] + " , " + e[7] + " , " + e[11] + " , " + e[15] + " ]"; 497 | }; 498 | 499 | matrix.prototype.rand = function(){ 500 | 501 | var e = this.elements; 502 | 503 | e[0] = Math.random()*1000; 504 | e[1] = Math.random()*1000; 505 | e[2] = Math.random()*1000; 506 | e[3] = Math.random()*1000; 507 | e[4] = Math.random()*1000; 508 | e[5] = Math.random()*1000; 509 | e[6] = Math.random()*1000; 510 | e[7] = Math.random()*1000; 511 | e[8] = Math.random()*1000; 512 | e[9] = Math.random()*1000; 513 | e[10] = Math.random()*1000; 514 | e[11] = Math.random()*1000; 515 | e[12] = Math.random()*1000; 516 | e[13] = Math.random()*1000; 517 | e[14] = Math.random()*1000; 518 | e[15] = Math.random()*1000; 519 | 520 | return this; 521 | }; 522 | 523 | matrix.I = function(){ 524 | return (new matrix()); 525 | } 526 | matrix.set = matrix.$ = function(){ 527 | var elements = arguments[15] ? [arguments[0],arguments[1],arguments[2],arguments[3], 528 | arguments[4],arguments[5],arguments[6],arguments[7], 529 | arguments[8],arguments[9],arguments[10],arguments[11], 530 | arguments[12],arguments[13],arguments[14],arguments[15]] : arguments[0]; 531 | return (new matrix(elements)); 532 | } 533 | matrix.makeFrustum = function (left, right, bottom, top, znear, zfar){ 534 | return new matrix([ 2*znear/(right-left), 535 | 0, 536 | 0, 537 | 0, 538 | 0, 539 | 2*znear/(top-bottom), 540 | 0, 541 | 0, 542 | (right+left)/(right-left), 543 | (top+bottom)/(top-bottom), 544 | -(zfar+znear)/(zfar-znear), 545 | -1, 546 | 0, 547 | 0, 548 | -2*zfar*znear/(zfar-znear), 549 | 0]); 550 | } 551 | 552 | matrix.makePerspective = function (fovy, aspect, znear, zfar) { 553 | 554 | var top = znear * Math.tan(fovy * Math.PI / 360.0), 555 | bottom = -top, 556 | left = bottom * aspect, 557 | right = top * aspect; 558 | 559 | return new matrix([ 2*znear/(right-left), 560 | 0, 561 | 0, 562 | 0, 563 | 0, 564 | 2*znear/(top-bottom), 565 | 0, 566 | 0, 567 | (right+left)/(right-left), 568 | (top+bottom)/(top-bottom), 569 | -(zfar+znear)/(zfar-znear), 570 | -1, 571 | 0, 572 | 0, 573 | -2*zfar*znear/(zfar-znear), 574 | 0]); 575 | }; 576 | 577 | matrix.makeOrtho = function(left, right, bottom, top, znear, zfar) { 578 | return new matrix([ 2 / (right-left), 579 | 0, 580 | 0, 581 | 0, 582 | 0, 583 | 2 / (top-bottom), 584 | 0, 585 | 0, 586 | 0, 587 | 0, 588 | -2 / (zfar-znear), 589 | 0, 590 | -(right+left)/(right-left), 591 | -(top+bottom)/(top-bottom), 592 | -(zfar+znear)/(zfar-znear), 593 | 0]); 594 | }; 595 | 596 | matrix.makeRotate = function(angle, axis){ 597 | var normAxis = !!axis.elements ? axis.normalize : vector.set(axis).normalize(), 598 | x = normAxis[0], y = normAxis[1], z = normAxis[2], 599 | c = Math.cos(angle), 600 | c1 = 1-c, 601 | s = Math.sin(angle); 602 | return new matrix([ x*x*c1+c, 603 | y*x*c1+z*s, 604 | z*x*c1-y*s, 605 | 0, 606 | x*y*c1-z*s, 607 | y*y*c1+c, 608 | y*z*c1+x*s, 609 | 0, 610 | x*z*c1+y*s, 611 | y*z*c1-x*s, 612 | z*z*c1+c, 613 | 0, 614 | 0, 615 | 0, 616 | 0, 617 | 1]); 618 | }; 619 | 620 | matrix.makeScale = function(vector){ 621 | var scale = vector.elements ? vector.elements : vector; 622 | return new matrix([ scale[0], 623 | 0, 624 | 0, 625 | 0, 626 | 0, 627 | scale[1], 628 | 0, 629 | 0, 630 | 0, 631 | 0, 632 | scale[2], 633 | 0, 634 | 0, 635 | 0, 636 | 0, 637 | 1]); 638 | }; 639 | 640 | matrix.makeTranslate = function(vector){ 641 | var translate = vector.elements ? vector.elements : vector; 642 | return new matrix( [1, 643 | 0, 644 | 0, 645 | 0, 646 | 0, 647 | 1, 648 | 0, 649 | 0, 650 | 0, 651 | 0, 652 | 1, 653 | 0, 654 | translate[0], 655 | translate[1], 656 | translate[2], 657 | 1]); 658 | }; 659 | 660 | var vector = function(){ 661 | this.elements = new WebGLFloatArray(arguments[0] || [0,0,0]); 662 | return this; 663 | }; 664 | 665 | vector.prototype.setElements = function(vector){ 666 | this.elements[0] = vector[0]; 667 | this.elements[1] = vector[1]; 668 | this.elements[2] = vector[2]; 669 | 670 | return this; 671 | }; 672 | 673 | vector.prototype.add = function(vector){ 674 | var a = this.elements, 675 | b = vector.elements; 676 | 677 | a[0] = a[0] + b[0]; 678 | a[1] = a[1] + b[1]; 679 | a[2] = a[2] + b[2]; 680 | 681 | return this; 682 | } 683 | 684 | vector.prototype.sub = function(vector){ 685 | var a = this.elements, 686 | b = vector.elements; 687 | 688 | a[0] = a[0] - b[0]; 689 | a[1] = a[1] - b[1]; 690 | a[2] = a[2] - b[2]; 691 | 692 | return this; 693 | } 694 | 695 | 696 | vector.prototype.mul = function(vector){ 697 | var a = this.elements, 698 | b = vector.elements, 699 | a0 = a[0],a1 = a[1],a2 = a[2], 700 | b0 = b[0],b1 = b[1],b2 = b[2]; 701 | 702 | a[0] = a1*b2 - a2*b1; 703 | a[1] = a2*b0 - a0*b2; 704 | a[2] = a0*b1 - a1*b0; 705 | 706 | return this; 707 | } 708 | 709 | vector.prototype.length = function(){ 710 | var a = this.elements; 711 | 712 | return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); 713 | }; 714 | 715 | vector.prototype.dot = function(vector){ 716 | var a = this.elements, 717 | b = vector.elements; 718 | 719 | return a[0] * b[0] + 720 | a[1] * b[1] + 721 | a[2] * b[2]; 722 | }; 723 | 724 | vector.prototype.normalize = function(){ 725 | var a = this.elements, 726 | l = 1/Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); 727 | 728 | a[0] = a[0]*l; 729 | a[1] = a[1]*l; 730 | a[2] = a[2]*l; 731 | 732 | return this; 733 | } 734 | 735 | vector.set =function(){ 736 | var elements = arguments[2] ? [arguments[0],arguments[1],arguments[2]] : arguments[0]; 737 | return (new matrix(elements)); 738 | } 739 | 740 | window.v3 = vector; 741 | window.m4x4 = matrix; 742 | })(); -------------------------------------------------------------------------------- /libs/Sylvester/Sylvester.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /libs/Sylvester/benchmark.js: -------------------------------------------------------------------------------- 1 | // Sylvester benchmark 2 | 3 | /*jslint browser: true, maxerr: 50, maxlen: 79, nomen: true, sloppy: true, 4 | unparam: true */ 5 | 6 | /*global TestHelper, Sylvester, Vector, Matrix, Line, Plane, $V, $M, $L, $P, 7 | pseudoRandom */ 8 | 9 | window.onload = TestHelper.main; 10 | 11 | var tests = (function () { 12 | // Matrix that 1. translates by a random vector and 2. rotates by a random 13 | // angle about a random axis. 14 | function randomMatrix() { 15 | var randomAxis = $V([pseudoRandom(), pseudoRandom(), pseudoRandom()]). 16 | toUnitVector(), 17 | randomAngle = pseudoRandom(), 18 | rotation3 = Matrix.Rotation(randomAngle, randomAxis), 19 | rotation = (rotation3.transpose().augment($V([0, 0, 0])). 20 | transpose().augment($V([0, 0, 0, 1]))), 21 | translation = $M([[1, 0, 0, pseudoRandom()], 22 | [0, 1, 0, pseudoRandom()], 23 | [0, 0, 1, pseudoRandom()], 24 | [0, 0, 0, 1]]); 25 | return rotation.multiply(translation); 26 | } 27 | 28 | function webglMatrix(m) { 29 | var rowI, colI, flattenedMatrix = []; 30 | for (colI = 0; colI < 4; colI += 1) { 31 | for (rowI = 0; rowI < 4; rowI += 1) { 32 | flattenedMatrix.push(m.elements[rowI][colI]); 33 | } 34 | } 35 | return flattenedMatrix; 36 | } 37 | 38 | // Based on Closure r1315's `makePerspective()`. 39 | function perspectiveMatrix(fovy, aspect, near, far) { 40 | var angle = fovy / 2, 41 | dz = far - near, 42 | sinAngle = Math.sin(angle), 43 | cot; 44 | 45 | if (dz === 0 || sinAngle === 0 || aspect === 0) { 46 | return false; 47 | } 48 | 49 | cot = Math.cos(angle) / sinAngle; 50 | return $M([[cot / aspect, 0, 0, 0], 51 | [0, cot, 0, 0], 52 | [0, 0, -(far + near) / dz, -1], 53 | [0, 0, -(2 * near * far) / dz, 0]]).transpose(); 54 | } 55 | 56 | return { 57 | 'Multiplication': { 58 | test: function (count, maxCount, milliSeconds) { 59 | var m1 = randomMatrix(), 60 | m2 = randomMatrix(), 61 | start = Date.now(), 62 | loopCount = 0, 63 | i; 64 | while (Date.now() - start < milliSeconds && 65 | loopCount !== maxCount) { 66 | loopCount += 1; 67 | for (i = 0; i < count; i += 1) { 68 | m1 = m1.multiply(m2); 69 | } 70 | } 71 | return { 72 | time: Date.now() - start, 73 | loopCount: loopCount, 74 | result: webglMatrix(m1) 75 | }; 76 | } 77 | }, 78 | 79 | 'Translation': { 80 | test: null // Sylvester has no dedicated translation function. 81 | }, 82 | 83 | 'Scaling': { 84 | test: null // Sylvester has no dedicated scaling function. 85 | }, 86 | 87 | 'Rotation (Arbitrary axis)': { 88 | test: null // Sylvester has no dedicated rotation function. 89 | }, 90 | 91 | 'Rotation (X axis)': { 92 | test: null // Sylvester has no dedicated rotation function. 93 | }, 94 | 95 | 'Transpose': { 96 | test: function (count, maxCount, milliSeconds) { 97 | var m1 = randomMatrix(), 98 | start = Date.now(), 99 | loopCount = 0, 100 | i; 101 | while (Date.now() - start < milliSeconds && 102 | loopCount !== maxCount) { 103 | loopCount += 1; 104 | for (i = 0; i < count; i += 1) { 105 | m1 = m1.transpose(); 106 | } 107 | } 108 | return { 109 | time: Date.now() - start, 110 | loopCount: loopCount, 111 | result: webglMatrix(m1) 112 | }; 113 | } 114 | }, 115 | 116 | 'Inverse': { 117 | test: function (count, maxCount, milliSeconds) { 118 | var m1 = perspectiveMatrix(Math.PI / 2, 0.5, 1, 1000), 119 | start = Date.now(), 120 | loopCount = 0, 121 | i; 122 | while (Date.now() - start < milliSeconds && 123 | loopCount !== maxCount) { 124 | loopCount += 1; 125 | for (i = 0; i < count; i += 1) { 126 | m1 = m1.inverse(); 127 | } 128 | } 129 | return { 130 | time: Date.now() - start, 131 | loopCount: loopCount, 132 | result: webglMatrix(m1) 133 | }; 134 | } 135 | }, 136 | 137 | 'Inverse 3x3': { 138 | test: function (count, maxCount, milliSeconds) { 139 | var m1 = randomMatrix(), 140 | start = Date.now(), 141 | loopCount = 0, 142 | i, 143 | mg = webglMatrix(m1); 144 | m1 = $M([[mg[0], mg[1], mg[2]], 145 | [mg[4], mg[5], mg[7]], 146 | [mg[8], mg[9], mg[10]]]).transpose(); 147 | while (Date.now() - start < milliSeconds && 148 | loopCount !== maxCount) { 149 | loopCount += 1; 150 | for (i = 0; i < count; i += 1) { 151 | m1 = m1.inverse(); 152 | } 153 | } 154 | m1 = m1.transpose().augment($V([0, 0, 0])). 155 | transpose().augment($V([0, 0, 0, 1])); 156 | return { 157 | time: Date.now() - start, 158 | loopCount: loopCount, 159 | result: webglMatrix(m1) 160 | }; 161 | } 162 | }, 163 | 164 | 'Vector Transformation': { 165 | test: null // Sylvester has no dedicated function for transforming 166 | // 3 dimensional vectors with 4x4 matrices. 167 | } 168 | }; 169 | }()); 170 | -------------------------------------------------------------------------------- /libs/Sylvester/sylvester.js: -------------------------------------------------------------------------------- 1 | eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9 17={3i:\'0.1.3\',16:1e-6};l v(){}v.23={e:l(i){8(i<1||i>7.4.q)?w:7.4[i-1]},2R:l(){8 7.4.q},1u:l(){8 F.1x(7.2u(7))},24:l(a){9 n=7.4.q;9 V=a.4||a;o(n!=V.q){8 1L}J{o(F.13(7.4[n-1]-V[n-1])>17.16){8 1L}}H(--n);8 2x},1q:l(){8 v.u(7.4)},1b:l(a){9 b=[];7.28(l(x,i){b.19(a(x,i))});8 v.u(b)},28:l(a){9 n=7.4.q,k=n,i;J{i=k-n;a(7.4[i],i+1)}H(--n)},2q:l(){9 r=7.1u();o(r===0){8 7.1q()}8 7.1b(l(x){8 x/r})},1C:l(a){9 V=a.4||a;9 n=7.4.q,k=n,i;o(n!=V.q){8 w}9 b=0,1D=0,1F=0;7.28(l(x,i){b+=x*V[i-1];1D+=x*x;1F+=V[i-1]*V[i-1]});1D=F.1x(1D);1F=F.1x(1F);o(1D*1F===0){8 w}9 c=b/(1D*1F);o(c<-1){c=-1}o(c>1){c=1}8 F.37(c)},1m:l(a){9 b=7.1C(a);8(b===w)?w:(b<=17.16)},34:l(a){9 b=7.1C(a);8(b===w)?w:(F.13(b-F.1A)<=17.16)},2k:l(a){9 b=7.2u(a);8(b===w)?w:(F.13(b)<=17.16)},2j:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x+V[i-1]})},2C:l(a){9 V=a.4||a;o(7.4.q!=V.q){8 w}8 7.1b(l(x,i){8 x-V[i-1]})},22:l(k){8 7.1b(l(x){8 x*k})},x:l(k){8 7.22(k)},2u:l(a){9 V=a.4||a;9 i,2g=0,n=7.4.q;o(n!=V.q){8 w}J{2g+=7.4[n-1]*V[n-1]}H(--n);8 2g},2f:l(a){9 B=a.4||a;o(7.4.q!=3||B.q!=3){8 w}9 A=7.4;8 v.u([(A[1]*B[2])-(A[2]*B[1]),(A[2]*B[0])-(A[0]*B[2]),(A[0]*B[1])-(A[1]*B[0])])},2A:l(){9 m=0,n=7.4.q,k=n,i;J{i=k-n;o(F.13(7.4[i])>F.13(m)){m=7.4[i]}}H(--n);8 m},2Z:l(x){9 a=w,n=7.4.q,k=n,i;J{i=k-n;o(a===w&&7.4[i]==x){a=i+1}}H(--n);8 a},3g:l(){8 S.2X(7.4)},2d:l(){8 7.1b(l(x){8 F.2d(x)})},2V:l(x){8 7.1b(l(y){8(F.13(y-x)<=17.16)?x:y})},1o:l(a){o(a.K){8 a.1o(7)}9 V=a.4||a;o(V.q!=7.4.q){8 w}9 b=0,2b;7.28(l(x,i){2b=x-V[i-1];b+=2b*2b});8 F.1x(b)},3a:l(a){8 a.1h(7)},2T:l(a){8 a.1h(7)},1V:l(t,a){9 V,R,x,y,z;2S(7.4.q){27 2:V=a.4||a;o(V.q!=2){8 w}R=S.1R(t).4;x=7.4[0]-V[0];y=7.4[1]-V[1];8 v.u([V[0]+R[0][0]*x+R[0][1]*y,V[1]+R[1][0]*x+R[1][1]*y]);1I;27 3:o(!a.U){8 w}9 C=a.1r(7).4;R=S.1R(t,a.U).4;x=7.4[0]-C[0];y=7.4[1]-C[1];z=7.4[2]-C[2];8 v.u([C[0]+R[0][0]*x+R[0][1]*y+R[0][2]*z,C[1]+R[1][0]*x+R[1][1]*y+R[1][2]*z,C[2]+R[2][0]*x+R[2][1]*y+R[2][2]*z]);1I;2P:8 w}},1t:l(a){o(a.K){9 P=7.4.2O();9 C=a.1r(P).4;8 v.u([C[0]+(C[0]-P[0]),C[1]+(C[1]-P[1]),C[2]+(C[2]-(P[2]||0))])}1d{9 Q=a.4||a;o(7.4.q!=Q.q){8 w}8 7.1b(l(x,i){8 Q[i-1]+(Q[i-1]-x)})}},1N:l(){9 V=7.1q();2S(V.4.q){27 3:1I;27 2:V.4.19(0);1I;2P:8 w}8 V},2n:l(){8\'[\'+7.4.2K(\', \')+\']\'},26:l(a){7.4=(a.4||a).2O();8 7}};v.u=l(a){9 V=25 v();8 V.26(a)};v.i=v.u([1,0,0]);v.j=v.u([0,1,0]);v.k=v.u([0,0,1]);v.2J=l(n){9 a=[];J{a.19(F.2F())}H(--n);8 v.u(a)};v.1j=l(n){9 a=[];J{a.19(0)}H(--n);8 v.u(a)};l S(){}S.23={e:l(i,j){o(i<1||i>7.4.q||j<1||j>7.4[0].q){8 w}8 7.4[i-1][j-1]},33:l(i){o(i>7.4.q){8 w}8 v.u(7.4[i-1])},2E:l(j){o(j>7.4[0].q){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][j-1])}H(--n);8 v.u(a)},2R:l(){8{2D:7.4.q,1p:7.4[0].q}},2D:l(){8 7.4.q},1p:l(){8 7.4[0].q},24:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(7.4.q!=M.q||7.4[0].q!=M[0].q){8 1L}9 b=7.4.q,15=b,i,G,10=7.4[0].q,j;J{i=15-b;G=10;J{j=10-G;o(F.13(7.4[i][j]-M[i][j])>17.16){8 1L}}H(--G)}H(--b);8 2x},1q:l(){8 S.u(7.4)},1b:l(a){9 b=[],12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;b[i]=[];J{j=10-G;b[i][j]=a(7.4[i][j],i+1,j+1)}H(--G)}H(--12);8 S.u(b)},2i:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4.q==M.q&&7.4[0].q==M[0].q)},2j:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x+M[i-1][j-1]})},2C:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2i(M)){8 w}8 7.1b(l(x,i,j){8 x-M[i-1][j-1]})},2B:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}8(7.4[0].q==M.q)},22:l(a){o(!a.4){8 7.1b(l(x){8 x*a})}9 b=a.1u?2x:1L;9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}o(!7.2B(M)){8 w}9 d=7.4.q,15=d,i,G,10=M[0].q,j;9 e=7.4[0].q,4=[],21,20,c;J{i=15-d;4[i]=[];G=10;J{j=10-G;21=0;20=e;J{c=e-20;21+=7.4[i][c]*M[c][j]}H(--20);4[i][j]=21}H(--G)}H(--d);9 M=S.u(4);8 b?M.2E(1):M},x:l(a){8 7.22(a)},32:l(a,b,c,d){9 e=[],12=c,i,G,j;9 f=7.4.q,1p=7.4[0].q;J{i=c-12;e[i]=[];G=d;J{j=d-G;e[i][j]=7.4[(a+i-1)%f][(b+j-1)%1p]}H(--G)}H(--12);8 S.u(e)},31:l(){9 a=7.4.q,1p=7.4[0].q;9 b=[],12=1p,i,G,j;J{i=1p-12;b[i]=[];G=a;J{j=a-G;b[i][j]=7.4[j][i]}H(--G)}H(--12);8 S.u(b)},1y:l(){8(7.4.q==7.4[0].q)},2A:l(){9 m=0,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(F.13(7.4[i][j])>F.13(m)){m=7.4[i][j]}}H(--G)}H(--12);8 m},2Z:l(x){9 a=w,12=7.4.q,15=12,i,G,10=7.4[0].q,j;J{i=15-12;G=10;J{j=10-G;o(7.4[i][j]==x){8{i:i+1,j:j+1}}}H(--G)}H(--12);8 w},30:l(){o(!7.1y){8 w}9 a=[],n=7.4.q,k=n,i;J{i=k-n;a.19(7.4[i][i])}H(--n);8 v.u(a)},1K:l(){9 M=7.1q(),1c;9 n=7.4.q,k=n,i,1s,1n=7.4[0].q,p;J{i=k-n;o(M.4[i][i]==0){2e(j=i+1;j17.16){1Y++;1I}}H(--G)}H(--a);8 1Y},3d:l(){8 7.1Y()},2W:l(a){9 M=a.4||a;o(1g(M[0][0])==\'1f\'){M=S.u(M).4}9 T=7.1q(),1p=T.4[0].q;9 b=T.4.q,15=b,i,G,10=M[0].q,j;o(b!=M.q){8 w}J{i=15-b;G=10;J{j=10-G;T.4[i][1p+j]=M[i][j]}H(--G)}H(--b);8 T},2w:l(){o(!7.1y()||7.2y()){8 w}9 a=7.4.q,15=a,i,j;9 M=7.2W(S.I(a)).1K();9 b,1n=M.4[0].q,p,1c,2v;9 c=[],2c;J{i=a-1;1c=[];b=1n;c[i]=[];2v=M.4[i][i];J{p=1n-b;2c=M.4[i][p]/2v;1c.19(2c);o(p>=15){c[i].19(2c)}}H(--b);M.4[i]=1c;2e(j=0;j3||b.4.q>3){8 w}9 c=b.1u();o(c===0){8 w}7.K=a;7.U=v.u([b.4[0]/c,b.4[1]/c,b.4[2]/c]);8 7}};14.u=l(a,b){9 L=25 14();8 L.1Z(a,b)};14.X=14.u(v.1j(3),v.i);14.Y=14.u(v.1j(3),v.j);14.Z=14.u(v.1j(3),v.k);l 11(){}11.23={24:l(a){8(7.1h(a.K)&&7.1m(a))},1q:l(){8 11.u(7.K,7.W)},2U:l(a){9 V=a.4||a;8 11.u([7.K.4[0]+V[0],7.K.4[1]+V[1],7.K.4[2]+(V[2]||0)],7.W)},1m:l(a){9 b;o(a.W){b=7.W.1C(a.W);8(F.13(b)<=17.16||F.13(F.1A-b)<=17.16)}1d o(a.U){8 7.W.2k(a.U)}8 w},2k:l(a){9 b=7.W.1C(a.W);8(F.13(F.1A/2-b)<=17.16)},1o:l(a){o(7.1v(a)||7.1h(a)){8 0}o(a.K){9 A=7.K.4,B=a.K.4,N=7.W.4;8 F.13((A[0]-B[0])*N[0]+(A[1]-B[1])*N[1]+(A[2]-B[2])*N[2])}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;8 F.13((A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2])}},1h:l(a){o(a.W){8 w}o(a.U){8(7.1h(a.K)&&7.1h(a.K.2j(a.U)))}1d{9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=F.13(N[0]*(A[0]-P[0])+N[1]*(A[1]-P[1])+N[2]*(A[2]-(P[2]||0)));8(b<=17.16)}},1v:l(a){o(1g(a.U)==\'1f\'&&1g(a.W)==\'1f\'){8 w}8!7.1m(a)},1U:l(a){o(!7.1v(a)){8 w}o(a.U){9 A=a.K.4,D=a.U.4,P=7.K.4,N=7.W.4;9 b=(N[0]*(P[0]-A[0])+N[1]*(P[1]-A[1])+N[2]*(P[2]-A[2]))/(N[0]*D[0]+N[1]*D[1]+N[2]*D[2]);8 v.u([A[0]+D[0]*b,A[1]+D[1]*b,A[2]+D[2]*b])}1d o(a.W){9 c=7.W.2f(a.W).2q();9 N=7.W.4,A=7.K.4,O=a.W.4,B=a.K.4;9 d=S.1j(2,2),i=0;H(d.2y()){i++;d=S.u([[N[i%3],N[(i+1)%3]],[O[i%3],O[(i+1)%3]]])}9 e=d.2w().4;9 x=N[0]*A[0]+N[1]*A[1]+N[2]*A[2];9 y=O[0]*B[0]+O[1]*B[1]+O[2]*B[2];9 f=[e[0][0]*x+e[0][1]*y,e[1][0]*x+e[1][1]*y];9 g=[];2e(9 j=1;j<=3;j++){g.19((i==j)?0:f[(j+(5-i)%3)%3])}8 14.u(g,c)}},1r:l(a){9 P=a.4||a;9 A=7.K.4,N=7.W.4;9 b=(A[0]-P[0])*N[0]+(A[1]-P[1])*N[1]+(A[2]-(P[2]||0))*N[2];8 v.u([P[0]+N[0]*b,P[1]+N[1]*b,(P[2]||0)+N[2]*b])},1V:l(t,a){9 R=S.1R(t,a.U).4;9 C=a.1r(7.K).4;9 A=7.K.4,N=7.W.4;9 b=C[0],1E=C[1],1J=C[2],1w=A[0],18=A[1],1a=A[2];9 x=1w-b,y=18-1E,z=1a-1J;8 11.u([b+R[0][0]*x+R[0][1]*y+R[0][2]*z,1E+R[1][0]*x+R[1][1]*y+R[1][2]*z,1J+R[2][0]*x+R[2][1]*y+R[2][2]*z],[R[0][0]*N[0]+R[0][1]*N[1]+R[0][2]*N[2],R[1][0]*N[0]+R[1][1]*N[1]+R[1][2]*N[2],R[2][0]*N[0]+R[2][1]*N[1]+R[2][2]*N[2]])},1t:l(a){o(a.W){9 A=7.K.4,N=7.W.4;9 b=A[0],18=A[1],1a=A[2],2M=N[0],2L=N[1],2Q=N[2];9 c=7.K.1t(a).4;9 d=b+2M,2p=18+2L,2m=1a+2Q;9 Q=a.1r([d,2p,2m]).4;9 e=[Q[0]+(Q[0]-d)-c[0],Q[1]+(Q[1]-2p)-c[1],Q[2]+(Q[2]-2m)-c[2]];8 11.u(c,e)}1d o(a.U){8 7.1V(F.1A,a)}1d{9 P=a.4||a;8 11.u(7.K.1t([P[0],P[1],(P[2]||0)]),7.W)}},1Z:l(a,b,c){a=v.u(a);a=a.1N();o(a===w){8 w}b=v.u(b);b=b.1N();o(b===w){8 w}o(1g(c)==\'1f\'){c=w}1d{c=v.u(c);c=c.1N();o(c===w){8 w}}9 d=a.4[0],18=a.4[1],1a=a.4[2];9 e=b.4[0],1W=b.4[1],1X=b.4[2];9 f,1i;o(c!==w){9 g=c.4[0],2l=c.4[1],2t=c.4[2];f=v.u([(1W-18)*(2t-1a)-(1X-1a)*(2l-18),(1X-1a)*(g-d)-(e-d)*(2t-1a),(e-d)*(2l-18)-(1W-18)*(g-d)]);1i=f.1u();o(1i===0){8 w}f=v.u([f.4[0]/1i,f.4[1]/1i,f.4[2]/1i])}1d{1i=F.1x(e*e+1W*1W+1X*1X);o(1i===0){8 w}f=v.u([b.4[0]/1i,b.4[1]/1i,b.4[2]/1i])}7.K=a;7.W=f;8 7}};11.u=l(a,b,c){9 P=25 11();8 P.1Z(a,b,c)};11.2I=11.u(v.1j(3),v.k);11.2H=11.u(v.1j(3),v.i);11.2G=11.u(v.1j(3),v.j);11.36=11.2I;11.35=11.2H;11.3j=11.2G;9 $V=v.u;9 $M=S.u;9 $L=14.u;9 $P=11.u;',62,206,'||||elements|||this|return|var||||||||||||function|||if||length||||create|Vector|null|||||||||Math|nj|while||do|anchor||||||||Matrix||direction||normal||||kj|Plane|ni|abs|Line|ki|precision|Sylvester|A2|push|A3|map|els|else||undefined|typeof|contains|mod|Zero|D3|D2|isParallelTo|kp|distanceFrom|cols|dup|pointClosestTo|np|reflectionIn|modulus|intersects|A1|sqrt|isSquare|X2|PI|X3|angleFrom|mod1|C2|mod2|sin|cos|break|C3|toRightTriangular|false|Y3|to3D|E2|E1|E3|Rotation|Y2|Y1|intersectionWith|rotate|v12|v13|rank|setVectors|nc|sum|multiply|prototype|eql|new|setElements|case|each|PA3|PA2|part|new_element|round|for|cross|product|AD2|isSameSizeAs|add|isPerpendicularTo|v22|AN3|inspect|AD3|AN2|toUnitVector|PsubQ3|PsubQ2|v23|dot|divisor|inverse|true|isSingular|determinant|max|canMultiplyFromLeft|subtract|rows|col|random|ZX|YZ|XY|Random|join|N2|N1|D1|slice|default|N3|dimensions|switch|liesIn|translate|snapTo|augment|Diagonal|trace|indexOf|diagonal|transpose|minor|row|isAntiparallelTo|ZY|YX|acos|RotationZ|RotationY|liesOn|RotationX|inv|rk|tr|det|toDiagonalMatrix|toUpperTriangular|version|XZ'.split('|'),0,{})) -------------------------------------------------------------------------------- /libs/closure/closure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/float32array.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview Supplies a Float32Array implementation that implements 18 | * most of the Float32Array spec and that can be used when a built-in 19 | * implementation is not available. 20 | * 21 | * Note that if no existing Float32Array implementation is found then 22 | * this class and all its public properties are exported as Float32Array. 23 | * 24 | * Adding support for the other TypedArray classes here does not make sense 25 | * since this vector math library only needs Float32Array. 26 | * 27 | */ 28 | goog.provide('goog.vec.Float32Array'); 29 | 30 | 31 | 32 | /** 33 | * Constructs a new Float32Array. The new array is initialized to all zeros. 34 | * 35 | * @param {goog.vec.Float32Array|Array|ArrayBuffer|TypedArray|number} p0 36 | * The length of the array, or an array to initialize the contents of the 37 | * new Float32Array. 38 | * @constructor 39 | */ 40 | goog.vec.Float32Array = function(p0) { 41 | this.length = p0.length || p0; 42 | for (var i = 0; i < this.length; i++) { 43 | this[i] = p0[i] || 0; 44 | } 45 | }; 46 | 47 | 48 | /** 49 | * The number of bytes in an element (as defined by the Typed Array 50 | * specification). 51 | * 52 | * @type {number} 53 | */ 54 | goog.vec.Float32Array.BYTES_PER_ELEMENT = 4; 55 | 56 | 57 | /** 58 | * The number of bytes in an element (as defined by the Typed Array 59 | * specification). 60 | * 61 | * @type {number} 62 | */ 63 | goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT = 4; 64 | 65 | 66 | /** 67 | * Sets elements of the array. 68 | * @param {Array.|Float32Array} values The array of values. 69 | * @param {number=} opt_offset The offset in this array to start. 70 | */ 71 | goog.vec.Float32Array.prototype.set = function(values, opt_offset) { 72 | opt_offset = opt_offset || 0; 73 | for (var i = 0; i < values.length && opt_offset + i < this.length; i++) { 74 | this[opt_offset + i] = values[i]; 75 | } 76 | }; 77 | 78 | 79 | /** 80 | * Creates a string representation of this array. 81 | * @return {string} The string version of this array. 82 | */ 83 | goog.vec.Float32Array.prototype.toString = Array.prototype.join; 84 | 85 | 86 | /** 87 | * Note that we cannot implement the subarray() or (deprecated) slice() 88 | * methods properly since doing so would require being able to overload 89 | * the [] operator which is not possible in javascript. So we leave 90 | * them unimplemented. Any attempt to call these methods will just result 91 | * in a javascript error since we leave them undefined. 92 | */ 93 | 94 | 95 | /** 96 | * If no existing Float32Array implementation is found then we export 97 | * goog.vec.Float32Array as Float32Array. 98 | */ 99 | if (typeof Float32Array == 'undefined') { 100 | goog.exportProperty(goog.vec.Float32Array, 'BYTES_PER_ELEMENT', 101 | goog.vec.Float32Array.BYTES_PER_ELEMENT); 102 | goog.exportProperty(goog.vec.Float32Array.prototype, 'BYTES_PER_ELEMENT', 103 | goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT); 104 | goog.exportProperty(goog.vec.Float32Array.prototype, 'set', 105 | goog.vec.Float32Array.prototype.set); 106 | goog.exportProperty(goog.vec.Float32Array.prototype, 'toString', 107 | goog.vec.Float32Array.prototype.toString); 108 | goog.exportSymbol('Float32Array', goog.vec.Float32Array); 109 | } 110 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/quaternion.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview Implements quaternions and their conversion functions. In this 18 | * implementation, quaternions are represented as 4 element vectors with the 19 | * first 3 elements holding the imaginary components and the 4th element holding 20 | * the real component. 21 | * 22 | */ 23 | goog.provide('goog.vec.Quaternion'); 24 | 25 | goog.require('goog.vec'); 26 | goog.require('goog.vec.Vec4'); 27 | 28 | 29 | 30 | /** 31 | * @typedef {goog.vec.Vec4.Type} 32 | */ 33 | goog.vec.Quaternion.Type; 34 | 35 | 36 | /** 37 | * Creates a quaternion (4 element vector), initialized to zero. 38 | * 39 | * @return {goog.vec.Quaternion.Type} The new quaternion. 40 | */ 41 | goog.vec.Quaternion.create = goog.vec.Vec4.create; 42 | 43 | 44 | /** 45 | * Creates a new quaternion initialized with the values from the supplied 46 | * array. 47 | * 48 | * @param {goog.vec.ArrayType} vec The source 4 element array. 49 | * @return {!goog.vec.Quaternion.Type} The new quaternion. 50 | */ 51 | goog.vec.Quaternion.createFromArray = 52 | goog.vec.Vec4.createFromArray; 53 | 54 | 55 | /** 56 | * Creates a new quaternion initialized with the supplied values. 57 | * 58 | * @param {number} v0 The value for element at index 0. 59 | * @param {number} v1 The value for element at index 1. 60 | * @param {number} v2 The value for element at index 2. 61 | * @param {number} v3 The value for element at index 3. 62 | * @return {!goog.vec.Quaternion.Type} The new quaternion. 63 | */ 64 | goog.vec.Quaternion.createFromValues = 65 | goog.vec.Vec4.createFromValues; 66 | 67 | 68 | /** 69 | * Creates a clone of the given quaternion. 70 | * 71 | * @param {goog.vec.Quaternion.Type} q The source quaternion. 72 | * @return {goog.vec.Quaternion.Type} The new quaternion. 73 | */ 74 | goog.vec.Quaternion.clone = 75 | goog.vec.Vec4.clone; 76 | 77 | 78 | /** 79 | * Initializes the quaternion with the given values. 80 | * 81 | * @param {goog.vec.ArrayType} q The quaternion to receive 82 | * the values. 83 | * @param {number} v0 The value for element at index 0. 84 | * @param {number} v1 The value for element at index 1. 85 | * @param {number} v2 The value for element at index 2. 86 | * @param {number} v3 The value for element at index 2. 87 | */ 88 | goog.vec.Quaternion.setFromValues = 89 | goog.vec.Vec4.setFromValues; 90 | 91 | 92 | /** 93 | * Initializes the quaternion with the given array of values. 94 | * 95 | * @param {goog.vec.ArrayType} q The quaternion to receive 96 | * the values. 97 | * @param {goog.vec.ArrayType} values The array of values. 98 | */ 99 | goog.vec.Quaternion.setFromArray = 100 | goog.vec.Vec4.setFromArray; 101 | 102 | 103 | /** 104 | * Adds the two quaternions. 105 | * 106 | * @param {goog.vec.ArrayType} quat0 The first addend. 107 | * @param {goog.vec.ArrayType} quat1 The second addend. 108 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 109 | * receive the result. May be quat0 or quat1. 110 | */ 111 | goog.vec.Quaternion.add = goog.vec.Vec4.add; 112 | 113 | 114 | /** 115 | * Negates a quaternion, storing the result into resultQuat. 116 | * 117 | * @param {goog.vec.ArrayType} quat0 The quaternion to negate. 118 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 119 | * receive the result. May be quat0. 120 | */ 121 | goog.vec.Quaternion.negate = goog.vec.Vec4.negate; 122 | 123 | 124 | /** 125 | * Multiplies each component of quat0 with scalar storing the product into 126 | * resultVec. 127 | * 128 | * @param {goog.vec.ArrayType} quat0 The source quaternion. 129 | * @param {number} scalar The value to multiply with each component of quat0. 130 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 131 | * receive the result. May be quat0. 132 | */ 133 | goog.vec.Quaternion.scale = goog.vec.Vec4.scale; 134 | 135 | 136 | /** 137 | * Returns the square magnitude of the given quaternion. 138 | * 139 | * @param {goog.vec.ArrayType} quat0 The quaternion. 140 | * @return {number} The magnitude of the quaternion. 141 | */ 142 | goog.vec.Quaternion.magnitudeSquared = 143 | goog.vec.Vec4.magnitudeSquared; 144 | 145 | 146 | /** 147 | * Returns the magnitude of the given quaternion. 148 | * 149 | * @param {goog.vec.ArrayType} quat0 The quaternion. 150 | * @return {number} The magnitude of the quaternion. 151 | */ 152 | goog.vec.Quaternion.magnitude = 153 | goog.vec.Vec4.magnitude; 154 | 155 | 156 | /** 157 | * Normalizes the given quaternion storing the result into resultVec. 158 | * 159 | * @param {goog.vec.ArrayType} quat0 The quaternion to normalize. 160 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 161 | * receive the result. May be quat0. 162 | */ 163 | goog.vec.Quaternion.normalize = goog.vec.Vec4.normalize; 164 | 165 | 166 | /** 167 | * Computes the dot (scalar) product of two quaternions. 168 | * 169 | * @param {goog.vec.ArrayType} q0 The first quaternion. 170 | * @param {goog.vec.ArrayType} q1 The second quaternion. 171 | * @return {number} The scalar product. 172 | */ 173 | goog.vec.Quaternion.dot = goog.vec.Vec4.dot; 174 | 175 | 176 | /** 177 | * Computes the conjugate of the quaternion in quat storing the result into 178 | * resultQuat. 179 | * 180 | * @param {goog.vec.ArrayType} quat The source quaternion. 181 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 182 | * receive the result. 183 | */ 184 | goog.vec.Quaternion.conjugate = function(quat, resultQuat) { 185 | resultQuat[0] = -quat[0]; 186 | resultQuat[1] = -quat[1]; 187 | resultQuat[2] = -quat[2]; 188 | resultQuat[3] = quat[3]; 189 | }; 190 | 191 | 192 | /** 193 | * Concatenates the two quaternions storing the result into resultQuat. 194 | * 195 | * @param {goog.vec.ArrayType} quat0 The first quaternion. 196 | * @param {goog.vec.ArrayType} quat1 The second quaternion. 197 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 198 | * receive the result. 199 | */ 200 | goog.vec.Quaternion.concat = function(quat0, quat1, resultQuat) { 201 | var x0 = quat0[0], y0 = quat0[1], z0 = quat0[2], w0 = quat0[3]; 202 | var x1 = quat1[0], y1 = quat1[1], z1 = quat1[2], w1 = quat1[3]; 203 | resultQuat[0] = w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1; 204 | resultQuat[1] = w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1; 205 | resultQuat[2] = w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1; 206 | resultQuat[3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; 207 | }; 208 | 209 | 210 | /** 211 | * Generates the quaternion from the given rotation matrix. 212 | * 213 | * @param {goog.vec.ArrayType} matrix The source matrix. 214 | * @param {goog.vec.ArrayType} quat The resulting quaternion. 215 | */ 216 | goog.vec.Quaternion.fromRotationMatrix4 = function(matrix, quat) { 217 | var sx = matrix[0], sy = matrix[5], sz = matrix[10]; 218 | quat[3] = Math.sqrt(Math.max(0, 1 + sx + sy + sz)) / 2; 219 | quat[0] = Math.sqrt(Math.max(0, 1 + sx - sy - sz)) / 2; 220 | quat[1] = Math.sqrt(Math.max(0, 1 - sx + sy - sz)) / 2; 221 | quat[2] = Math.sqrt(Math.max(0, 1 - sx - sy + sz)) / 2; 222 | 223 | quat[0] = (matrix[6] - matrix[9] < 0) != (quat[0] < 0) ? -quat[0] : quat[0]; 224 | quat[1] = (matrix[8] - matrix[2] < 0) != (quat[1] < 0) ? -quat[1] : quat[1]; 225 | quat[2] = (matrix[1] - matrix[4] < 0) != (quat[2] < 0) ? -quat[2] : quat[2]; 226 | }; 227 | 228 | 229 | /** 230 | * Generates the rotation matrix from the given quaternion. 231 | * 232 | * @param {goog.vec.ArrayType} quat The source quaternion. 233 | * @param {goog.vec.ArrayType} matrix The resulting matrix. 234 | */ 235 | goog.vec.Quaternion.toRotationMatrix4 = function(quat, matrix) { 236 | var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; 237 | var x2 = 2 * x, y2 = 2 * y, z2 = 2 * z; 238 | var wx = x2 * w; 239 | var wy = y2 * w; 240 | var wz = z2 * w; 241 | var xx = x2 * x; 242 | var xy = y2 * x; 243 | var xz = z2 * x; 244 | var yy = y2 * y; 245 | var yz = z2 * y; 246 | var zz = z2 * z; 247 | 248 | matrix[0] = 1 - (yy + zz); 249 | matrix[1] = xy + wz; 250 | matrix[2] = xz - wy; 251 | matrix[3] = 0; 252 | matrix[4] = xy - wz; 253 | matrix[5] = 1 - (xx + zz); 254 | matrix[6] = yz + wx; 255 | matrix[7] = 0; 256 | matrix[8] = xz + wy; 257 | matrix[9] = yz - wx; 258 | matrix[10] = 1 - (xx + yy); 259 | matrix[11] = 0; 260 | matrix[12] = 0; 261 | matrix[13] = 0; 262 | matrix[14] = 0; 263 | matrix[15] = 1; 264 | }; 265 | 266 | 267 | /** 268 | * Computes the spherical linear interpolated value from the given quaternions 269 | * q0 and q1 according to the coefficient t. The resulting quaternion is stored 270 | * in resultQuat. 271 | * 272 | * @param {goog.vec.ArrayType} q0 The first quaternion. 273 | * @param {goog.vec.ArrayType} q1 The second quaternion. 274 | * @param {number} t The interpolating coefficient. 275 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 276 | * receive the result. 277 | */ 278 | goog.vec.Quaternion.slerp = function(q0, q1, t, resultQuat) { 279 | // Compute the dot product between q0 and q1 (cos of the angle between q0 and 280 | // q1). If it's outside the interval [-1,1], then the arccos is not defined. 281 | // The usual reason for this is that q0 and q1 are colinear. In this case 282 | // the angle between the two is zero, so just return q1. 283 | var cosVal = goog.vec.Quaternion.dot(q0, q1); 284 | if (cosVal > 1 || cosVal < -1) { 285 | goog.vec.Quaternion.setFromArray(resultQuat, q1); 286 | return; 287 | } 288 | 289 | // Quaternions are a double cover on the space of rotations. That is, q and -q 290 | // represent the same rotation. Thus we have two possibilities when 291 | // interpolating between q0 and q1: going the short way or the long way. We 292 | // prefer the short way since that is the likely expectation from users. 293 | var factor = 1; 294 | if (cosVal < 0) { 295 | factor = -1; 296 | cosVal = -cosVal; 297 | } 298 | 299 | // Compute the angle between q0 and q1. If it's very small, then just return 300 | // q1 to avoid a very large denominator below. 301 | var angle = Math.acos(cosVal); 302 | if (angle <= goog.vec.EPSILON) { 303 | goog.vec.Quaternion.setFromArray(resultQuat, q1); 304 | return; 305 | } 306 | 307 | // Compute the coefficients and interpolate. 308 | var invSinVal = 1 / Math.sin(angle); 309 | var c0 = Math.sin((1 - t) * angle) * invSinVal; 310 | var c1 = factor * Math.sin(t * angle) * invSinVal; 311 | 312 | resultQuat[0] = q0[0] * c0 + q1[0] * c1; 313 | resultQuat[1] = q0[1] * c0 + q1[1] * c1; 314 | resultQuat[2] = q0[2] * c0 + q1[2] * c1; 315 | resultQuat[3] = q0[3] * c0 + q1[3] * c1; 316 | }; 317 | 318 | 319 | /** 320 | * Compute the simple linear interpolation of the two quaternions q0 and q1 321 | * according to the coefficient t. The resulting quaternion is stored in 322 | * resultVec. 323 | * 324 | * @param {goog.vec.ArrayType} q0 The first quaternion. 325 | * @param {goog.vec.ArrayType} q1 The second quaternion. 326 | * @param {number} t The interpolation factor. 327 | * @param {goog.vec.ArrayType} resultQuat The quaternion to 328 | * receive the results (may be q0 or q1). 329 | */ 330 | goog.vec.Quaternion.nlerp = goog.vec.Vec4.lerp; 331 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/ray.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** 16 | * @fileoverview Implements a 3D ray that are compatible with WebGL. 17 | * Each element is a float64 in case high precision is required. 18 | * The API is structured to avoid unnecessary memory allocations. 19 | * The last parameter will typically be the output vector and an 20 | * object can be both an input and output parameter to all methods 21 | * except where noted. 22 | * 23 | */ 24 | goog.provide('goog.vec.Ray'); 25 | 26 | goog.require('goog.vec.Vec3'); 27 | 28 | 29 | 30 | /** 31 | * Constructs a new ray with an optional origin and direction. If not specified, 32 | * the default is [0, 0, 0]. 33 | * @param {goog.vec.ArrayType=} opt_origin The optional origin. 34 | * @param {goog.vec.ArrayType=} opt_dir The optional direction. 35 | * @constructor 36 | */ 37 | goog.vec.Ray = function(opt_origin, opt_dir) { 38 | /** 39 | * @type {Array.} 40 | */ 41 | this.origin = [0, 0, 0]; 42 | if (opt_origin) { 43 | goog.vec.Vec3.setFromArray(this.origin, opt_origin); 44 | } 45 | 46 | /** 47 | * @type {Array.} 48 | */ 49 | this.dir = [0, 0, 0]; 50 | if (opt_dir) { 51 | goog.vec.Vec3.setFromArray(this.dir, opt_dir); 52 | } 53 | }; 54 | 55 | 56 | /** 57 | * Sets the origin and direction of the ray. 58 | * @param {goog.vec.ArrayType} origin The new origin. 59 | * @param {goog.vec.ArrayType} dir The new direction. 60 | */ 61 | goog.vec.Ray.prototype.set = function(origin, dir) { 62 | goog.vec.Vec3.setFromArray(this.origin, origin); 63 | goog.vec.Vec3.setFromArray(this.dir, dir); 64 | }; 65 | 66 | 67 | /** 68 | * Sets the origin of the ray. 69 | * @param {goog.vec.ArrayType} origin the new origin. 70 | */ 71 | goog.vec.Ray.prototype.setOrigin = function(origin) { 72 | goog.vec.Vec3.setFromArray(this.origin, origin); 73 | }; 74 | 75 | 76 | /** 77 | * Sets the direction of the ray. 78 | * @param {goog.vec.ArrayType} dir The new direction. 79 | */ 80 | goog.vec.Ray.prototype.setDir = function(dir) { 81 | goog.vec.Vec3.setFromArray(this.dir, dir); 82 | }; 83 | 84 | 85 | /** 86 | * Returns true if this ray is equal to the other ray. 87 | * @param {goog.vec.Ray} other The other ray. 88 | * @return {boolean} True if this ray is equal to the other ray. 89 | */ 90 | goog.vec.Ray.prototype.equals = function(other) { 91 | return other != null && 92 | goog.vec.Vec3.equals(this.origin, other.origin) && 93 | goog.vec.Vec3.equals(this.dir, other.dir); 94 | }; 95 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/vec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview Supplies global data types and constants for the vector math 18 | * library. 19 | */ 20 | goog.provide('goog.vec'); 21 | 22 | /** 23 | * On platforms that don't have native Float32Array support we use a javascript 24 | * implementation so that this math library can be used on all platforms. 25 | */ 26 | goog.require('goog.vec.Float32Array'); 27 | 28 | 29 | /** 30 | * All vector and matrix operations are based upon arrays of numbers using 31 | * either a standard Javascript Array or the Float32Array typed array. 32 | * 33 | * @typedef {Float32Array|Array.} 34 | */ 35 | goog.vec.ArrayType; 36 | 37 | 38 | /** 39 | * For graphics work, 6 decimal places of accuracy are typically all that is 40 | * required. 41 | * 42 | * @type {number} 43 | * @const 44 | */ 45 | goog.vec.EPSILON = 1e-6; 46 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/vec3.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview Supplies 3 element vectors that are compatible with WebGL. 18 | * Each element is a float32 since that is typically the desired size of a 19 | * 3-vector in the GPU. The API is structured to avoid unnecessary memory 20 | * allocations. The last parameter will typically be the output vector and 21 | * an object can be both an input and output parameter to all methods except 22 | * where noted. 23 | * 24 | */ 25 | goog.provide('goog.vec.Vec3'); 26 | 27 | goog.require('goog.vec'); 28 | 29 | 30 | /** 31 | * Type used when an argument can be either an array of numbers or a 32 | * typed float32 array. This allows using the class on normal js arrays too. 33 | * E.g. the following code is perfectly valid: 34 | *
 35 |  * var vecA = [1, 2, 3];
 36 |  * var vecB = goog.vec.Vec3.createFromArray([0, 1 ,2]);
 37 |  * goog.vec.Vec3.subtract(vecA, vecB, vecA);
 38 |  * 
39 | * Note that vecA is a double precision vector (doubles), while vecB is a 40 | * single precision vector (floats). 41 | * @typedef {goog.vec.ArrayType} 42 | */ 43 | goog.vec.Vec3.Vec3Like; 44 | 45 | 46 | /** 47 | * @typedef {Float32Array} 48 | */ 49 | goog.vec.Vec3.Type; 50 | 51 | 52 | /** 53 | * Creates a 3 element vector of Float32Array. The array is initialized to zero. 54 | * 55 | * @return {!goog.vec.Vec3.Type} The new 3 element array. 56 | */ 57 | goog.vec.Vec3.create = function() { 58 | return new Float32Array(3); 59 | }; 60 | 61 | 62 | /** 63 | * Creates a new 3 element vector initialized with the value from the given 64 | * array. 65 | * 66 | * @param {goog.vec.Vec3.Vec3Like} vec The source 3 element array. 67 | * @return {!goog.vec.Vec3.Type} The new 3 element array. 68 | */ 69 | goog.vec.Vec3.createFromArray = function(vec) { 70 | var newVec = goog.vec.Vec3.create(); 71 | goog.vec.Vec3.setFromArray(newVec, vec); 72 | return newVec; 73 | }; 74 | 75 | 76 | /** 77 | * Creates a new 3 element vector initialized with the supplied values. 78 | * 79 | * @param {number} v0 The value for element at index 0. 80 | * @param {number} v1 The value for element at index 1. 81 | * @param {number} v2 The value for element at index 2. 82 | * @return {!goog.vec.Vec3.Type} The new vector. 83 | */ 84 | goog.vec.Vec3.createFromValues = function(v0, v1, v2) { 85 | var vec = goog.vec.Vec3.create(); 86 | goog.vec.Vec3.setFromValues(vec, v0, v1, v2); 87 | return vec; 88 | }; 89 | 90 | 91 | /** 92 | * Creates a clone of the given 3 element vector. 93 | * 94 | * @param {goog.vec.Vec3.Vec3Like} vec The source 3 element vector. 95 | * @return {!goog.vec.Vec3.Type} The new cloned vector. 96 | */ 97 | goog.vec.Vec3.clone = goog.vec.Vec3.createFromArray; 98 | 99 | 100 | /** 101 | * Initializes the vector with the given values. 102 | * 103 | * @param {goog.vec.Vec3.Vec3Like} vec The vector to receive the values. 104 | * @param {number} v0 The value for element at index 0. 105 | * @param {number} v1 The value for element at index 1. 106 | * @param {number} v2 The value for element at index 2. 107 | */ 108 | goog.vec.Vec3.setFromValues = function(vec, v0, v1, v2) { 109 | vec[0] = v0; 110 | vec[1] = v1; 111 | vec[2] = v2; 112 | }; 113 | 114 | 115 | /** 116 | * Initializes the vector with the given array of values. 117 | * 118 | * @param {goog.vec.Vec3.Vec3Like} vec The vector to receive the 119 | * values. 120 | * @param {goog.vec.Vec3.Vec3Like} values The array of values. 121 | */ 122 | goog.vec.Vec3.setFromArray = function(vec, values) { 123 | vec[0] = values[0]; 124 | vec[1] = values[1]; 125 | vec[2] = values[2]; 126 | }; 127 | 128 | 129 | /** 130 | * Performs a component-wise addition of vec0 and vec1 together storing the 131 | * result into resultVec. 132 | * 133 | * @param {goog.vec.Vec3.Vec3Like} vec0 The first addend. 134 | * @param {goog.vec.Vec3.Vec3Like} vec1 The second addend. 135 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to 136 | * receive the result. May be vec0 or vec1. 137 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 138 | * chained together. 139 | */ 140 | goog.vec.Vec3.add = function(vec0, vec1, resultVec) { 141 | resultVec[0] = vec0[0] + vec1[0]; 142 | resultVec[1] = vec0[1] + vec1[1]; 143 | resultVec[2] = vec0[2] + vec1[2]; 144 | return resultVec; 145 | }; 146 | 147 | 148 | /** 149 | * Performs a component-wise subtraction of vec1 from vec0 storing the 150 | * result into resultVec. 151 | * 152 | * @param {goog.vec.Vec3.Vec3Like} vec0 The minuend. 153 | * @param {goog.vec.Vec3.Vec3Like} vec1 The subtrahend. 154 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to 155 | * receive the result. May be vec0 or vec1. 156 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 157 | * chained together. 158 | */ 159 | goog.vec.Vec3.subtract = function(vec0, vec1, resultVec) { 160 | resultVec[0] = vec0[0] - vec1[0]; 161 | resultVec[1] = vec0[1] - vec1[1]; 162 | resultVec[2] = vec0[2] - vec1[2]; 163 | return resultVec; 164 | }; 165 | 166 | 167 | /** 168 | * Negates vec0, storing the result into resultVec. 169 | * 170 | * @param {goog.vec.Vec3.Vec3Like} vec0 The vector to negate. 171 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to 172 | * receive the result. May be vec0. 173 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 174 | * chained together. 175 | */ 176 | goog.vec.Vec3.negate = function(vec0, resultVec) { 177 | resultVec[0] = -vec0[0]; 178 | resultVec[1] = -vec0[1]; 179 | resultVec[2] = -vec0[2]; 180 | return resultVec; 181 | }; 182 | 183 | 184 | /** 185 | * Multiplies each component of vec0 with scalar storing the product into 186 | * resultVec. 187 | * 188 | * @param {goog.vec.Vec3.Vec3Like} vec0 The source vector. 189 | * @param {number} scalar The value to multiply with each component of vec0. 190 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to 191 | * receive the result. May be vec0. 192 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 193 | * chained together. 194 | */ 195 | goog.vec.Vec3.scale = function(vec0, scalar, resultVec) { 196 | resultVec[0] = vec0[0] * scalar; 197 | resultVec[1] = vec0[1] * scalar; 198 | resultVec[2] = vec0[2] * scalar; 199 | return resultVec; 200 | }; 201 | 202 | 203 | /** 204 | * Returns the magnitudeSquared of the given vector. 205 | * 206 | * @param {goog.vec.Vec3.Vec3Like} vec0 The vector. 207 | * @return {number} The magnitude of the vector. 208 | */ 209 | goog.vec.Vec3.magnitudeSquared = function(vec0) { 210 | var x = vec0[0], y = vec0[1], z = vec0[2]; 211 | return x * x + y * y + z * z; 212 | }; 213 | 214 | 215 | /** 216 | * Returns the magnitude of the given vector. 217 | * 218 | * @param {goog.vec.Vec3.Vec3Like} vec0 The vector. 219 | * @return {number} The magnitude of the vector. 220 | */ 221 | goog.vec.Vec3.magnitude = function(vec0) { 222 | var x = vec0[0], y = vec0[1], z = vec0[2]; 223 | return Math.sqrt(x * x + y * y + z * z); 224 | }; 225 | 226 | 227 | /** 228 | * Normalizes the given vector storing the result into resultVec. 229 | * 230 | * @param {goog.vec.Vec3.Vec3Like} vec0 The vector to normalize. 231 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to 232 | * receive the result. May be vec0. 233 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 234 | * chained together. 235 | */ 236 | goog.vec.Vec3.normalize = function(vec0, resultVec) { 237 | var ilen = 1 / goog.vec.Vec3.magnitude(vec0); 238 | resultVec[0] = vec0[0] * ilen; 239 | resultVec[1] = vec0[1] * ilen; 240 | resultVec[2] = vec0[2] * ilen; 241 | return resultVec; 242 | }; 243 | 244 | 245 | /** 246 | * Returns the scalar product of vectors v0 and v1. 247 | * 248 | * @param {goog.vec.Vec3.Vec3Like} v0 The first vector. 249 | * @param {goog.vec.Vec3.Vec3Like} v1 The second vector. 250 | * @return {number} The scalar product. 251 | */ 252 | goog.vec.Vec3.dot = function(v0, v1) { 253 | return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2]; 254 | }; 255 | 256 | 257 | /** 258 | * Computes the vector (cross) product of v0 and v1 storing the result into 259 | * resultVec. 260 | * 261 | * @param {goog.vec.Vec3.Vec3Like} v0 The first vector. 262 | * @param {goog.vec.Vec3.Vec3Like} v1 The second vector. 263 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to receive the 264 | * results. May be either v0 or v1. 265 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 266 | * chained together. 267 | */ 268 | goog.vec.Vec3.cross = function(v0, v1, resultVec) { 269 | var x0 = v0[0], y0 = v0[1], z0 = v0[2]; 270 | var x1 = v1[0], y1 = v1[1], z1 = v1[2]; 271 | resultVec[0] = y0 * z1 - z0 * y1; 272 | resultVec[1] = z0 * x1 - x0 * z1; 273 | resultVec[2] = x0 * y1 - y0 * x1; 274 | return resultVec; 275 | }; 276 | 277 | 278 | /** 279 | * Linearly interpolate from v0 to v1 according to f. The value of f should be 280 | * in the range [0..1] otherwise the results are undefined. 281 | * 282 | * @param {goog.vec.Vec3.Vec3Like} v0 The first vector. 283 | * @param {goog.vec.Vec3.Vec3Like} v1 The second vector. 284 | * @param {number} f The interpolation factor. 285 | * @param {goog.vec.Vec3.Vec3Like} resultVec The vector to receive the 286 | * results (may be v0 or v1). 287 | * @return {!goog.vec.Vec3.Vec3Like} return resultVec so that operations can be 288 | * chained together. 289 | */ 290 | goog.vec.Vec3.lerp = function(v0, v1, f, resultVec) { 291 | var x = v0[0], y = v0[1], z = v0[2]; 292 | resultVec[0] = (v1[0] - x) * f + x; 293 | resultVec[1] = (v1[1] - y) * f + y; 294 | resultVec[2] = (v1[2] - z) * f + z; 295 | return resultVec; 296 | }; 297 | 298 | 299 | /** 300 | * Returns true if the components of v0 are equal to the components of v1. 301 | * 302 | * @param {goog.vec.Vec3.Vec3Like} v0 The first vector. 303 | * @param {goog.vec.Vec3.Vec3Like} v1 The second vector. 304 | * @return {boolean} True if the vectors are equal, false otherwise. 305 | */ 306 | goog.vec.Vec3.equals = function(v0, v1) { 307 | return v0.length == v1.length && 308 | v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2]; 309 | }; 310 | -------------------------------------------------------------------------------- /libs/closure/goog/vec/vec4.js: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview Supplies 4 element vectors that are compatible with WebGL. 18 | * Each element is a float32 since that is typically the desired size of a 19 | * 4-vector in the GPU. The API is structured to avoid unnecessary memory 20 | * allocations. The last parameter will typically be the output vector and 21 | * an object can be both an input and output parameter to all methods except 22 | * where noted. 23 | * 24 | */ 25 | goog.provide('goog.vec.Vec4'); 26 | 27 | goog.require('goog.vec'); 28 | 29 | 30 | /** 31 | * Type used when an argument can be either an array of numbers or a 32 | * typed float32 array. This allows using the class on normal js arrays too. 33 | * E.g. the following code is perfectly valid: 34 | *
 35 |  * var vecA = [1, 2, 3, 4];
 36 |  * var vecB = goog.vec.Vec4.createFromArray([0, 1 ,2, 3]);
 37 |  * goog.vec.Vec4.subtract(vecA, vecB, vecA);
 38 |  * 
39 | * Note that vecA is a double precision vector (doubles), while vecB is a 40 | * single precision vector (floats). 41 | * @typedef {goog.vec.ArrayType} 42 | */ 43 | goog.vec.Vec4.Vec4Like; 44 | 45 | 46 | /** 47 | * @typedef {Float32Array} 48 | */ 49 | goog.vec.Vec4.Type; 50 | 51 | 52 | /** 53 | * Creates a 4 element vector of Float32Array. The array is initialized to zero. 54 | * 55 | * @return {!goog.vec.Vec4.Type} The new 4 element array. 56 | */ 57 | goog.vec.Vec4.create = function() { 58 | return new Float32Array(4); 59 | }; 60 | 61 | 62 | /** 63 | * Creates a new 4 element vector initialized with the value from the given 64 | * array. 65 | * 66 | * @param {goog.vec.Vec4.Vec4Like} vec The source 4 element array. 67 | * @return {!goog.vec.Vec4.Type} The new 4 element array. 68 | */ 69 | goog.vec.Vec4.createFromArray = function(vec) { 70 | var newVec = goog.vec.Vec4.create(); 71 | goog.vec.Vec4.setFromArray(newVec, vec); 72 | return newVec; 73 | }; 74 | 75 | 76 | /** 77 | * Creates a new 4 element vector initialized with the supplied values. 78 | * 79 | * @param {number} v0 The value for element at index 0. 80 | * @param {number} v1 The value for element at index 1. 81 | * @param {number} v2 The value for element at index 2. 82 | * @param {number} v3 The value for element at index 2. 83 | * @return {!goog.vec.Vec4.Type} The new vector. 84 | */ 85 | goog.vec.Vec4.createFromValues = function(v0, v1, v2, v3) { 86 | var vec = goog.vec.Vec4.create(); 87 | goog.vec.Vec4.setFromValues(vec, v0, v1, v2, v3); 88 | return vec; 89 | }; 90 | 91 | 92 | /** 93 | * Creates a clone of the given 4 element vector. 94 | * 95 | * @param {goog.vec.Vec4.Vec4Like} vec The source 4 element vector. 96 | * @return {!goog.vec.Vec4.Type} The new cloned vector. 97 | */ 98 | goog.vec.Vec4.clone = goog.vec.Vec4.createFromArray; 99 | 100 | 101 | /** 102 | * Initializes the vector with the given values. 103 | * 104 | * @param {goog.vec.Vec4.Vec4Like} vec The vector to receive the values. 105 | * @param {number} v0 The value for element at index 0. 106 | * @param {number} v1 The value for element at index 1. 107 | * @param {number} v2 The value for element at index 2. 108 | * @param {number} v3 The value for element at index 3. 109 | */ 110 | goog.vec.Vec4.setFromValues = function(vec, v0, v1, v2, v3) { 111 | vec[0] = v0; 112 | vec[1] = v1; 113 | vec[2] = v2; 114 | vec[3] = v3; 115 | }; 116 | 117 | 118 | /** 119 | * Initializes the vector with the given array of values. 120 | * 121 | * @param {goog.vec.Vec4.Vec4Like} vec The vector to receive the 122 | * values. 123 | * @param {goog.vec.Vec4.Vec4Like} values The array of values. 124 | */ 125 | goog.vec.Vec4.setFromArray = function(vec, values) { 126 | vec[0] = values[0]; 127 | vec[1] = values[1]; 128 | vec[2] = values[2]; 129 | vec[3] = values[3]; 130 | }; 131 | 132 | 133 | /** 134 | * Performs a component-wise addition of vec0 and vec1 together storing the 135 | * result into resultVec. 136 | * 137 | * @param {goog.vec.Vec4.Vec4Like} vec0 The first addend. 138 | * @param {goog.vec.Vec4.Vec4Like} vec1 The second addend. 139 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to 140 | * receive the result. May be vec0 or vec1. 141 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 142 | * chained together. 143 | */ 144 | goog.vec.Vec4.add = function(vec0, vec1, resultVec) { 145 | resultVec[0] = vec0[0] + vec1[0]; 146 | resultVec[1] = vec0[1] + vec1[1]; 147 | resultVec[2] = vec0[2] + vec1[2]; 148 | resultVec[3] = vec0[3] + vec1[3]; 149 | return resultVec; 150 | }; 151 | 152 | 153 | /** 154 | * Performs a component-wise subtraction of vec1 from vec0 storing the 155 | * result into resultVec. 156 | * 157 | * @param {goog.vec.Vec4.Vec4Like} vec0 The minuend. 158 | * @param {goog.vec.Vec4.Vec4Like} vec1 The subtrahend. 159 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to 160 | * receive the result. May be vec0 or vec1. 161 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 162 | * chained together. 163 | */ 164 | goog.vec.Vec4.subtract = function(vec0, vec1, resultVec) { 165 | resultVec[0] = vec0[0] - vec1[0]; 166 | resultVec[1] = vec0[1] - vec1[1]; 167 | resultVec[2] = vec0[2] - vec1[2]; 168 | resultVec[3] = vec0[3] - vec1[3]; 169 | return resultVec; 170 | }; 171 | 172 | 173 | /** 174 | * Negates vec0, storing the result into resultVec. 175 | * 176 | * @param {goog.vec.Vec4.Vec4Like} vec0 The vector to negate. 177 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to 178 | * receive the result. May be vec0. 179 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 180 | * chained together. 181 | */ 182 | goog.vec.Vec4.negate = function(vec0, resultVec) { 183 | resultVec[0] = -vec0[0]; 184 | resultVec[1] = -vec0[1]; 185 | resultVec[2] = -vec0[2]; 186 | resultVec[3] = -vec0[3]; 187 | return resultVec; 188 | }; 189 | 190 | 191 | /** 192 | * Multiplies each component of vec0 with scalar storing the product into 193 | * resultVec. 194 | * 195 | * @param {goog.vec.Vec4.Vec4Like} vec0 The source vector. 196 | * @param {number} scalar The value to multiply with each component of vec0. 197 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to 198 | * receive the result. May be vec0. 199 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 200 | * chained together. 201 | */ 202 | goog.vec.Vec4.scale = function(vec0, scalar, resultVec) { 203 | resultVec[0] = vec0[0] * scalar; 204 | resultVec[1] = vec0[1] * scalar; 205 | resultVec[2] = vec0[2] * scalar; 206 | resultVec[3] = vec0[3] * scalar; 207 | return resultVec; 208 | }; 209 | 210 | 211 | /** 212 | * Returns the magnitudeSquared of the given vector. 213 | * 214 | * @param {goog.vec.Vec4.Vec4Like} vec0 The vector. 215 | * @return {number} The magnitude of the vector. 216 | */ 217 | goog.vec.Vec4.magnitudeSquared = function(vec0) { 218 | var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3]; 219 | return x * x + y * y + z * z + w * w; 220 | }; 221 | 222 | 223 | /** 224 | * Returns the magnitude of the given vector. 225 | * 226 | * @param {goog.vec.Vec4.Vec4Like} vec0 The vector. 227 | * @return {number} The magnitude of the vector. 228 | */ 229 | goog.vec.Vec4.magnitude = function(vec0) { 230 | var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3]; 231 | return Math.sqrt(x * x + y * y + z * z + w * w); 232 | }; 233 | 234 | 235 | /** 236 | * Normalizes the given vector storing the result into resultVec. 237 | * 238 | * @param {goog.vec.Vec4.Vec4Like} vec0 The vector to normalize. 239 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to 240 | * receive the result. May be vec0. 241 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 242 | * chained together. 243 | */ 244 | goog.vec.Vec4.normalize = function(vec0, resultVec) { 245 | var ilen = 1 / goog.vec.Vec4.magnitude(vec0); 246 | resultVec[0] = vec0[0] * ilen; 247 | resultVec[1] = vec0[1] * ilen; 248 | resultVec[2] = vec0[2] * ilen; 249 | resultVec[3] = vec0[3] * ilen; 250 | return resultVec; 251 | }; 252 | 253 | 254 | /** 255 | * Returns the scalar product of vectors v0 and v1. 256 | * 257 | * @param {goog.vec.Vec4.Vec4Like} v0 The first vector. 258 | * @param {goog.vec.Vec4.Vec4Like} v1 The second vector. 259 | * @return {number} The scalar product. 260 | */ 261 | goog.vec.Vec4.dot = function(v0, v1) { 262 | return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2] + v0[3] * v1[3]; 263 | }; 264 | 265 | 266 | /** 267 | * Linearly interpolate from v0 to v1 according to f. The value of f should be 268 | * in the range [0..1] otherwise the results are undefined. 269 | * 270 | * @param {goog.vec.Vec4.Vec4Like} v0 The first vector. 271 | * @param {goog.vec.Vec4.Vec4Like} v1 The second vector. 272 | * @param {number} f The interpolation factor. 273 | * @param {goog.vec.Vec4.Vec4Like} resultVec The vector to receive the 274 | * results (may be v0 or v1). 275 | * @return {!goog.vec.Vec4.Vec4Like} return resultVec so that operations can be 276 | * chained together. 277 | */ 278 | goog.vec.Vec4.lerp = function(v0, v1, f, resultVec) { 279 | var x = v0[0], y = v0[1], z = v0[2], w = v0[3]; 280 | resultVec[0] = (v1[0] - x) * f + x; 281 | resultVec[1] = (v1[1] - y) * f + y; 282 | resultVec[2] = (v1[2] - z) * f + z; 283 | resultVec[3] = (v1[3] - w) * f + w; 284 | return resultVec; 285 | }; 286 | 287 | 288 | /** 289 | * Returns true if the components of v0 are equal to the components of v1. 290 | * 291 | * @param {goog.vec.Vec4.Vec4Like} v0 The first vector. 292 | * @param {goog.vec.Vec4.Vec4Like} v1 The second vector. 293 | * @return {boolean} True if the vectors are equal, false otherwise. 294 | */ 295 | goog.vec.Vec4.equals = function(v0, v1) { 296 | return v0.length == v1.length && 297 | v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] && v0[3] == v1[3]; 298 | }; 299 | -------------------------------------------------------------------------------- /libs/glMatrix/glMatrix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /libs/mjs/mjs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /libs/tdl/tdl-fast.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /libs/tdl/tdl-math.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Matrix Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /libs/tdl/tdl/base.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009, Google Inc. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above 12 | * copyright notice, this list of conditions and the following disclaimer 13 | * in the documentation and/or other materials provided with the 14 | * distribution. 15 | * * Neither the name of Google Inc. nor the names of its 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | 33 | /** 34 | * @fileoverview Base for all tdl sample utilties. 35 | * 36 | * The main point of this module is to provide a central place to 37 | * have an init function to register an tdl namespace object because many other 38 | * modules need access to it. 39 | */ 40 | 41 | /** 42 | * A namespace for all the tdl utility libraries. 43 | * @namespace 44 | */ 45 | var tdl = tdl || {}; 46 | 47 | /** 48 | * Define this because the Google internal JSCompiler needs goog.typedef below. 49 | */ 50 | var goog = goog || {}; 51 | 52 | 53 | if (!window.Int32Array) { 54 | window.Int32Array = function() { }; 55 | window.Float32Array = function() { }; 56 | window.Uint16Array = function() { }; 57 | } 58 | 59 | /** 60 | * A macro for defining composite types. 61 | * 62 | * By assigning goog.typedef to a name, this tells Google internal JSCompiler 63 | * that this is not the name of a class, but rather it's the name of a composite 64 | * type. 65 | * 66 | * For example, 67 | * /** @type {Array|NodeList} / goog.ArrayLike = goog.typedef; 68 | * will tell JSCompiler to replace all appearances of goog.ArrayLike in type 69 | * definitions with the union of Array and NodeList. 70 | * 71 | * Does nothing in uncompiled code. 72 | */ 73 | goog.typedef = true; 74 | 75 | /** 76 | * Reference to the global context. In most cases this will be 'window'. 77 | */ 78 | tdl.global = this; 79 | 80 | /** 81 | * Some javascripts don't support __defineGetter__ or __defineSetter__ 82 | * so we define some here so at least we don't get compile errors. 83 | * We expect the initialzation code will check and complain. This stubs 84 | * are just here to make sure we can actually get to the initialization code. 85 | */ 86 | //if (!Object.prototype.__defineSetter__) { 87 | // Object.prototype.__defineSetter__ = function() {} 88 | // Object.prototype.__defineGetter__ = function() {} 89 | //} 90 | // 91 | /** 92 | * Flag used to force a function to run in the browser when it is called 93 | * from V8. 94 | * @type {boolean} 95 | */ 96 | tdl.BROWSER_ONLY = true; 97 | 98 | /** 99 | * Array of namespaces that have been provided. 100 | * @private 101 | * @type {!Array.} 102 | */ 103 | tdl.provided_ = []; 104 | 105 | /** 106 | * Creates object stubs for a namespace. When present in a file, 107 | * tdl.provide also indicates that the file defines the indicated 108 | * object. 109 | * @param {string} name name of the object that this file defines. 110 | */ 111 | tdl.provide = function(name) { 112 | // Ensure that the same namespace isn't provided twice. 113 | if (tdl.getObjectByName(name) && 114 | !tdl.implicitNamespaces_[name]) { 115 | throw 'Namespace "' + name + '" already declared.'; 116 | } 117 | 118 | var namespace = name; 119 | while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { 120 | tdl.implicitNamespaces_[namespace] = true; 121 | } 122 | 123 | tdl.exportPath_(name); 124 | tdl.provided_.push(name); 125 | }; 126 | 127 | 128 | /** 129 | * Namespaces implicitly defined by tdl.provide. For example, 130 | * tdl.provide('tdl.events.Event') implicitly declares 131 | * that 'tdl' and 'tdl.events' must be namespaces. 132 | * 133 | * @type {Object} 134 | * @private 135 | */ 136 | tdl.implicitNamespaces_ = {}; 137 | 138 | /** 139 | * Builds an object structure for the provided namespace path, 140 | * ensuring that names that already exist are not overwritten. For 141 | * example: 142 | * "a.b.c" -> a = {};a.b={};a.b.c={}; 143 | * Used by tdl.provide and tdl.exportSymbol. 144 | * @param {string} name name of the object that this file defines. 145 | * @param {Object} opt_object the object to expose at the end of the path. 146 | * @param {Object} opt_objectToExportTo The object to add the path to; default 147 | * is |tdl.global|. 148 | * @private 149 | */ 150 | tdl.exportPath_ = function(name, opt_object, opt_objectToExportTo) { 151 | var parts = name.split('.'); 152 | var cur = opt_objectToExportTo || tdl.global; 153 | var part; 154 | 155 | // Internet Explorer exhibits strange behavior when throwing errors from 156 | // methods externed in this manner. See the testExportSymbolExceptions in 157 | // base_test.html for an example. 158 | if (!(parts[0] in cur) && cur.execScript) { 159 | cur.execScript('var ' + parts[0]); 160 | } 161 | 162 | // Parentheses added to eliminate strict JS warning in Firefox. 163 | while (parts.length && (part = parts.shift())) { 164 | if (!parts.length && tdl.isDef(opt_object)) { 165 | // last part and we have an object; use it. 166 | cur[part] = opt_object; 167 | } else if (cur[part]) { 168 | cur = cur[part]; 169 | } else { 170 | cur = cur[part] = {}; 171 | } 172 | } 173 | }; 174 | 175 | 176 | /** 177 | * Returns an object based on its fully qualified external name. If you are 178 | * using a compilation pass that renames property names beware that using this 179 | * function will not find renamed properties. 180 | * 181 | * @param {string} name The fully qualified name. 182 | * @param {Object} opt_obj The object within which to look; default is 183 | * |tdl.global|. 184 | * @return {Object} The object or, if not found, null. 185 | */ 186 | tdl.getObjectByName = function(name, opt_obj) { 187 | var parts = name.split('.'); 188 | var cur = opt_obj || tdl.global; 189 | for (var pp = 0; pp < parts.length; ++pp) { 190 | var part = parts[pp]; 191 | if (cur[part]) { 192 | cur = cur[part]; 193 | } else { 194 | return null; 195 | } 196 | } 197 | return cur; 198 | }; 199 | 200 | 201 | /** 202 | * Implements a system for the dynamic resolution of dependencies. 203 | * @param {string} rule Rule to include, in the form tdl.package.part. 204 | */ 205 | tdl.require = function(rule) { 206 | // TODO(gman): For some unknown reason, when we call 207 | // tdl.util.getScriptTagText_ it calls 208 | // document.getElementsByTagName('script') and for some reason the scripts do 209 | // not always show up. Calling it here seems to fix that as long as we 210 | // actually ask for the length, at least in FF 3.5.1 It would be nice to 211 | // figure out why. 212 | var dummy = document.getElementsByTagName('script').length; 213 | // if the object already exists we do not need do do anything 214 | if (tdl.getObjectByName(rule)) { 215 | return; 216 | } 217 | var path = tdl.getPathFromRule_(rule); 218 | if (path) { 219 | tdl.included_[path] = true; 220 | tdl.writeScripts_(); 221 | } else { 222 | throw new Error('tdl.require could not find: ' + rule); 223 | } 224 | }; 225 | 226 | 227 | /** 228 | * Path for included scripts. 229 | * @type {string} 230 | */ 231 | tdl.basePath = ''; 232 | 233 | 234 | /** 235 | * Object used to keep track of urls that have already been added. This 236 | * record allows the prevention of circular dependencies. 237 | * @type {Object} 238 | * @private 239 | */ 240 | tdl.included_ = {}; 241 | 242 | 243 | /** 244 | * This object is used to keep track of dependencies and other data that is 245 | * used for loading scripts. 246 | * @private 247 | * @type {Object} 248 | */ 249 | tdl.dependencies_ = { 250 | visited: {}, // used when resolving dependencies to prevent us from 251 | // visiting the file twice. 252 | written: {} // used to keep track of script files we have written. 253 | }; 254 | 255 | 256 | /** 257 | * Tries to detect the base path of the tdl-base.js script that 258 | * bootstraps the tdl libraries. 259 | * @private 260 | */ 261 | tdl.findBasePath_ = function() { 262 | var doc = tdl.global.document; 263 | if (typeof doc == 'undefined') { 264 | return; 265 | } 266 | if (tdl.global.BASE_PATH) { 267 | tdl.basePath = tdl.global.BASE_PATH; 268 | return; 269 | } else { 270 | // HACKHACK to hide compiler warnings :( 271 | tdl.global.BASE_PATH = null; 272 | } 273 | var expectedBase = 'tdl/base.js'; 274 | var scripts = doc.getElementsByTagName('script'); 275 | for (var script, i = 0; script = scripts[i]; i++) { 276 | var src = script.src; 277 | var l = src.length; 278 | if (src.substr(l - expectedBase.length) == expectedBase) { 279 | tdl.basePath = src.substr(0, l - expectedBase.length); 280 | return; 281 | } 282 | } 283 | }; 284 | 285 | 286 | /** 287 | * Writes a script tag if, and only if, that script hasn't already been added 288 | * to the document. (Must be called at execution time.) 289 | * @param {string} src Script source. 290 | * @private 291 | */ 292 | tdl.writeScriptTag_ = function(src) { 293 | var doc = tdl.global.document; 294 | if (typeof doc != 'undefined' && 295 | !tdl.dependencies_.written[src]) { 296 | tdl.dependencies_.written[src] = true; 297 | var html = ' 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 154 | 155 | 156 | 168 | 169 | 170 |

171 | This page benchmarks the performance of a collection of matrix libraries most of which are intended for use with WebGL:
172 | glMatrix (v1.2, 2011-12-13), 173 | mjs (rev 16, 2010-12-15), 174 | CanvasMatrix, 175 | EWGL_math (rev 32, 2011-03-15), 176 | the math utilities in Google's Closure (svn rev: 1364, 2011-11-3), 177 | tdl (commit: 59d484f, 2011-06-03), and 178 | Sylvester (v0.1.3, 2007-07-05).
179 | Benchmarks for each library are run in an iframe. Results measure millions of iterations per second of the target operation.
180 |

181 |
182 |
183 | 184 | 185 | 186 | 187 | 188 |
189 |
190 |

191 | Adapted by Stephen Bannasch from the benchmarks Brandon Jones created in his glmatrix library.
192 | Additional improvements by Gregg Tavares.
193 | Sylvester benchmarks by Felix E. Klee.
194 | JavaScript Plotting library: Flotr; 195 | Sortable Table by Andrew Tetlaw.
196 | The source code for these benchmarks can be found here on github. Pull requests quite welcome!
197 |

198 |

199 |
200 | 201 | 202 | 433 | 438 | 439 | 440 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Simple benchmarks for testing the speed of JavaScript matrix libraries adapted from Brandon Jones benchmarks 2 | in his glmatrix library: https://glmatrix.googlecode.com/hg/ 3 | 4 | If you have a browser with WebGL you can run the benchmarks [here](http://stepheneb.github.com/webgl-matrix-benchmarks/matrix_benchmark.html). 5 | 6 | This work is based on Brandon's work as of this commit: 7 | 8 | e5ad8f6975eef038de668914a44ed36e2c611966 9 | Date: October 10, 2010 12:49:00 PM EDT 10 | Upped version to 0.9.5 11 | 12 | Comparing these matrix libraries: 13 | 14 | * [glMatrix](http://code.google.com/p/glmatrix), [zlib license](http://www.opensource.org/licenses/Zlib) 15 | * [mjs](http://code.google.com/p/webgl-mjs), [MIT license](http://www.opensource.org/licenses/mit-license.php) 16 | * CanvasMatrix 17 | * [EWGL_math](http://code.google.com/p/ewgl-matrices), [New BSD license](http://www.opensource.org/licenses/bsd-license.php) 18 | * [tdl](http://code.google.com/p/threedlibrary/), [New BSD license](http://www.opensource.org/licenses/bsd-license.php) 19 | * [Closure](http://closure-library.googlecode.com/), [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) 20 | * [Sylvester](http://sylvester.jcoglan.com/), [MIT license](http://www.opensource.org/licenses/mit-license.php) 21 | 22 | Changes from Brandon's original benchmark code include: 23 | 24 | * Only including the benchmark code from glmatrix. 25 | * Updated to the latest mjs as of Dec 15: 16:8e5b0944ef1e and included it in several more tests. 26 | * Added a graph display of the results using flotr, see: http://solutoire.com/flotr/ 27 | * Added tdl library (thanks to Gregg Tavares) 28 | * each library runs in an iframe so the code won't affect the other libraries (thanks to Gregg Tavares) 29 | * Added Sylvester library (thanks to [Felix E. Klee](mailto:felix.klee@inka.de)) 30 | 31 | Brandon's original code was released under the [New BSD license](http://www.opensource.org/licenses/bsd-license.php). 32 | My additions to the benchmarking code are released under the same license. 33 | 34 | ## Running locally requires a web server. 35 | 36 | With the recent changes by Gregg Tavares that run each library in an iFrame you will need to either: 37 | 38 | * Run the benchmarks from a local web server 39 | * Configure the browser to allow local file access 40 | 41 | ### Configuring Chrome to allow local file access 42 | 43 | On Windows you can add a flag in the shortcut. 44 | 45 | On Mac OS X start Chrome from the command line like this: 46 | 47 | /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files 48 | 49 | ### Using Python's SimpleHTTPServer 50 | 51 | cd /path/to/webgl-matrix-benchmarks 52 | python -m SimpleHTTPServer 53 | 54 | Now open: 55 | 56 | ### Set up an webgl-matrix-benchmarks.local local host and Apache vhost on Mac OS X 57 | 58 | On OS X, turn on Web Sharing via (Apple Menu) -> System Preferences -> Sharing -> Web Sharing 59 | 60 | Now, make sure that virtual hosting is enabled by editing `/private/etc/apache2/httpd.conf` and uncommenting the 61 | virtual hosting line (at about line 465 of the stock `httpd.conf`) as follows: 62 | 63 | # Virtual hosts 64 | Include /private/etc/apache2/extra/httpd-vhosts.conf 65 | 66 | At the top of httpd-vhosts.conf enable name-based virtual hosts for port 80 on all interfaces: 67 | 68 | NameVirtualHost *:80 69 | 70 | Edit the virtual hosting configuration file `/private/etc/apache2/extra/httpd-vhosts.conf` to include the entry: 71 | 72 | 73 | ServerName webgl-matrix-benchmarks 74 | DocumentRoot /path/to/webgl-matrix-benchmarks 75 | PassengerEnabled off 76 | 77 | Options +Indexes +FollowSymLinks +MultiViews +Includes 78 | AllowOverride All 79 | Order allow,deny 80 | Allow from all 81 | DirectoryIndex matrix_benchmark.html 82 | 83 | 84 | 85 | after making changes test the config: `apachectl configtest` 86 | 87 | When the configuration syntax is correct restart apache: `sudo apachectl restart` 88 | 89 | If there are issues try tailing the general apache2 error log: `tail -n 200 -f /var/log/apache2/error_log` 90 | 91 | For more instructions, set . 92 | 93 | And, finally, edit your `/etc/hosts` file to include the following line: 94 | 95 | 127.0.0.1 webgl-matrix-benchmarks.local 96 | 97 | Confirm that the new entry works: 98 | 99 | $ dscacheutil -q host -a name webgl-matrix-benchmarks.local 100 | name: webgl-matrix-benchmarks.local 101 | ip_address: 127.0.0.1 102 | 103 | It might be necessary to flush the local DNS cache: 104 | 105 | $ sudo dscacheutil -flushcache 106 | 107 | Now open: 108 | -------------------------------------------------------------------------------- /sprintf.js: -------------------------------------------------------------------------------- 1 | /** 2 | sprintf() for JavaScript 0.7-beta1 3 | http://www.diveintojavascript.com/projects/javascript-sprintf 4 | 5 | Copyright (c) Alexandru Marasteanu 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | * Neither the name of sprintf() for JavaScript nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | Changelog: 32 | 2010.09.06 - 0.7-beta1 33 | - features: vsprintf, support for named placeholders 34 | - enhancements: format cache, reduced global namespace pollution 35 | 36 | 2010.05.22 - 0.6: 37 | - reverted to 0.4 and fixed the bug regarding the sign of the number 0 38 | Note: 39 | Thanks to Raphael Pigulla (http://www.n3rd.org/) 40 | who warned me about a bug in 0.5, I discovered that the last update was 41 | a regress. I appologize for that. 42 | 43 | 2010.05.09 - 0.5: 44 | - bug fix: 0 is now preceeded with a + sign 45 | - bug fix: the sign was not at the right position on padded results (Kamal Abdali) 46 | - switched from GPL to BSD license 47 | 48 | 2007.10.21 - 0.4: 49 | - unit test and patch (David Baird) 50 | 51 | 2007.09.17 - 0.3: 52 | - bug fix: no longer throws exception on empty paramenters (Hans Pufal) 53 | 54 | 2007.09.11 - 0.2: 55 | - feature: added argument swapping 56 | 57 | 2007.04.03 - 0.1: 58 | - initial release 59 | **/ 60 | 61 | var sprintf = (function() { 62 | function get_type(variable) { 63 | return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); 64 | } 65 | function str_repeat(input, multiplier) { 66 | for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} 67 | return output.join(''); 68 | } 69 | 70 | var str_format = function() { 71 | if (!str_format.cache.hasOwnProperty(arguments[0])) { 72 | str_format.cache[arguments[0]] = str_format.parse(arguments[0]); 73 | } 74 | return str_format.format.call(null, str_format.cache[arguments[0]], arguments); 75 | }; 76 | 77 | str_format.format = function(parse_tree, argv) { 78 | var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; 79 | for (i = 0; i < tree_length; i++) { 80 | node_type = get_type(parse_tree[i]); 81 | if (node_type === 'string') { 82 | output.push(parse_tree[i]); 83 | } 84 | else if (node_type === 'array') { 85 | match = parse_tree[i]; // convenience purposes only 86 | if (match[2]) { // keyword argument 87 | arg = argv[cursor]; 88 | for (k = 0; k < match[2].length; k++) { 89 | if (!arg.hasOwnProperty(match[2][k])) { 90 | throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); 91 | } 92 | arg = arg[match[2][k]]; 93 | } 94 | } 95 | else if (match[1]) { // positional argument (explicit) 96 | arg = argv[match[1]]; 97 | } 98 | else { // positional argument (implicit) 99 | arg = argv[cursor++]; 100 | } 101 | 102 | if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { 103 | throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); 104 | } 105 | switch (match[8]) { 106 | case 'b': arg = arg.toString(2); break; 107 | case 'c': arg = String.fromCharCode(arg); break; 108 | case 'd': arg = parseInt(arg, 10); break; 109 | case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; 110 | case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; 111 | case 'o': arg = arg.toString(8); break; 112 | case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; 113 | case 'u': arg = Math.abs(arg); break; 114 | case 'x': arg = arg.toString(16); break; 115 | case 'X': arg = arg.toString(16).toUpperCase(); break; 116 | } 117 | arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); 118 | pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; 119 | pad_length = match[6] - String(arg).length; 120 | pad = match[6] ? str_repeat(pad_character, pad_length) : ''; 121 | output.push(match[5] ? arg + pad : pad + arg); 122 | } 123 | } 124 | return output.join(''); 125 | }; 126 | 127 | str_format.cache = {}; 128 | 129 | str_format.parse = function(fmt) { 130 | var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; 131 | while (_fmt) { 132 | if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { 133 | parse_tree.push(match[0]); 134 | } 135 | else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { 136 | parse_tree.push('%'); 137 | } 138 | else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { 139 | if (match[2]) { 140 | arg_names |= 1; 141 | var field_list = [], replacement_field = match[2], field_match = []; 142 | if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 143 | field_list.push(field_match[1]); 144 | while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { 145 | if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 146 | field_list.push(field_match[1]); 147 | } 148 | else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { 149 | field_list.push(field_match[1]); 150 | } 151 | else { 152 | throw('[sprintf] huh?'); 153 | } 154 | } 155 | } 156 | else { 157 | throw('[sprintf] huh?'); 158 | } 159 | match[2] = field_list; 160 | } 161 | else { 162 | arg_names |= 2; 163 | } 164 | if (arg_names === 3) { 165 | throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); 166 | } 167 | parse_tree.push(match); 168 | } 169 | else { 170 | throw('[sprintf] huh?'); 171 | } 172 | _fmt = _fmt.substring(match[0].length); 173 | } 174 | return parse_tree; 175 | }; 176 | 177 | return str_format; 178 | })(); 179 | 180 | var vsprintf = function(fmt, argv) { 181 | argv.unshift(fmt); 182 | return sprintf.apply(null, argv); 183 | }; 184 | -------------------------------------------------------------------------------- /table/fastinit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2006 Andrew Tetlaw 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * * 25 | * 26 | /* 27 | * FastInit 28 | * http://tetlaw.id.au/view/blog/prototype-class-fastinit/ 29 | * Andrew Tetlaw 30 | * Version 1.2 (2006-10-19) 31 | * Based on: 32 | * http://dean.edwards.name/weblog/2006/03/faster 33 | * http://dean.edwards.name/weblog/2006/06/again/ 34 | * 35 | */ 36 | var FastInit = { 37 | done : false, 38 | onload : function() { 39 | if (FastInit.done) return; 40 | FastInit.done = true; 41 | FastInit.actions.each(function(func) { 42 | func(); 43 | }) 44 | }, 45 | actions : $A([]), 46 | addOnLoad : function() { 47 | for(var x = 0; x < arguments.length; x++) { 48 | var func = arguments[x]; 49 | if(!func || typeof func != 'function') continue; 50 | FastInit.actions.push(func); 51 | } 52 | } 53 | } 54 | 55 | if (/WebKit|khtml/i.test(navigator.userAgent)) { 56 | var _timer = setInterval(function() { 57 | if (/loaded|complete/.test(document.readyState)) { 58 | clearInterval(_timer); 59 | delete _timer; 60 | FastInit.onload(); 61 | } 62 | }, 10); 63 | } 64 | if (document.addEventListener) { 65 | document.addEventListener('DOMContentLoaded', FastInit.onload, false); 66 | FastInit.legacy = false; 67 | } 68 | 69 | Event.observe(window, 'load', FastInit.onload); 70 | 71 | 72 | /*@cc_on @*/ 73 | /*@if (@_win32) 74 | document.write('