├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── dist ├── glmw-browser.js ├── glmw-node.es.js └── glmw-node.js ├── example ├── gl-matrix.min.js └── index.html ├── interfaces ├── generate.js ├── ignore_this.txt ├── index.js ├── interfaces-special.json ├── interfaces.json └── modules.js ├── package.json ├── rollup ├── compile.wasm.js ├── rollup.bundle.js ├── rollup.config.cjs.js ├── rollup.config.es.js ├── rollup.config.iife.js └── rollup.config.js └── src ├── gl-matrix ├── bridges │ ├── mat4.js │ ├── vec3.js │ └── vec4.js ├── common.h ├── main.c ├── mat4.c ├── vec3.c └── vec4.c ├── index.js └── utils.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | src/module.js 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directories 29 | node_modules 30 | jspm_packages 31 | 32 | # Optional npm cache directory 33 | .npm 34 | 35 | # Optional REPL history 36 | .node_repl_history 37 | 38 | # ========================= 39 | # Operating System Files 40 | # ========================= 41 | 42 | # OSX 43 | # ========================= 44 | 45 | .DS_Store 46 | .AppleDouble 47 | .LSOverride 48 | 49 | # Thumbnails 50 | ._* 51 | 52 | # Files that might appear in the root of a volume 53 | .DocumentRevisions-V100 54 | .fseventsd 55 | .Spotlight-V100 56 | .TemporaryItems 57 | .Trashes 58 | .VolumeIcon.icns 59 | 60 | # Directories potentially created on remote AFP share 61 | .AppleDB 62 | .AppleDesktop 63 | Network Trash Folder 64 | Temporary Items 65 | .apdisk 66 | 67 | # Windows 68 | # ========================= 69 | 70 | # Windows image file caches 71 | Thumbs.db 72 | ehthumbs.db 73 | 74 | # Folder config file 75 | Desktop.ini 76 | 77 | # Recycle Bin used on file shares 78 | $RECYCLE.BIN/ 79 | 80 | # Windows Installer files 81 | *.cab 82 | *.msi 83 | *.msm 84 | *.msp 85 | 86 | # Windows shortcuts 87 | *.lnk 88 | 89 | www 90 | 91 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Felix Maier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | GLMW - WebAssembly powered Matrix and Vector library 3 |

4 | 5 |
6 | 7 | ### Description 8 | This is an experimental near 1:1 port of [gl-matrix](https://github.com/toji/gl-matrix) [v2.4.0](https://github.com/toji/gl-matrix/blob/master/package.json#L4) to WebAssembly. 9 | 10 | ### Performance 11 | In many cases *glmw* runs more than twice as fast as *gl-matrix*. 12 | 13 | Some methods like ``*.str`` and ``*.equals`` are bridged and bring in some extra overhead. 14 | 15 | Creating views with ``*.view`` is cheap, because they return a typed ``subarray`` of the WebAssembly module's memory buffer. 16 | 17 | ### Benchmarks 18 | - [**mat4**](https://maierfelix.github.io/glmw/mat4/) 19 | 20 | ### Limitations 21 | - This library requires async instantiation, since WebAssembly has a [synchronous buffer instantiation size limitation](https://github.com/WebAssembly/design/issues/1190). 22 | - You need to manually free data, since there is no garbage collection yet (**be careful! :p**). 23 | - Methods like ``mat4.create`` and ``mat4.multiply`` return a numeric address. To get an view on your data you need to use e.g. ``mat4.view(address)``. This returns a ``Float32Array`` which is a direct view onto the allocated data in WebAssembly's memory. You can manually read/write from this view. 24 | - WebAssembly's memory cannot be directly shared with JavaScript's memory. This means that you cannot pass an JavaScript array into methods like ``vec3.sqrLength``. You first have to convert it into the given module type (e.g. ``vec3.fromValues``) which then gives you the memory address of the allocated data. 25 | - There is some overhead when calling from JavaScript->WebAssembly, but it seems acceptable. Slight performance drops are noticeable when calling a function more than ~15.000 times. 26 | 27 | ### Bridged methods 28 | - ``*.str`` so a *JavaScript String* is returned. 29 | - ``*.equals`` so a *JavaScript Boolean* is returned. 30 | - ``*.exactEquals`` (see ``*.equals``). 31 | 32 | ### New methods 33 | - ``*.view`` lets you create views onto your data in WebAssembly's memory. 34 | - ``*.free`` to free data from WebAssembly's memory. 35 | 36 | ### What is left 37 | 38 | #### API modules 39 | - ``mat2`` 40 | - ``mat2d`` 41 | - ``mat3`` 42 | - ``vec2`` 43 | - ``quat`` 44 | 45 | ### Installation 46 | ```` 47 | npm install glmw 48 | ```` 49 | or the browser distribution from [here](//rawgit.com/maierfelix/glmw/master/dist/glmw-browser.js). 50 | 51 | ### Instantiation 52 | Before being able to use the library, you first have to call it's ``init`` method which then asynchronously compiles the WebAssembly module. 53 | 54 | If you call a ``glmw`` function before it got instantiated somewhere, then a ``TypeError`` is thrown, because the function is simply not compiled yet. 55 | 56 | #### Browser 57 | This builds and compiles the WebAssembly module. 58 | ````html 59 | 60 | ```` 61 | ````js 62 | glmw.init().then(ready => { 63 | // glmw is now ready and can be used anywhere 64 | }); 65 | ```` 66 | 67 | #### ES 68 | Import and call the init method in your main file. Afterwards you can use ``glmw`` **anywhere**. 69 | 70 | *index.js* 71 | ````js 72 | import { init, vec3 } from "glmw"; 73 | import calc from "./calc"; 74 | 75 | init().then(ready => { 76 | // glmw is now ready and can be used anywhere 77 | calc(); 78 | }); 79 | ```` 80 | 81 | *calc.js* 82 | ````js 83 | import { mat4 } from "glmw"; 84 | export default function() { 85 | return mat4.create(); 86 | }; 87 | ```` 88 | 89 | #### Node 90 | Require and call the init method in your main file. Afterwards you can use ``glmw`` **anywhere**. 91 | 92 | *index.js* 93 | ````js 94 | const { init, vec3 } = require("glmw"); 95 | const calc = require("./calc"); 96 | 97 | init().then(ready => { 98 | // glmw is now ready and can be used anywhere 99 | calc(); 100 | }); 101 | ```` 102 | 103 | *calc.js* 104 | ````js 105 | const { mat4 } = require("glmw"); 106 | module.exports = function() { 107 | return mat4.create(); 108 | }; 109 | ```` 110 | 111 | ### Usage 112 | 113 | #### Simple example 114 | As you can see here, the API didn't really change. 115 | ````js 116 | let a = vec3.create(); 117 | let b = vec3.fromValues(1.0, 2.0, 3.0); 118 | vec3.add(a, a, b); 119 | console.log( vec3.view(a) ); // Float32Array(3) [1, 2, 3] 120 | ```` 121 | 122 | #### Creating views 123 | First, this is what *glmw* returns to you. Instead of references, only the numeric addresses are returned: 124 | ````js 125 | a = mat4.create(); // 65688 126 | b = mat4.create(); // 65760 127 | c = mat4.multiply(a, a, b); // 65688 128 | ```` 129 | You can change data by hand this way: 130 | ````js 131 | vA = mat4.view(a); // Float32Array([1, 0, 0...]) 132 | vA[0] = 2; // you can now read/write 133 | vA; // Float32Array([2, 0, 0...]) 134 | ```` 135 | 136 | #### Freeing data 137 | Since WebAssembly doesn't have garbage collection yet, you have to be careful when and where you allocate data. 138 | You can free data by calling ``*.free``: 139 | ````js 140 | a = mat4.create(); // allocate data for a 141 | mat4.free(a); // a's data is now freed 142 | ```` -------------------------------------------------------------------------------- /example/gl-matrix.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview gl-matrix - High performance matrix and vector operations 3 | * @author Brandon Jones 4 | * @author Colin MacKenzie IV 5 | * @version 2.4.0 6 | */ 7 | 8 | /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. */ 27 | 28 | !function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(this,function(){return function(t){function n(a){if(r[a])return r[a].exports;var e=r[a]={i:a,l:!1,exports:{}};return t[a].call(e.exports,e,e.exports,n),e.l=!0,e.exports}var r={};return n.m=t,n.c=r,n.d=function(t,r,a){n.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:a})},n.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=4)}([function(t,n,r){"use strict";function a(t){n.ARRAY_TYPE=i=t}function e(t){return t*s}function u(t,n){return Math.abs(t-n)<=o*Math.max(1,Math.abs(t),Math.abs(n))}Object.defineProperty(n,"__esModule",{value:!0}),n.setMatrixArrayType=a,n.toRadian=e,n.equals=u;var o=n.EPSILON=1e-6,i=n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,s=(n.RANDOM=Math.random,Math.PI/180)},function(t,n,r){"use strict";function a(){var t=new g.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function e(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t}function u(t){var n=new g.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n}function o(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function i(t,n,r,a,e,u,o,i,s){var c=new g.ARRAY_TYPE(9);return c[0]=t,c[1]=n,c[2]=r,c[3]=a,c[4]=e,c[5]=u,c[6]=o,c[7]=i,c[8]=s,c}function s(t,n,r,a,e,u,o,i,s,c){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t[6]=i,t[7]=s,t[8]=c,t}function c(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function f(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t}function M(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=f*o-i*c,h=-f*u+i*s,l=c*u-o*s,v=r*M+a*h+e*l;return v?(v=1/v,t[0]=M*v,t[1]=(-f*a+e*c)*v,t[2]=(i*a-e*o)*v,t[3]=h*v,t[4]=(f*r-e*s)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-c*r+a*s)*v,t[8]=(o*r-a*u)*v,t):null}function h(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8];return t[0]=o*f-i*c,t[1]=e*c-a*f,t[2]=a*i-e*o,t[3]=i*s-u*f,t[4]=r*f-e*s,t[5]=e*u-r*i,t[6]=u*c-o*s,t[7]=a*s-r*c,t[8]=r*o-a*u,t}function l(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],s=t[7],c=t[8];return n*(c*u-o*s)+r*(-c*e+o*i)+a*(s*e-u*i)}function v(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1],v=r[2],d=r[3],b=r[4],m=r[5],p=r[6],P=r[7],E=r[8];return t[0]=h*a+l*o+v*c,t[1]=h*e+l*i+v*f,t[2]=h*u+l*s+v*M,t[3]=d*a+b*o+m*c,t[4]=d*e+b*i+m*f,t[5]=d*u+b*s+m*M,t[6]=p*a+P*o+E*c,t[7]=p*e+P*i+E*f,t[8]=p*u+P*s+E*M,t}function d(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=s,t[6]=h*a+l*o+c,t[7]=h*e+l*i+f,t[8]=h*u+l*s+M,t}function b(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=Math.sin(r),l=Math.cos(r);return t[0]=l*a+h*o,t[1]=l*e+h*i,t[2]=l*u+h*s,t[3]=l*o-h*a,t[4]=l*i-h*e,t[5]=l*s-h*u,t[6]=c,t[7]=f,t[8]=M,t}function m(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function p(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t}function P(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function E(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function O(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t}function x(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[3]=f-m,t[6]=h+b,t[1]=f+m,t[4]=1-c-v,t[7]=l-d,t[2]=h-b,t[5]=l+d,t[8]=1-c-M,t}function A(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15],p=r*i-a*o,P=r*s-e*o,E=r*c-u*o,O=a*s-e*i,x=a*c-u*i,A=e*c-u*s,q=f*d-M*v,y=f*b-h*v,w=f*m-l*v,R=M*b-h*d,L=M*m-l*d,S=h*m-l*b,_=p*S-P*L+E*R+O*w-x*y+A*q;return _?(_=1/_,t[0]=(i*S-s*L+c*R)*_,t[1]=(s*w-o*S-c*y)*_,t[2]=(o*L-i*w+c*q)*_,t[3]=(e*L-a*S-u*R)*_,t[4]=(r*S-e*w+u*y)*_,t[5]=(a*w-r*L-u*q)*_,t[6]=(d*A-b*x+m*O)*_,t[7]=(b*E-v*A-m*P)*_,t[8]=(v*x-d*E+m*p)*_,t):null}function q(t,n,r){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/r,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t}function y(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"}function w(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))}function R(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t}function L(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t}function S(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t}function _(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t}function I(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]}function N(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=t[4],i=t[5],s=t[6],c=t[7],f=t[8],M=n[0],h=n[1],l=n[2],v=n[3],d=n[4],b=n[5],m=n[6],p=n[7],P=n[8];return Math.abs(r-M)<=g.EPSILON*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(a-h)<=g.EPSILON*Math.max(1,Math.abs(a),Math.abs(h))&&Math.abs(e-l)<=g.EPSILON*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(u-v)<=g.EPSILON*Math.max(1,Math.abs(u),Math.abs(v))&&Math.abs(o-d)<=g.EPSILON*Math.max(1,Math.abs(o),Math.abs(d))&&Math.abs(i-b)<=g.EPSILON*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(s-m)<=g.EPSILON*Math.max(1,Math.abs(s),Math.abs(m))&&Math.abs(c-p)<=g.EPSILON*Math.max(1,Math.abs(c),Math.abs(p))&&Math.abs(f-P)<=g.EPSILON*Math.max(1,Math.abs(f),Math.abs(P))}Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=a,n.fromMat4=e,n.clone=u,n.copy=o,n.fromValues=i,n.set=s,n.identity=c,n.transpose=f,n.invert=M,n.adjoint=h,n.determinant=l,n.multiply=v,n.translate=d,n.rotate=b,n.scale=m,n.fromTranslation=p,n.fromRotation=P,n.fromScaling=E,n.fromMat2d=O,n.fromQuat=x,n.normalFromMat4=A,n.projection=q,n.str=y,n.frob=w,n.add=R,n.subtract=L,n.multiplyScalar=S,n.multiplyScalarAndAdd=_,n.exactEquals=I,n.equals=N;var Y=r(0),g=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(Y);n.mul=v,n.sub=L},function(t,n,r){"use strict";function a(){var t=new Z.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t}function e(t){var n=new Z.ARRAY_TYPE(3);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n}function u(t){var n=t[0],r=t[1],a=t[2];return Math.sqrt(n*n+r*r+a*a)}function o(t,n,r){var a=new Z.ARRAY_TYPE(3);return a[0]=t,a[1]=n,a[2]=r,a}function i(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t}function s(t,n,r,a){return t[0]=n,t[1]=r,t[2]=a,t}function c(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t}function f(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t}function M(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t}function h(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t}function l(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t[2]=Math.ceil(n[2]),t}function v(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t[2]=Math.floor(n[2]),t}function d(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t}function b(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t}function m(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t[2]=Math.round(n[2]),t}function p(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t}function P(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t}function E(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return Math.sqrt(r*r+a*a+e*e)}function O(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return r*r+a*a+e*e}function x(t){var n=t[0],r=t[1],a=t[2];return n*n+r*r+a*a}function A(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t}function q(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t}function y(t,n){var r=n[0],a=n[1],e=n[2],u=r*r+a*a+e*e;return u>0&&(u=1/Math.sqrt(u),t[0]=n[0]*u,t[1]=n[1]*u,t[2]=n[2]*u),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function R(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2];return t[0]=e*s-u*i,t[1]=u*o-a*s,t[2]=a*i-e*o,t}function L(t,n,r,a){var e=n[0],u=n[1],o=n[2];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t}function S(t,n,r,a,e,u){var o=u*u,i=o*(2*u-3)+1,s=o*(u-2)+u,c=o*(u-1),f=o*(3-2*u);return t[0]=n[0]*i+r[0]*s+a[0]*c+e[0]*f,t[1]=n[1]*i+r[1]*s+a[1]*c+e[1]*f,t[2]=n[2]*i+r[2]*s+a[2]*c+e[2]*f,t}function _(t,n,r,a,e,u){var o=1-u,i=o*o,s=u*u,c=i*o,f=3*u*i,M=3*s*o,h=s*u;return t[0]=n[0]*c+r[0]*f+a[0]*M+e[0]*h,t[1]=n[1]*c+r[1]*f+a[1]*M+e[1]*h,t[2]=n[2]*c+r[2]*f+a[2]*M+e[2]*h,t}function I(t,n){n=n||1;var r=2*Z.RANDOM()*Math.PI,a=2*Z.RANDOM()-1,e=Math.sqrt(1-a*a)*n;return t[0]=Math.cos(r)*e,t[1]=Math.sin(r)*e,t[2]=a*n,t}function N(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[3]*a+r[7]*e+r[11]*u+r[15];return o=o||1,t[0]=(r[0]*a+r[4]*e+r[8]*u+r[12])/o,t[1]=(r[1]*a+r[5]*e+r[9]*u+r[13])/o,t[2]=(r[2]*a+r[6]*e+r[10]*u+r[14])/o,t}function Y(t,n,r){var a=n[0],e=n[1],u=n[2];return t[0]=a*r[0]+e*r[3]+u*r[6],t[1]=a*r[1]+e*r[4]+u*r[7],t[2]=a*r[2]+e*r[5]+u*r[8],t}function g(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2],c=r[3],f=c*a+i*u-s*e,M=c*e+s*a-o*u,h=c*u+o*e-i*a,l=-o*a-i*e-s*u;return t[0]=f*c+l*-o+M*-s-h*-i,t[1]=M*c+l*-i+h*-o-f*-s,t[2]=h*c+l*-s+f*-i-M*-o,t}function T(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0],u[1]=e[1]*Math.cos(a)-e[2]*Math.sin(a),u[2]=e[1]*Math.sin(a)+e[2]*Math.cos(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function j(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[2]*Math.sin(a)+e[0]*Math.cos(a),u[1]=e[1],u[2]=e[2]*Math.cos(a)-e[0]*Math.sin(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function D(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0]*Math.cos(a)-e[1]*Math.sin(a),u[1]=e[0]*Math.sin(a)+e[1]*Math.cos(a),u[2]=e[2],t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function V(t,n){var r=o(t[0],t[1],t[2]),a=o(n[0],n[1],n[2]);y(r,r),y(a,a);var e=w(r,a);return e>1?0:e<-1?Math.PI:Math.acos(e)}function z(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"}function F(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]}function Q(t,n){var r=t[0],a=t[1],e=t[2],u=n[0],o=n[1],i=n[2];return Math.abs(r-u)<=Z.EPSILON*Math.max(1,Math.abs(r),Math.abs(u))&&Math.abs(a-o)<=Z.EPSILON*Math.max(1,Math.abs(a),Math.abs(o))&&Math.abs(e-i)<=Z.EPSILON*Math.max(1,Math.abs(e),Math.abs(i))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.len=n.sqrDist=n.dist=n.div=n.mul=n.sub=void 0,n.create=a,n.clone=e,n.length=u,n.fromValues=o,n.copy=i,n.set=s,n.add=c,n.subtract=f,n.multiply=M,n.divide=h,n.ceil=l,n.floor=v,n.min=d,n.max=b,n.round=m,n.scale=p,n.scaleAndAdd=P,n.distance=E,n.squaredDistance=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.cross=R,n.lerp=L,n.hermite=S,n.bezier=_,n.random=I,n.transformMat4=N,n.transformMat3=Y,n.transformQuat=g,n.rotateX=T,n.rotateY=j,n.rotateZ=D,n.angle=V,n.str=z,n.exactEquals=F,n.equals=Q;var X=r(0),Z=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(X);n.sub=f,n.mul=M,n.div=h,n.dist=E,n.sqrDist=O,n.len=u,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=3),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=a*o,t[2]=e*o,t[3]=u*o),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function R(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t[3]=i+a*(r[3]-i),t}function L(t,n){return n=n||1,t[0]=T.RANDOM(),t[1]=T.RANDOM(),t[2]=T.RANDOM(),t[3]=T.RANDOM(),y(t,t),m(t,t,n),t}function S(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3];return t[0]=r[0]*a+r[4]*e+r[8]*u+r[12]*o,t[1]=r[1]*a+r[5]*e+r[9]*u+r[13]*o,t[2]=r[2]*a+r[6]*e+r[10]*u+r[14]*o,t[3]=r[3]*a+r[7]*e+r[11]*u+r[15]*o,t}function _(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2],c=r[3],f=c*a+i*u-s*e,M=c*e+s*a-o*u,h=c*u+o*e-i*a,l=-o*a-i*e-s*u;return t[0]=f*c+l*-o+M*-s-h*-i,t[1]=M*c+l*-i+h*-o-f*-s,t[2]=h*c+l*-s+f*-i-M*-o,t[3]=n[3],t}function I(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}function N(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function Y(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=n[0],i=n[1],s=n[2],c=n[3];return Math.abs(r-o)<=T.EPSILON*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(a-i)<=T.EPSILON*Math.max(1,Math.abs(a),Math.abs(i))&&Math.abs(e-s)<=T.EPSILON*Math.max(1,Math.abs(e),Math.abs(s))&&Math.abs(u-c)<=T.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.len=n.sqrDist=n.dist=n.div=n.mul=n.sub=void 0,n.create=a,n.clone=e,n.fromValues=u,n.copy=o,n.set=i,n.add=s,n.subtract=c,n.multiply=f,n.divide=M,n.ceil=h,n.floor=l,n.min=v,n.max=d,n.round=b,n.scale=m,n.scaleAndAdd=p,n.distance=P,n.squaredDistance=E,n.length=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.lerp=R,n.random=L,n.transformMat4=S,n.transformQuat=_,n.str=I,n.exactEquals=N,n.equals=Y;var g=r(0),T=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(g);n.sub=c,n.mul=f,n.div=M,n.dist=P,n.sqrDist=E,n.len=O,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=4),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i0?(a=2*Math.sqrt(r+1),t[3]=.25*a,t[0]=(n[6]-n[9])/a,t[1]=(n[8]-n[2])/a,t[2]=(n[1]-n[4])/a):n[0]>n[5]&n[0]>n[10]?(a=2*Math.sqrt(1+n[0]-n[5]-n[10]),t[3]=(n[6]-n[9])/a,t[0]=.25*a,t[1]=(n[1]+n[4])/a,t[2]=(n[8]+n[2])/a):n[5]>n[10]?(a=2*Math.sqrt(1+n[5]-n[0]-n[10]),t[3]=(n[8]-n[2])/a,t[0]=(n[1]+n[4])/a,t[1]=.25*a,t[2]=(n[6]+n[9])/a):(a=2*Math.sqrt(1+n[10]-n[0]-n[5]),t[3]=(n[1]-n[4])/a,t[0]=(n[8]+n[2])/a,t[1]=(n[6]+n[9])/a,t[2]=.25*a),t}function _(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],s=e+e,c=u+u,f=o+o,M=e*s,h=e*c,l=e*f,v=u*c,d=u*f,b=o*f,m=i*s,p=i*c,P=i*f,E=a[0],O=a[1],x=a[2];return t[0]=(1-(v+b))*E,t[1]=(h+P)*E,t[2]=(l-p)*E,t[3]=0,t[4]=(h-P)*O,t[5]=(1-(M+b))*O,t[6]=(d+m)*O,t[7]=0,t[8]=(l+p)*x,t[9]=(d-m)*x,t[10]=(1-(M+v))*x,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t}function I(t,n,r,a,e){var u=n[0],o=n[1],i=n[2],s=n[3],c=u+u,f=o+o,M=i+i,h=u*c,l=u*f,v=u*M,d=o*f,b=o*M,m=i*M,p=s*c,P=s*f,E=s*M,O=a[0],x=a[1],A=a[2],q=e[0],y=e[1],w=e[2];return t[0]=(1-(d+m))*O,t[1]=(l+E)*O,t[2]=(v-P)*O,t[3]=0,t[4]=(l-E)*x,t[5]=(1-(h+m))*x,t[6]=(b+p)*x,t[7]=0,t[8]=(v+P)*A,t[9]=(b-p)*A,t[10]=(1-(h+d))*A,t[11]=0,t[12]=r[0]+q-(t[0]*q+t[4]*y+t[8]*w),t[13]=r[1]+y-(t[1]*q+t[5]*y+t[9]*w),t[14]=r[2]+w-(t[2]*q+t[6]*y+t[10]*w),t[15]=1,t}function N(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[1]=f+m,t[2]=h-b,t[3]=0,t[4]=f-m,t[5]=1-c-v,t[6]=l+d,t[7]=0,t[8]=h+b,t[9]=l-d,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function Y(t,n,r,a,e,u,o){var i=1/(r-n),s=1/(e-a),c=1/(u-o);return t[0]=2*u*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*s,t[6]=0,t[7]=0,t[8]=(r+n)*i,t[9]=(e+a)*s,t[10]=(o+u)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*u*2*c,t[15]=0,t}function g(t,n,r,a,e){var u=1/Math.tan(n/2),o=1/(a-e);return t[0]=u/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(e+a)*o,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*e*a*o,t[15]=0,t}function T(t,n,r,a){var e=Math.tan(n.upDegrees*Math.PI/180),u=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),s=2/(o+i),c=2/(e+u);return t[0]=s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*s*.5,t[9]=(e-u)*c*.5,t[10]=a/(r-a),t[11]=-1,t[12]=0,t[13]=0,t[14]=a*r/(r-a),t[15]=0,t}function j(t,n,r,a,e,u,o){var i=1/(n-r),s=1/(a-e),c=1/(u-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*s,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+r)*i,t[13]=(e+a)*s,t[14]=(o+u)*c,t[15]=1,t}function D(t,n,r,a){var e=void 0,u=void 0,o=void 0,i=void 0,s=void 0,c=void 0,f=void 0,M=void 0,h=void 0,l=void 0,v=n[0],d=n[1],b=n[2],m=a[0],p=a[1],P=a[2],E=r[0],O=r[1],x=r[2];return Math.abs(v-E)0&&(l=1/Math.sqrt(l),f*=l,M*=l,h*=l);var v=s*h-c*M,d=c*f-i*h,b=i*M-s*f;return t[0]=v,t[1]=d,t[2]=b,t[3]=0,t[4]=M*b-h*d,t[5]=h*v-f*b,t[6]=f*d-M*v,t[7]=0,t[8]=f,t[9]=M,t[10]=h,t[11]=0,t[12]=e,t[13]=u,t[14]=o,t[15]=1,t}function z(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"}function F(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2)+Math.pow(t[9],2)+Math.pow(t[10],2)+Math.pow(t[11],2)+Math.pow(t[12],2)+Math.pow(t[13],2)+Math.pow(t[14],2)+Math.pow(t[15],2))}function Q(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t[9]=n[9]+r[9],t[10]=n[10]+r[10],t[11]=n[11]+r[11],t[12]=n[12]+r[12],t[13]=n[13]+r[13],t[14]=n[14]+r[14],t[15]=n[15]+r[15],t}function X(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t[9]=n[9]-r[9],t[10]=n[10]-r[10],t[11]=n[11]-r[11],t[12]=n[12]-r[12],t[13]=n[13]-r[13],t[14]=n[14]-r[14],t[15]=n[15]-r[15],t}function Z(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t[9]=n[9]*r,t[10]=n[10]*r,t[11]=n[11]*r,t[12]=n[12]*r,t[13]=n[13]*r,t[14]=n[14]*r,t[15]=n[15]*r,t}function k(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t[9]=n[9]+r[9]*a,t[10]=n[10]+r[10]*a,t[11]=n[11]+r[11]*a,t[12]=n[12]+r[12]*a,t[13]=n[13]+r[13]*a,t[14]=n[14]+r[14]*a,t[15]=n[15]+r[15]*a,t}function U(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]}function W(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=t[4],i=t[5],s=t[6],c=t[7],f=t[8],M=t[9],h=t[10],l=t[11],v=t[12],d=t[13],b=t[14],m=t[15],p=n[0],P=n[1],E=n[2],O=n[3],x=n[4],A=n[5],q=n[6],y=n[7],w=n[8],R=n[9],L=n[10],S=n[11],_=n[12],I=n[13],N=n[14],Y=n[15];return Math.abs(r-p)<=C.EPSILON*Math.max(1,Math.abs(r),Math.abs(p))&&Math.abs(a-P)<=C.EPSILON*Math.max(1,Math.abs(a),Math.abs(P))&&Math.abs(e-E)<=C.EPSILON*Math.max(1,Math.abs(e),Math.abs(E))&&Math.abs(u-O)<=C.EPSILON*Math.max(1,Math.abs(u),Math.abs(O))&&Math.abs(o-x)<=C.EPSILON*Math.max(1,Math.abs(o),Math.abs(x))&&Math.abs(i-A)<=C.EPSILON*Math.max(1,Math.abs(i),Math.abs(A))&&Math.abs(s-q)<=C.EPSILON*Math.max(1,Math.abs(s),Math.abs(q))&&Math.abs(c-y)<=C.EPSILON*Math.max(1,Math.abs(c),Math.abs(y))&&Math.abs(f-w)<=C.EPSILON*Math.max(1,Math.abs(f),Math.abs(w))&&Math.abs(M-R)<=C.EPSILON*Math.max(1,Math.abs(M),Math.abs(R))&&Math.abs(h-L)<=C.EPSILON*Math.max(1,Math.abs(h),Math.abs(L))&&Math.abs(l-S)<=C.EPSILON*Math.max(1,Math.abs(l),Math.abs(S))&&Math.abs(v-_)<=C.EPSILON*Math.max(1,Math.abs(v),Math.abs(_))&&Math.abs(d-I)<=C.EPSILON*Math.max(1,Math.abs(d),Math.abs(I))&&Math.abs(b-N)<=C.EPSILON*Math.max(1,Math.abs(b),Math.abs(N))&&Math.abs(m-Y)<=C.EPSILON*Math.max(1,Math.abs(m),Math.abs(Y))}Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=a,n.clone=e,n.copy=u,n.fromValues=o,n.set=i,n.identity=s,n.transpose=c,n.invert=f,n.adjoint=M,n.determinant=h,n.multiply=l,n.translate=v,n.scale=d,n.rotate=b,n.rotateX=m,n.rotateY=p,n.rotateZ=P,n.fromTranslation=E,n.fromScaling=O,n.fromRotation=x,n.fromXRotation=A,n.fromYRotation=q,n.fromZRotation=y,n.fromRotationTranslation=w,n.getTranslation=R,n.getScaling=L,n.getRotation=S,n.fromRotationTranslationScale=_,n.fromRotationTranslationScaleOrigin=I,n.fromQuat=N,n.frustum=Y,n.perspective=g,n.perspectiveFromFieldOfView=T,n.ortho=j,n.lookAt=D,n.targetTo=V,n.str=z,n.frob=F,n.add=Q,n.subtract=X,n.multiplyScalar=Z,n.multiplyScalarAndAdd=k,n.exactEquals=U,n.equals=W;var B=r(0),C=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(B);n.mul=l,n.sub=X},function(t,n,r){"use strict";function a(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}function e(){var t=new E.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function u(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function o(t,n,r){r*=.5;var a=Math.sin(r);return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=Math.cos(r),t}function i(t,n){var r=2*Math.acos(n[3]),a=Math.sin(r/2);return 0!=a?(t[0]=n[0]/a,t[1]=n[1]/a,t[2]=n[2]/a):(t[0]=1,t[1]=0,t[2]=0),r}function s(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],s=r[1],c=r[2],f=r[3];return t[0]=a*f+o*i+e*c-u*s,t[1]=e*f+o*s+u*i-a*c,t[2]=u*f+o*c+a*s-e*i,t[3]=o*f-a*i-e*s-u*c,t}function c(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+o*i,t[1]=e*s+u*i,t[2]=u*s-e*i,t[3]=o*s-a*i,t}function f(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s-u*i,t[1]=e*s+o*i,t[2]=u*s+a*i,t[3]=o*s-e*i,t}function M(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+e*i,t[1]=e*s-a*i,t[2]=u*s+o*i,t[3]=o*s-u*i,t}function h(t,n){var r=n[0],a=n[1],e=n[2];return t[0]=r,t[1]=a,t[2]=e,t[3]=Math.sqrt(Math.abs(1-r*r-a*a-e*e)),t}function l(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],s=r[0],c=r[1],f=r[2],M=r[3],h=void 0,l=void 0,v=void 0,d=void 0,b=void 0;return l=e*s+u*c+o*f+i*M,l<0&&(l=-l,s=-s,c=-c,f=-f,M=-M),1-l>1e-6?(h=Math.acos(l),v=Math.sin(h),d=Math.sin((1-a)*h)/v,b=Math.sin(a*h)/v):(d=1-a,b=a),t[0]=d*e+b*s,t[1]=d*u+b*c,t[2]=d*o+b*f,t[3]=d*i+b*M,t}function v(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u,i=o?1/o:0;return t[0]=-r*i,t[1]=-a*i,t[2]=-e*i,t[3]=u*i,t}function d(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t}function b(t,n){var r=n[0]+n[4]+n[8],a=void 0;if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var e=0;n[4]>n[0]&&(e=1),n[8]>n[3*e+e]&&(e=2);var u=(e+1)%3,o=(e+2)%3;a=Math.sqrt(n[3*e+e]-n[3*u+u]-n[3*o+o]+1),t[e]=.5*a,a=.5/a,t[3]=(n[3*u+o]-n[3*o+u])*a,t[u]=(n[3*u+e]+n[3*e+u])*a,t[o]=(n[3*o+e]+n[3*e+o])*a}return t}function m(t,n,r,a){var e=.5*Math.PI/180;n*=e,r*=e,a*=e;var u=Math.sin(n),o=Math.cos(n),i=Math.sin(r),s=Math.cos(r),c=Math.sin(a),f=Math.cos(a);return t[0]=u*s*f-o*i*c,t[1]=o*i*f+u*s*c,t[2]=o*s*c-u*i*f,t[3]=o*s*f+u*i*c,t}function p(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}Object.defineProperty(n,"__esModule",{value:!0}),n.setAxes=n.sqlerp=n.rotationTo=n.equals=n.exactEquals=n.normalize=n.sqrLen=n.squaredLength=n.len=n.length=n.lerp=n.dot=n.scale=n.mul=n.add=n.set=n.copy=n.fromValues=n.clone=void 0,n.create=e,n.identity=u,n.setAxisAngle=o,n.getAxisAngle=i,n.multiply=s,n.rotateX=c,n.rotateY=f,n.rotateZ=M,n.calculateW=h,n.slerp=l,n.invert=v,n.conjugate=d,n.fromMat3=b,n.fromEuler=m,n.str=p;var P=r(0),E=a(P),O=r(1),x=a(O),A=r(2),q=a(A),y=r(3),w=a(y),R=(n.clone=w.clone,n.fromValues=w.fromValues,n.copy=w.copy,n.set=w.set,n.add=w.add,n.mul=s,n.scale=w.scale,n.dot=w.dot,n.lerp=w.lerp,n.length=w.length),L=(n.len=R,n.squaredLength=w.squaredLength),S=(n.sqrLen=L,n.normalize=w.normalize);n.exactEquals=w.exactEquals,n.equals=w.equals,n.rotationTo=function(){var t=q.create(),n=q.fromValues(1,0,0),r=q.fromValues(0,1,0);return function(a,e,u){var i=q.dot(e,u);return i<-.999999?(q.cross(t,n,e),q.len(t)<1e-6&&q.cross(t,r,e),q.normalize(t,t),o(a,t,Math.PI),a):i>.999999?(a[0]=0,a[1]=0,a[2]=0,a[3]=1,a):(q.cross(t,e,u),a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=1+i,S(a,a))}}(),n.sqlerp=function(){var t=e(),n=e();return function(r,a,e,u,o,i){return l(t,a,o,i),l(n,e,u,i),l(r,t,n,2*i*(1-i)),r}}(),n.setAxes=function(){var t=x.create();return function(n,r,a,e){return t[0]=a[0],t[3]=a[1],t[6]=a[2],t[1]=e[0],t[4]=e[1],t[7]=e[2],t[2]=-r[0],t[5]=-r[1],t[8]=-r[2],S(n,b(n,t))}}()},function(t,n,r){"use strict";function a(){var t=new V.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t}function e(t){var n=new V.ARRAY_TYPE(2);return n[0]=t[0],n[1]=t[1],n}function u(t,n){var r=new V.ARRAY_TYPE(2);return r[0]=t,r[1]=n,r}function o(t,n){return t[0]=n[0],t[1]=n[1],t}function i(t,n,r){return t[0]=n,t[1]=r,t}function s(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t}function c(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t}function f(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t}function M(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t}function h(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t}function l(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t}function v(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t}function d(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t}function b(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t}function m(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t}function p(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t}function P(t,n){var r=n[0]-t[0],a=n[1]-t[1];return Math.sqrt(r*r+a*a)}function E(t,n){var r=n[0]-t[0],a=n[1]-t[1];return r*r+a*a}function O(t){var n=t[0],r=t[1];return Math.sqrt(n*n+r*r)}function x(t){var n=t[0],r=t[1];return n*n+r*r}function A(t,n){return t[0]=-n[0],t[1]=-n[1],t}function q(t,n){return t[0]=1/n[0],t[1]=1/n[1],t}function y(t,n){var r=n[0],a=n[1],e=r*r+a*a;return e>0&&(e=1/Math.sqrt(e),t[0]=n[0]*e,t[1]=n[1]*e),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]}function R(t,n,r){var a=n[0]*r[1]-n[1]*r[0];return t[0]=t[1]=0,t[2]=a,t}function L(t,n,r,a){var e=n[0],u=n[1];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t}function S(t,n){n=n||1;var r=2*V.RANDOM()*Math.PI;return t[0]=Math.cos(r)*n,t[1]=Math.sin(r)*n,t}function _(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e,t[1]=r[1]*a+r[3]*e,t}function I(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e+r[4],t[1]=r[1]*a+r[3]*e+r[5],t}function N(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[3]*e+r[6],t[1]=r[1]*a+r[4]*e+r[7],t}function Y(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[4]*e+r[12],t[1]=r[1]*a+r[5]*e+r[13],t}function g(t){return"vec2("+t[0]+", "+t[1]+")"}function T(t,n){return t[0]===n[0]&&t[1]===n[1]}function j(t,n){var r=t[0],a=t[1],e=n[0],u=n[1];return Math.abs(r-e)<=V.EPSILON*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(a-u)<=V.EPSILON*Math.max(1,Math.abs(a),Math.abs(u))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.sqrDist=n.dist=n.div=n.mul=n.sub=n.len=void 0,n.create=a,n.clone=e,n.fromValues=u,n.copy=o,n.set=i,n.add=s,n.subtract=c,n.multiply=f,n.divide=M,n.ceil=h,n.floor=l,n.min=v,n.max=d,n.round=b,n.scale=m,n.scaleAndAdd=p,n.distance=P,n.squaredDistance=E,n.length=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.cross=R,n.lerp=L,n.random=S,n.transformMat2=_,n.transformMat2d=I,n.transformMat3=N,n.transformMat4=Y,n.str=g,n.exactEquals=T,n.equals=j;var D=r(0),V=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(D);n.len=O,n.sub=c,n.mul=f,n.div=M,n.dist=P,n.sqrDist=E,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=2),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i 2 | 3 | 4 | -------------------------------------------------------------------------------- /interfaces/generate.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const acorn = require("acorn"); 3 | let walker = require("acorn/dist/walk"); 4 | 5 | let options = { 6 | ecmaVersion: 7, 7 | allowImportExportEverywhere: true 8 | }; 9 | 10 | function findReturn(node) { 11 | let ret = null; 12 | walker.simple(node, { 13 | ReturnStatement(child) { 14 | ret = child; 15 | } 16 | }); 17 | return ret; 18 | }; 19 | 20 | function findAllocation(node) { 21 | let ret = null; 22 | walker.simple(node, { 23 | NewExpression(child) { 24 | let callee = child.callee; 25 | let args = child.arguments; 26 | let object = callee.object; 27 | let property = callee.property; 28 | let computed = callee.computed; 29 | if ( 30 | !computed && 31 | object.type === "Identifier" && 32 | object.name === "glMatrix" && 33 | property.type === "Identifier" && 34 | property.name === "ARRAY_TYPE" 35 | ) { 36 | let size = args[0]; 37 | if ( 38 | size && 39 | size.type === "Literal" 40 | ) { 41 | ret = size.value; 42 | } 43 | } 44 | } 45 | }); 46 | return ret; 47 | }; 48 | 49 | function getReturnType(node) { 50 | let type = node.type; 51 | if (type === "Identifier") return "out"; 52 | return type; 53 | }; 54 | 55 | function getExport(node) { 56 | let decl = node.declaration; 57 | if (decl.type === "FunctionDeclaration") { 58 | let declName = decl.id.name; 59 | let ret = findReturn(node); 60 | let retType = getReturnType(ret.argument); 61 | let allocation = findAllocation(node); 62 | let result = { 63 | id: declName, 64 | returns: retType 65 | }; 66 | if (allocation) result.allocation = allocation; 67 | return result; 68 | } 69 | }; 70 | 71 | function isCustomInterfaceRequired(moduleInterface) { 72 | return ( 73 | (moduleInterface.returns !== "out") || 74 | (moduleInterface.allocation !== void 0) 75 | ); 76 | }; 77 | 78 | function processComment(comment) { 79 | let arg = { 80 | arguments: [], 81 | returns: null 82 | }; 83 | let split = comment.split("\n"); 84 | split.map(line => { 85 | if (line.match("@param")) { 86 | let start = line.indexOf("{") + 1; 87 | let end = line.lastIndexOf("}"); 88 | let type = line.substr(start, end - start); 89 | } 90 | else if (line.match("@return")) { 91 | let start = line.indexOf("{") + 1; 92 | let end = line.lastIndexOf("}"); 93 | let type = line.substr(start, end - start); 94 | console.log(type); 95 | } 96 | }); 97 | return arg; 98 | }; 99 | 100 | module.exports = function(source) { 101 | 102 | let cmnts = []; 103 | options.onComment = cmnts; 104 | 105 | let ast = acorn.parse(source, options); 106 | let program = ast; 107 | 108 | let table = {}; 109 | for (let ii = 0; ii < program.body.length; ++ii) { 110 | let node = program.body[ii]; 111 | if (node.type === "ExportNamedDeclaration") { 112 | let decl = getExport(node); 113 | if (!decl) continue; 114 | decl.specialInterface = isCustomInterfaceRequired(decl); 115 | table[decl.id] = decl; 116 | } 117 | }; 118 | 119 | let comments = []; 120 | for (let ii = 0; ii < cmnts.length; ++ii) { 121 | let comment = cmnts[ii].value; 122 | if ( 123 | cmnts[ii].type === "Block" && 124 | (comment.match("@returns ") !== null || comment.match("@return ") !== null) 125 | ) { 126 | comments.push(processComment(comment)); 127 | } 128 | }; 129 | 130 | return table; 131 | 132 | }; 133 | -------------------------------------------------------------------------------- /interfaces/ignore_this.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maierfelix/glmw/4b1b39868f1038ded299f4a983adf8882104124d/interfaces/ignore_this.txt -------------------------------------------------------------------------------- /interfaces/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const glMatrix = require("../static/gl-matrix.min.js"); 3 | const generate = require("./generate"); 4 | 5 | let sourceDir = __dirname + "/../gl-matrix/"; 6 | let moduleSources = require(__dirname + "/modules"); 7 | 8 | //let baseTablePath = __dirname + "/base-table.js"; 9 | 10 | let interfaces = {}; 11 | let specialInterfaces = {}; 12 | moduleSources.map(moduleName => { 13 | let file = fs.readFileSync(sourceDir + moduleName + ".js", "utf-8"); 14 | let table = generate(file); 15 | // full interface 16 | { 17 | interfaces[moduleName] = {}; 18 | let interface = interfaces[moduleName]; 19 | for (let name in table) { 20 | let method = table[name]; 21 | interface[name] = method; 22 | }; 23 | } 24 | // special interface 25 | { 26 | specialInterfaces[moduleName] = {}; 27 | let interface = specialInterfaces[moduleName]; 28 | for (let name in table) { 29 | let method = table[name]; 30 | if (method.specialInterface) interface[name] = method; 31 | }; 32 | } 33 | }); 34 | 35 | let stubs = { 36 | 37 | }; 38 | 39 | for (let key in interfaces) { 40 | let methods = interfaces[key]; 41 | for (let key in methods) { 42 | let method = methods[key]; 43 | if (!method.specialInterface) { 44 | let stub = function(out, a, b) { 45 | 46 | }; 47 | } 48 | }; 49 | }; 50 | 51 | //fs.writeFileSync(__dirname + "/interfaces.json", JSON.stringify(interfaces, null, 2), "utf-8"); 52 | //fs.writeFileSync(__dirname + "/interfaces-special.json", JSON.stringify(specialInterfaces, null, 2), "utf-8"); 53 | -------------------------------------------------------------------------------- /interfaces/interfaces-special.json: -------------------------------------------------------------------------------- 1 | { 2 | "mat2": { 3 | "create": { 4 | "id": "create", 5 | "returns": "out", 6 | "allocation": 4, 7 | "specialInterface": true 8 | }, 9 | "clone": { 10 | "id": "clone", 11 | "returns": "out", 12 | "allocation": 4, 13 | "specialInterface": true 14 | }, 15 | "fromValues": { 16 | "id": "fromValues", 17 | "returns": "out", 18 | "allocation": 4, 19 | "specialInterface": true 20 | }, 21 | "determinant": { 22 | "id": "determinant", 23 | "returns": "BinaryExpression", 24 | "specialInterface": true 25 | }, 26 | "str": { 27 | "id": "str", 28 | "returns": "BinaryExpression", 29 | "specialInterface": true 30 | }, 31 | "frob": { 32 | "id": "frob", 33 | "returns": "CallExpression", 34 | "specialInterface": true 35 | }, 36 | "LDU": { 37 | "id": "LDU", 38 | "returns": "ArrayExpression", 39 | "specialInterface": true 40 | }, 41 | "exactEquals": { 42 | "id": "exactEquals", 43 | "returns": "LogicalExpression", 44 | "specialInterface": true 45 | }, 46 | "equals": { 47 | "id": "equals", 48 | "returns": "LogicalExpression", 49 | "specialInterface": true 50 | } 51 | }, 52 | "mat2d": { 53 | "create": { 54 | "id": "create", 55 | "returns": "out", 56 | "allocation": 6, 57 | "specialInterface": true 58 | }, 59 | "clone": { 60 | "id": "clone", 61 | "returns": "out", 62 | "allocation": 6, 63 | "specialInterface": true 64 | }, 65 | "fromValues": { 66 | "id": "fromValues", 67 | "returns": "out", 68 | "allocation": 6, 69 | "specialInterface": true 70 | }, 71 | "determinant": { 72 | "id": "determinant", 73 | "returns": "BinaryExpression", 74 | "specialInterface": true 75 | }, 76 | "str": { 77 | "id": "str", 78 | "returns": "BinaryExpression", 79 | "specialInterface": true 80 | }, 81 | "frob": { 82 | "id": "frob", 83 | "returns": "CallExpression", 84 | "specialInterface": true 85 | }, 86 | "exactEquals": { 87 | "id": "exactEquals", 88 | "returns": "LogicalExpression", 89 | "specialInterface": true 90 | }, 91 | "equals": { 92 | "id": "equals", 93 | "returns": "LogicalExpression", 94 | "specialInterface": true 95 | } 96 | }, 97 | "mat3": { 98 | "create": { 99 | "id": "create", 100 | "returns": "out", 101 | "allocation": 9, 102 | "specialInterface": true 103 | }, 104 | "clone": { 105 | "id": "clone", 106 | "returns": "out", 107 | "allocation": 9, 108 | "specialInterface": true 109 | }, 110 | "fromValues": { 111 | "id": "fromValues", 112 | "returns": "out", 113 | "allocation": 9, 114 | "specialInterface": true 115 | }, 116 | "determinant": { 117 | "id": "determinant", 118 | "returns": "BinaryExpression", 119 | "specialInterface": true 120 | }, 121 | "str": { 122 | "id": "str", 123 | "returns": "BinaryExpression", 124 | "specialInterface": true 125 | }, 126 | "frob": { 127 | "id": "frob", 128 | "returns": "CallExpression", 129 | "specialInterface": true 130 | }, 131 | "exactEquals": { 132 | "id": "exactEquals", 133 | "returns": "LogicalExpression", 134 | "specialInterface": true 135 | }, 136 | "equals": { 137 | "id": "equals", 138 | "returns": "LogicalExpression", 139 | "specialInterface": true 140 | } 141 | }, 142 | "mat4": { 143 | "create": { 144 | "id": "create", 145 | "returns": "out", 146 | "allocation": 16, 147 | "specialInterface": true 148 | }, 149 | "clone": { 150 | "id": "clone", 151 | "returns": "out", 152 | "allocation": 16, 153 | "specialInterface": true 154 | }, 155 | "fromValues": { 156 | "id": "fromValues", 157 | "returns": "out", 158 | "allocation": 16, 159 | "specialInterface": true 160 | }, 161 | "determinant": { 162 | "id": "determinant", 163 | "returns": "BinaryExpression", 164 | "specialInterface": true 165 | }, 166 | "str": { 167 | "id": "str", 168 | "returns": "BinaryExpression", 169 | "specialInterface": true 170 | }, 171 | "frob": { 172 | "id": "frob", 173 | "returns": "CallExpression", 174 | "specialInterface": true 175 | }, 176 | "exactEquals": { 177 | "id": "exactEquals", 178 | "returns": "LogicalExpression", 179 | "specialInterface": true 180 | }, 181 | "equals": { 182 | "id": "equals", 183 | "returns": "LogicalExpression", 184 | "specialInterface": true 185 | } 186 | }, 187 | "quat": { 188 | "create": { 189 | "id": "create", 190 | "returns": "out", 191 | "allocation": 4, 192 | "specialInterface": true 193 | }, 194 | "str": { 195 | "id": "str", 196 | "returns": "BinaryExpression", 197 | "specialInterface": true 198 | } 199 | }, 200 | "vec2": { 201 | "create": { 202 | "id": "create", 203 | "returns": "out", 204 | "allocation": 2, 205 | "specialInterface": true 206 | }, 207 | "clone": { 208 | "id": "clone", 209 | "returns": "out", 210 | "allocation": 2, 211 | "specialInterface": true 212 | }, 213 | "fromValues": { 214 | "id": "fromValues", 215 | "returns": "out", 216 | "allocation": 2, 217 | "specialInterface": true 218 | }, 219 | "distance": { 220 | "id": "distance", 221 | "returns": "CallExpression", 222 | "specialInterface": true 223 | }, 224 | "squaredDistance": { 225 | "id": "squaredDistance", 226 | "returns": "BinaryExpression", 227 | "specialInterface": true 228 | }, 229 | "length": { 230 | "id": "length", 231 | "returns": "CallExpression", 232 | "specialInterface": true 233 | }, 234 | "squaredLength": { 235 | "id": "squaredLength", 236 | "returns": "BinaryExpression", 237 | "specialInterface": true 238 | }, 239 | "dot": { 240 | "id": "dot", 241 | "returns": "BinaryExpression", 242 | "specialInterface": true 243 | }, 244 | "str": { 245 | "id": "str", 246 | "returns": "BinaryExpression", 247 | "specialInterface": true 248 | }, 249 | "exactEquals": { 250 | "id": "exactEquals", 251 | "returns": "LogicalExpression", 252 | "specialInterface": true 253 | }, 254 | "equals": { 255 | "id": "equals", 256 | "returns": "LogicalExpression", 257 | "specialInterface": true 258 | } 259 | }, 260 | "vec3": { 261 | "create": { 262 | "id": "create", 263 | "returns": "out", 264 | "allocation": 3, 265 | "specialInterface": true 266 | }, 267 | "clone": { 268 | "id": "clone", 269 | "returns": "out", 270 | "allocation": 3, 271 | "specialInterface": true 272 | }, 273 | "length": { 274 | "id": "length", 275 | "returns": "CallExpression", 276 | "specialInterface": true 277 | }, 278 | "fromValues": { 279 | "id": "fromValues", 280 | "returns": "out", 281 | "allocation": 3, 282 | "specialInterface": true 283 | }, 284 | "distance": { 285 | "id": "distance", 286 | "returns": "CallExpression", 287 | "specialInterface": true 288 | }, 289 | "squaredDistance": { 290 | "id": "squaredDistance", 291 | "returns": "BinaryExpression", 292 | "specialInterface": true 293 | }, 294 | "squaredLength": { 295 | "id": "squaredLength", 296 | "returns": "BinaryExpression", 297 | "specialInterface": true 298 | }, 299 | "dot": { 300 | "id": "dot", 301 | "returns": "BinaryExpression", 302 | "specialInterface": true 303 | }, 304 | "angle": { 305 | "id": "angle", 306 | "returns": "CallExpression", 307 | "specialInterface": true 308 | }, 309 | "str": { 310 | "id": "str", 311 | "returns": "BinaryExpression", 312 | "specialInterface": true 313 | }, 314 | "exactEquals": { 315 | "id": "exactEquals", 316 | "returns": "LogicalExpression", 317 | "specialInterface": true 318 | }, 319 | "equals": { 320 | "id": "equals", 321 | "returns": "LogicalExpression", 322 | "specialInterface": true 323 | } 324 | }, 325 | "vec4": { 326 | "create": { 327 | "id": "create", 328 | "returns": "out", 329 | "allocation": 4, 330 | "specialInterface": true 331 | }, 332 | "clone": { 333 | "id": "clone", 334 | "returns": "out", 335 | "allocation": 4, 336 | "specialInterface": true 337 | }, 338 | "fromValues": { 339 | "id": "fromValues", 340 | "returns": "out", 341 | "allocation": 4, 342 | "specialInterface": true 343 | }, 344 | "distance": { 345 | "id": "distance", 346 | "returns": "CallExpression", 347 | "specialInterface": true 348 | }, 349 | "squaredDistance": { 350 | "id": "squaredDistance", 351 | "returns": "BinaryExpression", 352 | "specialInterface": true 353 | }, 354 | "length": { 355 | "id": "length", 356 | "returns": "CallExpression", 357 | "specialInterface": true 358 | }, 359 | "squaredLength": { 360 | "id": "squaredLength", 361 | "returns": "BinaryExpression", 362 | "specialInterface": true 363 | }, 364 | "dot": { 365 | "id": "dot", 366 | "returns": "BinaryExpression", 367 | "specialInterface": true 368 | }, 369 | "str": { 370 | "id": "str", 371 | "returns": "BinaryExpression", 372 | "specialInterface": true 373 | }, 374 | "exactEquals": { 375 | "id": "exactEquals", 376 | "returns": "LogicalExpression", 377 | "specialInterface": true 378 | }, 379 | "equals": { 380 | "id": "equals", 381 | "returns": "LogicalExpression", 382 | "specialInterface": true 383 | } 384 | } 385 | } -------------------------------------------------------------------------------- /interfaces/interfaces.json: -------------------------------------------------------------------------------- 1 | { 2 | "mat2": { 3 | "create": { 4 | "id": "create", 5 | "returns": "out", 6 | "allocation": 4, 7 | "specialInterface": true 8 | }, 9 | "clone": { 10 | "id": "clone", 11 | "returns": "out", 12 | "allocation": 4, 13 | "specialInterface": true 14 | }, 15 | "copy": { 16 | "id": "copy", 17 | "returns": "out", 18 | "specialInterface": false 19 | }, 20 | "identity": { 21 | "id": "identity", 22 | "returns": "out", 23 | "specialInterface": false 24 | }, 25 | "fromValues": { 26 | "id": "fromValues", 27 | "returns": "out", 28 | "allocation": 4, 29 | "specialInterface": true 30 | }, 31 | "set": { 32 | "id": "set", 33 | "returns": "out", 34 | "specialInterface": false 35 | }, 36 | "transpose": { 37 | "id": "transpose", 38 | "returns": "out", 39 | "specialInterface": false 40 | }, 41 | "invert": { 42 | "id": "invert", 43 | "returns": "out", 44 | "specialInterface": false 45 | }, 46 | "adjoint": { 47 | "id": "adjoint", 48 | "returns": "out", 49 | "specialInterface": false 50 | }, 51 | "determinant": { 52 | "id": "determinant", 53 | "returns": "BinaryExpression", 54 | "specialInterface": true 55 | }, 56 | "multiply": { 57 | "id": "multiply", 58 | "returns": "out", 59 | "specialInterface": false 60 | }, 61 | "rotate": { 62 | "id": "rotate", 63 | "returns": "out", 64 | "specialInterface": false 65 | }, 66 | "scale": { 67 | "id": "scale", 68 | "returns": "out", 69 | "specialInterface": false 70 | }, 71 | "fromRotation": { 72 | "id": "fromRotation", 73 | "returns": "out", 74 | "specialInterface": false 75 | }, 76 | "fromScaling": { 77 | "id": "fromScaling", 78 | "returns": "out", 79 | "specialInterface": false 80 | }, 81 | "str": { 82 | "id": "str", 83 | "returns": "BinaryExpression", 84 | "specialInterface": true 85 | }, 86 | "frob": { 87 | "id": "frob", 88 | "returns": "CallExpression", 89 | "specialInterface": true 90 | }, 91 | "LDU": { 92 | "id": "LDU", 93 | "returns": "ArrayExpression", 94 | "specialInterface": true 95 | }, 96 | "add": { 97 | "id": "add", 98 | "returns": "out", 99 | "specialInterface": false 100 | }, 101 | "subtract": { 102 | "id": "subtract", 103 | "returns": "out", 104 | "specialInterface": false 105 | }, 106 | "exactEquals": { 107 | "id": "exactEquals", 108 | "returns": "LogicalExpression", 109 | "specialInterface": true 110 | }, 111 | "equals": { 112 | "id": "equals", 113 | "returns": "LogicalExpression", 114 | "specialInterface": true 115 | }, 116 | "multiplyScalar": { 117 | "id": "multiplyScalar", 118 | "returns": "out", 119 | "specialInterface": false 120 | }, 121 | "multiplyScalarAndAdd": { 122 | "id": "multiplyScalarAndAdd", 123 | "returns": "out", 124 | "specialInterface": false 125 | } 126 | }, 127 | "mat2d": { 128 | "create": { 129 | "id": "create", 130 | "returns": "out", 131 | "allocation": 6, 132 | "specialInterface": true 133 | }, 134 | "clone": { 135 | "id": "clone", 136 | "returns": "out", 137 | "allocation": 6, 138 | "specialInterface": true 139 | }, 140 | "copy": { 141 | "id": "copy", 142 | "returns": "out", 143 | "specialInterface": false 144 | }, 145 | "identity": { 146 | "id": "identity", 147 | "returns": "out", 148 | "specialInterface": false 149 | }, 150 | "fromValues": { 151 | "id": "fromValues", 152 | "returns": "out", 153 | "allocation": 6, 154 | "specialInterface": true 155 | }, 156 | "set": { 157 | "id": "set", 158 | "returns": "out", 159 | "specialInterface": false 160 | }, 161 | "invert": { 162 | "id": "invert", 163 | "returns": "out", 164 | "specialInterface": false 165 | }, 166 | "determinant": { 167 | "id": "determinant", 168 | "returns": "BinaryExpression", 169 | "specialInterface": true 170 | }, 171 | "multiply": { 172 | "id": "multiply", 173 | "returns": "out", 174 | "specialInterface": false 175 | }, 176 | "rotate": { 177 | "id": "rotate", 178 | "returns": "out", 179 | "specialInterface": false 180 | }, 181 | "scale": { 182 | "id": "scale", 183 | "returns": "out", 184 | "specialInterface": false 185 | }, 186 | "translate": { 187 | "id": "translate", 188 | "returns": "out", 189 | "specialInterface": false 190 | }, 191 | "fromRotation": { 192 | "id": "fromRotation", 193 | "returns": "out", 194 | "specialInterface": false 195 | }, 196 | "fromScaling": { 197 | "id": "fromScaling", 198 | "returns": "out", 199 | "specialInterface": false 200 | }, 201 | "fromTranslation": { 202 | "id": "fromTranslation", 203 | "returns": "out", 204 | "specialInterface": false 205 | }, 206 | "str": { 207 | "id": "str", 208 | "returns": "BinaryExpression", 209 | "specialInterface": true 210 | }, 211 | "frob": { 212 | "id": "frob", 213 | "returns": "CallExpression", 214 | "specialInterface": true 215 | }, 216 | "add": { 217 | "id": "add", 218 | "returns": "out", 219 | "specialInterface": false 220 | }, 221 | "subtract": { 222 | "id": "subtract", 223 | "returns": "out", 224 | "specialInterface": false 225 | }, 226 | "multiplyScalar": { 227 | "id": "multiplyScalar", 228 | "returns": "out", 229 | "specialInterface": false 230 | }, 231 | "multiplyScalarAndAdd": { 232 | "id": "multiplyScalarAndAdd", 233 | "returns": "out", 234 | "specialInterface": false 235 | }, 236 | "exactEquals": { 237 | "id": "exactEquals", 238 | "returns": "LogicalExpression", 239 | "specialInterface": true 240 | }, 241 | "equals": { 242 | "id": "equals", 243 | "returns": "LogicalExpression", 244 | "specialInterface": true 245 | } 246 | }, 247 | "mat3": { 248 | "create": { 249 | "id": "create", 250 | "returns": "out", 251 | "allocation": 9, 252 | "specialInterface": true 253 | }, 254 | "fromMat4": { 255 | "id": "fromMat4", 256 | "returns": "out", 257 | "specialInterface": false 258 | }, 259 | "clone": { 260 | "id": "clone", 261 | "returns": "out", 262 | "allocation": 9, 263 | "specialInterface": true 264 | }, 265 | "copy": { 266 | "id": "copy", 267 | "returns": "out", 268 | "specialInterface": false 269 | }, 270 | "fromValues": { 271 | "id": "fromValues", 272 | "returns": "out", 273 | "allocation": 9, 274 | "specialInterface": true 275 | }, 276 | "set": { 277 | "id": "set", 278 | "returns": "out", 279 | "specialInterface": false 280 | }, 281 | "identity": { 282 | "id": "identity", 283 | "returns": "out", 284 | "specialInterface": false 285 | }, 286 | "transpose": { 287 | "id": "transpose", 288 | "returns": "out", 289 | "specialInterface": false 290 | }, 291 | "invert": { 292 | "id": "invert", 293 | "returns": "out", 294 | "specialInterface": false 295 | }, 296 | "adjoint": { 297 | "id": "adjoint", 298 | "returns": "out", 299 | "specialInterface": false 300 | }, 301 | "determinant": { 302 | "id": "determinant", 303 | "returns": "BinaryExpression", 304 | "specialInterface": true 305 | }, 306 | "multiply": { 307 | "id": "multiply", 308 | "returns": "out", 309 | "specialInterface": false 310 | }, 311 | "translate": { 312 | "id": "translate", 313 | "returns": "out", 314 | "specialInterface": false 315 | }, 316 | "rotate": { 317 | "id": "rotate", 318 | "returns": "out", 319 | "specialInterface": false 320 | }, 321 | "scale": { 322 | "id": "scale", 323 | "returns": "out", 324 | "specialInterface": false 325 | }, 326 | "fromTranslation": { 327 | "id": "fromTranslation", 328 | "returns": "out", 329 | "specialInterface": false 330 | }, 331 | "fromRotation": { 332 | "id": "fromRotation", 333 | "returns": "out", 334 | "specialInterface": false 335 | }, 336 | "fromScaling": { 337 | "id": "fromScaling", 338 | "returns": "out", 339 | "specialInterface": false 340 | }, 341 | "fromMat2d": { 342 | "id": "fromMat2d", 343 | "returns": "out", 344 | "specialInterface": false 345 | }, 346 | "fromQuat": { 347 | "id": "fromQuat", 348 | "returns": "out", 349 | "specialInterface": false 350 | }, 351 | "normalFromMat4": { 352 | "id": "normalFromMat4", 353 | "returns": "out", 354 | "specialInterface": false 355 | }, 356 | "projection": { 357 | "id": "projection", 358 | "returns": "out", 359 | "specialInterface": false 360 | }, 361 | "str": { 362 | "id": "str", 363 | "returns": "BinaryExpression", 364 | "specialInterface": true 365 | }, 366 | "frob": { 367 | "id": "frob", 368 | "returns": "CallExpression", 369 | "specialInterface": true 370 | }, 371 | "add": { 372 | "id": "add", 373 | "returns": "out", 374 | "specialInterface": false 375 | }, 376 | "subtract": { 377 | "id": "subtract", 378 | "returns": "out", 379 | "specialInterface": false 380 | }, 381 | "multiplyScalar": { 382 | "id": "multiplyScalar", 383 | "returns": "out", 384 | "specialInterface": false 385 | }, 386 | "multiplyScalarAndAdd": { 387 | "id": "multiplyScalarAndAdd", 388 | "returns": "out", 389 | "specialInterface": false 390 | }, 391 | "exactEquals": { 392 | "id": "exactEquals", 393 | "returns": "LogicalExpression", 394 | "specialInterface": true 395 | }, 396 | "equals": { 397 | "id": "equals", 398 | "returns": "LogicalExpression", 399 | "specialInterface": true 400 | } 401 | }, 402 | "mat4": { 403 | "create": { 404 | "id": "create", 405 | "returns": "out", 406 | "allocation": 16, 407 | "specialInterface": true 408 | }, 409 | "clone": { 410 | "id": "clone", 411 | "returns": "out", 412 | "allocation": 16, 413 | "specialInterface": true 414 | }, 415 | "copy": { 416 | "id": "copy", 417 | "returns": "out", 418 | "specialInterface": false 419 | }, 420 | "fromValues": { 421 | "id": "fromValues", 422 | "returns": "out", 423 | "allocation": 16, 424 | "specialInterface": true 425 | }, 426 | "set": { 427 | "id": "set", 428 | "returns": "out", 429 | "specialInterface": false 430 | }, 431 | "identity": { 432 | "id": "identity", 433 | "returns": "out", 434 | "specialInterface": false 435 | }, 436 | "transpose": { 437 | "id": "transpose", 438 | "returns": "out", 439 | "specialInterface": false 440 | }, 441 | "invert": { 442 | "id": "invert", 443 | "returns": "out", 444 | "specialInterface": false 445 | }, 446 | "adjoint": { 447 | "id": "adjoint", 448 | "returns": "out", 449 | "specialInterface": false 450 | }, 451 | "determinant": { 452 | "id": "determinant", 453 | "returns": "BinaryExpression", 454 | "specialInterface": true 455 | }, 456 | "multiply": { 457 | "id": "multiply", 458 | "returns": "out", 459 | "specialInterface": false 460 | }, 461 | "translate": { 462 | "id": "translate", 463 | "returns": "out", 464 | "specialInterface": false 465 | }, 466 | "scale": { 467 | "id": "scale", 468 | "returns": "out", 469 | "specialInterface": false 470 | }, 471 | "rotate": { 472 | "id": "rotate", 473 | "returns": "out", 474 | "specialInterface": false 475 | }, 476 | "rotateX": { 477 | "id": "rotateX", 478 | "returns": "out", 479 | "specialInterface": false 480 | }, 481 | "rotateY": { 482 | "id": "rotateY", 483 | "returns": "out", 484 | "specialInterface": false 485 | }, 486 | "rotateZ": { 487 | "id": "rotateZ", 488 | "returns": "out", 489 | "specialInterface": false 490 | }, 491 | "fromTranslation": { 492 | "id": "fromTranslation", 493 | "returns": "out", 494 | "specialInterface": false 495 | }, 496 | "fromScaling": { 497 | "id": "fromScaling", 498 | "returns": "out", 499 | "specialInterface": false 500 | }, 501 | "fromRotation": { 502 | "id": "fromRotation", 503 | "returns": "out", 504 | "specialInterface": false 505 | }, 506 | "fromXRotation": { 507 | "id": "fromXRotation", 508 | "returns": "out", 509 | "specialInterface": false 510 | }, 511 | "fromYRotation": { 512 | "id": "fromYRotation", 513 | "returns": "out", 514 | "specialInterface": false 515 | }, 516 | "fromZRotation": { 517 | "id": "fromZRotation", 518 | "returns": "out", 519 | "specialInterface": false 520 | }, 521 | "fromRotationTranslation": { 522 | "id": "fromRotationTranslation", 523 | "returns": "out", 524 | "specialInterface": false 525 | }, 526 | "getTranslation": { 527 | "id": "getTranslation", 528 | "returns": "out", 529 | "specialInterface": false 530 | }, 531 | "getScaling": { 532 | "id": "getScaling", 533 | "returns": "out", 534 | "specialInterface": false 535 | }, 536 | "getRotation": { 537 | "id": "getRotation", 538 | "returns": "out", 539 | "specialInterface": false 540 | }, 541 | "fromRotationTranslationScale": { 542 | "id": "fromRotationTranslationScale", 543 | "returns": "out", 544 | "specialInterface": false 545 | }, 546 | "fromRotationTranslationScaleOrigin": { 547 | "id": "fromRotationTranslationScaleOrigin", 548 | "returns": "out", 549 | "specialInterface": false 550 | }, 551 | "fromQuat": { 552 | "id": "fromQuat", 553 | "returns": "out", 554 | "specialInterface": false 555 | }, 556 | "frustum": { 557 | "id": "frustum", 558 | "returns": "out", 559 | "specialInterface": false 560 | }, 561 | "perspective": { 562 | "id": "perspective", 563 | "returns": "out", 564 | "specialInterface": false 565 | }, 566 | "perspectiveFromFieldOfView": { 567 | "id": "perspectiveFromFieldOfView", 568 | "returns": "out", 569 | "specialInterface": false 570 | }, 571 | "ortho": { 572 | "id": "ortho", 573 | "returns": "out", 574 | "specialInterface": false 575 | }, 576 | "lookAt": { 577 | "id": "lookAt", 578 | "returns": "out", 579 | "specialInterface": false 580 | }, 581 | "targetTo": { 582 | "id": "targetTo", 583 | "returns": "out", 584 | "specialInterface": false 585 | }, 586 | "str": { 587 | "id": "str", 588 | "returns": "BinaryExpression", 589 | "specialInterface": true 590 | }, 591 | "frob": { 592 | "id": "frob", 593 | "returns": "CallExpression", 594 | "specialInterface": true 595 | }, 596 | "add": { 597 | "id": "add", 598 | "returns": "out", 599 | "specialInterface": false 600 | }, 601 | "subtract": { 602 | "id": "subtract", 603 | "returns": "out", 604 | "specialInterface": false 605 | }, 606 | "multiplyScalar": { 607 | "id": "multiplyScalar", 608 | "returns": "out", 609 | "specialInterface": false 610 | }, 611 | "multiplyScalarAndAdd": { 612 | "id": "multiplyScalarAndAdd", 613 | "returns": "out", 614 | "specialInterface": false 615 | }, 616 | "exactEquals": { 617 | "id": "exactEquals", 618 | "returns": "LogicalExpression", 619 | "specialInterface": true 620 | }, 621 | "equals": { 622 | "id": "equals", 623 | "returns": "LogicalExpression", 624 | "specialInterface": true 625 | } 626 | }, 627 | "quat": { 628 | "create": { 629 | "id": "create", 630 | "returns": "out", 631 | "allocation": 4, 632 | "specialInterface": true 633 | }, 634 | "identity": { 635 | "id": "identity", 636 | "returns": "out", 637 | "specialInterface": false 638 | }, 639 | "setAxisAngle": { 640 | "id": "setAxisAngle", 641 | "returns": "out", 642 | "specialInterface": false 643 | }, 644 | "getAxisAngle": { 645 | "id": "getAxisAngle", 646 | "returns": "out", 647 | "specialInterface": false 648 | }, 649 | "multiply": { 650 | "id": "multiply", 651 | "returns": "out", 652 | "specialInterface": false 653 | }, 654 | "rotateX": { 655 | "id": "rotateX", 656 | "returns": "out", 657 | "specialInterface": false 658 | }, 659 | "rotateY": { 660 | "id": "rotateY", 661 | "returns": "out", 662 | "specialInterface": false 663 | }, 664 | "rotateZ": { 665 | "id": "rotateZ", 666 | "returns": "out", 667 | "specialInterface": false 668 | }, 669 | "calculateW": { 670 | "id": "calculateW", 671 | "returns": "out", 672 | "specialInterface": false 673 | }, 674 | "slerp": { 675 | "id": "slerp", 676 | "returns": "out", 677 | "specialInterface": false 678 | }, 679 | "invert": { 680 | "id": "invert", 681 | "returns": "out", 682 | "specialInterface": false 683 | }, 684 | "conjugate": { 685 | "id": "conjugate", 686 | "returns": "out", 687 | "specialInterface": false 688 | }, 689 | "fromMat3": { 690 | "id": "fromMat3", 691 | "returns": "out", 692 | "specialInterface": false 693 | }, 694 | "fromEuler": { 695 | "id": "fromEuler", 696 | "returns": "out", 697 | "specialInterface": false 698 | }, 699 | "str": { 700 | "id": "str", 701 | "returns": "BinaryExpression", 702 | "specialInterface": true 703 | } 704 | }, 705 | "vec2": { 706 | "create": { 707 | "id": "create", 708 | "returns": "out", 709 | "allocation": 2, 710 | "specialInterface": true 711 | }, 712 | "clone": { 713 | "id": "clone", 714 | "returns": "out", 715 | "allocation": 2, 716 | "specialInterface": true 717 | }, 718 | "fromValues": { 719 | "id": "fromValues", 720 | "returns": "out", 721 | "allocation": 2, 722 | "specialInterface": true 723 | }, 724 | "copy": { 725 | "id": "copy", 726 | "returns": "out", 727 | "specialInterface": false 728 | }, 729 | "set": { 730 | "id": "set", 731 | "returns": "out", 732 | "specialInterface": false 733 | }, 734 | "add": { 735 | "id": "add", 736 | "returns": "out", 737 | "specialInterface": false 738 | }, 739 | "subtract": { 740 | "id": "subtract", 741 | "returns": "out", 742 | "specialInterface": false 743 | }, 744 | "multiply": { 745 | "id": "multiply", 746 | "returns": "out", 747 | "specialInterface": false 748 | }, 749 | "divide": { 750 | "id": "divide", 751 | "returns": "out", 752 | "specialInterface": false 753 | }, 754 | "ceil": { 755 | "id": "ceil", 756 | "returns": "out", 757 | "specialInterface": false 758 | }, 759 | "floor": { 760 | "id": "floor", 761 | "returns": "out", 762 | "specialInterface": false 763 | }, 764 | "min": { 765 | "id": "min", 766 | "returns": "out", 767 | "specialInterface": false 768 | }, 769 | "max": { 770 | "id": "max", 771 | "returns": "out", 772 | "specialInterface": false 773 | }, 774 | "round": { 775 | "id": "round", 776 | "returns": "out", 777 | "specialInterface": false 778 | }, 779 | "scale": { 780 | "id": "scale", 781 | "returns": "out", 782 | "specialInterface": false 783 | }, 784 | "scaleAndAdd": { 785 | "id": "scaleAndAdd", 786 | "returns": "out", 787 | "specialInterface": false 788 | }, 789 | "distance": { 790 | "id": "distance", 791 | "returns": "CallExpression", 792 | "specialInterface": true 793 | }, 794 | "squaredDistance": { 795 | "id": "squaredDistance", 796 | "returns": "BinaryExpression", 797 | "specialInterface": true 798 | }, 799 | "length": { 800 | "id": "length", 801 | "returns": "CallExpression", 802 | "specialInterface": true 803 | }, 804 | "squaredLength": { 805 | "id": "squaredLength", 806 | "returns": "BinaryExpression", 807 | "specialInterface": true 808 | }, 809 | "negate": { 810 | "id": "negate", 811 | "returns": "out", 812 | "specialInterface": false 813 | }, 814 | "inverse": { 815 | "id": "inverse", 816 | "returns": "out", 817 | "specialInterface": false 818 | }, 819 | "normalize": { 820 | "id": "normalize", 821 | "returns": "out", 822 | "specialInterface": false 823 | }, 824 | "dot": { 825 | "id": "dot", 826 | "returns": "BinaryExpression", 827 | "specialInterface": true 828 | }, 829 | "cross": { 830 | "id": "cross", 831 | "returns": "out", 832 | "specialInterface": false 833 | }, 834 | "lerp": { 835 | "id": "lerp", 836 | "returns": "out", 837 | "specialInterface": false 838 | }, 839 | "random": { 840 | "id": "random", 841 | "returns": "out", 842 | "specialInterface": false 843 | }, 844 | "transformMat2": { 845 | "id": "transformMat2", 846 | "returns": "out", 847 | "specialInterface": false 848 | }, 849 | "transformMat2d": { 850 | "id": "transformMat2d", 851 | "returns": "out", 852 | "specialInterface": false 853 | }, 854 | "transformMat3": { 855 | "id": "transformMat3", 856 | "returns": "out", 857 | "specialInterface": false 858 | }, 859 | "transformMat4": { 860 | "id": "transformMat4", 861 | "returns": "out", 862 | "specialInterface": false 863 | }, 864 | "str": { 865 | "id": "str", 866 | "returns": "BinaryExpression", 867 | "specialInterface": true 868 | }, 869 | "exactEquals": { 870 | "id": "exactEquals", 871 | "returns": "LogicalExpression", 872 | "specialInterface": true 873 | }, 874 | "equals": { 875 | "id": "equals", 876 | "returns": "LogicalExpression", 877 | "specialInterface": true 878 | } 879 | }, 880 | "vec3": { 881 | "create": { 882 | "id": "create", 883 | "returns": "out", 884 | "allocation": 3, 885 | "specialInterface": true 886 | }, 887 | "clone": { 888 | "id": "clone", 889 | "returns": "out", 890 | "allocation": 3, 891 | "specialInterface": true 892 | }, 893 | "length": { 894 | "id": "length", 895 | "returns": "CallExpression", 896 | "specialInterface": true 897 | }, 898 | "fromValues": { 899 | "id": "fromValues", 900 | "returns": "out", 901 | "allocation": 3, 902 | "specialInterface": true 903 | }, 904 | "copy": { 905 | "id": "copy", 906 | "returns": "out", 907 | "specialInterface": false 908 | }, 909 | "set": { 910 | "id": "set", 911 | "returns": "out", 912 | "specialInterface": false 913 | }, 914 | "add": { 915 | "id": "add", 916 | "returns": "out", 917 | "specialInterface": false 918 | }, 919 | "subtract": { 920 | "id": "subtract", 921 | "returns": "out", 922 | "specialInterface": false 923 | }, 924 | "multiply": { 925 | "id": "multiply", 926 | "returns": "out", 927 | "specialInterface": false 928 | }, 929 | "divide": { 930 | "id": "divide", 931 | "returns": "out", 932 | "specialInterface": false 933 | }, 934 | "ceil": { 935 | "id": "ceil", 936 | "returns": "out", 937 | "specialInterface": false 938 | }, 939 | "floor": { 940 | "id": "floor", 941 | "returns": "out", 942 | "specialInterface": false 943 | }, 944 | "min": { 945 | "id": "min", 946 | "returns": "out", 947 | "specialInterface": false 948 | }, 949 | "max": { 950 | "id": "max", 951 | "returns": "out", 952 | "specialInterface": false 953 | }, 954 | "round": { 955 | "id": "round", 956 | "returns": "out", 957 | "specialInterface": false 958 | }, 959 | "scale": { 960 | "id": "scale", 961 | "returns": "out", 962 | "specialInterface": false 963 | }, 964 | "scaleAndAdd": { 965 | "id": "scaleAndAdd", 966 | "returns": "out", 967 | "specialInterface": false 968 | }, 969 | "distance": { 970 | "id": "distance", 971 | "returns": "CallExpression", 972 | "specialInterface": true 973 | }, 974 | "squaredDistance": { 975 | "id": "squaredDistance", 976 | "returns": "BinaryExpression", 977 | "specialInterface": true 978 | }, 979 | "squaredLength": { 980 | "id": "squaredLength", 981 | "returns": "BinaryExpression", 982 | "specialInterface": true 983 | }, 984 | "negate": { 985 | "id": "negate", 986 | "returns": "out", 987 | "specialInterface": false 988 | }, 989 | "inverse": { 990 | "id": "inverse", 991 | "returns": "out", 992 | "specialInterface": false 993 | }, 994 | "normalize": { 995 | "id": "normalize", 996 | "returns": "out", 997 | "specialInterface": false 998 | }, 999 | "dot": { 1000 | "id": "dot", 1001 | "returns": "BinaryExpression", 1002 | "specialInterface": true 1003 | }, 1004 | "cross": { 1005 | "id": "cross", 1006 | "returns": "out", 1007 | "specialInterface": false 1008 | }, 1009 | "lerp": { 1010 | "id": "lerp", 1011 | "returns": "out", 1012 | "specialInterface": false 1013 | }, 1014 | "hermite": { 1015 | "id": "hermite", 1016 | "returns": "out", 1017 | "specialInterface": false 1018 | }, 1019 | "bezier": { 1020 | "id": "bezier", 1021 | "returns": "out", 1022 | "specialInterface": false 1023 | }, 1024 | "random": { 1025 | "id": "random", 1026 | "returns": "out", 1027 | "specialInterface": false 1028 | }, 1029 | "transformMat4": { 1030 | "id": "transformMat4", 1031 | "returns": "out", 1032 | "specialInterface": false 1033 | }, 1034 | "transformMat3": { 1035 | "id": "transformMat3", 1036 | "returns": "out", 1037 | "specialInterface": false 1038 | }, 1039 | "transformQuat": { 1040 | "id": "transformQuat", 1041 | "returns": "out", 1042 | "specialInterface": false 1043 | }, 1044 | "rotateX": { 1045 | "id": "rotateX", 1046 | "returns": "out", 1047 | "specialInterface": false 1048 | }, 1049 | "rotateY": { 1050 | "id": "rotateY", 1051 | "returns": "out", 1052 | "specialInterface": false 1053 | }, 1054 | "rotateZ": { 1055 | "id": "rotateZ", 1056 | "returns": "out", 1057 | "specialInterface": false 1058 | }, 1059 | "angle": { 1060 | "id": "angle", 1061 | "returns": "CallExpression", 1062 | "specialInterface": true 1063 | }, 1064 | "str": { 1065 | "id": "str", 1066 | "returns": "BinaryExpression", 1067 | "specialInterface": true 1068 | }, 1069 | "exactEquals": { 1070 | "id": "exactEquals", 1071 | "returns": "LogicalExpression", 1072 | "specialInterface": true 1073 | }, 1074 | "equals": { 1075 | "id": "equals", 1076 | "returns": "LogicalExpression", 1077 | "specialInterface": true 1078 | } 1079 | }, 1080 | "vec4": { 1081 | "create": { 1082 | "id": "create", 1083 | "returns": "out", 1084 | "allocation": 4, 1085 | "specialInterface": true 1086 | }, 1087 | "clone": { 1088 | "id": "clone", 1089 | "returns": "out", 1090 | "allocation": 4, 1091 | "specialInterface": true 1092 | }, 1093 | "fromValues": { 1094 | "id": "fromValues", 1095 | "returns": "out", 1096 | "allocation": 4, 1097 | "specialInterface": true 1098 | }, 1099 | "copy": { 1100 | "id": "copy", 1101 | "returns": "out", 1102 | "specialInterface": false 1103 | }, 1104 | "set": { 1105 | "id": "set", 1106 | "returns": "out", 1107 | "specialInterface": false 1108 | }, 1109 | "add": { 1110 | "id": "add", 1111 | "returns": "out", 1112 | "specialInterface": false 1113 | }, 1114 | "subtract": { 1115 | "id": "subtract", 1116 | "returns": "out", 1117 | "specialInterface": false 1118 | }, 1119 | "multiply": { 1120 | "id": "multiply", 1121 | "returns": "out", 1122 | "specialInterface": false 1123 | }, 1124 | "divide": { 1125 | "id": "divide", 1126 | "returns": "out", 1127 | "specialInterface": false 1128 | }, 1129 | "ceil": { 1130 | "id": "ceil", 1131 | "returns": "out", 1132 | "specialInterface": false 1133 | }, 1134 | "floor": { 1135 | "id": "floor", 1136 | "returns": "out", 1137 | "specialInterface": false 1138 | }, 1139 | "min": { 1140 | "id": "min", 1141 | "returns": "out", 1142 | "specialInterface": false 1143 | }, 1144 | "max": { 1145 | "id": "max", 1146 | "returns": "out", 1147 | "specialInterface": false 1148 | }, 1149 | "round": { 1150 | "id": "round", 1151 | "returns": "out", 1152 | "specialInterface": false 1153 | }, 1154 | "scale": { 1155 | "id": "scale", 1156 | "returns": "out", 1157 | "specialInterface": false 1158 | }, 1159 | "scaleAndAdd": { 1160 | "id": "scaleAndAdd", 1161 | "returns": "out", 1162 | "specialInterface": false 1163 | }, 1164 | "distance": { 1165 | "id": "distance", 1166 | "returns": "CallExpression", 1167 | "specialInterface": true 1168 | }, 1169 | "squaredDistance": { 1170 | "id": "squaredDistance", 1171 | "returns": "BinaryExpression", 1172 | "specialInterface": true 1173 | }, 1174 | "length": { 1175 | "id": "length", 1176 | "returns": "CallExpression", 1177 | "specialInterface": true 1178 | }, 1179 | "squaredLength": { 1180 | "id": "squaredLength", 1181 | "returns": "BinaryExpression", 1182 | "specialInterface": true 1183 | }, 1184 | "negate": { 1185 | "id": "negate", 1186 | "returns": "out", 1187 | "specialInterface": false 1188 | }, 1189 | "inverse": { 1190 | "id": "inverse", 1191 | "returns": "out", 1192 | "specialInterface": false 1193 | }, 1194 | "normalize": { 1195 | "id": "normalize", 1196 | "returns": "out", 1197 | "specialInterface": false 1198 | }, 1199 | "dot": { 1200 | "id": "dot", 1201 | "returns": "BinaryExpression", 1202 | "specialInterface": true 1203 | }, 1204 | "lerp": { 1205 | "id": "lerp", 1206 | "returns": "out", 1207 | "specialInterface": false 1208 | }, 1209 | "random": { 1210 | "id": "random", 1211 | "returns": "out", 1212 | "specialInterface": false 1213 | }, 1214 | "transformMat4": { 1215 | "id": "transformMat4", 1216 | "returns": "out", 1217 | "specialInterface": false 1218 | }, 1219 | "transformQuat": { 1220 | "id": "transformQuat", 1221 | "returns": "out", 1222 | "specialInterface": false 1223 | }, 1224 | "str": { 1225 | "id": "str", 1226 | "returns": "BinaryExpression", 1227 | "specialInterface": true 1228 | }, 1229 | "exactEquals": { 1230 | "id": "exactEquals", 1231 | "returns": "LogicalExpression", 1232 | "specialInterface": true 1233 | }, 1234 | "equals": { 1235 | "id": "equals", 1236 | "returns": "LogicalExpression", 1237 | "specialInterface": true 1238 | } 1239 | } 1240 | } -------------------------------------------------------------------------------- /interfaces/modules.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | "mat2", 3 | "mat2d", 4 | "mat3", 5 | "mat4", 6 | "quat", 7 | "vec2", 8 | "vec3", 9 | "vec4" 10 | ]; 11 | 12 | module.exports = [ 13 | "mat4" 14 | ]; 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glmw", 3 | "version": "0.1.3", 4 | "description": "WebAssembly powered Matrix and Vector library", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+ssh://git@github.com/maierfelix/glmw.git" 9 | }, 10 | "main": "dist/glmw-node.js", 11 | "module": "dist/glmw-node.es.js", 12 | "keywords": [ 13 | "matrix", 14 | "vector", 15 | "webgl", 16 | "webassembly", 17 | "wasm" 18 | ], 19 | "homepage": "http://maierfelix.github.io/glmw/", 20 | "author": "Felix Maier ", 21 | "contributors": [ 22 | "Felix Maier (https://github.com/maierfelix)" 23 | ], 24 | "bugs": { 25 | "url": "https://github.com/maierfelix/glmw/issues" 26 | }, 27 | "engines": { 28 | "node": ">= 6.x" 29 | }, 30 | "scripts": { 31 | "dist": "npm run browser && npm run build", 32 | "build": "rollup -c rollup/rollup.config.cjs.js && rollup -c rollup/rollup.config.es.js", 33 | "browser": "node rollup/rollup.bundle.js" 34 | }, 35 | "devDependencies": { 36 | "rollup": "^0.47.2", 37 | "rollup-plugin-buble": "^0.15.0", 38 | "rollup-plugin-commonjs": "^8.1.0", 39 | "rollup-plugin-json": "^2.3.0", 40 | "rollup-plugin-node-resolve": "^3.0.0", 41 | "webassembly": "^0.11.0" 42 | }, 43 | "dependencies": {} 44 | } 45 | -------------------------------------------------------------------------------- /rollup/compile.wasm.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const compiler = require("webassembly/cli/compiler"); 3 | 4 | let source = `src/gl-matrix/`; 5 | 6 | let args = [ 7 | "-q", 8 | "-O3", 9 | source + "main.c", 10 | "-o", "./wasm_tmp.wasm", 11 | "-i", source + "mat4.c", 12 | "-i", source + "vec3.c", 13 | "-i", source + "vec4.c" 14 | ]; 15 | 16 | module.exports = function() { 17 | return new Promise((resolve) => { 18 | compiler.main(args, (e, path) => { 19 | if (e) throw e; 20 | let data = fs.readFileSync(path); 21 | let code = ` 22 | let binary = new Uint8Array([${new Uint8Array(data).toString()}]); 23 | export default binary; 24 | `; 25 | fs.unlinkSync(path); 26 | fs.writeFileSync("src/module.js", code, "utf-8"); 27 | resolve(); 28 | }); 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /rollup/rollup.bundle.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const pkg = require("../package.json"); 3 | const wasm = require("./compile.wasm"); 4 | 5 | const rollup = require("rollup"); 6 | const json = require("rollup-plugin-json"); 7 | const buble = require("rollup-plugin-buble"); 8 | const resolve = require("rollup-plugin-node-resolve"); 9 | const commonjs = require("rollup-plugin-commonjs"); 10 | 11 | let config = {}; 12 | config.entry = "src/index.js"; 13 | config.moduleName = "glmw"; 14 | config.useStrict = true; 15 | config.format = "iife"; 16 | config.dest = pkg.browser; 17 | config.external = []; 18 | config.plugins = [ 19 | json(), 20 | buble(), 21 | resolve({ 22 | browser: true 23 | }), 24 | commonjs() 25 | ]; 26 | 27 | const outputOptions = {}; 28 | 29 | async function build() { 30 | 31 | await wasm(); 32 | 33 | const bundle = await rollup.rollup(config); 34 | 35 | const { code, map } = await bundle.generate(config); 36 | fs.writeFileSync("dist/glmw-browser.js", code, "utf-8"); 37 | 38 | } 39 | 40 | build(); 41 | -------------------------------------------------------------------------------- /rollup/rollup.config.cjs.js: -------------------------------------------------------------------------------- 1 | const pkg = require("../package.json"); 2 | import config from "./rollup.config"; 3 | 4 | config.format = "cjs"; 5 | config.dest = pkg.main; 6 | config.paths = {}; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /rollup/rollup.config.es.js: -------------------------------------------------------------------------------- 1 | const pkg = require("../package.json"); 2 | import config from "./rollup.config"; 3 | 4 | config.format = "es"; 5 | config.dest = pkg.module; 6 | 7 | export default config; 8 | -------------------------------------------------------------------------------- /rollup/rollup.config.iife.js: -------------------------------------------------------------------------------- 1 | const pkg = require("../package.json"); 2 | import config from "./rollup.config"; 3 | import json from "rollup-plugin-json"; 4 | import buble from "rollup-plugin-buble"; 5 | import resolve from "rollup-plugin-node-resolve"; 6 | import commonjs from "rollup-plugin-commonjs"; 7 | 8 | config.format = "iife"; 9 | config.dest = pkg.browser; 10 | config.external = []; 11 | config.plugins = [ 12 | json(), 13 | buble(), 14 | resolve({ 15 | jsnext: true, 16 | browser: true 17 | }), 18 | commonjs({ 19 | namedExports: {} 20 | }) 21 | ]; 22 | 23 | export default config; 24 | -------------------------------------------------------------------------------- /rollup/rollup.config.js: -------------------------------------------------------------------------------- 1 | import json from "rollup-plugin-json"; 2 | 3 | export default { 4 | entry: "src/index.js", 5 | moduleName: "iroh", 6 | external: [], 7 | plugins: [ 8 | json() 9 | ] 10 | }; 11 | -------------------------------------------------------------------------------- /src/gl-matrix/bridges/mat4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The following methods need to be bridged 3 | * within js which results in some overhead 4 | */ 5 | export default function(module, memory) { 6 | // @str 7 | module.str = function(address) { 8 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 16); 9 | let out = ""; 10 | for (let ii = 0; ii < 16; ++ii) { 11 | if (ii + 1 < 16) out += view[ii] + ", "; 12 | else out += view[ii]; 13 | }; 14 | return "mat4(" + out + ")"; 15 | }; 16 | // @view 17 | module.view = function(address) { 18 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 16); 19 | //view.address = address; 20 | return view; 21 | }; 22 | // @exactEquals 23 | let _exactEquals = module.exactEquals; 24 | module.exactEquals = function(a, b) { 25 | return !!_exactEquals(a, b); 26 | }; 27 | // @equals 28 | let _equals = module.equals; 29 | module.equals = function(a, b) { 30 | return !!_equals(a, b); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /src/gl-matrix/bridges/vec3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The following methods need to be bridged 3 | * within js which results in some overhead 4 | */ 5 | export default function(module, memory) { 6 | // @str 7 | module.str = function(address) { 8 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 3); 9 | return `vec3(${ view[0] }, ${ view[1] }, ${ view[2] })`; 10 | }; 11 | // @view 12 | module.view = function(address) { 13 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 3); 14 | //view.address = address; 15 | return view; 16 | }; 17 | // @exactEquals 18 | let _exactEquals = module.exactEquals; 19 | module.exactEquals = function(a, b) { 20 | return !!_exactEquals(a, b); 21 | }; 22 | // @equals 23 | let _equals = module.equals; 24 | module.equals = function(a, b) { 25 | return !!_equals(a, b); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /src/gl-matrix/bridges/vec4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The following methods need to be bridged 3 | * within js which results in some overhead 4 | */ 5 | export default function(module, memory) { 6 | // @str 7 | module.str = function(address) { 8 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 4); 9 | return `vec4(${ view[0] }, ${ view[1] }, ${ view[2] }, ${ view[3] })`; 10 | }; 11 | // @view 12 | module.view = function(address) { 13 | let view = memory.F32.subarray(address >> 2, (address >> 2) + 4); 14 | //view.address = address; 15 | return view; 16 | }; 17 | // @exactEquals 18 | let _exactEquals = module.exactEquals; 19 | module.exactEquals = function(a, b) { 20 | return !!_exactEquals(a, b); 21 | }; 22 | // @equals 23 | let _equals = module.equals; 24 | module.equals = function(a, b) { 25 | return !!_equals(a, b); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /src/gl-matrix/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef FOO_H_ 4 | #define FOO_H_ 5 | 6 | import float randf(); 7 | 8 | float const PI = 3.141592653589793; 9 | 10 | float const degree = PI / 180.0; 11 | 12 | float toRadian(a) { 13 | return a * degree; 14 | }; 15 | 16 | float const EPSILON = 0.000001; 17 | 18 | // sizes 19 | int const VEC_SIZE_3 = 3; 20 | int const VEC_SIZE_4 = 4; 21 | int const MAT_SIZE_4 = 4 * 4; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/gl-matrix/main.c: -------------------------------------------------------------------------------- 1 | // entry 2 | -------------------------------------------------------------------------------- /src/gl-matrix/mat4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | 5 | #define mat4(x) mat4_##x 6 | 7 | /** 8 | * Frees a mat4 9 | */ 10 | export float *mat4(free)(float *a) { 11 | free(a); 12 | return NULL; 13 | }; 14 | 15 | /** 16 | * Creates a new identity mat4 17 | * 18 | * @returns {mat4} a new 4x4 matrix 19 | */ 20 | export float *mat4(create)() { 21 | float *out = malloc(MAT_SIZE_4 * sizeof(*out)); 22 | out[0] = 1; 23 | out[1] = 0; 24 | out[2] = 0; 25 | out[3] = 0; 26 | out[4] = 0; 27 | out[5] = 1; 28 | out[6] = 0; 29 | out[7] = 0; 30 | out[8] = 0; 31 | out[9] = 0; 32 | out[10] = 1; 33 | out[11] = 0; 34 | out[12] = 0; 35 | out[13] = 0; 36 | out[14] = 0; 37 | out[15] = 1; 38 | return out; 39 | }; 40 | 41 | /** 42 | * Creates a new mat4 initialized with values from an existing matrix 43 | * 44 | * @param {mat4} a matrix to clone 45 | * @returns {mat4} a new 4x4 matrix 46 | */ 47 | export float *mat4(clone)(float *a) { 48 | float *out = malloc(MAT_SIZE_4 * sizeof(float)); 49 | out[0] = a[0]; 50 | out[1] = a[1]; 51 | out[2] = a[2]; 52 | out[3] = a[3]; 53 | out[4] = a[4]; 54 | out[5] = a[5]; 55 | out[6] = a[6]; 56 | out[7] = a[7]; 57 | out[8] = a[8]; 58 | out[9] = a[9]; 59 | out[10] = a[10]; 60 | out[11] = a[11]; 61 | out[12] = a[12]; 62 | out[13] = a[13]; 63 | out[14] = a[14]; 64 | out[15] = a[15]; 65 | return out; 66 | }; 67 | 68 | /** 69 | * Copy the values from one mat4 to another 70 | * 71 | * @param {mat4} out the receiving matrix 72 | * @param {mat4} a the source matrix 73 | * @returns {mat4} out 74 | */ 75 | export float *mat4(copy)(float *out, float *a) { 76 | out[0] = a[0]; 77 | out[1] = a[1]; 78 | out[2] = a[2]; 79 | out[3] = a[3]; 80 | out[4] = a[4]; 81 | out[5] = a[5]; 82 | out[6] = a[6]; 83 | out[7] = a[7]; 84 | out[8] = a[8]; 85 | out[9] = a[9]; 86 | out[10] = a[10]; 87 | out[11] = a[11]; 88 | out[12] = a[12]; 89 | out[13] = a[13]; 90 | out[14] = a[14]; 91 | out[15] = a[15]; 92 | return out; 93 | }; 94 | 95 | /** 96 | * Create a new mat4 with the given values 97 | * 98 | * @param {Number} m00 Component in column 0, row 0 position (index 0) 99 | * @param {Number} m01 Component in column 0, row 1 position (index 1) 100 | * @param {Number} m02 Component in column 0, row 2 position (index 2) 101 | * @param {Number} m03 Component in column 0, row 3 position (index 3) 102 | * @param {Number} m10 Component in column 1, row 0 position (index 4) 103 | * @param {Number} m11 Component in column 1, row 1 position (index 5) 104 | * @param {Number} m12 Component in column 1, row 2 position (index 6) 105 | * @param {Number} m13 Component in column 1, row 3 position (index 7) 106 | * @param {Number} m20 Component in column 2, row 0 position (index 8) 107 | * @param {Number} m21 Component in column 2, row 1 position (index 9) 108 | * @param {Number} m22 Component in column 2, row 2 position (index 10) 109 | * @param {Number} m23 Component in column 2, row 3 position (index 11) 110 | * @param {Number} m30 Component in column 3, row 0 position (index 12) 111 | * @param {Number} m31 Component in column 3, row 1 position (index 13) 112 | * @param {Number} m32 Component in column 3, row 2 position (index 14) 113 | * @param {Number} m33 Component in column 3, row 3 position (index 15) 114 | * @returns {mat4} A new mat4 115 | */ 116 | export float *mat4(fromValues)(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) { 117 | float *out = malloc(MAT_SIZE_4 * sizeof(*out)); 118 | out[0] = m00; 119 | out[1] = m01; 120 | out[2] = m02; 121 | out[3] = m03; 122 | out[4] = m10; 123 | out[5] = m11; 124 | out[6] = m12; 125 | out[7] = m13; 126 | out[8] = m20; 127 | out[9] = m21; 128 | out[10] = m22; 129 | out[11] = m23; 130 | out[12] = m30; 131 | out[13] = m31; 132 | out[14] = m32; 133 | out[15] = m33; 134 | return out; 135 | }; 136 | 137 | /** 138 | * Set the components of a mat4 to the given values 139 | * 140 | * @param {mat4} out the receiving matrix 141 | * @param {Number} m00 Component in column 0, row 0 position (index 0) 142 | * @param {Number} m01 Component in column 0, row 1 position (index 1) 143 | * @param {Number} m02 Component in column 0, row 2 position (index 2) 144 | * @param {Number} m03 Component in column 0, row 3 position (index 3) 145 | * @param {Number} m10 Component in column 1, row 0 position (index 4) 146 | * @param {Number} m11 Component in column 1, row 1 position (index 5) 147 | * @param {Number} m12 Component in column 1, row 2 position (index 6) 148 | * @param {Number} m13 Component in column 1, row 3 position (index 7) 149 | * @param {Number} m20 Component in column 2, row 0 position (index 8) 150 | * @param {Number} m21 Component in column 2, row 1 position (index 9) 151 | * @param {Number} m22 Component in column 2, row 2 position (index 10) 152 | * @param {Number} m23 Component in column 2, row 3 position (index 11) 153 | * @param {Number} m30 Component in column 3, row 0 position (index 12) 154 | * @param {Number} m31 Component in column 3, row 1 position (index 13) 155 | * @param {Number} m32 Component in column 3, row 2 position (index 14) 156 | * @param {Number} m33 Component in column 3, row 3 position (index 15) 157 | * @returns {mat4} out 158 | */ 159 | export float *mat4(set)(float *out, float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) { 160 | out[0] = m00; 161 | out[1] = m01; 162 | out[2] = m02; 163 | out[3] = m03; 164 | out[4] = m10; 165 | out[5] = m11; 166 | out[6] = m12; 167 | out[7] = m13; 168 | out[8] = m20; 169 | out[9] = m21; 170 | out[10] = m22; 171 | out[11] = m23; 172 | out[12] = m30; 173 | out[13] = m31; 174 | out[14] = m32; 175 | out[15] = m33; 176 | return out; 177 | }; 178 | 179 | /** 180 | * Set a mat4 to the identity matrix 181 | * 182 | * @param {mat4} out the receiving matrix 183 | * @returns {mat4} out 184 | */ 185 | export float *mat4(identity)(float *out) { 186 | out[0] = 1; 187 | out[1] = 0; 188 | out[2] = 0; 189 | out[3] = 0; 190 | out[4] = 0; 191 | out[5] = 1; 192 | out[6] = 0; 193 | out[7] = 0; 194 | out[8] = 0; 195 | out[9] = 0; 196 | out[10] = 1; 197 | out[11] = 0; 198 | out[12] = 0; 199 | out[13] = 0; 200 | out[14] = 0; 201 | out[15] = 1; 202 | return out; 203 | }; 204 | 205 | /** 206 | * Transpose the values of a mat4 207 | * 208 | * @param {mat4} out the receiving matrix 209 | * @param {mat4} a the source matrix 210 | * @returns {mat4} out 211 | */ 212 | export float *mat4(transpose)(float *out, float *a) { 213 | // If we are transposing ourselves we can skip a few steps but have to cache some values 214 | if (out == a) { 215 | float a01 = a[1], a02 = a[2], a03 = a[3]; 216 | float a12 = a[6], a13 = a[7]; 217 | float a23 = a[11]; 218 | 219 | out[1] = a[4]; 220 | out[2] = a[8]; 221 | out[3] = a[12]; 222 | out[4] = a01; 223 | out[6] = a[9]; 224 | out[7] = a[13]; 225 | out[8] = a02; 226 | out[9] = a12; 227 | out[11] = a[14]; 228 | out[12] = a03; 229 | out[13] = a13; 230 | out[14] = a23; 231 | } else { 232 | out[0] = a[0]; 233 | out[1] = a[4]; 234 | out[2] = a[8]; 235 | out[3] = a[12]; 236 | out[4] = a[1]; 237 | out[5] = a[5]; 238 | out[6] = a[9]; 239 | out[7] = a[13]; 240 | out[8] = a[2]; 241 | out[9] = a[6]; 242 | out[10] = a[10]; 243 | out[11] = a[14]; 244 | out[12] = a[3]; 245 | out[13] = a[7]; 246 | out[14] = a[11]; 247 | out[15] = a[15]; 248 | } 249 | 250 | return out; 251 | }; 252 | 253 | /** 254 | * Inverts a mat4 255 | * 256 | * @param {mat4} out the receiving matrix 257 | * @param {mat4} a the source matrix 258 | * @returns {mat4} out 259 | */ 260 | export float *mat4(invert)(float *out, float *a) { 261 | float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; 262 | float a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; 263 | float a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; 264 | float a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 265 | 266 | float b00 = a00 * a11 - a01 * a10; 267 | float b01 = a00 * a12 - a02 * a10; 268 | float b02 = a00 * a13 - a03 * a10; 269 | float b03 = a01 * a12 - a02 * a11; 270 | float b04 = a01 * a13 - a03 * a11; 271 | float b05 = a02 * a13 - a03 * a12; 272 | float b06 = a20 * a31 - a21 * a30; 273 | float b07 = a20 * a32 - a22 * a30; 274 | float b08 = a20 * a33 - a23 * a30; 275 | float b09 = a21 * a32 - a22 * a31; 276 | float b10 = a21 * a33 - a23 * a31; 277 | float b11 = a22 * a33 - a23 * a32; 278 | 279 | // Calculate the determinant 280 | float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 281 | 282 | if (!det) { 283 | return NULL; 284 | } 285 | det = 1.0 / det; 286 | 287 | out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 288 | out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 289 | out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 290 | out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 291 | out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 292 | out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 293 | out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 294 | out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 295 | out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 296 | out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 297 | out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 298 | out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 299 | out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 300 | out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 301 | out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 302 | out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 303 | 304 | return out; 305 | }; 306 | 307 | /** 308 | * Calculates the adjugate of a mat4 309 | * 310 | * @param {mat4} out the receiving matrix 311 | * @param {mat4} a the source matrix 312 | * @returns {mat4} out 313 | */ 314 | export float *mat4(adjoint)(float *out, float *a) { 315 | float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; 316 | float a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; 317 | float a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; 318 | float a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 319 | 320 | out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); 321 | out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); 322 | out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); 323 | out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); 324 | out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); 325 | out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); 326 | out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); 327 | out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); 328 | out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); 329 | out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); 330 | out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); 331 | out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); 332 | out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); 333 | out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); 334 | out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); 335 | out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); 336 | return out; 337 | }; 338 | 339 | /** 340 | * Calculates the determinant of a mat4 341 | * 342 | * @param {mat4} a the source matrix 343 | * @returns {Number} determinant of a 344 | */ 345 | export float mat4(determinant)(float *a) { 346 | float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; 347 | float a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; 348 | float a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; 349 | float a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 350 | 351 | float b00 = a00 * a11 - a01 * a10; 352 | float b01 = a00 * a12 - a02 * a10; 353 | float b02 = a00 * a13 - a03 * a10; 354 | float b03 = a01 * a12 - a02 * a11; 355 | float b04 = a01 * a13 - a03 * a11; 356 | float b05 = a02 * a13 - a03 * a12; 357 | float b06 = a20 * a31 - a21 * a30; 358 | float b07 = a20 * a32 - a22 * a30; 359 | float b08 = a20 * a33 - a23 * a30; 360 | float b09 = a21 * a32 - a22 * a31; 361 | float b10 = a21 * a33 - a23 * a31; 362 | float b11 = a22 * a33 - a23 * a32; 363 | 364 | // Calculate the determinant 365 | return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 366 | }; 367 | 368 | /** 369 | * Multiplies two mat4s 370 | * 371 | * @param {mat4} out the receiving matrix 372 | * @param {mat4} a the first operand 373 | * @param {mat4} b the second operand 374 | * @returns {mat4} out 375 | */ 376 | export float *mat4(multiply)(float *out, float *a, float *b) { 377 | float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; 378 | float a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; 379 | float a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; 380 | float a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 381 | 382 | // Cache only the current line of the second matrix 383 | float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 384 | out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 385 | out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 386 | out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 387 | out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 388 | 389 | b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; 390 | out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 391 | out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 392 | out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 393 | out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 394 | 395 | b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; 396 | out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 397 | out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 398 | out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 399 | out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 400 | 401 | b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; 402 | out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 403 | out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 404 | out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 405 | out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 406 | return out; 407 | }; 408 | 409 | /** 410 | * Translate a mat4 by the given vector 411 | * 412 | * @param {mat4} out the receiving matrix 413 | * @param {mat4} a the matrix to translate 414 | * @param {vec3} v vector to translate by 415 | * @returns {mat4} out 416 | */ 417 | export float *mat4(translate)(float *out, float *a, float *v) { 418 | float x = v[0], y = v[1], z = v[2]; 419 | float a00, a01, a02, a03; 420 | float a10, a11, a12, a13; 421 | float a20, a21, a22, a23; 422 | 423 | if (a == out) { 424 | out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 425 | out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 426 | out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 427 | out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 428 | } else { 429 | a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 430 | a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 431 | a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 432 | 433 | out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; 434 | out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; 435 | out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; 436 | 437 | out[12] = a00 * x + a10 * y + a20 * z + a[12]; 438 | out[13] = a01 * x + a11 * y + a21 * z + a[13]; 439 | out[14] = a02 * x + a12 * y + a22 * z + a[14]; 440 | out[15] = a03 * x + a13 * y + a23 * z + a[15]; 441 | } 442 | 443 | return out; 444 | }; 445 | 446 | /** 447 | * Scales the mat4 by the dimensions in the given vec3 not using vectorization 448 | * 449 | * @param {mat4} out the receiving matrix 450 | * @param {mat4} a the matrix to scale 451 | * @param {vec3} v the vec3 to scale the matrix by 452 | * @returns {mat4} out 453 | **/ 454 | export float *mat4(scale)(float *out, float *a, float *v) { 455 | float x = v[0], y = v[1], z = v[2]; 456 | 457 | out[0] = a[0] * x; 458 | out[1] = a[1] * x; 459 | out[2] = a[2] * x; 460 | out[3] = a[3] * x; 461 | out[4] = a[4] * y; 462 | out[5] = a[5] * y; 463 | out[6] = a[6] * y; 464 | out[7] = a[7] * y; 465 | out[8] = a[8] * z; 466 | out[9] = a[9] * z; 467 | out[10] = a[10] * z; 468 | out[11] = a[11] * z; 469 | out[12] = a[12]; 470 | out[13] = a[13]; 471 | out[14] = a[14]; 472 | out[15] = a[15]; 473 | return out; 474 | }; 475 | 476 | /** 477 | * Rotates a mat4 by the given angle around the given axis 478 | * 479 | * @param {mat4} out the receiving matrix 480 | * @param {mat4} a the matrix to rotate 481 | * @param {Number} rad the angle to rotate the matrix by 482 | * @param {vec3} axis the axis to rotate around 483 | * @returns {mat4} out 484 | */ 485 | export float *mat4(rotate)(float *out, float *a, float rad, float *axis) { 486 | float x = axis[0], y = axis[1], z = axis[2]; 487 | float len = sqrtf(x * x + y * y + z * z); 488 | float s, c, t; 489 | float a00, a01, a02, a03; 490 | float a10, a11, a12, a13; 491 | float a20, a21, a22, a23; 492 | float b00, b01, b02; 493 | float b10, b11, b12; 494 | float b20, b21, b22; 495 | 496 | if (fabs(len) < EPSILON) { return NULL; } 497 | 498 | len = 1.0 / len; 499 | x *= len; 500 | y *= len; 501 | z *= len; 502 | 503 | s = sinf(rad); 504 | c = cosf(rad); 505 | t = 1 - c; 506 | 507 | a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 508 | a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 509 | a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 510 | 511 | // Construct the elements of the rotation matrix 512 | b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; 513 | b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; 514 | b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; 515 | 516 | // Perform rotation-specific matrix multiplication 517 | out[0] = a00 * b00 + a10 * b01 + a20 * b02; 518 | out[1] = a01 * b00 + a11 * b01 + a21 * b02; 519 | out[2] = a02 * b00 + a12 * b01 + a22 * b02; 520 | out[3] = a03 * b00 + a13 * b01 + a23 * b02; 521 | out[4] = a00 * b10 + a10 * b11 + a20 * b12; 522 | out[5] = a01 * b10 + a11 * b11 + a21 * b12; 523 | out[6] = a02 * b10 + a12 * b11 + a22 * b12; 524 | out[7] = a03 * b10 + a13 * b11 + a23 * b12; 525 | out[8] = a00 * b20 + a10 * b21 + a20 * b22; 526 | out[9] = a01 * b20 + a11 * b21 + a21 * b22; 527 | out[10] = a02 * b20 + a12 * b21 + a22 * b22; 528 | out[11] = a03 * b20 + a13 * b21 + a23 * b22; 529 | 530 | if (a != out) { // If the source and destination differ, copy the unchanged last row 531 | out[12] = a[12]; 532 | out[13] = a[13]; 533 | out[14] = a[14]; 534 | out[15] = a[15]; 535 | } 536 | return out; 537 | }; 538 | 539 | /** 540 | * Rotates a matrix by the given angle around the X axis 541 | * 542 | * @param {mat4} out the receiving matrix 543 | * @param {mat4} a the matrix to rotate 544 | * @param {Number} rad the angle to rotate the matrix by 545 | * @returns {mat4} out 546 | */ 547 | export float *mat4(rotateX)(float *out, float *a, float rad) { 548 | float s = sinf(rad); 549 | float c = cosf(rad); 550 | float a10 = a[4]; 551 | float a11 = a[5]; 552 | float a12 = a[6]; 553 | float a13 = a[7]; 554 | float a20 = a[8]; 555 | float a21 = a[9]; 556 | float a22 = a[10]; 557 | float a23 = a[11]; 558 | 559 | if (a != out) { // If the source and destination differ, copy the unchanged rows 560 | out[0] = a[0]; 561 | out[1] = a[1]; 562 | out[2] = a[2]; 563 | out[3] = a[3]; 564 | out[12] = a[12]; 565 | out[13] = a[13]; 566 | out[14] = a[14]; 567 | out[15] = a[15]; 568 | } 569 | 570 | // Perform axis-specific matrix multiplication 571 | out[4] = a10 * c + a20 * s; 572 | out[5] = a11 * c + a21 * s; 573 | out[6] = a12 * c + a22 * s; 574 | out[7] = a13 * c + a23 * s; 575 | out[8] = a20 * c - a10 * s; 576 | out[9] = a21 * c - a11 * s; 577 | out[10] = a22 * c - a12 * s; 578 | out[11] = a23 * c - a13 * s; 579 | return out; 580 | }; 581 | 582 | /** 583 | * Rotates a matrix by the given angle around the Y axis 584 | * 585 | * @param {mat4} out the receiving matrix 586 | * @param {mat4} a the matrix to rotate 587 | * @param {Number} rad the angle to rotate the matrix by 588 | * @returns {mat4} out 589 | */ 590 | export float *mat4(rotateY)(float *out, float *a, float rad) { 591 | float s = sinf(rad); 592 | float c = cosf(rad); 593 | float a00 = a[0]; 594 | float a01 = a[1]; 595 | float a02 = a[2]; 596 | float a03 = a[3]; 597 | float a20 = a[8]; 598 | float a21 = a[9]; 599 | float a22 = a[10]; 600 | float a23 = a[11]; 601 | 602 | if (a != out) { // If the source and destination differ, copy the unchanged rows 603 | out[4] = a[4]; 604 | out[5] = a[5]; 605 | out[6] = a[6]; 606 | out[7] = a[7]; 607 | out[12] = a[12]; 608 | out[13] = a[13]; 609 | out[14] = a[14]; 610 | out[15] = a[15]; 611 | } 612 | 613 | // Perform axis-specific matrix multiplication 614 | out[0] = a00 * c - a20 * s; 615 | out[1] = a01 * c - a21 * s; 616 | out[2] = a02 * c - a22 * s; 617 | out[3] = a03 * c - a23 * s; 618 | out[8] = a00 * s + a20 * c; 619 | out[9] = a01 * s + a21 * c; 620 | out[10] = a02 * s + a22 * c; 621 | out[11] = a03 * s + a23 * c; 622 | return out; 623 | }; 624 | 625 | /** 626 | * Rotates a matrix by the given angle around the Z axis 627 | * 628 | * @param {mat4} out the receiving matrix 629 | * @param {mat4} a the matrix to rotate 630 | * @param {Number} rad the angle to rotate the matrix by 631 | * @returns {mat4} out 632 | */ 633 | export float *mat4(rotateZ)(float *out, float *a, float rad) { 634 | float s = sinf(rad); 635 | float c = cosf(rad); 636 | float a00 = a[0]; 637 | float a01 = a[1]; 638 | float a02 = a[2]; 639 | float a03 = a[3]; 640 | float a10 = a[4]; 641 | float a11 = a[5]; 642 | float a12 = a[6]; 643 | float a13 = a[7]; 644 | 645 | if (a != out) { // If the source and destination differ, copy the unchanged last row 646 | out[8] = a[8]; 647 | out[9] = a[9]; 648 | out[10] = a[10]; 649 | out[11] = a[11]; 650 | out[12] = a[12]; 651 | out[13] = a[13]; 652 | out[14] = a[14]; 653 | out[15] = a[15]; 654 | } 655 | 656 | // Perform axis-specific matrix multiplication 657 | out[0] = a00 * c + a10 * s; 658 | out[1] = a01 * c + a11 * s; 659 | out[2] = a02 * c + a12 * s; 660 | out[3] = a03 * c + a13 * s; 661 | out[4] = a10 * c - a00 * s; 662 | out[5] = a11 * c - a01 * s; 663 | out[6] = a12 * c - a02 * s; 664 | out[7] = a13 * c - a03 * s; 665 | return out; 666 | }; 667 | 668 | /** 669 | * Creates a matrix from a vector translation 670 | * This is equivalent to (but much faster than): 671 | * 672 | * mat4.identity(dest); 673 | * mat4.translate(dest, dest, vec); 674 | * 675 | * @param {mat4} out mat4 receiving operation result 676 | * @param {vec3} v Translation vector 677 | * @returns {mat4} out 678 | */ 679 | export float *mat4(fromTranslation)(float *out, float *v) { 680 | out[0] = 1; 681 | out[1] = 0; 682 | out[2] = 0; 683 | out[3] = 0; 684 | out[4] = 0; 685 | out[5] = 1; 686 | out[6] = 0; 687 | out[7] = 0; 688 | out[8] = 0; 689 | out[9] = 0; 690 | out[10] = 1; 691 | out[11] = 0; 692 | out[12] = v[0]; 693 | out[13] = v[1]; 694 | out[14] = v[2]; 695 | out[15] = 1; 696 | return out; 697 | }; 698 | 699 | /** 700 | * Creates a matrix from a vector scaling 701 | * This is equivalent to (but much faster than): 702 | * 703 | * mat4.identity(dest); 704 | * mat4.scale(dest, dest, vec); 705 | * 706 | * @param {mat4} out mat4 receiving operation result 707 | * @param {vec3} v Scaling vector 708 | * @returns {mat4} out 709 | */ 710 | export float *mat4(fromScaling)(float *out, float *v) { 711 | out[0] = v[0]; 712 | out[1] = 0; 713 | out[2] = 0; 714 | out[3] = 0; 715 | out[4] = 0; 716 | out[5] = v[1]; 717 | out[6] = 0; 718 | out[7] = 0; 719 | out[8] = 0; 720 | out[9] = 0; 721 | out[10] = v[2]; 722 | out[11] = 0; 723 | out[12] = 0; 724 | out[13] = 0; 725 | out[14] = 0; 726 | out[15] = 1; 727 | return out; 728 | }; 729 | 730 | /** 731 | * Creates a matrix from a given angle around a given axis 732 | * This is equivalent to (but much faster than): 733 | * 734 | * mat4.identity(dest); 735 | * mat4.rotate(dest, dest, rad, axis); 736 | * 737 | * @param {mat4} out mat4 receiving operation result 738 | * @param {Number} rad the angle to rotate the matrix by 739 | * @param {vec3} axis the axis to rotate around 740 | * @returns {mat4} out 741 | */ 742 | export float *mat4(fromRotation)(float *out, float rad, float *axis) { 743 | float x = axis[0], y = axis[1], z = axis[2]; 744 | float len = sqrtf(x * x + y * y + z * z); 745 | float s, c, t; 746 | 747 | if (fabs(len) < EPSILON) { return NULL; } 748 | 749 | len = 1.0 / len; 750 | x *= len; 751 | y *= len; 752 | z *= len; 753 | 754 | s = sinf(rad); 755 | c = cosf(rad); 756 | t = 1 - c; 757 | 758 | // Perform rotation-specific matrix multiplication 759 | out[0] = x * x * t + c; 760 | out[1] = y * x * t + z * s; 761 | out[2] = z * x * t - y * s; 762 | out[3] = 0; 763 | out[4] = x * y * t - z * s; 764 | out[5] = y * y * t + c; 765 | out[6] = z * y * t + x * s; 766 | out[7] = 0; 767 | out[8] = x * z * t + y * s; 768 | out[9] = y * z * t - x * s; 769 | out[10] = z * z * t + c; 770 | out[11] = 0; 771 | out[12] = 0; 772 | out[13] = 0; 773 | out[14] = 0; 774 | out[15] = 1; 775 | return out; 776 | }; 777 | 778 | /** 779 | * Creates a matrix from the given angle around the X axis 780 | * This is equivalent to (but much faster than): 781 | * 782 | * mat4.identity(dest); 783 | * mat4.rotateX(dest, dest, rad); 784 | * 785 | * @param {mat4} out mat4 receiving operation result 786 | * @param {Number} rad the angle to rotate the matrix by 787 | * @returns {mat4} out 788 | */ 789 | export float *mat4(fromXRotation)(float *out, float rad) { 790 | float s = sinf(rad); 791 | float c = cosf(rad); 792 | 793 | // Perform axis-specific matrix multiplication 794 | out[0] = 1; 795 | out[1] = 0; 796 | out[2] = 0; 797 | out[3] = 0; 798 | out[4] = 0; 799 | out[5] = c; 800 | out[6] = s; 801 | out[7] = 0; 802 | out[8] = 0; 803 | out[9] = -s; 804 | out[10] = c; 805 | out[11] = 0; 806 | out[12] = 0; 807 | out[13] = 0; 808 | out[14] = 0; 809 | out[15] = 1; 810 | return out; 811 | }; 812 | 813 | /** 814 | * Creates a matrix from the given angle around the Y axis 815 | * This is equivalent to (but much faster than): 816 | * 817 | * mat4.identity(dest); 818 | * mat4.rotateY(dest, dest, rad); 819 | * 820 | * @param {mat4} out mat4 receiving operation result 821 | * @param {Number} rad the angle to rotate the matrix by 822 | * @returns {mat4} out 823 | */ 824 | export float *mat4(fromYRotation)(float *out, float rad) { 825 | float s = sinf(rad); 826 | float c = cosf(rad); 827 | 828 | // Perform axis-specific matrix multiplication 829 | out[0] = c; 830 | out[1] = 0; 831 | out[2] = -s; 832 | out[3] = 0; 833 | out[4] = 0; 834 | out[5] = 1; 835 | out[6] = 0; 836 | out[7] = 0; 837 | out[8] = s; 838 | out[9] = 0; 839 | out[10] = c; 840 | out[11] = 0; 841 | out[12] = 0; 842 | out[13] = 0; 843 | out[14] = 0; 844 | out[15] = 1; 845 | return out; 846 | }; 847 | 848 | /** 849 | * Creates a matrix from the given angle around the Z axis 850 | * This is equivalent to (but much faster than): 851 | * 852 | * mat4.identity(dest); 853 | * mat4.rotateZ(dest, dest, rad); 854 | * 855 | * @param {mat4} out mat4 receiving operation result 856 | * @param {Number} rad the angle to rotate the matrix by 857 | * @returns {mat4} out 858 | */ 859 | export float *mat4(fromZRotation)(float *out, float rad) { 860 | float s = sinf(rad); 861 | float c = cosf(rad); 862 | 863 | // Perform axis-specific matrix multiplication 864 | out[0] = c; 865 | out[1] = s; 866 | out[2] = 0; 867 | out[3] = 0; 868 | out[4] = -s; 869 | out[5] = c; 870 | out[6] = 0; 871 | out[7] = 0; 872 | out[8] = 0; 873 | out[9] = 0; 874 | out[10] = 1; 875 | out[11] = 0; 876 | out[12] = 0; 877 | out[13] = 0; 878 | out[14] = 0; 879 | out[15] = 1; 880 | return out; 881 | }; 882 | 883 | /** 884 | * Creates a matrix from a quaternion rotation and vector translation 885 | * This is equivalent to (but much faster than): 886 | * 887 | * mat4.identity(dest); 888 | * mat4.translate(dest, vec); 889 | * let quatMat = mat4.create(); 890 | * quat4.toMat4(quat, quatMat); 891 | * mat4.multiply(dest, quatMat); 892 | * 893 | * @param {mat4} out mat4 receiving operation result 894 | * @param {quat4} q Rotation quaternion 895 | * @param {vec3} v Translation vector 896 | * @returns {mat4} out 897 | */ 898 | export float *mat4(fromRotationTranslation)(float *out, float *q, float *v) { 899 | // Quaternion math 900 | float x = q[0], y = q[1], z = q[2], w = q[3]; 901 | float x2 = x + x; 902 | float y2 = y + y; 903 | float z2 = z + z; 904 | 905 | float xx = x * x2; 906 | float xy = x * y2; 907 | float xz = x * z2; 908 | float yy = y * y2; 909 | float yz = y * z2; 910 | float zz = z * z2; 911 | float wx = w * x2; 912 | float wy = w * y2; 913 | float wz = w * z2; 914 | 915 | out[0] = 1 - (yy + zz); 916 | out[1] = xy + wz; 917 | out[2] = xz - wy; 918 | out[3] = 0; 919 | out[4] = xy - wz; 920 | out[5] = 1 - (xx + zz); 921 | out[6] = yz + wx; 922 | out[7] = 0; 923 | out[8] = xz + wy; 924 | out[9] = yz - wx; 925 | out[10] = 1 - (xx + yy); 926 | out[11] = 0; 927 | out[12] = v[0]; 928 | out[13] = v[1]; 929 | out[14] = v[2]; 930 | out[15] = 1; 931 | 932 | return out; 933 | }; 934 | 935 | /** 936 | * Returns the translation vector component of a transformation 937 | * matrix. If a matrix is built with fromRotationTranslation, 938 | * the returned vector will be the same as the translation vector 939 | * originally supplied. 940 | * @param {vec3} out Vector to receive translation component 941 | * @param {mat4} mat Matrix to be decomposed (input) 942 | * @return {vec3} out 943 | */ 944 | export float *mat4(getTranslation)(float *out, float *mat) { 945 | out[0] = mat[12]; 946 | out[1] = mat[13]; 947 | out[2] = mat[14]; 948 | 949 | return out; 950 | }; 951 | 952 | /** 953 | * Returns the scaling factor component of a transformation 954 | * matrix. If a matrix is built with fromRotationTranslationScale 955 | * with a normalized Quaternion paramter, the returned vector will be 956 | * the same as the scaling vector 957 | * originally supplied. 958 | * @param {vec3} out Vector to receive scaling factor component 959 | * @param {mat4} mat Matrix to be decomposed (input) 960 | * @return {vec3} out 961 | */ 962 | export float *mat4(getScaling)(float *out, float *mat) { 963 | float m11 = mat[0]; 964 | float m12 = mat[1]; 965 | float m13 = mat[2]; 966 | float m21 = mat[4]; 967 | float m22 = mat[5]; 968 | float m23 = mat[6]; 969 | float m31 = mat[8]; 970 | float m32 = mat[9]; 971 | float m33 = mat[10]; 972 | 973 | out[0] = sqrtf(m11 * m11 + m12 * m12 + m13 * m13); 974 | out[1] = sqrtf(m21 * m21 + m22 * m22 + m23 * m23); 975 | out[2] = sqrtf(m31 * m31 + m32 * m32 + m33 * m33); 976 | 977 | return out; 978 | }; 979 | 980 | /** 981 | * Returns a quaternion representing the rotational component 982 | * of a transformation matrix. If a matrix is built with 983 | * fromRotationTranslation, the returned quaternion will be the 984 | * same as the quaternion originally supplied. 985 | * @param {quat} out Quaternion to receive the rotation component 986 | * @param {mat4} mat Matrix to be decomposed (input) 987 | * @return {quat} out 988 | */ 989 | export float *mat4(getRotation)(float *out, float *mat) { 990 | // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 991 | float trace = mat[0] + mat[5] + mat[10]; 992 | float S = 0; 993 | 994 | if (trace > 0) { 995 | S = sqrtf(trace + 1.0) * 2; 996 | out[3] = 0.25 * S; 997 | out[0] = (mat[6] - mat[9]) / S; 998 | out[1] = (mat[8] - mat[2]) / S; 999 | out[2] = (mat[1] - mat[4]) / S; 1000 | } else if ((mat[0] > mat[5])&(mat[0] > mat[10])) { 1001 | S = sqrtf(1.0 + mat[0] - mat[5] - mat[10]) * 2; 1002 | out[3] = (mat[6] - mat[9]) / S; 1003 | out[0] = 0.25 * S; 1004 | out[1] = (mat[1] + mat[4]) / S; 1005 | out[2] = (mat[8] + mat[2]) / S; 1006 | } else if (mat[5] > mat[10]) { 1007 | S = sqrtf(1.0 + mat[5] - mat[0] - mat[10]) * 2; 1008 | out[3] = (mat[8] - mat[2]) / S; 1009 | out[0] = (mat[1] + mat[4]) / S; 1010 | out[1] = 0.25 * S; 1011 | out[2] = (mat[6] + mat[9]) / S; 1012 | } else { 1013 | S = sqrtf(1.0 + mat[10] - mat[0] - mat[5]) * 2; 1014 | out[3] = (mat[1] - mat[4]) / S; 1015 | out[0] = (mat[8] + mat[2]) / S; 1016 | out[1] = (mat[6] + mat[9]) / S; 1017 | out[2] = 0.25 * S; 1018 | } 1019 | 1020 | return out; 1021 | }; 1022 | 1023 | /** 1024 | * Creates a matrix from a quaternion rotation, vector translation and vector scale 1025 | * This is equivalent to (but much faster than): 1026 | * 1027 | * mat4.identity(dest); 1028 | * mat4.translate(dest, vec); 1029 | * let quatMat = mat4.create(); 1030 | * quat4.toMat4(quat, quatMat); 1031 | * mat4.multiply(dest, quatMat); 1032 | * mat4.scale(dest, scale) 1033 | * 1034 | * @param {mat4} out mat4 receiving operation result 1035 | * @param {quat4} q Rotation quaternion 1036 | * @param {vec3} v Translation vector 1037 | * @param {vec3} s Scaling vector 1038 | * @returns {mat4} out 1039 | */ 1040 | export float *mat4(fromRotationTranslationScale)(float *out, float *q, float *v, float *s) { 1041 | // Quaternion math 1042 | float x = q[0], y = q[1], z = q[2], w = q[3]; 1043 | float x2 = x + x; 1044 | float y2 = y + y; 1045 | float z2 = z + z; 1046 | 1047 | float xx = x * x2; 1048 | float xy = x * y2; 1049 | float xz = x * z2; 1050 | float yy = y * y2; 1051 | float yz = y * z2; 1052 | float zz = z * z2; 1053 | float wx = w * x2; 1054 | float wy = w * y2; 1055 | float wz = w * z2; 1056 | float sx = s[0]; 1057 | float sy = s[1]; 1058 | float sz = s[2]; 1059 | 1060 | out[0] = (1 - (yy + zz)) * sx; 1061 | out[1] = (xy + wz) * sx; 1062 | out[2] = (xz - wy) * sx; 1063 | out[3] = 0; 1064 | out[4] = (xy - wz) * sy; 1065 | out[5] = (1 - (xx + zz)) * sy; 1066 | out[6] = (yz + wx) * sy; 1067 | out[7] = 0; 1068 | out[8] = (xz + wy) * sz; 1069 | out[9] = (yz - wx) * sz; 1070 | out[10] = (1 - (xx + yy)) * sz; 1071 | out[11] = 0; 1072 | out[12] = v[0]; 1073 | out[13] = v[1]; 1074 | out[14] = v[2]; 1075 | out[15] = 1; 1076 | 1077 | return out; 1078 | }; 1079 | 1080 | /** 1081 | * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin 1082 | * This is equivalent to (but much faster than): 1083 | * 1084 | * mat4.identity(dest); 1085 | * mat4.translate(dest, vec); 1086 | * mat4.translate(dest, origin); 1087 | * let quatMat = mat4.create(); 1088 | * quat4.toMat4(quat, quatMat); 1089 | * mat4.multiply(dest, quatMat); 1090 | * mat4.scale(dest, scale) 1091 | * mat4.translate(dest, negativeOrigin); 1092 | * 1093 | * @param {mat4} out mat4 receiving operation result 1094 | * @param {quat4} q Rotation quaternion 1095 | * @param {vec3} v Translation vector 1096 | * @param {vec3} s Scaling vector 1097 | * @param {vec3} o The origin vector around which to scale and rotate 1098 | * @returns {mat4} out 1099 | */ 1100 | export float *mat4(fromRotationTranslationScaleOrigin)(float *out, float *q, float *v, float *s, float *o) { 1101 | // Quaternion math 1102 | float x = q[0], y = q[1], z = q[2], w = q[3]; 1103 | float x2 = x + x; 1104 | float y2 = y + y; 1105 | float z2 = z + z; 1106 | 1107 | float xx = x * x2; 1108 | float xy = x * y2; 1109 | float xz = x * z2; 1110 | float yy = y * y2; 1111 | float yz = y * z2; 1112 | float zz = z * z2; 1113 | float wx = w * x2; 1114 | float wy = w * y2; 1115 | float wz = w * z2; 1116 | 1117 | float sx = s[0]; 1118 | float sy = s[1]; 1119 | float sz = s[2]; 1120 | 1121 | float ox = o[0]; 1122 | float oy = o[1]; 1123 | float oz = o[2]; 1124 | 1125 | out[0] = (1 - (yy + zz)) * sx; 1126 | out[1] = (xy + wz) * sx; 1127 | out[2] = (xz - wy) * sx; 1128 | out[3] = 0; 1129 | out[4] = (xy - wz) * sy; 1130 | out[5] = (1 - (xx + zz)) * sy; 1131 | out[6] = (yz + wx) * sy; 1132 | out[7] = 0; 1133 | out[8] = (xz + wy) * sz; 1134 | out[9] = (yz - wx) * sz; 1135 | out[10] = (1 - (xx + yy)) * sz; 1136 | out[11] = 0; 1137 | out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz); 1138 | out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz); 1139 | out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz); 1140 | out[15] = 1; 1141 | 1142 | return out; 1143 | }; 1144 | 1145 | /** 1146 | * Calculates a 4x4 matrix from the given quaternion 1147 | * 1148 | * @param {mat4} out mat4 receiving operation result 1149 | * @param {quat} q Quaternion to create matrix from 1150 | * 1151 | * @returns {mat4} out 1152 | */ 1153 | export float *mat4(fromQuat)(float *out, float *q) { 1154 | float x = q[0], y = q[1], z = q[2], w = q[3]; 1155 | float x2 = x + x; 1156 | float y2 = y + y; 1157 | float z2 = z + z; 1158 | 1159 | float xx = x * x2; 1160 | float yx = y * x2; 1161 | float yy = y * y2; 1162 | float zx = z * x2; 1163 | float zy = z * y2; 1164 | float zz = z * z2; 1165 | float wx = w * x2; 1166 | float wy = w * y2; 1167 | float wz = w * z2; 1168 | 1169 | out[0] = 1 - yy - zz; 1170 | out[1] = yx + wz; 1171 | out[2] = zx - wy; 1172 | out[3] = 0; 1173 | 1174 | out[4] = yx - wz; 1175 | out[5] = 1 - xx - zz; 1176 | out[6] = zy + wx; 1177 | out[7] = 0; 1178 | 1179 | out[8] = zx + wy; 1180 | out[9] = zy - wx; 1181 | out[10] = 1 - xx - yy; 1182 | out[11] = 0; 1183 | 1184 | out[12] = 0; 1185 | out[13] = 0; 1186 | out[14] = 0; 1187 | out[15] = 1; 1188 | 1189 | return out; 1190 | }; 1191 | 1192 | /** 1193 | * Generates a frustum matrix with the given bounds 1194 | * 1195 | * @param {mat4} out mat4 frustum matrix will be written into 1196 | * @param {Number} left Left bound of the frustum 1197 | * @param {Number} right Right bound of the frustum 1198 | * @param {Number} bottom Bottom bound of the frustum 1199 | * @param {Number} top Top bound of the frustum 1200 | * @param {Number} near Near bound of the frustum 1201 | * @param {Number} far Far bound of the frustum 1202 | * @returns {mat4} out 1203 | */ 1204 | export float *mat4(frustum)(float *out, float left, float right, float bottom, float top, float near, float far) { 1205 | float rl = 1.0 / (right - left); 1206 | float tb = 1.0 / (top - bottom); 1207 | float nf = 1.0 / (near - far); 1208 | out[0] = (near * 2) * rl; 1209 | out[1] = 0; 1210 | out[2] = 0; 1211 | out[3] = 0; 1212 | out[4] = 0; 1213 | out[5] = (near * 2) * tb; 1214 | out[6] = 0; 1215 | out[7] = 0; 1216 | out[8] = (right + left) * rl; 1217 | out[9] = (top + bottom) * tb; 1218 | out[10] = (far + near) * nf; 1219 | out[11] = -1; 1220 | out[12] = 0; 1221 | out[13] = 0; 1222 | out[14] = (far * near * 2) * nf; 1223 | out[15] = 0; 1224 | return out; 1225 | }; 1226 | 1227 | /** 1228 | * Generates a perspective projection matrix with the given bounds 1229 | * 1230 | * @param {mat4} out mat4 frustum matrix will be written into 1231 | * @param {number} fovy Vertical field of view in radians 1232 | * @param {number} aspect Aspect ratio. typically viewport width/height 1233 | * @param {number} near Near bound of the frustum 1234 | * @param {number} far Far bound of the frustum 1235 | * @returns {mat4} out 1236 | */ 1237 | export float *mat4(perspective)(float *out, float fovy, float aspect, float near, float far) { 1238 | float f = 1.0 / tanf(fovy / 2); 1239 | float nf = 1.0 / (near - far); 1240 | out[0] = f / aspect; 1241 | out[1] = 0; 1242 | out[2] = 0; 1243 | out[3] = 0; 1244 | out[4] = 0; 1245 | out[5] = f; 1246 | out[6] = 0; 1247 | out[7] = 0; 1248 | out[8] = 0; 1249 | out[9] = 0; 1250 | out[10] = (far + near) * nf; 1251 | out[11] = -1; 1252 | out[12] = 0; 1253 | out[13] = 0; 1254 | out[14] = (2 * far * near) * nf; 1255 | out[15] = 0; 1256 | return out; 1257 | }; 1258 | 1259 | /** 1260 | * Generates a perspective projection matrix with the given field of view. 1261 | * This is primarily useful for generating projection matrices to be used 1262 | * with the still experiemental WebVR API. 1263 | * 1264 | * @param {mat4} out mat4 frustum matrix will be written into 1265 | * @param {number} upDegrees Property of Object "fov" 1266 | * @param {number} downDegrees Property of Object "fov" 1267 | * @param {number} leftDegrees Property of Object "fov" 1268 | * @param {number} rightDegrees Property of Object "fov" 1269 | * @param {number} near Near bound of the frustum 1270 | * @param {number} far Far bound of the frustum 1271 | * @returns {mat4} out 1272 | */ 1273 | export float *mat4(perspectiveFromFieldOfView)(float *out, float upDegrees, float downDegrees, float leftDegrees, float rightDegrees, float near, float far) { 1274 | float upTan = tanf(upDegrees * M_PI/180.0); 1275 | float downTan = tanf(downDegrees * M_PI/180.0); 1276 | float leftTan = tanf(leftDegrees * M_PI/180.0); 1277 | float rightTan = tanf(rightDegrees * M_PI/180.0); 1278 | float xScale = 2.0 / (leftTan + rightTan); 1279 | float yScale = 2.0 / (upTan + downTan); 1280 | 1281 | out[0] = xScale; 1282 | out[1] = 0.0; 1283 | out[2] = 0.0; 1284 | out[3] = 0.0; 1285 | out[4] = 0.0; 1286 | out[5] = yScale; 1287 | out[6] = 0.0; 1288 | out[7] = 0.0; 1289 | out[8] = -((leftTan - rightTan) * xScale * 0.5); 1290 | out[9] = ((upTan - downTan) * yScale * 0.5); 1291 | out[10] = far / (near - far); 1292 | out[11] = -1.0; 1293 | out[12] = 0.0; 1294 | out[13] = 0.0; 1295 | out[14] = (far * near) / (near - far); 1296 | out[15] = 0.0; 1297 | return out; 1298 | }; 1299 | 1300 | /** 1301 | * Generates a orthogonal projection matrix with the given bounds 1302 | * 1303 | * @param {mat4} out mat4 frustum matrix will be written into 1304 | * @param {number} left Left bound of the frustum 1305 | * @param {number} right Right bound of the frustum 1306 | * @param {number} bottom Bottom bound of the frustum 1307 | * @param {number} top Top bound of the frustum 1308 | * @param {number} near Near bound of the frustum 1309 | * @param {number} far Far bound of the frustum 1310 | * @returns {mat4} out 1311 | */ 1312 | export float *mat4(ortho)(float *out, float left, float right, float bottom, float top, float near, float far) { 1313 | float lr = 1.0 / (left - right); 1314 | float bt = 1.0 / (bottom - top); 1315 | float nf = 1.0 / (near - far); 1316 | out[0] = -2 * lr; 1317 | out[1] = 0; 1318 | out[2] = 0; 1319 | out[3] = 0; 1320 | out[4] = 0; 1321 | out[5] = -2 * bt; 1322 | out[6] = 0; 1323 | out[7] = 0; 1324 | out[8] = 0; 1325 | out[9] = 0; 1326 | out[10] = 2 * nf; 1327 | out[11] = 0; 1328 | out[12] = (left + right) * lr; 1329 | out[13] = (top + bottom) * bt; 1330 | out[14] = (far + near) * nf; 1331 | out[15] = 1; 1332 | return out; 1333 | }; 1334 | 1335 | /** 1336 | * Generates a look-at matrix with the given eye position, focal point, and up axis 1337 | * 1338 | * @param {mat4} out mat4 frustum matrix will be written into 1339 | * @param {vec3} eye Position of the viewer 1340 | * @param {vec3} center Point the viewer is looking at 1341 | * @param {vec3} up vec3 pointing up 1342 | * @returns {mat4} out 1343 | */ 1344 | export float *mat4(lookAt)(float *out, float *eye, float *center, float *up) { 1345 | float x0, x1, x2, y0, y1, y2, z0, z1, z2, len; 1346 | float eyex = eye[0]; 1347 | float eyey = eye[1]; 1348 | float eyez = eye[2]; 1349 | float upx = up[0]; 1350 | float upy = up[1]; 1351 | float upz = up[2]; 1352 | float centerx = center[0]; 1353 | float centery = center[1]; 1354 | float centerz = center[2]; 1355 | 1356 | if (fabs(eyex - centerx) < EPSILON && 1357 | fabs(eyey - centery) < EPSILON && 1358 | fabs(eyez - centerz) < EPSILON) { 1359 | return mat4(identity)(out); 1360 | } 1361 | 1362 | z0 = eyex - centerx; 1363 | z1 = eyey - centery; 1364 | z2 = eyez - centerz; 1365 | 1366 | len = 1.0 / sqrtf(z0 * z0 + z1 * z1 + z2 * z2); 1367 | z0 *= len; 1368 | z1 *= len; 1369 | z2 *= len; 1370 | 1371 | x0 = upy * z2 - upz * z1; 1372 | x1 = upz * z0 - upx * z2; 1373 | x2 = upx * z1 - upy * z0; 1374 | len = sqrtf(x0 * x0 + x1 * x1 + x2 * x2); 1375 | if (!len) { 1376 | x0 = 0; 1377 | x1 = 0; 1378 | x2 = 0; 1379 | } else { 1380 | len = 1.0 / len; 1381 | x0 *= len; 1382 | x1 *= len; 1383 | x2 *= len; 1384 | } 1385 | 1386 | y0 = z1 * x2 - z2 * x1; 1387 | y1 = z2 * x0 - z0 * x2; 1388 | y2 = z0 * x1 - z1 * x0; 1389 | 1390 | len = sqrtf(y0 * y0 + y1 * y1 + y2 * y2); 1391 | if (!len) { 1392 | y0 = 0; 1393 | y1 = 0; 1394 | y2 = 0; 1395 | } else { 1396 | len = 1.0 / len; 1397 | y0 *= len; 1398 | y1 *= len; 1399 | y2 *= len; 1400 | } 1401 | 1402 | out[0] = x0; 1403 | out[1] = y0; 1404 | out[2] = z0; 1405 | out[3] = 0; 1406 | out[4] = x1; 1407 | out[5] = y1; 1408 | out[6] = z1; 1409 | out[7] = 0; 1410 | out[8] = x2; 1411 | out[9] = y2; 1412 | out[10] = z2; 1413 | out[11] = 0; 1414 | out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 1415 | out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 1416 | out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 1417 | out[15] = 1; 1418 | 1419 | return out; 1420 | }; 1421 | 1422 | /** 1423 | * Generates a matrix that makes something look at something else. 1424 | * 1425 | * @param {mat4} out mat4 frustum matrix will be written into 1426 | * @param {vec3} eye Position of the viewer 1427 | * @param {vec3} target Point the viewer is looking at 1428 | * @param {vec3} up vec3 pointing up 1429 | * @returns {mat4} out 1430 | */ 1431 | export float *mat4(targetTo)(float *out, float *eye, float *target, float *up) { 1432 | float eyex = eye[0], 1433 | eyey = eye[1], 1434 | eyez = eye[2], 1435 | upx = up[0], 1436 | upy = up[1], 1437 | upz = up[2]; 1438 | 1439 | float z0 = eyex - target[0], 1440 | z1 = eyey - target[1], 1441 | z2 = eyez - target[2]; 1442 | 1443 | float len = z0*z0 + z1*z1 + z2*z2; 1444 | if (len > 0) { 1445 | len = 1.0 / sqrtf(len); 1446 | z0 *= len; 1447 | z1 *= len; 1448 | z2 *= len; 1449 | } 1450 | 1451 | float x0 = upy * z2 - upz * z1, 1452 | x1 = upz * z0 - upx * z2, 1453 | x2 = upx * z1 - upy * z0; 1454 | 1455 | out[0] = x0; 1456 | out[1] = x1; 1457 | out[2] = x2; 1458 | out[3] = 0; 1459 | out[4] = z1 * x2 - z2 * x1; 1460 | out[5] = z2 * x0 - z0 * x2; 1461 | out[6] = z0 * x1 - z1 * x0; 1462 | out[7] = 0; 1463 | out[8] = z0; 1464 | out[9] = z1; 1465 | out[10] = z2; 1466 | out[11] = 0; 1467 | out[12] = eyex; 1468 | out[13] = eyey; 1469 | out[14] = eyez; 1470 | out[15] = 1; 1471 | return out; 1472 | }; 1473 | 1474 | /** 1475 | * Returns a string representation of a mat4 1476 | * 1477 | * @param {mat4} a matrix to represent as a string 1478 | * @returns {String} string representation of the matrix 1479 | */ 1480 | export float *mat4(str)(float *a) { 1481 | return a; 1482 | }; 1483 | 1484 | /** 1485 | * Returns Frobenius norm of a mat4 1486 | * 1487 | * @param {mat4} a the matrix to calculate Frobenius norm of 1488 | * @returns {Number} Frobenius norm 1489 | */ 1490 | export float mat4(frob)(float *a) { 1491 | return(sqrt( 1492 | powf(a[0], 2) + 1493 | powf(a[1], 2) + 1494 | powf(a[2], 2) + 1495 | powf(a[3], 2) + 1496 | powf(a[4], 2) + 1497 | powf(a[5], 2) + 1498 | powf(a[6], 2) + 1499 | powf(a[7], 2) + 1500 | powf(a[8], 2) + 1501 | powf(a[9], 2) + 1502 | powf(a[10], 2) + 1503 | powf(a[11], 2) + 1504 | powf(a[12], 2) + 1505 | powf(a[13], 2) + 1506 | powf(a[14], 2) + 1507 | powf(a[15], 2) )); 1508 | }; 1509 | 1510 | /** 1511 | * Adds two mat4's 1512 | * 1513 | * @param {mat4} out the receiving matrix 1514 | * @param {mat4} a the first operand 1515 | * @param {mat4} b the second operand 1516 | * @returns {mat4} out 1517 | */ 1518 | export float *mat4(add)(float *out, float *a, float *b) { 1519 | out[0] = a[0] + b[0]; 1520 | out[1] = a[1] + b[1]; 1521 | out[2] = a[2] + b[2]; 1522 | out[3] = a[3] + b[3]; 1523 | out[4] = a[4] + b[4]; 1524 | out[5] = a[5] + b[5]; 1525 | out[6] = a[6] + b[6]; 1526 | out[7] = a[7] + b[7]; 1527 | out[8] = a[8] + b[8]; 1528 | out[9] = a[9] + b[9]; 1529 | out[10] = a[10] + b[10]; 1530 | out[11] = a[11] + b[11]; 1531 | out[12] = a[12] + b[12]; 1532 | out[13] = a[13] + b[13]; 1533 | out[14] = a[14] + b[14]; 1534 | out[15] = a[15] + b[15]; 1535 | return out; 1536 | }; 1537 | 1538 | /** 1539 | * Subtracts matrix b from matrix a 1540 | * 1541 | * @param {mat4} out the receiving matrix 1542 | * @param {mat4} a the first operand 1543 | * @param {mat4} b the second operand 1544 | * @returns {mat4} out 1545 | */ 1546 | export float *mat4(subtract)(float *out, float *a, float *b) { 1547 | out[0] = a[0] - b[0]; 1548 | out[1] = a[1] - b[1]; 1549 | out[2] = a[2] - b[2]; 1550 | out[3] = a[3] - b[3]; 1551 | out[4] = a[4] - b[4]; 1552 | out[5] = a[5] - b[5]; 1553 | out[6] = a[6] - b[6]; 1554 | out[7] = a[7] - b[7]; 1555 | out[8] = a[8] - b[8]; 1556 | out[9] = a[9] - b[9]; 1557 | out[10] = a[10] - b[10]; 1558 | out[11] = a[11] - b[11]; 1559 | out[12] = a[12] - b[12]; 1560 | out[13] = a[13] - b[13]; 1561 | out[14] = a[14] - b[14]; 1562 | out[15] = a[15] - b[15]; 1563 | return out; 1564 | }; 1565 | 1566 | /** 1567 | * Multiply each element of the matrix by a scalar. 1568 | * 1569 | * @param {mat4} out the receiving matrix 1570 | * @param {mat4} a the matrix to scale 1571 | * @param {Number} b amount to scale the matrix's elements by 1572 | * @returns {mat4} out 1573 | */ 1574 | export float *mat4(multiplyScalar)(float *out, float *a, float b) { 1575 | out[0] = a[0] * b; 1576 | out[1] = a[1] * b; 1577 | out[2] = a[2] * b; 1578 | out[3] = a[3] * b; 1579 | out[4] = a[4] * b; 1580 | out[5] = a[5] * b; 1581 | out[6] = a[6] * b; 1582 | out[7] = a[7] * b; 1583 | out[8] = a[8] * b; 1584 | out[9] = a[9] * b; 1585 | out[10] = a[10] * b; 1586 | out[11] = a[11] * b; 1587 | out[12] = a[12] * b; 1588 | out[13] = a[13] * b; 1589 | out[14] = a[14] * b; 1590 | out[15] = a[15] * b; 1591 | return out; 1592 | }; 1593 | 1594 | /** 1595 | * Adds two mat4's after multiplying each element of the second operand by a scalar value. 1596 | * 1597 | * @param {mat4} out the receiving vector 1598 | * @param {mat4} a the first operand 1599 | * @param {mat4} b the second operand 1600 | * @param {Number} scale the amount to scale b's elements by before adding 1601 | * @returns {mat4} out 1602 | */ 1603 | export float *mat4(multiplyScalarAndAdd)(float *out, float *a, float *b, float scale) { 1604 | out[0] = a[0] + (b[0] * scale); 1605 | out[1] = a[1] + (b[1] * scale); 1606 | out[2] = a[2] + (b[2] * scale); 1607 | out[3] = a[3] + (b[3] * scale); 1608 | out[4] = a[4] + (b[4] * scale); 1609 | out[5] = a[5] + (b[5] * scale); 1610 | out[6] = a[6] + (b[6] * scale); 1611 | out[7] = a[7] + (b[7] * scale); 1612 | out[8] = a[8] + (b[8] * scale); 1613 | out[9] = a[9] + (b[9] * scale); 1614 | out[10] = a[10] + (b[10] * scale); 1615 | out[11] = a[11] + (b[11] * scale); 1616 | out[12] = a[12] + (b[12] * scale); 1617 | out[13] = a[13] + (b[13] * scale); 1618 | out[14] = a[14] + (b[14] * scale); 1619 | out[15] = a[15] + (b[15] * scale); 1620 | return out; 1621 | }; 1622 | 1623 | /** 1624 | * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) 1625 | * 1626 | * @param {mat4} a The first matrix. 1627 | * @param {mat4} b The second matrix. 1628 | * @returns {Boolean} True if the matrices are equal, false otherwise. 1629 | */ 1630 | export int mat4(exactEquals)(float *a, float *b) { 1631 | return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3] && 1632 | a[4] == b[4] && a[5] == b[5] && a[6] == b[6] && a[7] == b[7] && 1633 | a[8] == b[8] && a[9] == b[9] && a[10] == b[10] && a[11] == b[11] && 1634 | a[12] == b[12] && a[13] == b[13] && a[14] == b[14] && a[15] == b[15]; 1635 | }; 1636 | 1637 | /** 1638 | * Returns whether or not the matrices have approximately the same elements in the same position. 1639 | * 1640 | * @param {mat4} a The first matrix. 1641 | * @param {mat4} b The second matrix. 1642 | * @returns {Boolean} True if the matrices are equal, false otherwise. 1643 | */ 1644 | export int mat4(equals)(float *a, float *b) { 1645 | float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; 1646 | float a4 = a[4], a5 = a[5], a6 = a[6], a7 = a[7]; 1647 | float a8 = a[8], a9 = a[9], a10 = a[10], a11 = a[11]; 1648 | float a12 = a[12], a13 = a[13], a14 = a[14], a15 = a[15]; 1649 | 1650 | float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 1651 | float b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7]; 1652 | float b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11]; 1653 | float b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15]; 1654 | 1655 | return (fabs(a0 - b0) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a0), fabs(b0))) && 1656 | fabs(a1 - b1) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a1), fabs(b1))) && 1657 | fabs(a2 - b2) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a2), fabs(b2))) && 1658 | fabs(a3 - b3) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a3), fabs(b3))) && 1659 | fabs(a4 - b4) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a4), fabs(b4))) && 1660 | fabs(a5 - b5) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a5), fabs(b5))) && 1661 | fabs(a6 - b6) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a6), fabs(b6))) && 1662 | fabs(a7 - b7) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a7), fabs(b7))) && 1663 | fabs(a8 - b8) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a8), fabs(b8))) && 1664 | fabs(a9 - b9) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a9), fabs(b9))) && 1665 | fabs(a10 - b10) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a10), fabs(b10))) && 1666 | fabs(a11 - b11) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a11), fabs(b11))) && 1667 | fabs(a12 - b12) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a12), fabs(b12))) && 1668 | fabs(a13 - b13) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a13), fabs(b13))) && 1669 | fabs(a14 - b14) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a14), fabs(b14))) && 1670 | fabs(a15 - b15) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a15), fabs(b15)))); 1671 | }; 1672 | 1673 | /** 1674 | * Alias for {@link mat4.multiply} 1675 | * @function 1676 | */ 1677 | export float *mat4(mul)(float *out, float *a, float *b) { 1678 | return mat4(multiply)(out, a, b); 1679 | }; 1680 | 1681 | /** 1682 | * Alias for {@link mat4.subtract} 1683 | * @function 1684 | */ 1685 | export float *mat4(sub)(float *out, float *a, float *b) { 1686 | return mat4(subtract)(out, a, b); 1687 | }; 1688 | -------------------------------------------------------------------------------- /src/gl-matrix/vec3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | 5 | #define vec3(x) vec3_##x 6 | 7 | /** 8 | * Frees a vec3 9 | */ 10 | export float *vec3(free)(float *a) { 11 | free(a); 12 | return NULL; 13 | }; 14 | 15 | /** 16 | * Creates a new, empty vec3 17 | * 18 | * @returns {vec3} a new 3D vector 19 | */ 20 | export float *vec3(create)() { 21 | float *out = malloc(VEC_SIZE_3 * sizeof(*out)); 22 | out[0] = 0; 23 | out[1] = 0; 24 | out[2] = 0; 25 | return out; 26 | }; 27 | 28 | /** 29 | * Creates a new vec3 initialized with values from an existing vector 30 | * 31 | * @param {vec3} a vector to clone 32 | * @returns {vec3} a new 3D vector 33 | */ 34 | export float *vec3(clone)(float *a) { 35 | float *out = malloc(VEC_SIZE_3 * sizeof(*out)); 36 | out[0] = a[0]; 37 | out[1] = a[1]; 38 | out[2] = a[2]; 39 | return out; 40 | }; 41 | 42 | /** 43 | * Calculates the length of a vec3 44 | * 45 | * @param {vec3} a vector to calculate length of 46 | * @returns {Number} length of a 47 | */ 48 | export float vec3(length)(float *a) { 49 | float x = a[0]; 50 | float y = a[1]; 51 | float z = a[2]; 52 | return sqrtf(x*x + y*y + z*z); 53 | }; 54 | 55 | /** 56 | * Creates a new vec3 initialized with the given values 57 | * 58 | * @param {Number} x X component 59 | * @param {Number} y Y component 60 | * @param {Number} z Z component 61 | * @returns {vec3} a new 3D vector 62 | */ 63 | export float *vec3(fromValues)(float x, float y, float z) { 64 | float *out = malloc(VEC_SIZE_3 * sizeof(*out)); 65 | out[0] = x; 66 | out[1] = y; 67 | out[2] = z; 68 | return out; 69 | }; 70 | 71 | /** 72 | * Copy the values from one vec3 to another 73 | * 74 | * @param {vec3} out the receiving vector 75 | * @param {vec3} a the source vector 76 | * @returns {vec3} out 77 | */ 78 | export float *vec3(copy)(float *out, float *a) { 79 | out[0] = a[0]; 80 | out[1] = a[1]; 81 | out[2] = a[2]; 82 | return out; 83 | }; 84 | 85 | /** 86 | * Set the components of a vec3 to the given values 87 | * 88 | * @param {vec3} out the receiving vector 89 | * @param {Number} x X component 90 | * @param {Number} y Y component 91 | * @param {Number} z Z component 92 | * @returns {vec3} out 93 | */ 94 | export float *vec3(set)(float *out, float x, float y, float z) { 95 | out[0] = x; 96 | out[1] = y; 97 | out[2] = z; 98 | return out; 99 | }; 100 | 101 | /** 102 | * Adds two vec3's 103 | * 104 | * @param {vec3} out the receiving vector 105 | * @param {vec3} a the first operand 106 | * @param {vec3} b the second operand 107 | * @returns {vec3} out 108 | */ 109 | export float *vec3(add)(float *out, float *a, float *b) { 110 | out[0] = a[0] + b[0]; 111 | out[1] = a[1] + b[1]; 112 | out[2] = a[2] + b[2]; 113 | return out; 114 | }; 115 | 116 | /** 117 | * Subtracts vector b from vector a 118 | * 119 | * @param {vec3} out the receiving vector 120 | * @param {vec3} a the first operand 121 | * @param {vec3} b the second operand 122 | * @returns {vec3} out 123 | */ 124 | export float *vec3(subtract)(float *out, float *a, float *b) { 125 | out[0] = a[0] - b[0]; 126 | out[1] = a[1] - b[1]; 127 | out[2] = a[2] - b[2]; 128 | return out; 129 | }; 130 | 131 | /** 132 | * Multiplies two vec3's 133 | * 134 | * @param {vec3} out the receiving vector 135 | * @param {vec3} a the first operand 136 | * @param {vec3} b the second operand 137 | * @returns {vec3} out 138 | */ 139 | export float *vec3(multiply)(float *out, float *a, float *b) { 140 | out[0] = a[0] * b[0]; 141 | out[1] = a[1] * b[1]; 142 | out[2] = a[2] * b[2]; 143 | return out; 144 | }; 145 | 146 | /** 147 | * Divides two vec3's 148 | * 149 | * @param {vec3} out the receiving vector 150 | * @param {vec3} a the first operand 151 | * @param {vec3} b the second operand 152 | * @returns {vec3} out 153 | */ 154 | export float *vec3(divide)(float *out, float *a, float *b) { 155 | out[0] = a[0] / b[0]; 156 | out[1] = a[1] / b[1]; 157 | out[2] = a[2] / b[2]; 158 | return out; 159 | }; 160 | 161 | /** 162 | * Math.ceil the components of a vec3 163 | * 164 | * @param {vec3} out the receiving vector 165 | * @param {vec3} a vector to ceil 166 | * @returns {vec3} out 167 | */ 168 | export float *vec3(ceil)(float *out, float *a) { 169 | out[0] = ceilf(a[0]); 170 | out[1] = ceilf(a[1]); 171 | out[2] = ceilf(a[2]); 172 | return out; 173 | }; 174 | 175 | /** 176 | * Math.floor the components of a vec3 177 | * 178 | * @param {vec3} out the receiving vector 179 | * @param {vec3} a vector to floor 180 | * @returns {vec3} out 181 | */ 182 | export float *vec3(floor)(float *out, float *a) { 183 | out[0] = floorf(a[0]); 184 | out[1] = floorf(a[1]); 185 | out[2] = floorf(a[2]); 186 | return out; 187 | }; 188 | 189 | /** 190 | * Returns the minimum of two vec3's 191 | * 192 | * @param {vec3} out the receiving vector 193 | * @param {vec3} a the first operand 194 | * @param {vec3} b the second operand 195 | * @returns {vec3} out 196 | */ 197 | export float *vec3(min)(float *out, float *a, float *b) { 198 | out[0] = fminf(a[0], b[0]); 199 | out[1] = fminf(a[1], b[1]); 200 | out[2] = fminf(a[2], b[2]); 201 | return out; 202 | }; 203 | 204 | /** 205 | * Returns the maximum of two vec3's 206 | * 207 | * @param {vec3} out the receiving vector 208 | * @param {vec3} a the first operand 209 | * @param {vec3} b the second operand 210 | * @returns {vec3} out 211 | */ 212 | export float *vec3(max)(float *out, float *a, float *b) { 213 | out[0] = fmaxf(a[0], b[0]); 214 | out[1] = fmaxf(a[1], b[1]); 215 | out[2] = fmaxf(a[2], b[2]); 216 | return out; 217 | }; 218 | 219 | /** 220 | * Math.round the components of a vec3 221 | * 222 | * @param {vec3} out the receiving vector 223 | * @param {vec3} a vector to round 224 | * @returns {vec3} out 225 | */ 226 | export float *vec3(round)(float *out, float *a) { 227 | out[0] = roundf(a[0]); 228 | out[1] = roundf(a[1]); 229 | out[2] = roundf(a[2]); 230 | return out; 231 | }; 232 | 233 | /** 234 | * Scales a vec3 by a scalar number 235 | * 236 | * @param {vec3} out the receiving vector 237 | * @param {vec3} a the vector to scale 238 | * @param {Number} b amount to scale the vector by 239 | * @returns {vec3} out 240 | */ 241 | export float *vec3(scale)(float *out, float *a, float b) { 242 | out[0] = a[0] * b; 243 | out[1] = a[1] * b; 244 | out[2] = a[2] * b; 245 | return out; 246 | }; 247 | 248 | /** 249 | * Adds two vec3's after scaling the second operand by a scalar value 250 | * 251 | * @param {vec3} out the receiving vector 252 | * @param {vec3} a the first operand 253 | * @param {vec3} b the second operand 254 | * @param {Number} scale the amount to scale b by before adding 255 | * @returns {vec3} out 256 | */ 257 | export float *vec3(scaleAndAdd)(float *out, float *a, float *b, float scale) { 258 | out[0] = a[0] + (b[0] * scale); 259 | out[1] = a[1] + (b[1] * scale); 260 | out[2] = a[2] + (b[2] * scale); 261 | return out; 262 | }; 263 | 264 | /** 265 | * Calculates the euclidian distance between two vec3's 266 | * 267 | * @param {vec3} a the first operand 268 | * @param {vec3} b the second operand 269 | * @returns {Number} distance between a and b 270 | */ 271 | export float vec3(distance)(float *a, float *b) { 272 | float x = b[0] - a[0]; 273 | float y = b[1] - a[1]; 274 | float z = b[2] - a[2]; 275 | return sqrtf(x*x + y*y + z*z); 276 | }; 277 | 278 | /** 279 | * Calculates the squared euclidian distance between two vec3's 280 | * 281 | * @param {vec3} a the first operand 282 | * @param {vec3} b the second operand 283 | * @returns {Number} squared distance between a and b 284 | */ 285 | export float vec3(squaredDistance)(float *a, float *b) { 286 | float x = b[0] - a[0]; 287 | float y = b[1] - a[1]; 288 | float z = b[2] - a[2]; 289 | return x*x + y*y + z*z; 290 | }; 291 | 292 | /** 293 | * Calculates the squared length of a vec3 294 | * 295 | * @param {vec3} a vector to calculate squared length of 296 | * @returns {Number} squared length of a 297 | */ 298 | export float vec3(squaredLength)(float *a) { 299 | float x = a[0]; 300 | float y = a[1]; 301 | float z = a[2]; 302 | return x*x + y*y + z*z; 303 | }; 304 | 305 | /** 306 | * Negates the components of a vec3 307 | * 308 | * @param {vec3} out the receiving vector 309 | * @param {vec3} a vector to negate 310 | * @returns {vec3} out 311 | */ 312 | export float *vec3(negate)(float *out, float *a) { 313 | out[0] = -a[0]; 314 | out[1] = -a[1]; 315 | out[2] = -a[2]; 316 | return out; 317 | }; 318 | 319 | /** 320 | * Returns the inverse of the components of a vec3 321 | * 322 | * @param {vec3} out the receiving vector 323 | * @param {vec3} a vector to invert 324 | * @returns {vec3} out 325 | */ 326 | export float *vec3(inverse)(float *out, float *a) { 327 | out[0] = 1.0 / a[0]; 328 | out[1] = 1.0 / a[1]; 329 | out[2] = 1.0 / a[2]; 330 | return out; 331 | }; 332 | 333 | /** 334 | * Normalize a vec3 335 | * 336 | * @param {vec3} out the receiving vector 337 | * @param {vec3} a vector to normalize 338 | * @returns {vec3} out 339 | */ 340 | export float *vec3(normalize)(float *out, float *a) { 341 | float x = a[0]; 342 | float y = a[1]; 343 | float z = a[2]; 344 | float len = x*x + y*y + z*z; 345 | if (len > 0) { 346 | //TODO: evaluate use of glm_invsqrt here? 347 | len = 1 / sqrtf(len); 348 | out[0] = a[0] * len; 349 | out[1] = a[1] * len; 350 | out[2] = a[2] * len; 351 | } 352 | return out; 353 | }; 354 | 355 | /** 356 | * Calculates the dot product of two vec3's 357 | * 358 | * @param {vec3} a the first operand 359 | * @param {vec3} b the second operand 360 | * @returns {Number} dot product of a and b 361 | */ 362 | export float vec3(dot)(float *a, float *b) { 363 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 364 | }; 365 | 366 | /** 367 | * Computes the cross product of two vec3's 368 | * 369 | * @param {vec3} out the receiving vector 370 | * @param {vec3} a the first operand 371 | * @param {vec3} b the second operand 372 | * @returns {vec3} out 373 | */ 374 | export float *vec3(cross)(float *out, float *a, float *b) { 375 | float ax = a[0], ay = a[1], az = a[2]; 376 | float bx = b[0], by = b[1], bz = b[2]; 377 | out[0] = ay * bz - az * by; 378 | out[1] = az * bx - ax * bz; 379 | out[2] = ax * by - ay * bx; 380 | return out; 381 | }; 382 | 383 | /** 384 | * Performs a linear interpolation between two vec3's 385 | * 386 | * @param {vec3} out the receiving vector 387 | * @param {vec3} a the first operand 388 | * @param {vec3} b the second operand 389 | * @param {Number} t interpolation amount between the two inputs 390 | * @returns {vec3} out 391 | */ 392 | export float *vec3(lerp)(float *out, float *a, float *b, float t) { 393 | float ax = a[0]; 394 | float ay = a[1]; 395 | float az = a[2]; 396 | out[0] = ax + t * (b[0] - ax); 397 | out[1] = ay + t * (b[1] - ay); 398 | out[2] = az + t * (b[2] - az); 399 | return out; 400 | }; 401 | 402 | /** 403 | * Performs a hermite interpolation with two control points 404 | * 405 | * @param {vec3} out the receiving vector 406 | * @param {vec3} a the first operand 407 | * @param {vec3} b the second operand 408 | * @param {vec3} c the third operand 409 | * @param {vec3} d the fourth operand 410 | * @param {Number} t interpolation amount between the two inputs 411 | * @returns {vec3} out 412 | */ 413 | export float *vec3(hermite)(float *out, float *a, float *b, float *c, float *d, float t) { 414 | float factorTimes2 = t * t; 415 | float factor1 = factorTimes2 * (2 * t - 3) + 1; 416 | float factor2 = factorTimes2 * (t - 2) + t; 417 | float factor3 = factorTimes2 * (t - 1); 418 | float factor4 = factorTimes2 * (3 - 2 * t); 419 | out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; 420 | out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; 421 | out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; 422 | return out; 423 | }; 424 | 425 | /** 426 | * Performs a bezier interpolation with two control points 427 | * 428 | * @param {vec3} out the receiving vector 429 | * @param {vec3} a the first operand 430 | * @param {vec3} b the second operand 431 | * @param {vec3} c the third operand 432 | * @param {vec3} d the fourth operand 433 | * @param {Number} t interpolation amount between the two inputs 434 | * @returns {vec3} out 435 | */ 436 | export float *vec3(bezier)(float *out, float *a, float *b, float *c, float *d, float t) { 437 | float inverseFactor = 1 - t; 438 | float inverseFactorTimesTwo = inverseFactor * inverseFactor; 439 | float factorTimes2 = t * t; 440 | float factor1 = inverseFactorTimesTwo * inverseFactor; 441 | float factor2 = 3 * t * inverseFactorTimesTwo; 442 | float factor3 = 3 * factorTimes2 * inverseFactor; 443 | float factor4 = factorTimes2 * t; 444 | out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; 445 | out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; 446 | out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; 447 | return out; 448 | }; 449 | 450 | /** 451 | * Generates a random vector with the given scale 452 | * 453 | * @param {vec3} out the receiving vector 454 | * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 455 | * @returns {vec3} out 456 | */ 457 | export float *vec3(random)(float *out, float scale) { 458 | float r = randf() * 2.0 * PI; 459 | float z = (randf() * 2.0) - 1.0; 460 | float zScale = sqrtf(1.0-z*z) * scale; 461 | out[0] = cosf(r) * zScale; 462 | out[1] = sinf(r) * zScale; 463 | out[2] = z * scale; 464 | return out; 465 | }; 466 | 467 | /** 468 | * Transforms the vec3 with a mat4. 469 | * 4th vector component is implicitly '1' 470 | * 471 | * @param {vec3} out the receiving vector 472 | * @param {vec3} a the vector to transform 473 | * @param {mat4} m matrix to transform with 474 | * @returns {vec3} out 475 | */ 476 | export float *vec3(transformMat4)(float *out, float *a, float *m) { 477 | float x = a[0], y = a[1], z = a[2]; 478 | float w = m[3] * x + m[7] * y + m[11] * z + m[15]; 479 | if (!w) w = w || 1.0; 480 | out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w; 481 | out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w; 482 | out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w; 483 | return out; 484 | }; 485 | 486 | /** 487 | * Transforms the vec3 with a mat3. 488 | * 489 | * @param {vec3} out the receiving vector 490 | * @param {vec3} a the vector to transform 491 | * @param {mat3} m the 3x3 matrix to transform with 492 | * @returns {vec3} out 493 | */ 494 | export float *vec3(transformMat3)(float *out, float *a, float *m) { 495 | float x = a[0], y = a[1], z = a[2]; 496 | out[0] = x * m[0] + y * m[3] + z * m[6]; 497 | out[1] = x * m[1] + y * m[4] + z * m[7]; 498 | out[2] = x * m[2] + y * m[5] + z * m[8]; 499 | return out; 500 | }; 501 | 502 | /** 503 | * Transforms the vec3 with a quat 504 | * 505 | * @param {vec3} out the receiving vector 506 | * @param {vec3} a the vector to transform 507 | * @param {quat} q quaternion to transform with 508 | * @returns {vec3} out 509 | */ 510 | export float *vec3(transformQuat)(float *out, float *a, float *q) { 511 | // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations 512 | float x = a[0], y = a[1], z = a[2]; 513 | float qx = q[0], qy = q[1], qz = q[2], qw = q[3]; 514 | // calculate quat * vec 515 | float ix = qw * x + qy * z - qz * y; 516 | float iy = qw * y + qz * x - qx * z; 517 | float iz = qw * z + qx * y - qy * x; 518 | float iw = -qx * x - qy * y - qz * z; 519 | // calculate result * inverse quat 520 | out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 521 | out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 522 | out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 523 | return out; 524 | }; 525 | 526 | /** 527 | * Rotate a 3D vector around the x-axis 528 | * @param {vec3} out The receiving vec3 529 | * @param {vec3} a The vec3 point to rotate 530 | * @param {vec3} b The origin of the rotation 531 | * @param {Number} c The angle of rotation 532 | * @returns {vec3} out 533 | */ 534 | export float *vec3(rotateX)(float *out, float *a, float *b, float c) { 535 | float p0, p1, p2; 536 | float r0, r1, r2; 537 | //Translate point to the origin 538 | p0 = a[0] - b[0]; 539 | p1 = a[1] - b[1]; 540 | p2 = a[2] - b[2]; 541 | //perform rotation 542 | r0 = p0; 543 | r1 = p1*cosf(c) - p2*sinf(c); 544 | r2 = p2*sinf(c) + p2*cosf(c); 545 | //translate to correct position 546 | out[0] = r0 + b[0]; 547 | out[1] = r1 + b[1]; 548 | out[2] = r2 + b[2]; 549 | return out; 550 | }; 551 | 552 | /** 553 | * Rotate a 3D vector around the y-axis 554 | * @param {vec3} out The receiving vec3 555 | * @param {vec3} a The vec3 point to rotate 556 | * @param {vec3} b The origin of the rotation 557 | * @param {Number} c The angle of rotation 558 | * @returns {vec3} out 559 | */ 560 | export float *vec3(rotateY)(float *out, float *a, float *b, float c) { 561 | float p0, p1, p2; 562 | float r0, r1, r2; 563 | //Translate point to the origin 564 | p0 = a[0] - b[0]; 565 | p1 = a[1] - b[1]; 566 | p2 = a[2] - b[2]; 567 | //perform rotation 568 | r0 = p2*sinf(c) + p0*cosf(c); 569 | r1 = p1; 570 | r2 = p2*cosf(c) - p1*sinf(c); 571 | //translate to correct position 572 | out[0] = r0 + b[0]; 573 | out[1] = r1 + b[1]; 574 | out[2] = r2 + b[2]; 575 | return out; 576 | }; 577 | 578 | /** 579 | * Rotate a 3D vector around the z-axis 580 | * @param {vec3} out The receiving vec3 581 | * @param {vec3} a The vec3 point to rotate 582 | * @param {vec3} b The origin of the rotation 583 | * @param {Number} c The angle of rotation 584 | * @returns {vec3} out 585 | */ 586 | export float *vec3(rotateZ)(float *out, float *a, float *b, float c) { 587 | float p0, p1, p2; 588 | float r0, r1, r2; 589 | //Translate point to the origin 590 | p0 = a[0] - b[0]; 591 | p1 = a[1] - b[1]; 592 | p2 = a[2] - b[2]; 593 | //perform rotation 594 | r0 = p0*cosf(c) - p1*sinf(c); 595 | r1 = p0*sinf(c) + p1*cosf(c); 596 | r2 = p2; 597 | //translate to correct position 598 | out[0] = r0 + b[0]; 599 | out[1] = r1 + b[1]; 600 | out[2] = r2 + b[2]; 601 | return out; 602 | }; 603 | 604 | float aH0[VEC_SIZE_3] = { 0.0, 0.0, 0.0 }; 605 | float aH1[VEC_SIZE_3] = { 0.0, 0.0, 0.0 }; 606 | /** 607 | * Get the angle between two 3D vectors 608 | * @param {vec3} a The first operand 609 | * @param {vec3} b The second operand 610 | * @returns {Number} The angle in radians 611 | */ 612 | export float vec3(angle)(float *a, float *b) { 613 | // hacky helper to avoid allocation 614 | // but remain self api usage 615 | aH0[0] = a[0]; aH0[1] = a[1]; aH0[2] = a[2]; 616 | aH1[0] = b[0]; aH1[1] = b[1]; aH1[2] = b[2]; 617 | float *tempA = aH0; 618 | float *tempB = aH1; 619 | vec3(normalize)(tempA, tempA); 620 | vec3(normalize)(tempB, tempB); 621 | float cosine = vec3(dot)(tempA, tempB); 622 | if(cosine > 1.0) { 623 | return 0; 624 | } 625 | else if(cosine < -1.0) { 626 | return PI; 627 | } else { 628 | return acosf(cosine); 629 | } 630 | }; 631 | 632 | /** 633 | * Returns a string representation of a vector 634 | * 635 | * @param {vec3} a vector to represent as a string 636 | * @returns {String} string representation of the vector 637 | */ 638 | export float *vec3(str)(float *a) { 639 | return a; 640 | }; 641 | 642 | /** 643 | * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) 644 | * 645 | * @param {vec3} a The first vector. 646 | * @param {vec3} b The second vector. 647 | * @returns {Boolean} True if the vectors are equal, false otherwise. 648 | */ 649 | export int vec3(exactEquals)(float *a, float *b) { 650 | return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]; 651 | }; 652 | 653 | /** 654 | * Returns whether or not the vectors have approximately the same elements in the same position. 655 | * 656 | * @param {vec3} a The first vector. 657 | * @param {vec3} b The second vector. 658 | * @returns {Boolean} True if the vectors are equal, false otherwise. 659 | */ 660 | export int vec3(equals)(float *a, float *b) { 661 | float a0 = a[0], a1 = a[1], a2 = a[2]; 662 | float b0 = b[0], b1 = b[1], b2 = b[2]; 663 | return (fabs(a0 - b0) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a0), fabs(b0))) && 664 | fabs(a1 - b1) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a1), fabs(b1))) && 665 | fabs(a2 - b2) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a2), fabs(b2)))); 666 | }; 667 | 668 | /** 669 | * Alias for {@link vec3.subtract} 670 | * @function 671 | */ 672 | export float *vec3(sub)(float *out, float *a, float *b) { 673 | return vec3(subtract)(out, a, b); 674 | }; 675 | 676 | /** 677 | * Alias for {@link vec3.multiply} 678 | * @function 679 | */ 680 | export float *vec3(mul)(float *out, float *a, float *b) { 681 | return vec3(multiply)(out, a, b); 682 | }; 683 | 684 | /** 685 | * Alias for {@link vec3.divide} 686 | * @function 687 | */ 688 | export float *vec3(div)(float *out, float *a, float *b) { 689 | return vec3(divide)(out, a, b); 690 | }; 691 | 692 | /** 693 | * Alias for {@link vec3.distance} 694 | * @function 695 | */ 696 | export float vec3(dist)(float *a, float *b) { 697 | return vec3(distance)(a, b); 698 | }; 699 | 700 | /** 701 | * Alias for {@link vec3.squaredDistance} 702 | * @function 703 | */ 704 | export float vec3(sqrDist)(float *a, float *b) { 705 | return vec3(squaredDistance)(a, b); 706 | }; 707 | 708 | /** 709 | * Alias for {@link vec3.length} 710 | * @function 711 | */ 712 | export float vec3(len)(float *a) { 713 | return vec3(length)(a); 714 | }; 715 | 716 | /** 717 | * Alias for {@link vec3.squaredLength} 718 | * @function 719 | */ 720 | export float vec3(sqrLen)(float *a) { 721 | return vec3(squaredLength)(a); 722 | }; 723 | -------------------------------------------------------------------------------- /src/gl-matrix/vec4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | 5 | #define vec4(x) vec4_##x 6 | 7 | /** 8 | * Frees a vec4 9 | */ 10 | export float *vec4(free)(float *a) { 11 | free(a); 12 | return NULL; 13 | }; 14 | 15 | /** 16 | * Creates a new, empty vec4 17 | * 18 | * @returns {vec4} a new 3D vector 19 | */ 20 | export float *vec4(create)() { 21 | float *out = malloc(VEC_SIZE_4 * sizeof(*out)); 22 | out[0] = 0; 23 | out[1] = 0; 24 | out[2] = 0; 25 | out[3] = 0; 26 | return out; 27 | }; 28 | 29 | /** 30 | * Creates a new vec4 initialized with values from an existing vector 31 | * 32 | * @param {vec4} a vector to clone 33 | * @returns {vec4} a new 4D vector 34 | */ 35 | export float *vec4(clone)(float *a) { 36 | float *out = malloc(VEC_SIZE_4 * sizeof(*out)); 37 | out[0] = a[0]; 38 | out[1] = a[1]; 39 | out[2] = a[2]; 40 | out[3] = a[3]; 41 | return out; 42 | }; 43 | 44 | /** 45 | * Creates a new vec4 initialized with the given values 46 | * 47 | * @param {Number} x X component 48 | * @param {Number} y Y component 49 | * @param {Number} z Z component 50 | * @param {Number} w W component 51 | * @returns {vec4} a new 4D vector 52 | */ 53 | export float *vec4(fromValues)(float x, float y, float z, float w) { 54 | float *out = malloc(VEC_SIZE_4 * sizeof(*out)); 55 | out[0] = x; 56 | out[1] = y; 57 | out[2] = z; 58 | out[3] = w; 59 | return out; 60 | }; 61 | 62 | /** 63 | * Copy the values from one vec4 to another 64 | * 65 | * @param {vec4} out the receiving vector 66 | * @param {vec4} a the source vector 67 | * @returns {vec4} out 68 | */ 69 | export float *vec4(copy)(float *out, float *a) { 70 | out[0] = a[0]; 71 | out[1] = a[1]; 72 | out[2] = a[2]; 73 | out[3] = a[3]; 74 | return out; 75 | }; 76 | 77 | /** 78 | * Set the components of a vec4 to the given values 79 | * 80 | * @param {vec4} out the receiving vector 81 | * @param {Number} x X component 82 | * @param {Number} y Y component 83 | * @param {Number} z Z component 84 | * @param {Number} w W component 85 | * @returns {vec4} out 86 | */ 87 | export float *vec4(set)(float *out, float x, float y, float z, float w) { 88 | out[0] = x; 89 | out[1] = y; 90 | out[2] = z; 91 | out[3] = w; 92 | return out; 93 | }; 94 | 95 | /** 96 | * Adds two vec4's 97 | * 98 | * @param {vec4} out the receiving vector 99 | * @param {vec4} a the first operand 100 | * @param {vec4} b the second operand 101 | * @returns {vec4} out 102 | */ 103 | export float *vec4(add)(float *out, float *a, float *b) { 104 | out[0] = a[0] + b[0]; 105 | out[1] = a[1] + b[1]; 106 | out[2] = a[2] + b[2]; 107 | out[3] = a[3] + b[3]; 108 | return out; 109 | }; 110 | 111 | /** 112 | * Subtracts vector b from vector a 113 | * 114 | * @param {vec4} out the receiving vector 115 | * @param {vec4} a the first operand 116 | * @param {vec4} b the second operand 117 | * @returns {vec4} out 118 | */ 119 | export float *vec4(subtract)(float *out, float *a, float *b) { 120 | out[0] = a[0] - b[0]; 121 | out[1] = a[1] - b[1]; 122 | out[2] = a[2] - b[2]; 123 | out[3] = a[3] - b[3]; 124 | return out; 125 | }; 126 | 127 | /** 128 | * Multiplies two vec4's 129 | * 130 | * @param {vec4} out the receiving vector 131 | * @param {vec4} a the first operand 132 | * @param {vec4} b the second operand 133 | * @returns {vec4} out 134 | */ 135 | export float *vec4(multiply)(float *out, float *a, float *b) { 136 | out[0] = a[0] * b[0]; 137 | out[1] = a[1] * b[1]; 138 | out[2] = a[2] * b[2]; 139 | out[3] = a[3] * b[3]; 140 | return out; 141 | }; 142 | 143 | /** 144 | * Divides two vec4's 145 | * 146 | * @param {vec4} out the receiving vector 147 | * @param {vec4} a the first operand 148 | * @param {vec4} b the second operand 149 | * @returns {vec4} out 150 | */ 151 | export float *vec4(divide)(float *out, float *a, float *b) { 152 | out[0] = a[0] / b[0]; 153 | out[1] = a[1] / b[1]; 154 | out[2] = a[2] / b[2]; 155 | out[3] = a[3] / b[3]; 156 | return out; 157 | }; 158 | 159 | /** 160 | * Math.ceil the components of a vec4 161 | * 162 | * @param {vec4} out the receiving vector 163 | * @param {vec4} a vector to ceil 164 | * @returns {vec4} out 165 | */ 166 | export float *vec4(ceil)(float *out, float *a) { 167 | out[0] = ceilf(a[0]); 168 | out[1] = ceilf(a[1]); 169 | out[2] = ceilf(a[2]); 170 | out[3] = ceilf(a[3]); 171 | return out; 172 | }; 173 | 174 | /** 175 | * Math.floor the components of a vec4 176 | * 177 | * @param {vec4} out the receiving vector 178 | * @param {vec4} a vector to floor 179 | * @returns {vec4} out 180 | */ 181 | export float *vec4(floor)(float *out, float *a) { 182 | out[0] = floorf(a[0]); 183 | out[1] = floorf(a[1]); 184 | out[2] = floorf(a[2]); 185 | out[3] = floorf(a[3]); 186 | return out; 187 | }; 188 | 189 | /** 190 | * Returns the minimum of two vec4's 191 | * 192 | * @param {vec4} out the receiving vector 193 | * @param {vec4} a the first operand 194 | * @param {vec4} b the second operand 195 | * @returns {vec4} out 196 | */ 197 | export float *vec4(min)(float *out, float *a, float *b) { 198 | out[0] = fminf(a[0], b[0]); 199 | out[1] = fminf(a[1], b[1]); 200 | out[2] = fminf(a[2], b[2]); 201 | out[3] = fminf(a[3], b[3]); 202 | return out; 203 | }; 204 | 205 | /** 206 | * Returns the maximum of two vec4's 207 | * 208 | * @param {vec4} out the receiving vector 209 | * @param {vec4} a the first operand 210 | * @param {vec4} b the second operand 211 | * @returns {vec4} out 212 | */ 213 | export float *vec4(max)(float *out, float *a, float *b) { 214 | out[0] = fmaxf(a[0], b[0]); 215 | out[1] = fmaxf(a[1], b[1]); 216 | out[2] = fmaxf(a[2], b[2]); 217 | out[3] = fmaxf(a[3], b[3]); 218 | return out; 219 | }; 220 | 221 | /** 222 | * Math.round the components of a vec4 223 | * 224 | * @param {vec4} out the receiving vector 225 | * @param {vec4} a vector to round 226 | * @returns {vec4} out 227 | */ 228 | export float *vec4(round)(float *out, float *a) { 229 | out[0] = roundf(a[0]); 230 | out[1] = roundf(a[1]); 231 | out[2] = roundf(a[2]); 232 | out[3] = roundf(a[3]); 233 | return out; 234 | }; 235 | 236 | /** 237 | * Scales a vec4 by a scalar number 238 | * 239 | * @param {vec4} out the receiving vector 240 | * @param {vec4} a the vector to scale 241 | * @param {Number} b amount to scale the vector by 242 | * @returns {vec4} out 243 | */ 244 | export float *vec4(scale)(float *out, float *a, float b) { 245 | out[0] = a[0] * b; 246 | out[1] = a[1] * b; 247 | out[2] = a[2] * b; 248 | out[3] = a[3] * b; 249 | return out; 250 | }; 251 | 252 | /** 253 | * Adds two vec4's after scaling the second operand by a scalar value 254 | * 255 | * @param {vec4} out the receiving vector 256 | * @param {vec4} a the first operand 257 | * @param {vec4} b the second operand 258 | * @param {Number} scale the amount to scale b by before adding 259 | * @returns {vec4} out 260 | */ 261 | export float *vec4(scaleAndAdd)(float *out, float *a, float *b, float scale) { 262 | out[0] = a[0] + (b[0] * scale); 263 | out[1] = a[1] + (b[1] * scale); 264 | out[2] = a[2] + (b[2] * scale); 265 | out[3] = a[3] + (b[3] * scale); 266 | return out; 267 | }; 268 | 269 | /** 270 | * Calculates the euclidian distance between two vec4's 271 | * 272 | * @param {vec4} a the first operand 273 | * @param {vec4} b the second operand 274 | * @returns {Number} distance between a and b 275 | */ 276 | export float vec4(distance)(float *a, float *b) { 277 | float x = b[0] - a[0]; 278 | float y = b[1] - a[1]; 279 | float z = b[2] - a[2]; 280 | float w = b[3] - a[3]; 281 | return sqrtf(x*x + y*y + z*z + w*w); 282 | }; 283 | 284 | /** 285 | * Calculates the squared euclidian distance between two vec4's 286 | * 287 | * @param {vec4} a the first operand 288 | * @param {vec4} b the second operand 289 | * @returns {Number} squared distance between a and b 290 | */ 291 | export float vec4(squaredDistance)(float *a, float *b) { 292 | float x = b[0] - a[0]; 293 | float y = b[1] - a[1]; 294 | float z = b[2] - a[2]; 295 | float w = b[3] - a[3]; 296 | return x*x + y*y + z*z + w*w; 297 | }; 298 | 299 | /** 300 | * Calculates the length of a vec4 301 | * 302 | * @param {vec4} a vector to calculate length of 303 | * @returns {Number} length of a 304 | */ 305 | export float vec4(length)(float *a) { 306 | float x = a[0]; 307 | float y = a[1]; 308 | float z = a[2]; 309 | float w = a[3]; 310 | return sqrtf(x*x + y*y + z*z + w*w); 311 | }; 312 | 313 | /** 314 | * Calculates the squared length of a vec4 315 | * 316 | * @param {vec4} a vector to calculate squared length of 317 | * @returns {Number} squared length of a 318 | */ 319 | export float vec4(squaredLength)(float *a) { 320 | float x = a[0]; 321 | float y = a[1]; 322 | float z = a[2]; 323 | float w = a[3]; 324 | return x*x + y*y + z*z + w*w; 325 | }; 326 | 327 | /** 328 | * Negates the components of a vec4 329 | * 330 | * @param {vec4} out the receiving vector 331 | * @param {vec4} a vector to negate 332 | * @returns {vec4} out 333 | */ 334 | export float *vec4(negate)(float *out, float *a) { 335 | out[0] = -a[0]; 336 | out[1] = -a[1]; 337 | out[2] = -a[2]; 338 | out[3] = -a[3]; 339 | return out; 340 | }; 341 | 342 | /** 343 | * Returns the inverse of the components of a vec4 344 | * 345 | * @param {vec4} out the receiving vector 346 | * @param {vec4} a vector to invert 347 | * @returns {vec4} out 348 | */ 349 | export float *vec4(inverse)(float *out, float *a) { 350 | out[0] = 1.0 / a[0]; 351 | out[1] = 1.0 / a[1]; 352 | out[2] = 1.0 / a[2]; 353 | out[3] = 1.0 / a[3]; 354 | return out; 355 | }; 356 | 357 | /** 358 | * Normalize a vec4 359 | * 360 | * @param {vec4} out the receiving vector 361 | * @param {vec4} a vector to normalize 362 | * @returns {vec4} out 363 | */ 364 | export float *vec4(normalize)(float *out, float *a) { 365 | float x = a[0]; 366 | float y = a[1]; 367 | float z = a[2]; 368 | float w = a[3]; 369 | float len = x*x + y*y + z*z + w*w; 370 | if (len > 0) { 371 | len = 1 / sqrtf(len); 372 | out[0] = x * len; 373 | out[1] = y * len; 374 | out[2] = z * len; 375 | out[3] = w * len; 376 | } 377 | return out; 378 | }; 379 | 380 | /** 381 | * Calculates the dot product of two vec4's 382 | * 383 | * @param {vec4} a the first operand 384 | * @param {vec4} b the second operand 385 | * @returns {Number} dot product of a and b 386 | */ 387 | export float vec4(dot)(float *a, float *b) { 388 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 389 | }; 390 | 391 | /** 392 | * Performs a linear interpolation between two vec4's 393 | * 394 | * @param {vec4} out the receiving vector 395 | * @param {vec4} a the first operand 396 | * @param {vec4} b the second operand 397 | * @param {Number} t interpolation amount between the two inputs 398 | * @returns {vec4} out 399 | */ 400 | export float *vec4(lerp)(float *out, float *a, float *b, float t) { 401 | float ax = a[0]; 402 | float ay = a[1]; 403 | float az = a[2]; 404 | float aw = a[3]; 405 | out[0] = ax + t * (b[0] - ax); 406 | out[1] = ay + t * (b[1] - ay); 407 | out[2] = az + t * (b[2] - az); 408 | out[3] = aw + t * (b[3] - aw); 409 | return out; 410 | }; 411 | 412 | /** 413 | * Generates a random vector with the given scale 414 | * 415 | * @param {vec4} out the receiving vector 416 | * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 417 | * @returns {vec4} out 418 | */ 419 | export float *vec4(random)(float *out, float scale) { 420 | //vectorScale = vectorScale || 1.0; 421 | //TODO: This is a pretty awful way of doing this. Find something better. 422 | out[0] = randf(); 423 | out[1] = randf(); 424 | out[2] = randf(); 425 | out[3] = randf(); 426 | vec3(normalize)(out, out); 427 | vec3(scale)(out, out, scale); 428 | return out; 429 | }; 430 | 431 | /** 432 | * Transforms the vec4 with a mat4. 433 | * 434 | * @param {vec4} out the receiving vector 435 | * @param {vec4} a the vector to transform 436 | * @param {mat4} m matrix to transform with 437 | * @returns {vec4} out 438 | */ 439 | export float *vec4(transformMat4)(float *out, float *a, float *m) { 440 | float x = a[0], y = a[1], z = a[2], w = a[3]; 441 | out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; 442 | out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; 443 | out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; 444 | out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; 445 | return out; 446 | }; 447 | 448 | /** 449 | * Transforms the vec4 with a quat 450 | * 451 | * @param {vec4} out the receiving vector 452 | * @param {vec4} a the vector to transform 453 | * @param {quat} q quaternion to transform with 454 | * @returns {vec4} out 455 | */ 456 | export float *vec4(transformQuat)(float *out, float *a, float *q) { 457 | float x = a[0], y = a[1], z = a[2]; 458 | float qx = q[0], qy = q[1], qz = q[2], qw = q[3]; 459 | // calculate quat * vec 460 | float ix = qw * x + qy * z - qz * y; 461 | float iy = qw * y + qz * x - qx * z; 462 | float iz = qw * z + qx * y - qy * x; 463 | float iw = -qx * x - qy * y - qz * z; 464 | // calculate result * inverse quat 465 | out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 466 | out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 467 | out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 468 | out[3] = a[3]; 469 | return out; 470 | }; 471 | 472 | /** 473 | * Returns a string representation of a vector 474 | * 475 | * @param {vec4} a vector to represent as a string 476 | * @returns {String} string representation of the vector 477 | */ 478 | export float *vec4(str)(float *a) { 479 | return a; 480 | }; 481 | 482 | /** 483 | * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) 484 | * 485 | * @param {vec4} a The first vector. 486 | * @param {vec4} b The second vector. 487 | * @returns {Boolean} True if the vectors are equal, false otherwise. 488 | */ 489 | export int vec4(exactEquals)(float *a, float *b) { 490 | return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]; 491 | }; 492 | 493 | /** 494 | * Returns whether or not the vectors have approximately the same elements in the same position. 495 | * 496 | * @param {vec4} a The first vector. 497 | * @param {vec4} b The second vector. 498 | * @returns {Boolean} True if the vectors are equal, false otherwise. 499 | */ 500 | export int vec4(equals)(float *a, float *b) { 501 | float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; 502 | float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 503 | return (fabs(a0 - b0) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a0), fabs(b0))) && 504 | fabs(a1 - b1) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a1), fabs(b1))) && 505 | fabs(a2 - b2) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a2), fabs(b2))) && 506 | fabs(a3 - b3) <= EPSILON*fmaxf(1.0, fmaxf(fabs(a3), fabs(b3)))); 507 | }; 508 | 509 | /** 510 | * Alias for {@link vec4.subtract} 511 | * @function 512 | */ 513 | export float *vec4(sub)(float *out, float *a, float *b) { 514 | return vec4(subtract)(out, a, b); 515 | }; 516 | 517 | /** 518 | * Alias for {@link vec4.multiply} 519 | * @function 520 | */ 521 | export float *vec4(mul)(float *out, float *a, float *b) { 522 | return vec4(multiply)(out, a, b); 523 | }; 524 | 525 | /** 526 | * Alias for {@link vec4.divide} 527 | * @function 528 | */ 529 | export float *vec4(div)(float *out, float *a, float *b) { 530 | return vec4(divide)(out, a, b); 531 | }; 532 | 533 | /** 534 | * Alias for {@link vec4.distance} 535 | * @function 536 | */ 537 | export float vec4(dist)(float *a, float *b) { 538 | return vec4(distance)(a, b); 539 | }; 540 | 541 | /** 542 | * Alias for {@link vec4.squaredDistance} 543 | * @function 544 | */ 545 | export float vec4(sqrDist)(float *a, float *b) { 546 | return vec4(squaredDistance)(a, b); 547 | }; 548 | 549 | /** 550 | * Alias for {@link vec4.length} 551 | * @function 552 | */ 553 | export float vec4(len)(float *a) { 554 | return vec4(length)(a); 555 | }; 556 | 557 | /** 558 | * Alias for {@link vec4.squaredLength} 559 | * @function 560 | */ 561 | export float vec4(sqrLen)(float *a) { 562 | return vec4(squaredLength)(a); 563 | }; 564 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | load, 3 | imports 4 | } from "./utils"; 5 | 6 | import module from "./module.js"; 7 | 8 | import vec3_bridge from "./gl-matrix/bridges/vec3.js"; 9 | import vec4_bridge from "./gl-matrix/bridges/vec4.js"; 10 | import mat4_bridge from "./gl-matrix/bridges/mat4.js"; 11 | 12 | let vec3 = {}; 13 | let vec4 = {}; 14 | let mat4 = {}; 15 | 16 | function validateEnvironment() { 17 | if (typeof WebAssembly === "undefined") { 18 | throw new Error(`WebAssembly is not available or unsupported!`); 19 | } 20 | }; 21 | 22 | function init() { 23 | return new Promise(resolve => { 24 | validateEnvironment(); 25 | load(module, imports).then(instance => { 26 | createLinks(vec3, "vec3", instance); 27 | createLinks(vec4, "vec4", instance); 28 | createLinks(mat4, "mat4", instance); 29 | resolve(true); 30 | }); 31 | }); 32 | }; 33 | 34 | function getMethodsFromExportsByName(exports, name) { 35 | let module = {}; 36 | for (let key in exports) { 37 | if (key.substr(0, name.length) === name) { 38 | module[key.substr(name.length + 1, key.length)] = exports[key]; 39 | } 40 | }; 41 | return module; 42 | }; 43 | 44 | function createLinks(module, name, instance) { 45 | let memory = instance.memory; 46 | let exports = instance.exports; 47 | // link 48 | let methods = getMethodsFromExportsByName(exports, name); 49 | Object.assign(module, methods); 50 | // bridge 51 | switch (name) { 52 | case "vec3": vec3_bridge(module, memory); break; 53 | case "vec4": vec4_bridge(module, memory); break; 54 | case "mat4": mat4_bridge(module, memory); break; 55 | }; 56 | }; 57 | 58 | export { 59 | init, 60 | vec3, 61 | vec4, 62 | mat4 63 | }; 64 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export let imports = { 2 | initialMemory: 0, 3 | imports: { 4 | randf: () => Math.random(), 5 | printi: console.log.bind(console), 6 | printch: (cc) => console.log(String.fromCharCode(cc)) 7 | } 8 | }; 9 | 10 | export function load(buffer, options = {}) { 11 | 12 | let imports = options.imports || {}; 13 | 14 | let memory = imports.memory; 15 | if (!memory) { 16 | let opts = { initial: options.initialMemory || 1 }; 17 | memory = new WebAssembly.Memory(opts); 18 | memory.initial = options.initialMemory || 1; 19 | } 20 | 21 | let table = imports.table; 22 | if (!table) table = new WebAssembly.Table({ initial: 0, element: "anyfunc" }); 23 | 24 | function grow() { 25 | let buffer = memory.buffer; 26 | memory.F32 = new Float32Array(buffer); 27 | memory.F64 = new Float64Array(buffer); 28 | }; 29 | 30 | grow(); 31 | 32 | let env = {}; 33 | env.memoryBase = imports.memoryBase || 0; 34 | env.memory = memory; 35 | env.tableBase = imports.tableBase || 0; 36 | env.table = table; 37 | 38 | Object.keys(imports).forEach(key => env[key] = imports[key]); 39 | 40 | env._abort = errno => { throw Error("abnormal abort in " + file + ": " + errno); }; 41 | env._exit = code => { if (code) throw Error("abnormal exit in " + file + ": " + code); } 42 | 43 | env._grow = grow; 44 | 45 | return WebAssembly.instantiate(buffer, { env: env }) 46 | .then(module => { 47 | var instance = module.instance; 48 | instance.imports = imports; 49 | instance.memory = memory; 50 | instance.env = env; 51 | return instance; 52 | }); 53 | 54 | }; 55 | --------------------------------------------------------------------------------