├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── .yo-rc.json ├── Gruntfile.js ├── README.md ├── examples └── curves-graph │ ├── build │ └── curves-graph.js │ ├── curves-graph.html │ ├── curves-graph.js │ └── style.css ├── index.js ├── package.json └── test └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "eqnull": true, 6 | "immed": true, 7 | "latedef": true, 8 | "mocha" : true, 9 | "newcap": true, 10 | "noarg": true, 11 | "node": true, 12 | "sub": true, 13 | "undef": true, 14 | "unused": true 15 | } 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 'iojs' 5 | - '0.12' 6 | - '0.10' 7 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-node": {} 3 | } -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function (grunt) { 3 | // Show elapsed time at the end 4 | require('time-grunt')(grunt); 5 | // Load all grunt tasks 6 | require('load-grunt-tasks')(grunt); 7 | 8 | grunt.initConfig({ 9 | browserify: { 10 | 'curves-graph': { 11 | src: ['examples/curves-graph/curves-graph.js'], 12 | dest: 'examples/curves-graph/build/curves-graph.js' 13 | } 14 | }, 15 | jshint: { 16 | options: { 17 | jshintrc: '.jshintrc', 18 | reporter: require('jshint-stylish') 19 | }, 20 | gruntfile: { 21 | src: ['Gruntfile.js'] 22 | }, 23 | js: { 24 | src: ['*.js'] 25 | }, 26 | test: { 27 | src: ['test/**/*.js'] 28 | } 29 | }, 30 | mochacli: { 31 | options: { 32 | reporter: 'nyan', 33 | bail: true 34 | }, 35 | all: ['test/*.js'] 36 | }, 37 | watch: { 38 | gruntfile: { 39 | files: '<%= jshint.gruntfile.src %>', 40 | tasks: ['jshint:gruntfile'] 41 | }, 42 | js: { 43 | files: '<%= jshint.js.src %>', 44 | tasks: ['jshint:js', 'mochacli'] 45 | }, 46 | test: { 47 | files: '<%= jshint.test.src %>', 48 | tasks: ['jshint:test', 'mochacli'] 49 | } 50 | } 51 | }); 52 | 53 | grunt.registerTask('examples', ['browserify:curves-graph']); 54 | grunt.registerTask('default', ['jshint', 'mochacli']); 55 | }; 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Catmull Rom spline interpolation made easy. 2 | 3 | 4 | ## Install 5 | 6 | ```sh 7 | $ npm install --save cat-rom-spline 8 | ``` 9 | 10 | 11 | ## Usage 12 | 13 | ```js 14 | var catRomSpline = require('cat-rom-spline'); 15 | 16 | // Points are arrays in the form of [x, y] 17 | var p0 = [0, 0]; 18 | var p1 = [5, 5]; 19 | var p2 = [5, 10]; 20 | var p3 = [15, 20]; 21 | 22 | // At least 4 points are needed to interpolate 23 | var points = [p0, p1, p2, p3]; 24 | 25 | // There are optional configurations that you can make but they aren't required 26 | // If 'samples' is not passed in the interpolation will sample a sensible amount 27 | // of points based on how far away control points are 28 | var options = { 29 | samples: 50, 30 | knot: 0.5 // Default is 0.5, Ranges from 0 - 1, 1 being stiffer curves. 31 | }; 32 | 33 | var interpolatedPoints = catRomSpline(points, options); 34 | ``` 35 | 36 | 37 | ## License 38 | 39 | MIT © [Nick Schaubeck](http://www.northofbrooklyn.nyc) 40 | 41 | 42 | [npm-image]: https://badge.fury.io/js/cat-rom-spline.svg 43 | [npm-url]: https://npmjs.org/package/cat-rom-spline 44 | [travis-image]: https://travis-ci.org/nschaubeck/cat-rom-spline.svg?branch=master 45 | [travis-url]: https://travis-ci.org/nschaubeck/cat-rom-spline 46 | [daviddm-image]: https://david-dm.org/nschaubeck/cat-rom-spline.svg?theme=shields.io 47 | [daviddm-url]: https://david-dm.org/nschaubeck/cat-rom-spline 48 | -------------------------------------------------------------------------------- /examples/curves-graph/build/curves-graph.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { 587 | //TODO: evaluate use of glm_invsqrt here? 588 | len = 1 / Math.sqrt(len); 589 | out[0] = a[0] * len; 590 | out[1] = a[1] * len; 591 | } 592 | return out; 593 | }; 594 | 595 | /** 596 | * Calculates the dot product of two vec2's 597 | * 598 | * @param {vec2} a the first operand 599 | * @param {vec2} b the second operand 600 | * @returns {Number} dot product of a and b 601 | */ 602 | vec2.dot = function (a, b) { 603 | return a[0] * b[0] + a[1] * b[1]; 604 | }; 605 | 606 | /** 607 | * Computes the cross product of two vec2's 608 | * Note that the cross product must by definition produce a 3D vector 609 | * 610 | * @param {vec3} out the receiving vector 611 | * @param {vec2} a the first operand 612 | * @param {vec2} b the second operand 613 | * @returns {vec3} out 614 | */ 615 | vec2.cross = function(out, a, b) { 616 | var z = a[0] * b[1] - a[1] * b[0]; 617 | out[0] = out[1] = 0; 618 | out[2] = z; 619 | return out; 620 | }; 621 | 622 | /** 623 | * Performs a linear interpolation between two vec2's 624 | * 625 | * @param {vec2} out the receiving vector 626 | * @param {vec2} a the first operand 627 | * @param {vec2} b the second operand 628 | * @param {Number} t interpolation amount between the two inputs 629 | * @returns {vec2} out 630 | */ 631 | vec2.lerp = function (out, a, b, t) { 632 | var ax = a[0], 633 | ay = a[1]; 634 | out[0] = ax + t * (b[0] - ax); 635 | out[1] = ay + t * (b[1] - ay); 636 | return out; 637 | }; 638 | 639 | /** 640 | * Transforms the vec2 with a mat2 641 | * 642 | * @param {vec2} out the receiving vector 643 | * @param {vec2} a the vector to transform 644 | * @param {mat2} m matrix to transform with 645 | * @returns {vec2} out 646 | */ 647 | vec2.transformMat2 = function(out, a, m) { 648 | var x = a[0], 649 | y = a[1]; 650 | out[0] = m[0] * x + m[2] * y; 651 | out[1] = m[1] * x + m[3] * y; 652 | return out; 653 | }; 654 | 655 | /** 656 | * Transforms the vec2 with a mat2d 657 | * 658 | * @param {vec2} out the receiving vector 659 | * @param {vec2} a the vector to transform 660 | * @param {mat2d} m matrix to transform with 661 | * @returns {vec2} out 662 | */ 663 | vec2.transformMat2d = function(out, a, m) { 664 | var x = a[0], 665 | y = a[1]; 666 | out[0] = m[0] * x + m[2] * y + m[4]; 667 | out[1] = m[1] * x + m[3] * y + m[5]; 668 | return out; 669 | }; 670 | 671 | /** 672 | * Transforms the vec2 with a mat3 673 | * 3rd vector component is implicitly '1' 674 | * 675 | * @param {vec2} out the receiving vector 676 | * @param {vec2} a the vector to transform 677 | * @param {mat3} m matrix to transform with 678 | * @returns {vec2} out 679 | */ 680 | vec2.transformMat3 = function(out, a, m) { 681 | var x = a[0], 682 | y = a[1]; 683 | out[0] = m[0] * x + m[3] * y + m[6]; 684 | out[1] = m[1] * x + m[4] * y + m[7]; 685 | return out; 686 | }; 687 | 688 | /** 689 | * Transforms the vec2 with a mat4 690 | * 3rd vector component is implicitly '0' 691 | * 4th vector component is implicitly '1' 692 | * 693 | * @param {vec2} out the receiving vector 694 | * @param {vec2} a the vector to transform 695 | * @param {mat4} m matrix to transform with 696 | * @returns {vec2} out 697 | */ 698 | vec2.transformMat4 = function(out, a, m) { 699 | var x = a[0], 700 | y = a[1]; 701 | out[0] = m[0] * x + m[4] * y + m[12]; 702 | out[1] = m[1] * x + m[5] * y + m[13]; 703 | return out; 704 | }; 705 | 706 | /** 707 | * Perform some operation over an array of vec2s. 708 | * 709 | * @param {Array} a the array of vectors to iterate over 710 | * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed 711 | * @param {Number} offset Number of elements to skip at the beginning of the array 712 | * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array 713 | * @param {Function} fn Function to call for each vector in the array 714 | * @param {Object} [arg] additional argument to pass to fn 715 | * @returns {Array} a 716 | * @function 717 | */ 718 | vec2.forEach = (function() { 719 | var vec = vec2.create(); 720 | 721 | return function(a, stride, offset, count, fn, arg) { 722 | var i, l; 723 | if(!stride) { 724 | stride = 2; 725 | } 726 | 727 | if(!offset) { 728 | offset = 0; 729 | } 730 | 731 | if(count) { 732 | l = Math.min((count * stride) + offset, a.length); 733 | } else { 734 | l = a.length; 735 | } 736 | 737 | for(i = offset; i < l; i += stride) { 738 | vec[0] = a[i]; vec[1] = a[i+1]; 739 | fn(vec, vec, arg); 740 | a[i] = vec[0]; a[i+1] = vec[1]; 741 | } 742 | 743 | return a; 744 | }; 745 | })(); 746 | 747 | /** 748 | * Returns a string representation of a vector 749 | * 750 | * @param {vec2} vec vector to represent as a string 751 | * @returns {String} string representation of the vector 752 | */ 753 | vec2.str = function (a) { 754 | return 'vec2(' + a[0] + ', ' + a[1] + ')'; 755 | }; 756 | 757 | if(typeof(exports) !== 'undefined') { 758 | exports.vec2 = vec2; 759 | } 760 | ; 761 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 762 | 763 | Redistribution and use in source and binary forms, with or without modification, 764 | are permitted provided that the following conditions are met: 765 | 766 | * Redistributions of source code must retain the above copyright notice, this 767 | list of conditions and the following disclaimer. 768 | * Redistributions in binary form must reproduce the above copyright notice, 769 | this list of conditions and the following disclaimer in the documentation 770 | and/or other materials provided with the distribution. 771 | 772 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 773 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 774 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 775 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 776 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 777 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 778 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 779 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 780 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 781 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 782 | 783 | /** 784 | * @class 3 Dimensional Vector 785 | * @name vec3 786 | */ 787 | 788 | var vec3 = {}; 789 | 790 | /** 791 | * Creates a new, empty vec3 792 | * 793 | * @returns {vec3} a new 3D vector 794 | */ 795 | vec3.create = function() { 796 | var out = new GLMAT_ARRAY_TYPE(3); 797 | out[0] = 0; 798 | out[1] = 0; 799 | out[2] = 0; 800 | return out; 801 | }; 802 | 803 | /** 804 | * Creates a new vec3 initialized with values from an existing vector 805 | * 806 | * @param {vec3} a vector to clone 807 | * @returns {vec3} a new 3D vector 808 | */ 809 | vec3.clone = function(a) { 810 | var out = new GLMAT_ARRAY_TYPE(3); 811 | out[0] = a[0]; 812 | out[1] = a[1]; 813 | out[2] = a[2]; 814 | return out; 815 | }; 816 | 817 | /** 818 | * Creates a new vec3 initialized with the given values 819 | * 820 | * @param {Number} x X component 821 | * @param {Number} y Y component 822 | * @param {Number} z Z component 823 | * @returns {vec3} a new 3D vector 824 | */ 825 | vec3.fromValues = function(x, y, z) { 826 | var out = new GLMAT_ARRAY_TYPE(3); 827 | out[0] = x; 828 | out[1] = y; 829 | out[2] = z; 830 | return out; 831 | }; 832 | 833 | /** 834 | * Copy the values from one vec3 to another 835 | * 836 | * @param {vec3} out the receiving vector 837 | * @param {vec3} a the source vector 838 | * @returns {vec3} out 839 | */ 840 | vec3.copy = function(out, a) { 841 | out[0] = a[0]; 842 | out[1] = a[1]; 843 | out[2] = a[2]; 844 | return out; 845 | }; 846 | 847 | /** 848 | * Set the components of a vec3 to the given values 849 | * 850 | * @param {vec3} out the receiving vector 851 | * @param {Number} x X component 852 | * @param {Number} y Y component 853 | * @param {Number} z Z component 854 | * @returns {vec3} out 855 | */ 856 | vec3.set = function(out, x, y, z) { 857 | out[0] = x; 858 | out[1] = y; 859 | out[2] = z; 860 | return out; 861 | }; 862 | 863 | /** 864 | * Adds two vec3's 865 | * 866 | * @param {vec3} out the receiving vector 867 | * @param {vec3} a the first operand 868 | * @param {vec3} b the second operand 869 | * @returns {vec3} out 870 | */ 871 | vec3.add = function(out, a, b) { 872 | out[0] = a[0] + b[0]; 873 | out[1] = a[1] + b[1]; 874 | out[2] = a[2] + b[2]; 875 | return out; 876 | }; 877 | 878 | /** 879 | * Subtracts two vec3's 880 | * 881 | * @param {vec3} out the receiving vector 882 | * @param {vec3} a the first operand 883 | * @param {vec3} b the second operand 884 | * @returns {vec3} out 885 | */ 886 | vec3.subtract = function(out, a, b) { 887 | out[0] = a[0] - b[0]; 888 | out[1] = a[1] - b[1]; 889 | out[2] = a[2] - b[2]; 890 | return out; 891 | }; 892 | 893 | /** 894 | * Alias for {@link vec3.subtract} 895 | * @function 896 | */ 897 | vec3.sub = vec3.subtract; 898 | 899 | /** 900 | * Multiplies two vec3's 901 | * 902 | * @param {vec3} out the receiving vector 903 | * @param {vec3} a the first operand 904 | * @param {vec3} b the second operand 905 | * @returns {vec3} out 906 | */ 907 | vec3.multiply = function(out, a, b) { 908 | out[0] = a[0] * b[0]; 909 | out[1] = a[1] * b[1]; 910 | out[2] = a[2] * b[2]; 911 | return out; 912 | }; 913 | 914 | /** 915 | * Alias for {@link vec3.multiply} 916 | * @function 917 | */ 918 | vec3.mul = vec3.multiply; 919 | 920 | /** 921 | * Divides two vec3's 922 | * 923 | * @param {vec3} out the receiving vector 924 | * @param {vec3} a the first operand 925 | * @param {vec3} b the second operand 926 | * @returns {vec3} out 927 | */ 928 | vec3.divide = function(out, a, b) { 929 | out[0] = a[0] / b[0]; 930 | out[1] = a[1] / b[1]; 931 | out[2] = a[2] / b[2]; 932 | return out; 933 | }; 934 | 935 | /** 936 | * Alias for {@link vec3.divide} 937 | * @function 938 | */ 939 | vec3.div = vec3.divide; 940 | 941 | /** 942 | * Returns the minimum of two vec3's 943 | * 944 | * @param {vec3} out the receiving vector 945 | * @param {vec3} a the first operand 946 | * @param {vec3} b the second operand 947 | * @returns {vec3} out 948 | */ 949 | vec3.min = function(out, a, b) { 950 | out[0] = Math.min(a[0], b[0]); 951 | out[1] = Math.min(a[1], b[1]); 952 | out[2] = Math.min(a[2], b[2]); 953 | return out; 954 | }; 955 | 956 | /** 957 | * Returns the maximum of two vec3's 958 | * 959 | * @param {vec3} out the receiving vector 960 | * @param {vec3} a the first operand 961 | * @param {vec3} b the second operand 962 | * @returns {vec3} out 963 | */ 964 | vec3.max = function(out, a, b) { 965 | out[0] = Math.max(a[0], b[0]); 966 | out[1] = Math.max(a[1], b[1]); 967 | out[2] = Math.max(a[2], b[2]); 968 | return out; 969 | }; 970 | 971 | /** 972 | * Scales a vec3 by a scalar number 973 | * 974 | * @param {vec3} out the receiving vector 975 | * @param {vec3} a the vector to scale 976 | * @param {Number} b amount to scale the vector by 977 | * @returns {vec3} out 978 | */ 979 | vec3.scale = function(out, a, b) { 980 | out[0] = a[0] * b; 981 | out[1] = a[1] * b; 982 | out[2] = a[2] * b; 983 | return out; 984 | }; 985 | 986 | /** 987 | * Calculates the euclidian distance between two vec3's 988 | * 989 | * @param {vec3} a the first operand 990 | * @param {vec3} b the second operand 991 | * @returns {Number} distance between a and b 992 | */ 993 | vec3.distance = function(a, b) { 994 | var x = b[0] - a[0], 995 | y = b[1] - a[1], 996 | z = b[2] - a[2]; 997 | return Math.sqrt(x*x + y*y + z*z); 998 | }; 999 | 1000 | /** 1001 | * Alias for {@link vec3.distance} 1002 | * @function 1003 | */ 1004 | vec3.dist = vec3.distance; 1005 | 1006 | /** 1007 | * Calculates the squared euclidian distance between two vec3's 1008 | * 1009 | * @param {vec3} a the first operand 1010 | * @param {vec3} b the second operand 1011 | * @returns {Number} squared distance between a and b 1012 | */ 1013 | vec3.squaredDistance = function(a, b) { 1014 | var x = b[0] - a[0], 1015 | y = b[1] - a[1], 1016 | z = b[2] - a[2]; 1017 | return x*x + y*y + z*z; 1018 | }; 1019 | 1020 | /** 1021 | * Alias for {@link vec3.squaredDistance} 1022 | * @function 1023 | */ 1024 | vec3.sqrDist = vec3.squaredDistance; 1025 | 1026 | /** 1027 | * Calculates the length of a vec3 1028 | * 1029 | * @param {vec3} a vector to calculate length of 1030 | * @returns {Number} length of a 1031 | */ 1032 | vec3.length = function (a) { 1033 | var x = a[0], 1034 | y = a[1], 1035 | z = a[2]; 1036 | return Math.sqrt(x*x + y*y + z*z); 1037 | }; 1038 | 1039 | /** 1040 | * Alias for {@link vec3.length} 1041 | * @function 1042 | */ 1043 | vec3.len = vec3.length; 1044 | 1045 | /** 1046 | * Calculates the squared length of a vec3 1047 | * 1048 | * @param {vec3} a vector to calculate squared length of 1049 | * @returns {Number} squared length of a 1050 | */ 1051 | vec3.squaredLength = function (a) { 1052 | var x = a[0], 1053 | y = a[1], 1054 | z = a[2]; 1055 | return x*x + y*y + z*z; 1056 | }; 1057 | 1058 | /** 1059 | * Alias for {@link vec3.squaredLength} 1060 | * @function 1061 | */ 1062 | vec3.sqrLen = vec3.squaredLength; 1063 | 1064 | /** 1065 | * Negates the components of a vec3 1066 | * 1067 | * @param {vec3} out the receiving vector 1068 | * @param {vec3} a vector to negate 1069 | * @returns {vec3} out 1070 | */ 1071 | vec3.negate = function(out, a) { 1072 | out[0] = -a[0]; 1073 | out[1] = -a[1]; 1074 | out[2] = -a[2]; 1075 | return out; 1076 | }; 1077 | 1078 | /** 1079 | * Normalize a vec3 1080 | * 1081 | * @param {vec3} out the receiving vector 1082 | * @param {vec3} a vector to normalize 1083 | * @returns {vec3} out 1084 | */ 1085 | vec3.normalize = function(out, a) { 1086 | var x = a[0], 1087 | y = a[1], 1088 | z = a[2]; 1089 | var len = x*x + y*y + z*z; 1090 | if (len > 0) { 1091 | //TODO: evaluate use of glm_invsqrt here? 1092 | len = 1 / Math.sqrt(len); 1093 | out[0] = a[0] * len; 1094 | out[1] = a[1] * len; 1095 | out[2] = a[2] * len; 1096 | } 1097 | return out; 1098 | }; 1099 | 1100 | /** 1101 | * Calculates the dot product of two vec3's 1102 | * 1103 | * @param {vec3} a the first operand 1104 | * @param {vec3} b the second operand 1105 | * @returns {Number} dot product of a and b 1106 | */ 1107 | vec3.dot = function (a, b) { 1108 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 1109 | }; 1110 | 1111 | /** 1112 | * Computes the cross product of two vec3's 1113 | * 1114 | * @param {vec3} out the receiving vector 1115 | * @param {vec3} a the first operand 1116 | * @param {vec3} b the second operand 1117 | * @returns {vec3} out 1118 | */ 1119 | vec3.cross = function(out, a, b) { 1120 | var ax = a[0], ay = a[1], az = a[2], 1121 | bx = b[0], by = b[1], bz = b[2]; 1122 | 1123 | out[0] = ay * bz - az * by; 1124 | out[1] = az * bx - ax * bz; 1125 | out[2] = ax * by - ay * bx; 1126 | return out; 1127 | }; 1128 | 1129 | /** 1130 | * Performs a linear interpolation between two vec3's 1131 | * 1132 | * @param {vec3} out the receiving vector 1133 | * @param {vec3} a the first operand 1134 | * @param {vec3} b the second operand 1135 | * @param {Number} t interpolation amount between the two inputs 1136 | * @returns {vec3} out 1137 | */ 1138 | vec3.lerp = function (out, a, b, t) { 1139 | var ax = a[0], 1140 | ay = a[1], 1141 | az = a[2]; 1142 | out[0] = ax + t * (b[0] - ax); 1143 | out[1] = ay + t * (b[1] - ay); 1144 | out[2] = az + t * (b[2] - az); 1145 | return out; 1146 | }; 1147 | 1148 | /** 1149 | * Transforms the vec3 with a mat4. 1150 | * 4th vector component is implicitly '1' 1151 | * 1152 | * @param {vec3} out the receiving vector 1153 | * @param {vec3} a the vector to transform 1154 | * @param {mat4} m matrix to transform with 1155 | * @returns {vec3} out 1156 | */ 1157 | vec3.transformMat4 = function(out, a, m) { 1158 | var x = a[0], y = a[1], z = a[2]; 1159 | out[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; 1160 | out[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; 1161 | out[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; 1162 | return out; 1163 | }; 1164 | 1165 | /** 1166 | * Transforms the vec3 with a quat 1167 | * 1168 | * @param {vec3} out the receiving vector 1169 | * @param {vec3} a the vector to transform 1170 | * @param {quat} q quaternion to transform with 1171 | * @returns {vec3} out 1172 | */ 1173 | vec3.transformQuat = function(out, a, q) { 1174 | var x = a[0], y = a[1], z = a[2], 1175 | qx = q[0], qy = q[1], qz = q[2], qw = q[3], 1176 | 1177 | // calculate quat * vec 1178 | ix = qw * x + qy * z - qz * y, 1179 | iy = qw * y + qz * x - qx * z, 1180 | iz = qw * z + qx * y - qy * x, 1181 | iw = -qx * x - qy * y - qz * z; 1182 | 1183 | // calculate result * inverse quat 1184 | out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 1185 | out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 1186 | out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 1187 | return out; 1188 | }; 1189 | 1190 | /** 1191 | * Perform some operation over an array of vec3s. 1192 | * 1193 | * @param {Array} a the array of vectors to iterate over 1194 | * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed 1195 | * @param {Number} offset Number of elements to skip at the beginning of the array 1196 | * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array 1197 | * @param {Function} fn Function to call for each vector in the array 1198 | * @param {Object} [arg] additional argument to pass to fn 1199 | * @returns {Array} a 1200 | * @function 1201 | */ 1202 | vec3.forEach = (function() { 1203 | var vec = vec3.create(); 1204 | 1205 | return function(a, stride, offset, count, fn, arg) { 1206 | var i, l; 1207 | if(!stride) { 1208 | stride = 3; 1209 | } 1210 | 1211 | if(!offset) { 1212 | offset = 0; 1213 | } 1214 | 1215 | if(count) { 1216 | l = Math.min((count * stride) + offset, a.length); 1217 | } else { 1218 | l = a.length; 1219 | } 1220 | 1221 | for(i = offset; i < l; i += stride) { 1222 | vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; 1223 | fn(vec, vec, arg); 1224 | a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; 1225 | } 1226 | 1227 | return a; 1228 | }; 1229 | })(); 1230 | 1231 | /** 1232 | * Returns a string representation of a vector 1233 | * 1234 | * @param {vec3} vec vector to represent as a string 1235 | * @returns {String} string representation of the vector 1236 | */ 1237 | vec3.str = function (a) { 1238 | return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; 1239 | }; 1240 | 1241 | if(typeof(exports) !== 'undefined') { 1242 | exports.vec3 = vec3; 1243 | } 1244 | ; 1245 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 1246 | 1247 | Redistribution and use in source and binary forms, with or without modification, 1248 | are permitted provided that the following conditions are met: 1249 | 1250 | * Redistributions of source code must retain the above copyright notice, this 1251 | list of conditions and the following disclaimer. 1252 | * Redistributions in binary form must reproduce the above copyright notice, 1253 | this list of conditions and the following disclaimer in the documentation 1254 | and/or other materials provided with the distribution. 1255 | 1256 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1257 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1258 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1259 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 1260 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1261 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1262 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1263 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1264 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1265 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 1266 | 1267 | /** 1268 | * @class 4 Dimensional Vector 1269 | * @name vec4 1270 | */ 1271 | 1272 | var vec4 = {}; 1273 | 1274 | /** 1275 | * Creates a new, empty vec4 1276 | * 1277 | * @returns {vec4} a new 4D vector 1278 | */ 1279 | vec4.create = function() { 1280 | var out = new GLMAT_ARRAY_TYPE(4); 1281 | out[0] = 0; 1282 | out[1] = 0; 1283 | out[2] = 0; 1284 | out[3] = 0; 1285 | return out; 1286 | }; 1287 | 1288 | /** 1289 | * Creates a new vec4 initialized with values from an existing vector 1290 | * 1291 | * @param {vec4} a vector to clone 1292 | * @returns {vec4} a new 4D vector 1293 | */ 1294 | vec4.clone = function(a) { 1295 | var out = new GLMAT_ARRAY_TYPE(4); 1296 | out[0] = a[0]; 1297 | out[1] = a[1]; 1298 | out[2] = a[2]; 1299 | out[3] = a[3]; 1300 | return out; 1301 | }; 1302 | 1303 | /** 1304 | * Creates a new vec4 initialized with the given values 1305 | * 1306 | * @param {Number} x X component 1307 | * @param {Number} y Y component 1308 | * @param {Number} z Z component 1309 | * @param {Number} w W component 1310 | * @returns {vec4} a new 4D vector 1311 | */ 1312 | vec4.fromValues = function(x, y, z, w) { 1313 | var out = new GLMAT_ARRAY_TYPE(4); 1314 | out[0] = x; 1315 | out[1] = y; 1316 | out[2] = z; 1317 | out[3] = w; 1318 | return out; 1319 | }; 1320 | 1321 | /** 1322 | * Copy the values from one vec4 to another 1323 | * 1324 | * @param {vec4} out the receiving vector 1325 | * @param {vec4} a the source vector 1326 | * @returns {vec4} out 1327 | */ 1328 | vec4.copy = function(out, a) { 1329 | out[0] = a[0]; 1330 | out[1] = a[1]; 1331 | out[2] = a[2]; 1332 | out[3] = a[3]; 1333 | return out; 1334 | }; 1335 | 1336 | /** 1337 | * Set the components of a vec4 to the given values 1338 | * 1339 | * @param {vec4} out the receiving vector 1340 | * @param {Number} x X component 1341 | * @param {Number} y Y component 1342 | * @param {Number} z Z component 1343 | * @param {Number} w W component 1344 | * @returns {vec4} out 1345 | */ 1346 | vec4.set = function(out, x, y, z, w) { 1347 | out[0] = x; 1348 | out[1] = y; 1349 | out[2] = z; 1350 | out[3] = w; 1351 | return out; 1352 | }; 1353 | 1354 | /** 1355 | * Adds two vec4's 1356 | * 1357 | * @param {vec4} out the receiving vector 1358 | * @param {vec4} a the first operand 1359 | * @param {vec4} b the second operand 1360 | * @returns {vec4} out 1361 | */ 1362 | vec4.add = function(out, a, b) { 1363 | out[0] = a[0] + b[0]; 1364 | out[1] = a[1] + b[1]; 1365 | out[2] = a[2] + b[2]; 1366 | out[3] = a[3] + b[3]; 1367 | return out; 1368 | }; 1369 | 1370 | /** 1371 | * Subtracts two vec4's 1372 | * 1373 | * @param {vec4} out the receiving vector 1374 | * @param {vec4} a the first operand 1375 | * @param {vec4} b the second operand 1376 | * @returns {vec4} out 1377 | */ 1378 | vec4.subtract = function(out, a, b) { 1379 | out[0] = a[0] - b[0]; 1380 | out[1] = a[1] - b[1]; 1381 | out[2] = a[2] - b[2]; 1382 | out[3] = a[3] - b[3]; 1383 | return out; 1384 | }; 1385 | 1386 | /** 1387 | * Alias for {@link vec4.subtract} 1388 | * @function 1389 | */ 1390 | vec4.sub = vec4.subtract; 1391 | 1392 | /** 1393 | * Multiplies two vec4's 1394 | * 1395 | * @param {vec4} out the receiving vector 1396 | * @param {vec4} a the first operand 1397 | * @param {vec4} b the second operand 1398 | * @returns {vec4} out 1399 | */ 1400 | vec4.multiply = function(out, a, b) { 1401 | out[0] = a[0] * b[0]; 1402 | out[1] = a[1] * b[1]; 1403 | out[2] = a[2] * b[2]; 1404 | out[3] = a[3] * b[3]; 1405 | return out; 1406 | }; 1407 | 1408 | /** 1409 | * Alias for {@link vec4.multiply} 1410 | * @function 1411 | */ 1412 | vec4.mul = vec4.multiply; 1413 | 1414 | /** 1415 | * Divides two vec4's 1416 | * 1417 | * @param {vec4} out the receiving vector 1418 | * @param {vec4} a the first operand 1419 | * @param {vec4} b the second operand 1420 | * @returns {vec4} out 1421 | */ 1422 | vec4.divide = function(out, a, b) { 1423 | out[0] = a[0] / b[0]; 1424 | out[1] = a[1] / b[1]; 1425 | out[2] = a[2] / b[2]; 1426 | out[3] = a[3] / b[3]; 1427 | return out; 1428 | }; 1429 | 1430 | /** 1431 | * Alias for {@link vec4.divide} 1432 | * @function 1433 | */ 1434 | vec4.div = vec4.divide; 1435 | 1436 | /** 1437 | * Returns the minimum of two vec4's 1438 | * 1439 | * @param {vec4} out the receiving vector 1440 | * @param {vec4} a the first operand 1441 | * @param {vec4} b the second operand 1442 | * @returns {vec4} out 1443 | */ 1444 | vec4.min = function(out, a, b) { 1445 | out[0] = Math.min(a[0], b[0]); 1446 | out[1] = Math.min(a[1], b[1]); 1447 | out[2] = Math.min(a[2], b[2]); 1448 | out[3] = Math.min(a[3], b[3]); 1449 | return out; 1450 | }; 1451 | 1452 | /** 1453 | * Returns the maximum of two vec4's 1454 | * 1455 | * @param {vec4} out the receiving vector 1456 | * @param {vec4} a the first operand 1457 | * @param {vec4} b the second operand 1458 | * @returns {vec4} out 1459 | */ 1460 | vec4.max = function(out, a, b) { 1461 | out[0] = Math.max(a[0], b[0]); 1462 | out[1] = Math.max(a[1], b[1]); 1463 | out[2] = Math.max(a[2], b[2]); 1464 | out[3] = Math.max(a[3], b[3]); 1465 | return out; 1466 | }; 1467 | 1468 | /** 1469 | * Scales a vec4 by a scalar number 1470 | * 1471 | * @param {vec4} out the receiving vector 1472 | * @param {vec4} a the vector to scale 1473 | * @param {Number} b amount to scale the vector by 1474 | * @returns {vec4} out 1475 | */ 1476 | vec4.scale = function(out, a, b) { 1477 | out[0] = a[0] * b; 1478 | out[1] = a[1] * b; 1479 | out[2] = a[2] * b; 1480 | out[3] = a[3] * b; 1481 | return out; 1482 | }; 1483 | 1484 | /** 1485 | * Calculates the euclidian distance between two vec4's 1486 | * 1487 | * @param {vec4} a the first operand 1488 | * @param {vec4} b the second operand 1489 | * @returns {Number} distance between a and b 1490 | */ 1491 | vec4.distance = function(a, b) { 1492 | var x = b[0] - a[0], 1493 | y = b[1] - a[1], 1494 | z = b[2] - a[2], 1495 | w = b[3] - a[3]; 1496 | return Math.sqrt(x*x + y*y + z*z + w*w); 1497 | }; 1498 | 1499 | /** 1500 | * Alias for {@link vec4.distance} 1501 | * @function 1502 | */ 1503 | vec4.dist = vec4.distance; 1504 | 1505 | /** 1506 | * Calculates the squared euclidian distance between two vec4's 1507 | * 1508 | * @param {vec4} a the first operand 1509 | * @param {vec4} b the second operand 1510 | * @returns {Number} squared distance between a and b 1511 | */ 1512 | vec4.squaredDistance = function(a, b) { 1513 | var x = b[0] - a[0], 1514 | y = b[1] - a[1], 1515 | z = b[2] - a[2], 1516 | w = b[3] - a[3]; 1517 | return x*x + y*y + z*z + w*w; 1518 | }; 1519 | 1520 | /** 1521 | * Alias for {@link vec4.squaredDistance} 1522 | * @function 1523 | */ 1524 | vec4.sqrDist = vec4.squaredDistance; 1525 | 1526 | /** 1527 | * Calculates the length of a vec4 1528 | * 1529 | * @param {vec4} a vector to calculate length of 1530 | * @returns {Number} length of a 1531 | */ 1532 | vec4.length = function (a) { 1533 | var x = a[0], 1534 | y = a[1], 1535 | z = a[2], 1536 | w = a[3]; 1537 | return Math.sqrt(x*x + y*y + z*z + w*w); 1538 | }; 1539 | 1540 | /** 1541 | * Alias for {@link vec4.length} 1542 | * @function 1543 | */ 1544 | vec4.len = vec4.length; 1545 | 1546 | /** 1547 | * Calculates the squared length of a vec4 1548 | * 1549 | * @param {vec4} a vector to calculate squared length of 1550 | * @returns {Number} squared length of a 1551 | */ 1552 | vec4.squaredLength = function (a) { 1553 | var x = a[0], 1554 | y = a[1], 1555 | z = a[2], 1556 | w = a[3]; 1557 | return x*x + y*y + z*z + w*w; 1558 | }; 1559 | 1560 | /** 1561 | * Alias for {@link vec4.squaredLength} 1562 | * @function 1563 | */ 1564 | vec4.sqrLen = vec4.squaredLength; 1565 | 1566 | /** 1567 | * Negates the components of a vec4 1568 | * 1569 | * @param {vec4} out the receiving vector 1570 | * @param {vec4} a vector to negate 1571 | * @returns {vec4} out 1572 | */ 1573 | vec4.negate = function(out, a) { 1574 | out[0] = -a[0]; 1575 | out[1] = -a[1]; 1576 | out[2] = -a[2]; 1577 | out[3] = -a[3]; 1578 | return out; 1579 | }; 1580 | 1581 | /** 1582 | * Normalize a vec4 1583 | * 1584 | * @param {vec4} out the receiving vector 1585 | * @param {vec4} a vector to normalize 1586 | * @returns {vec4} out 1587 | */ 1588 | vec4.normalize = function(out, a) { 1589 | var x = a[0], 1590 | y = a[1], 1591 | z = a[2], 1592 | w = a[3]; 1593 | var len = x*x + y*y + z*z + w*w; 1594 | if (len > 0) { 1595 | len = 1 / Math.sqrt(len); 1596 | out[0] = a[0] * len; 1597 | out[1] = a[1] * len; 1598 | out[2] = a[2] * len; 1599 | out[3] = a[3] * len; 1600 | } 1601 | return out; 1602 | }; 1603 | 1604 | /** 1605 | * Calculates the dot product of two vec4's 1606 | * 1607 | * @param {vec4} a the first operand 1608 | * @param {vec4} b the second operand 1609 | * @returns {Number} dot product of a and b 1610 | */ 1611 | vec4.dot = function (a, b) { 1612 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 1613 | }; 1614 | 1615 | /** 1616 | * Performs a linear interpolation between two vec4's 1617 | * 1618 | * @param {vec4} out the receiving vector 1619 | * @param {vec4} a the first operand 1620 | * @param {vec4} b the second operand 1621 | * @param {Number} t interpolation amount between the two inputs 1622 | * @returns {vec4} out 1623 | */ 1624 | vec4.lerp = function (out, a, b, t) { 1625 | var ax = a[0], 1626 | ay = a[1], 1627 | az = a[2], 1628 | aw = a[3]; 1629 | out[0] = ax + t * (b[0] - ax); 1630 | out[1] = ay + t * (b[1] - ay); 1631 | out[2] = az + t * (b[2] - az); 1632 | out[3] = aw + t * (b[3] - aw); 1633 | return out; 1634 | }; 1635 | 1636 | /** 1637 | * Transforms the vec4 with a mat4. 1638 | * 1639 | * @param {vec4} out the receiving vector 1640 | * @param {vec4} a the vector to transform 1641 | * @param {mat4} m matrix to transform with 1642 | * @returns {vec4} out 1643 | */ 1644 | vec4.transformMat4 = function(out, a, m) { 1645 | var x = a[0], y = a[1], z = a[2], w = a[3]; 1646 | out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; 1647 | out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; 1648 | out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; 1649 | out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; 1650 | return out; 1651 | }; 1652 | 1653 | /** 1654 | * Transforms the vec4 with a quat 1655 | * 1656 | * @param {vec4} out the receiving vector 1657 | * @param {vec4} a the vector to transform 1658 | * @param {quat} q quaternion to transform with 1659 | * @returns {vec4} out 1660 | */ 1661 | vec4.transformQuat = function(out, a, q) { 1662 | var x = a[0], y = a[1], z = a[2], 1663 | qx = q[0], qy = q[1], qz = q[2], qw = q[3], 1664 | 1665 | // calculate quat * vec 1666 | ix = qw * x + qy * z - qz * y, 1667 | iy = qw * y + qz * x - qx * z, 1668 | iz = qw * z + qx * y - qy * x, 1669 | iw = -qx * x - qy * y - qz * z; 1670 | 1671 | // calculate result * inverse quat 1672 | out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 1673 | out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 1674 | out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 1675 | return out; 1676 | }; 1677 | 1678 | /** 1679 | * Perform some operation over an array of vec4s. 1680 | * 1681 | * @param {Array} a the array of vectors to iterate over 1682 | * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed 1683 | * @param {Number} offset Number of elements to skip at the beginning of the array 1684 | * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array 1685 | * @param {Function} fn Function to call for each vector in the array 1686 | * @param {Object} [arg] additional argument to pass to fn 1687 | * @returns {Array} a 1688 | * @function 1689 | */ 1690 | vec4.forEach = (function() { 1691 | var vec = vec4.create(); 1692 | 1693 | return function(a, stride, offset, count, fn, arg) { 1694 | var i, l; 1695 | if(!stride) { 1696 | stride = 4; 1697 | } 1698 | 1699 | if(!offset) { 1700 | offset = 0; 1701 | } 1702 | 1703 | if(count) { 1704 | l = Math.min((count * stride) + offset, a.length); 1705 | } else { 1706 | l = a.length; 1707 | } 1708 | 1709 | for(i = offset; i < l; i += stride) { 1710 | vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; 1711 | fn(vec, vec, arg); 1712 | a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; 1713 | } 1714 | 1715 | return a; 1716 | }; 1717 | })(); 1718 | 1719 | /** 1720 | * Returns a string representation of a vector 1721 | * 1722 | * @param {vec4} vec vector to represent as a string 1723 | * @returns {String} string representation of the vector 1724 | */ 1725 | vec4.str = function (a) { 1726 | return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; 1727 | }; 1728 | 1729 | if(typeof(exports) !== 'undefined') { 1730 | exports.vec4 = vec4; 1731 | } 1732 | ; 1733 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 1734 | 1735 | Redistribution and use in source and binary forms, with or without modification, 1736 | are permitted provided that the following conditions are met: 1737 | 1738 | * Redistributions of source code must retain the above copyright notice, this 1739 | list of conditions and the following disclaimer. 1740 | * Redistributions in binary form must reproduce the above copyright notice, 1741 | this list of conditions and the following disclaimer in the documentation 1742 | and/or other materials provided with the distribution. 1743 | 1744 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1745 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1746 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1747 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 1748 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1749 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1750 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1751 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1752 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1753 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 1754 | 1755 | /** 1756 | * @class 2x2 Matrix 1757 | * @name mat2 1758 | */ 1759 | 1760 | var mat2 = {}; 1761 | 1762 | var mat2Identity = new Float32Array([ 1763 | 1, 0, 1764 | 0, 1 1765 | ]); 1766 | 1767 | /** 1768 | * Creates a new identity mat2 1769 | * 1770 | * @returns {mat2} a new 2x2 matrix 1771 | */ 1772 | mat2.create = function() { 1773 | var out = new GLMAT_ARRAY_TYPE(4); 1774 | out[0] = 1; 1775 | out[1] = 0; 1776 | out[2] = 0; 1777 | out[3] = 1; 1778 | return out; 1779 | }; 1780 | 1781 | /** 1782 | * Creates a new mat2 initialized with values from an existing matrix 1783 | * 1784 | * @param {mat2} a matrix to clone 1785 | * @returns {mat2} a new 2x2 matrix 1786 | */ 1787 | mat2.clone = function(a) { 1788 | var out = new GLMAT_ARRAY_TYPE(4); 1789 | out[0] = a[0]; 1790 | out[1] = a[1]; 1791 | out[2] = a[2]; 1792 | out[3] = a[3]; 1793 | return out; 1794 | }; 1795 | 1796 | /** 1797 | * Copy the values from one mat2 to another 1798 | * 1799 | * @param {mat2} out the receiving matrix 1800 | * @param {mat2} a the source matrix 1801 | * @returns {mat2} out 1802 | */ 1803 | mat2.copy = function(out, a) { 1804 | out[0] = a[0]; 1805 | out[1] = a[1]; 1806 | out[2] = a[2]; 1807 | out[3] = a[3]; 1808 | return out; 1809 | }; 1810 | 1811 | /** 1812 | * Set a mat2 to the identity matrix 1813 | * 1814 | * @param {mat2} out the receiving matrix 1815 | * @returns {mat2} out 1816 | */ 1817 | mat2.identity = function(out) { 1818 | out[0] = 1; 1819 | out[1] = 0; 1820 | out[2] = 0; 1821 | out[3] = 1; 1822 | return out; 1823 | }; 1824 | 1825 | /** 1826 | * Transpose the values of a mat2 1827 | * 1828 | * @param {mat2} out the receiving matrix 1829 | * @param {mat2} a the source matrix 1830 | * @returns {mat2} out 1831 | */ 1832 | mat2.transpose = function(out, a) { 1833 | // If we are transposing ourselves we can skip a few steps but have to cache some values 1834 | if (out === a) { 1835 | var a1 = a[1]; 1836 | out[1] = a[2]; 1837 | out[2] = a1; 1838 | } else { 1839 | out[0] = a[0]; 1840 | out[1] = a[2]; 1841 | out[2] = a[1]; 1842 | out[3] = a[3]; 1843 | } 1844 | 1845 | return out; 1846 | }; 1847 | 1848 | /** 1849 | * Inverts a mat2 1850 | * 1851 | * @param {mat2} out the receiving matrix 1852 | * @param {mat2} a the source matrix 1853 | * @returns {mat2} out 1854 | */ 1855 | mat2.invert = function(out, a) { 1856 | var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], 1857 | 1858 | // Calculate the determinant 1859 | det = a0 * a3 - a2 * a1; 1860 | 1861 | if (!det) { 1862 | return null; 1863 | } 1864 | det = 1.0 / det; 1865 | 1866 | out[0] = a3 * det; 1867 | out[1] = -a1 * det; 1868 | out[2] = -a2 * det; 1869 | out[3] = a0 * det; 1870 | 1871 | return out; 1872 | }; 1873 | 1874 | /** 1875 | * Calculates the adjugate of a mat2 1876 | * 1877 | * @param {mat2} out the receiving matrix 1878 | * @param {mat2} a the source matrix 1879 | * @returns {mat2} out 1880 | */ 1881 | mat2.adjoint = function(out, a) { 1882 | // Caching this value is nessecary if out == a 1883 | var a0 = a[0]; 1884 | out[0] = a[3]; 1885 | out[1] = -a[1]; 1886 | out[2] = -a[2]; 1887 | out[3] = a0; 1888 | 1889 | return out; 1890 | }; 1891 | 1892 | /** 1893 | * Calculates the determinant of a mat2 1894 | * 1895 | * @param {mat2} a the source matrix 1896 | * @returns {Number} determinant of a 1897 | */ 1898 | mat2.determinant = function (a) { 1899 | return a[0] * a[3] - a[2] * a[1]; 1900 | }; 1901 | 1902 | /** 1903 | * Multiplies two mat2's 1904 | * 1905 | * @param {mat2} out the receiving matrix 1906 | * @param {mat2} a the first operand 1907 | * @param {mat2} b the second operand 1908 | * @returns {mat2} out 1909 | */ 1910 | mat2.multiply = function (out, a, b) { 1911 | var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; 1912 | var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 1913 | out[0] = a0 * b0 + a1 * b2; 1914 | out[1] = a0 * b1 + a1 * b3; 1915 | out[2] = a2 * b0 + a3 * b2; 1916 | out[3] = a2 * b1 + a3 * b3; 1917 | return out; 1918 | }; 1919 | 1920 | /** 1921 | * Alias for {@link mat2.multiply} 1922 | * @function 1923 | */ 1924 | mat2.mul = mat2.multiply; 1925 | 1926 | /** 1927 | * Rotates a mat2 by the given angle 1928 | * 1929 | * @param {mat2} out the receiving matrix 1930 | * @param {mat2} a the matrix to rotate 1931 | * @param {Number} rad the angle to rotate the matrix by 1932 | * @returns {mat2} out 1933 | */ 1934 | mat2.rotate = function (out, a, rad) { 1935 | var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], 1936 | s = Math.sin(rad), 1937 | c = Math.cos(rad); 1938 | out[0] = a0 * c + a1 * s; 1939 | out[1] = a0 * -s + a1 * c; 1940 | out[2] = a2 * c + a3 * s; 1941 | out[3] = a2 * -s + a3 * c; 1942 | return out; 1943 | }; 1944 | 1945 | /** 1946 | * Scales the mat2 by the dimensions in the given vec2 1947 | * 1948 | * @param {mat2} out the receiving matrix 1949 | * @param {mat2} a the matrix to rotate 1950 | * @param {vec2} v the vec2 to scale the matrix by 1951 | * @returns {mat2} out 1952 | **/ 1953 | mat2.scale = function(out, a, v) { 1954 | var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], 1955 | v0 = v[0], v1 = v[1]; 1956 | out[0] = a0 * v0; 1957 | out[1] = a1 * v1; 1958 | out[2] = a2 * v0; 1959 | out[3] = a3 * v1; 1960 | return out; 1961 | }; 1962 | 1963 | /** 1964 | * Returns a string representation of a mat2 1965 | * 1966 | * @param {mat2} mat matrix to represent as a string 1967 | * @returns {String} string representation of the matrix 1968 | */ 1969 | mat2.str = function (a) { 1970 | return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; 1971 | }; 1972 | 1973 | if(typeof(exports) !== 'undefined') { 1974 | exports.mat2 = mat2; 1975 | } 1976 | ; 1977 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 1978 | 1979 | Redistribution and use in source and binary forms, with or without modification, 1980 | are permitted provided that the following conditions are met: 1981 | 1982 | * Redistributions of source code must retain the above copyright notice, this 1983 | list of conditions and the following disclaimer. 1984 | * Redistributions in binary form must reproduce the above copyright notice, 1985 | this list of conditions and the following disclaimer in the documentation 1986 | and/or other materials provided with the distribution. 1987 | 1988 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1989 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1990 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1991 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 1992 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1993 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1994 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1995 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1996 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1997 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 1998 | 1999 | /** 2000 | * @class 2x3 Matrix 2001 | * @name mat2d 2002 | * 2003 | * @description 2004 | * A mat2d contains six elements defined as: 2005 | *
2006 |  * [a, b,
2007 |  *  c, d,
2008 |  *  tx,ty]
2009 |  * 
2010 | * This is a short form for the 3x3 matrix: 2011 | *
2012 |  * [a, b, 0
2013 |  *  c, d, 0
2014 |  *  tx,ty,1]
2015 |  * 
2016 | * The last column is ignored so the array is shorter and operations are faster. 2017 | */ 2018 | 2019 | var mat2d = {}; 2020 | 2021 | var mat2dIdentity = new Float32Array([ 2022 | 1, 0, 2023 | 0, 1, 2024 | 0, 0 2025 | ]); 2026 | 2027 | /** 2028 | * Creates a new identity mat2d 2029 | * 2030 | * @returns {mat2d} a new 2x3 matrix 2031 | */ 2032 | mat2d.create = function() { 2033 | var out = new GLMAT_ARRAY_TYPE(6); 2034 | out[0] = 1; 2035 | out[1] = 0; 2036 | out[2] = 0; 2037 | out[3] = 1; 2038 | out[4] = 0; 2039 | out[5] = 0; 2040 | return out; 2041 | }; 2042 | 2043 | /** 2044 | * Creates a new mat2d initialized with values from an existing matrix 2045 | * 2046 | * @param {mat2d} a matrix to clone 2047 | * @returns {mat2d} a new 2x3 matrix 2048 | */ 2049 | mat2d.clone = function(a) { 2050 | var out = new GLMAT_ARRAY_TYPE(6); 2051 | out[0] = a[0]; 2052 | out[1] = a[1]; 2053 | out[2] = a[2]; 2054 | out[3] = a[3]; 2055 | out[4] = a[4]; 2056 | out[5] = a[5]; 2057 | return out; 2058 | }; 2059 | 2060 | /** 2061 | * Copy the values from one mat2d to another 2062 | * 2063 | * @param {mat2d} out the receiving matrix 2064 | * @param {mat2d} a the source matrix 2065 | * @returns {mat2d} out 2066 | */ 2067 | mat2d.copy = function(out, a) { 2068 | out[0] = a[0]; 2069 | out[1] = a[1]; 2070 | out[2] = a[2]; 2071 | out[3] = a[3]; 2072 | out[4] = a[4]; 2073 | out[5] = a[5]; 2074 | return out; 2075 | }; 2076 | 2077 | /** 2078 | * Set a mat2d to the identity matrix 2079 | * 2080 | * @param {mat2d} out the receiving matrix 2081 | * @returns {mat2d} out 2082 | */ 2083 | mat2d.identity = function(out) { 2084 | out[0] = 1; 2085 | out[1] = 0; 2086 | out[2] = 0; 2087 | out[3] = 1; 2088 | out[4] = 0; 2089 | out[5] = 0; 2090 | return out; 2091 | }; 2092 | 2093 | /** 2094 | * Inverts a mat2d 2095 | * 2096 | * @param {mat2d} out the receiving matrix 2097 | * @param {mat2d} a the source matrix 2098 | * @returns {mat2d} out 2099 | */ 2100 | mat2d.invert = function(out, a) { 2101 | var aa = a[0], ab = a[1], ac = a[2], ad = a[3], 2102 | atx = a[4], aty = a[5]; 2103 | 2104 | var det = aa * ad - ab * ac; 2105 | if(!det){ 2106 | return null; 2107 | } 2108 | det = 1.0 / det; 2109 | 2110 | out[0] = ad * det; 2111 | out[1] = -ab * det; 2112 | out[2] = -ac * det; 2113 | out[3] = aa * det; 2114 | out[4] = (ac * aty - ad * atx) * det; 2115 | out[5] = (ab * atx - aa * aty) * det; 2116 | return out; 2117 | }; 2118 | 2119 | /** 2120 | * Calculates the determinant of a mat2d 2121 | * 2122 | * @param {mat2d} a the source matrix 2123 | * @returns {Number} determinant of a 2124 | */ 2125 | mat2d.determinant = function (a) { 2126 | return a[0] * a[3] - a[1] * a[2]; 2127 | }; 2128 | 2129 | /** 2130 | * Multiplies two mat2d's 2131 | * 2132 | * @param {mat2d} out the receiving matrix 2133 | * @param {mat2d} a the first operand 2134 | * @param {mat2d} b the second operand 2135 | * @returns {mat2d} out 2136 | */ 2137 | mat2d.multiply = function (out, a, b) { 2138 | var aa = a[0], ab = a[1], ac = a[2], ad = a[3], 2139 | atx = a[4], aty = a[5], 2140 | ba = b[0], bb = b[1], bc = b[2], bd = b[3], 2141 | btx = b[4], bty = b[5]; 2142 | 2143 | out[0] = aa*ba + ab*bc; 2144 | out[1] = aa*bb + ab*bd; 2145 | out[2] = ac*ba + ad*bc; 2146 | out[3] = ac*bb + ad*bd; 2147 | out[4] = ba*atx + bc*aty + btx; 2148 | out[5] = bb*atx + bd*aty + bty; 2149 | return out; 2150 | }; 2151 | 2152 | /** 2153 | * Alias for {@link mat2d.multiply} 2154 | * @function 2155 | */ 2156 | mat2d.mul = mat2d.multiply; 2157 | 2158 | 2159 | /** 2160 | * Rotates a mat2d by the given angle 2161 | * 2162 | * @param {mat2d} out the receiving matrix 2163 | * @param {mat2d} a the matrix to rotate 2164 | * @param {Number} rad the angle to rotate the matrix by 2165 | * @returns {mat2d} out 2166 | */ 2167 | mat2d.rotate = function (out, a, rad) { 2168 | var aa = a[0], 2169 | ab = a[1], 2170 | ac = a[2], 2171 | ad = a[3], 2172 | atx = a[4], 2173 | aty = a[5], 2174 | st = Math.sin(rad), 2175 | ct = Math.cos(rad); 2176 | 2177 | out[0] = aa*ct + ab*st; 2178 | out[1] = -aa*st + ab*ct; 2179 | out[2] = ac*ct + ad*st; 2180 | out[3] = -ac*st + ct*ad; 2181 | out[4] = ct*atx + st*aty; 2182 | out[5] = ct*aty - st*atx; 2183 | return out; 2184 | }; 2185 | 2186 | /** 2187 | * Scales the mat2d by the dimensions in the given vec2 2188 | * 2189 | * @param {mat2d} out the receiving matrix 2190 | * @param {mat2d} a the matrix to translate 2191 | * @param {mat2d} v the vec2 to scale the matrix by 2192 | * @returns {mat2d} out 2193 | **/ 2194 | mat2d.scale = function(out, a, v) { 2195 | var vx = v[0], vy = v[1]; 2196 | out[0] = a[0] * vx; 2197 | out[1] = a[1] * vy; 2198 | out[2] = a[2] * vx; 2199 | out[3] = a[3] * vy; 2200 | out[4] = a[4] * vx; 2201 | out[5] = a[5] * vy; 2202 | return out; 2203 | }; 2204 | 2205 | /** 2206 | * Translates the mat2d by the dimensions in the given vec2 2207 | * 2208 | * @param {mat2d} out the receiving matrix 2209 | * @param {mat2d} a the matrix to translate 2210 | * @param {mat2d} v the vec2 to translate the matrix by 2211 | * @returns {mat2d} out 2212 | **/ 2213 | mat2d.translate = function(out, a, v) { 2214 | out[0] = a[0]; 2215 | out[1] = a[1]; 2216 | out[2] = a[2]; 2217 | out[3] = a[3]; 2218 | out[4] = a[4] + v[0]; 2219 | out[5] = a[5] + v[1]; 2220 | return out; 2221 | }; 2222 | 2223 | /** 2224 | * Returns a string representation of a mat2d 2225 | * 2226 | * @param {mat2d} a matrix to represent as a string 2227 | * @returns {String} string representation of the matrix 2228 | */ 2229 | mat2d.str = function (a) { 2230 | return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 2231 | a[3] + ', ' + a[4] + ', ' + a[5] + ')'; 2232 | }; 2233 | 2234 | if(typeof(exports) !== 'undefined') { 2235 | exports.mat2d = mat2d; 2236 | } 2237 | ; 2238 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2239 | 2240 | Redistribution and use in source and binary forms, with or without modification, 2241 | are permitted provided that the following conditions are met: 2242 | 2243 | * Redistributions of source code must retain the above copyright notice, this 2244 | list of conditions and the following disclaimer. 2245 | * Redistributions in binary form must reproduce the above copyright notice, 2246 | this list of conditions and the following disclaimer in the documentation 2247 | and/or other materials provided with the distribution. 2248 | 2249 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 2250 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2251 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2252 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 2253 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2254 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2255 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2256 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2257 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2258 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 2259 | 2260 | /** 2261 | * @class 3x3 Matrix 2262 | * @name mat3 2263 | */ 2264 | 2265 | var mat3 = {}; 2266 | 2267 | var mat3Identity = new Float32Array([ 2268 | 1, 0, 0, 2269 | 0, 1, 0, 2270 | 0, 0, 1 2271 | ]); 2272 | 2273 | /** 2274 | * Creates a new identity mat3 2275 | * 2276 | * @returns {mat3} a new 3x3 matrix 2277 | */ 2278 | mat3.create = function() { 2279 | var out = new GLMAT_ARRAY_TYPE(9); 2280 | out[0] = 1; 2281 | out[1] = 0; 2282 | out[2] = 0; 2283 | out[3] = 0; 2284 | out[4] = 1; 2285 | out[5] = 0; 2286 | out[6] = 0; 2287 | out[7] = 0; 2288 | out[8] = 1; 2289 | return out; 2290 | }; 2291 | 2292 | /** 2293 | * Creates a new mat3 initialized with values from an existing matrix 2294 | * 2295 | * @param {mat3} a matrix to clone 2296 | * @returns {mat3} a new 3x3 matrix 2297 | */ 2298 | mat3.clone = function(a) { 2299 | var out = new GLMAT_ARRAY_TYPE(9); 2300 | out[0] = a[0]; 2301 | out[1] = a[1]; 2302 | out[2] = a[2]; 2303 | out[3] = a[3]; 2304 | out[4] = a[4]; 2305 | out[5] = a[5]; 2306 | out[6] = a[6]; 2307 | out[7] = a[7]; 2308 | out[8] = a[8]; 2309 | return out; 2310 | }; 2311 | 2312 | /** 2313 | * Copy the values from one mat3 to another 2314 | * 2315 | * @param {mat3} out the receiving matrix 2316 | * @param {mat3} a the source matrix 2317 | * @returns {mat3} out 2318 | */ 2319 | mat3.copy = function(out, a) { 2320 | out[0] = a[0]; 2321 | out[1] = a[1]; 2322 | out[2] = a[2]; 2323 | out[3] = a[3]; 2324 | out[4] = a[4]; 2325 | out[5] = a[5]; 2326 | out[6] = a[6]; 2327 | out[7] = a[7]; 2328 | out[8] = a[8]; 2329 | return out; 2330 | }; 2331 | 2332 | /** 2333 | * Set a mat3 to the identity matrix 2334 | * 2335 | * @param {mat3} out the receiving matrix 2336 | * @returns {mat3} out 2337 | */ 2338 | mat3.identity = function(out) { 2339 | out[0] = 1; 2340 | out[1] = 0; 2341 | out[2] = 0; 2342 | out[3] = 0; 2343 | out[4] = 1; 2344 | out[5] = 0; 2345 | out[6] = 0; 2346 | out[7] = 0; 2347 | out[8] = 1; 2348 | return out; 2349 | }; 2350 | 2351 | /** 2352 | * Transpose the values of a mat3 2353 | * 2354 | * @param {mat3} out the receiving matrix 2355 | * @param {mat3} a the source matrix 2356 | * @returns {mat3} out 2357 | */ 2358 | mat3.transpose = function(out, a) { 2359 | // If we are transposing ourselves we can skip a few steps but have to cache some values 2360 | if (out === a) { 2361 | var a01 = a[1], a02 = a[2], a12 = a[5]; 2362 | out[1] = a[3]; 2363 | out[2] = a[6]; 2364 | out[3] = a01; 2365 | out[5] = a[7]; 2366 | out[6] = a02; 2367 | out[7] = a12; 2368 | } else { 2369 | out[0] = a[0]; 2370 | out[1] = a[3]; 2371 | out[2] = a[6]; 2372 | out[3] = a[1]; 2373 | out[4] = a[4]; 2374 | out[5] = a[7]; 2375 | out[6] = a[2]; 2376 | out[7] = a[5]; 2377 | out[8] = a[8]; 2378 | } 2379 | 2380 | return out; 2381 | }; 2382 | 2383 | /** 2384 | * Inverts a mat3 2385 | * 2386 | * @param {mat3} out the receiving matrix 2387 | * @param {mat3} a the source matrix 2388 | * @returns {mat3} out 2389 | */ 2390 | mat3.invert = function(out, a) { 2391 | var a00 = a[0], a01 = a[1], a02 = a[2], 2392 | a10 = a[3], a11 = a[4], a12 = a[5], 2393 | a20 = a[6], a21 = a[7], a22 = a[8], 2394 | 2395 | b01 = a22 * a11 - a12 * a21, 2396 | b11 = -a22 * a10 + a12 * a20, 2397 | b21 = a21 * a10 - a11 * a20, 2398 | 2399 | // Calculate the determinant 2400 | det = a00 * b01 + a01 * b11 + a02 * b21; 2401 | 2402 | if (!det) { 2403 | return null; 2404 | } 2405 | det = 1.0 / det; 2406 | 2407 | out[0] = b01 * det; 2408 | out[1] = (-a22 * a01 + a02 * a21) * det; 2409 | out[2] = (a12 * a01 - a02 * a11) * det; 2410 | out[3] = b11 * det; 2411 | out[4] = (a22 * a00 - a02 * a20) * det; 2412 | out[5] = (-a12 * a00 + a02 * a10) * det; 2413 | out[6] = b21 * det; 2414 | out[7] = (-a21 * a00 + a01 * a20) * det; 2415 | out[8] = (a11 * a00 - a01 * a10) * det; 2416 | return out; 2417 | }; 2418 | 2419 | /** 2420 | * Calculates the adjugate of a mat3 2421 | * 2422 | * @param {mat3} out the receiving matrix 2423 | * @param {mat3} a the source matrix 2424 | * @returns {mat3} out 2425 | */ 2426 | mat3.adjoint = function(out, a) { 2427 | var a00 = a[0], a01 = a[1], a02 = a[2], 2428 | a10 = a[3], a11 = a[4], a12 = a[5], 2429 | a20 = a[6], a21 = a[7], a22 = a[8]; 2430 | 2431 | out[0] = (a11 * a22 - a12 * a21); 2432 | out[1] = (a02 * a21 - a01 * a22); 2433 | out[2] = (a01 * a12 - a02 * a11); 2434 | out[3] = (a12 * a20 - a10 * a22); 2435 | out[4] = (a00 * a22 - a02 * a20); 2436 | out[5] = (a02 * a10 - a00 * a12); 2437 | out[6] = (a10 * a21 - a11 * a20); 2438 | out[7] = (a01 * a20 - a00 * a21); 2439 | out[8] = (a00 * a11 - a01 * a10); 2440 | return out; 2441 | }; 2442 | 2443 | /** 2444 | * Calculates the determinant of a mat3 2445 | * 2446 | * @param {mat3} a the source matrix 2447 | * @returns {Number} determinant of a 2448 | */ 2449 | mat3.determinant = function (a) { 2450 | var a00 = a[0], a01 = a[1], a02 = a[2], 2451 | a10 = a[3], a11 = a[4], a12 = a[5], 2452 | a20 = a[6], a21 = a[7], a22 = a[8]; 2453 | 2454 | return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); 2455 | }; 2456 | 2457 | /** 2458 | * Multiplies two mat3's 2459 | * 2460 | * @param {mat3} out the receiving matrix 2461 | * @param {mat3} a the first operand 2462 | * @param {mat3} b the second operand 2463 | * @returns {mat3} out 2464 | */ 2465 | mat3.multiply = function (out, a, b) { 2466 | var a00 = a[0], a01 = a[1], a02 = a[2], 2467 | a10 = a[3], a11 = a[4], a12 = a[5], 2468 | a20 = a[6], a21 = a[7], a22 = a[8], 2469 | 2470 | b00 = b[0], b01 = b[1], b02 = b[2], 2471 | b10 = b[3], b11 = b[4], b12 = b[5], 2472 | b20 = b[6], b21 = b[7], b22 = b[8]; 2473 | 2474 | out[0] = b00 * a00 + b01 * a10 + b02 * a20; 2475 | out[1] = b00 * a01 + b01 * a11 + b02 * a21; 2476 | out[2] = b00 * a02 + b01 * a12 + b02 * a22; 2477 | 2478 | out[3] = b10 * a00 + b11 * a10 + b12 * a20; 2479 | out[4] = b10 * a01 + b11 * a11 + b12 * a21; 2480 | out[5] = b10 * a02 + b11 * a12 + b12 * a22; 2481 | 2482 | out[6] = b20 * a00 + b21 * a10 + b22 * a20; 2483 | out[7] = b20 * a01 + b21 * a11 + b22 * a21; 2484 | out[8] = b20 * a02 + b21 * a12 + b22 * a22; 2485 | return out; 2486 | }; 2487 | 2488 | /** 2489 | * Alias for {@link mat3.multiply} 2490 | * @function 2491 | */ 2492 | mat3.mul = mat3.multiply; 2493 | 2494 | /** 2495 | * Translate a mat3 by the given vector 2496 | * 2497 | * @param {mat3} out the receiving matrix 2498 | * @param {mat3} a the matrix to translate 2499 | * @param {vec2} v vector to translate by 2500 | * @returns {mat3} out 2501 | */ 2502 | mat3.translate = function(out, a, v) { 2503 | var a00 = a[0], a01 = a[1], a02 = a[2], 2504 | a10 = a[3], a11 = a[4], a12 = a[5], 2505 | a20 = a[6], a21 = a[7], a22 = a[8], 2506 | x = v[0], y = v[1]; 2507 | 2508 | out[0] = a00; 2509 | out[1] = a01; 2510 | out[2] = a02; 2511 | 2512 | out[3] = a10; 2513 | out[4] = a11; 2514 | out[5] = a12; 2515 | 2516 | out[6] = x * a00 + y * a10 + a20; 2517 | out[7] = x * a01 + y * a11 + a21; 2518 | out[8] = x * a02 + y * a12 + a22; 2519 | return out; 2520 | }; 2521 | 2522 | /** 2523 | * Rotates a mat3 by the given angle 2524 | * 2525 | * @param {mat3} out the receiving matrix 2526 | * @param {mat3} a the matrix to rotate 2527 | * @param {Number} rad the angle to rotate the matrix by 2528 | * @returns {mat3} out 2529 | */ 2530 | mat3.rotate = function (out, a, rad) { 2531 | var a00 = a[0], a01 = a[1], a02 = a[2], 2532 | a10 = a[3], a11 = a[4], a12 = a[5], 2533 | a20 = a[6], a21 = a[7], a22 = a[8], 2534 | 2535 | s = Math.sin(rad), 2536 | c = Math.cos(rad); 2537 | 2538 | out[0] = c * a00 + s * a10; 2539 | out[1] = c * a01 + s * a11; 2540 | out[2] = c * a02 + s * a12; 2541 | 2542 | out[3] = c * a10 - s * a00; 2543 | out[4] = c * a11 - s * a01; 2544 | out[5] = c * a12 - s * a02; 2545 | 2546 | out[6] = a20; 2547 | out[7] = a21; 2548 | out[8] = a22; 2549 | return out; 2550 | }; 2551 | 2552 | /** 2553 | * Scales the mat3 by the dimensions in the given vec2 2554 | * 2555 | * @param {mat3} out the receiving matrix 2556 | * @param {mat3} a the matrix to rotate 2557 | * @param {vec2} v the vec2 to scale the matrix by 2558 | * @returns {mat3} out 2559 | **/ 2560 | mat3.scale = function(out, a, v) { 2561 | var x = v[0], y = v[2]; 2562 | 2563 | out[0] = x * a[0]; 2564 | out[1] = x * a[1]; 2565 | out[2] = x * a[2]; 2566 | 2567 | out[3] = y * a[3]; 2568 | out[4] = y * a[4]; 2569 | out[5] = y * a[5]; 2570 | 2571 | out[6] = a[6]; 2572 | out[7] = a[7]; 2573 | out[8] = a[8]; 2574 | return out; 2575 | }; 2576 | 2577 | /** 2578 | * Copies the values from a mat2d into a mat3 2579 | * 2580 | * @param {mat3} out the receiving matrix 2581 | * @param {mat3} a the matrix to rotate 2582 | * @param {vec2} v the vec2 to scale the matrix by 2583 | * @returns {mat3} out 2584 | **/ 2585 | mat3.fromMat2d = function(out, a) { 2586 | out[0] = a[0]; 2587 | out[1] = a[1]; 2588 | out[2] = 0; 2589 | 2590 | out[3] = a[2]; 2591 | out[4] = a[3]; 2592 | out[5] = 0; 2593 | 2594 | out[6] = a[4]; 2595 | out[7] = a[5]; 2596 | out[8] = 1; 2597 | return out; 2598 | }; 2599 | 2600 | /** 2601 | * Calculates a 3x3 matrix from the given quaternion 2602 | * 2603 | * @param {mat3} out mat3 receiving operation result 2604 | * @param {quat} q Quaternion to create matrix from 2605 | * 2606 | * @returns {mat3} out 2607 | */ 2608 | mat3.fromQuat = function (out, q) { 2609 | var x = q[0], y = q[1], z = q[2], w = q[3], 2610 | x2 = x + x, 2611 | y2 = y + y, 2612 | z2 = z + z, 2613 | 2614 | xx = x * x2, 2615 | xy = x * y2, 2616 | xz = x * z2, 2617 | yy = y * y2, 2618 | yz = y * z2, 2619 | zz = z * z2, 2620 | wx = w * x2, 2621 | wy = w * y2, 2622 | wz = w * z2; 2623 | 2624 | out[0] = 1 - (yy + zz); 2625 | out[1] = xy + wz; 2626 | out[2] = xz - wy; 2627 | 2628 | out[3] = xy - wz; 2629 | out[4] = 1 - (xx + zz); 2630 | out[5] = yz + wx; 2631 | 2632 | out[6] = xz + wy; 2633 | out[7] = yz - wx; 2634 | out[8] = 1 - (xx + yy); 2635 | 2636 | return out; 2637 | }; 2638 | 2639 | /** 2640 | * Returns a string representation of a mat3 2641 | * 2642 | * @param {mat3} mat matrix to represent as a string 2643 | * @returns {String} string representation of the matrix 2644 | */ 2645 | mat3.str = function (a) { 2646 | return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 2647 | a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + 2648 | a[6] + ', ' + a[7] + ', ' + a[8] + ')'; 2649 | }; 2650 | 2651 | if(typeof(exports) !== 'undefined') { 2652 | exports.mat3 = mat3; 2653 | } 2654 | ; 2655 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2656 | 2657 | Redistribution and use in source and binary forms, with or without modification, 2658 | are permitted provided that the following conditions are met: 2659 | 2660 | * Redistributions of source code must retain the above copyright notice, this 2661 | list of conditions and the following disclaimer. 2662 | * Redistributions in binary form must reproduce the above copyright notice, 2663 | this list of conditions and the following disclaimer in the documentation 2664 | and/or other materials provided with the distribution. 2665 | 2666 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 2667 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2668 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2669 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 2670 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2671 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2672 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2673 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2674 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2675 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 2676 | 2677 | /** 2678 | * @class 4x4 Matrix 2679 | * @name mat4 2680 | */ 2681 | 2682 | var mat4 = {}; 2683 | 2684 | var mat4Identity = new Float32Array([ 2685 | 1, 0, 0, 0, 2686 | 0, 1, 0, 0, 2687 | 0, 0, 1, 0, 2688 | 0, 0, 0, 1 2689 | ]); 2690 | 2691 | /** 2692 | * Creates a new identity mat4 2693 | * 2694 | * @returns {mat4} a new 4x4 matrix 2695 | */ 2696 | mat4.create = function() { 2697 | var out = new GLMAT_ARRAY_TYPE(16); 2698 | out[0] = 1; 2699 | out[1] = 0; 2700 | out[2] = 0; 2701 | out[3] = 0; 2702 | out[4] = 0; 2703 | out[5] = 1; 2704 | out[6] = 0; 2705 | out[7] = 0; 2706 | out[8] = 0; 2707 | out[9] = 0; 2708 | out[10] = 1; 2709 | out[11] = 0; 2710 | out[12] = 0; 2711 | out[13] = 0; 2712 | out[14] = 0; 2713 | out[15] = 1; 2714 | return out; 2715 | }; 2716 | 2717 | /** 2718 | * Creates a new mat4 initialized with values from an existing matrix 2719 | * 2720 | * @param {mat4} a matrix to clone 2721 | * @returns {mat4} a new 4x4 matrix 2722 | */ 2723 | mat4.clone = function(a) { 2724 | var out = new GLMAT_ARRAY_TYPE(16); 2725 | out[0] = a[0]; 2726 | out[1] = a[1]; 2727 | out[2] = a[2]; 2728 | out[3] = a[3]; 2729 | out[4] = a[4]; 2730 | out[5] = a[5]; 2731 | out[6] = a[6]; 2732 | out[7] = a[7]; 2733 | out[8] = a[8]; 2734 | out[9] = a[9]; 2735 | out[10] = a[10]; 2736 | out[11] = a[11]; 2737 | out[12] = a[12]; 2738 | out[13] = a[13]; 2739 | out[14] = a[14]; 2740 | out[15] = a[15]; 2741 | return out; 2742 | }; 2743 | 2744 | /** 2745 | * Copy the values from one mat4 to another 2746 | * 2747 | * @param {mat4} out the receiving matrix 2748 | * @param {mat4} a the source matrix 2749 | * @returns {mat4} out 2750 | */ 2751 | mat4.copy = function(out, a) { 2752 | out[0] = a[0]; 2753 | out[1] = a[1]; 2754 | out[2] = a[2]; 2755 | out[3] = a[3]; 2756 | out[4] = a[4]; 2757 | out[5] = a[5]; 2758 | out[6] = a[6]; 2759 | out[7] = a[7]; 2760 | out[8] = a[8]; 2761 | out[9] = a[9]; 2762 | out[10] = a[10]; 2763 | out[11] = a[11]; 2764 | out[12] = a[12]; 2765 | out[13] = a[13]; 2766 | out[14] = a[14]; 2767 | out[15] = a[15]; 2768 | return out; 2769 | }; 2770 | 2771 | /** 2772 | * Set a mat4 to the identity matrix 2773 | * 2774 | * @param {mat4} out the receiving matrix 2775 | * @returns {mat4} out 2776 | */ 2777 | mat4.identity = function(out) { 2778 | out[0] = 1; 2779 | out[1] = 0; 2780 | out[2] = 0; 2781 | out[3] = 0; 2782 | out[4] = 0; 2783 | out[5] = 1; 2784 | out[6] = 0; 2785 | out[7] = 0; 2786 | out[8] = 0; 2787 | out[9] = 0; 2788 | out[10] = 1; 2789 | out[11] = 0; 2790 | out[12] = 0; 2791 | out[13] = 0; 2792 | out[14] = 0; 2793 | out[15] = 1; 2794 | return out; 2795 | }; 2796 | 2797 | /** 2798 | * Transpose the values of a mat4 2799 | * 2800 | * @param {mat4} out the receiving matrix 2801 | * @param {mat4} a the source matrix 2802 | * @returns {mat4} out 2803 | */ 2804 | mat4.transpose = function(out, a) { 2805 | // If we are transposing ourselves we can skip a few steps but have to cache some values 2806 | if (out === a) { 2807 | var a01 = a[1], a02 = a[2], a03 = a[3], 2808 | a12 = a[6], a13 = a[7], 2809 | a23 = a[11]; 2810 | 2811 | out[1] = a[4]; 2812 | out[2] = a[8]; 2813 | out[3] = a[12]; 2814 | out[4] = a01; 2815 | out[6] = a[9]; 2816 | out[7] = a[13]; 2817 | out[8] = a02; 2818 | out[9] = a12; 2819 | out[11] = a[14]; 2820 | out[12] = a03; 2821 | out[13] = a13; 2822 | out[14] = a23; 2823 | } else { 2824 | out[0] = a[0]; 2825 | out[1] = a[4]; 2826 | out[2] = a[8]; 2827 | out[3] = a[12]; 2828 | out[4] = a[1]; 2829 | out[5] = a[5]; 2830 | out[6] = a[9]; 2831 | out[7] = a[13]; 2832 | out[8] = a[2]; 2833 | out[9] = a[6]; 2834 | out[10] = a[10]; 2835 | out[11] = a[14]; 2836 | out[12] = a[3]; 2837 | out[13] = a[7]; 2838 | out[14] = a[11]; 2839 | out[15] = a[15]; 2840 | } 2841 | 2842 | return out; 2843 | }; 2844 | 2845 | /** 2846 | * Inverts a mat4 2847 | * 2848 | * @param {mat4} out the receiving matrix 2849 | * @param {mat4} a the source matrix 2850 | * @returns {mat4} out 2851 | */ 2852 | mat4.invert = function(out, a) { 2853 | var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 2854 | a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 2855 | a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 2856 | a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], 2857 | 2858 | b00 = a00 * a11 - a01 * a10, 2859 | b01 = a00 * a12 - a02 * a10, 2860 | b02 = a00 * a13 - a03 * a10, 2861 | b03 = a01 * a12 - a02 * a11, 2862 | b04 = a01 * a13 - a03 * a11, 2863 | b05 = a02 * a13 - a03 * a12, 2864 | b06 = a20 * a31 - a21 * a30, 2865 | b07 = a20 * a32 - a22 * a30, 2866 | b08 = a20 * a33 - a23 * a30, 2867 | b09 = a21 * a32 - a22 * a31, 2868 | b10 = a21 * a33 - a23 * a31, 2869 | b11 = a22 * a33 - a23 * a32, 2870 | 2871 | // Calculate the determinant 2872 | det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 2873 | 2874 | if (!det) { 2875 | return null; 2876 | } 2877 | det = 1.0 / det; 2878 | 2879 | out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 2880 | out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 2881 | out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 2882 | out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 2883 | out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 2884 | out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 2885 | out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 2886 | out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 2887 | out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 2888 | out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 2889 | out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 2890 | out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 2891 | out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 2892 | out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 2893 | out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 2894 | out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 2895 | 2896 | return out; 2897 | }; 2898 | 2899 | /** 2900 | * Calculates the adjugate of a mat4 2901 | * 2902 | * @param {mat4} out the receiving matrix 2903 | * @param {mat4} a the source matrix 2904 | * @returns {mat4} out 2905 | */ 2906 | mat4.adjoint = function(out, a) { 2907 | var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 2908 | a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 2909 | a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 2910 | a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 2911 | 2912 | out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); 2913 | out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); 2914 | out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); 2915 | out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); 2916 | out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); 2917 | out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); 2918 | out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); 2919 | out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); 2920 | out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); 2921 | out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); 2922 | out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); 2923 | out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); 2924 | out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); 2925 | out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); 2926 | out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); 2927 | out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); 2928 | return out; 2929 | }; 2930 | 2931 | /** 2932 | * Calculates the determinant of a mat4 2933 | * 2934 | * @param {mat4} a the source matrix 2935 | * @returns {Number} determinant of a 2936 | */ 2937 | mat4.determinant = function (a) { 2938 | var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 2939 | a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 2940 | a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 2941 | a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], 2942 | 2943 | b00 = a00 * a11 - a01 * a10, 2944 | b01 = a00 * a12 - a02 * a10, 2945 | b02 = a00 * a13 - a03 * a10, 2946 | b03 = a01 * a12 - a02 * a11, 2947 | b04 = a01 * a13 - a03 * a11, 2948 | b05 = a02 * a13 - a03 * a12, 2949 | b06 = a20 * a31 - a21 * a30, 2950 | b07 = a20 * a32 - a22 * a30, 2951 | b08 = a20 * a33 - a23 * a30, 2952 | b09 = a21 * a32 - a22 * a31, 2953 | b10 = a21 * a33 - a23 * a31, 2954 | b11 = a22 * a33 - a23 * a32; 2955 | 2956 | // Calculate the determinant 2957 | return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 2958 | }; 2959 | 2960 | /** 2961 | * Multiplies two mat4's 2962 | * 2963 | * @param {mat4} out the receiving matrix 2964 | * @param {mat4} a the first operand 2965 | * @param {mat4} b the second operand 2966 | * @returns {mat4} out 2967 | */ 2968 | mat4.multiply = function (out, a, b) { 2969 | var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 2970 | a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 2971 | a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 2972 | a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 2973 | 2974 | // Cache only the current line of the second matrix 2975 | var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 2976 | out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 2977 | out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 2978 | out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 2979 | out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 2980 | 2981 | b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; 2982 | out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 2983 | out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 2984 | out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 2985 | out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 2986 | 2987 | b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; 2988 | out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 2989 | out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 2990 | out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 2991 | out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 2992 | 2993 | b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; 2994 | out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 2995 | out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 2996 | out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 2997 | out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 2998 | return out; 2999 | }; 3000 | 3001 | /** 3002 | * Alias for {@link mat4.multiply} 3003 | * @function 3004 | */ 3005 | mat4.mul = mat4.multiply; 3006 | 3007 | /** 3008 | * Translate a mat4 by the given vector 3009 | * 3010 | * @param {mat4} out the receiving matrix 3011 | * @param {mat4} a the matrix to translate 3012 | * @param {vec3} v vector to translate by 3013 | * @returns {mat4} out 3014 | */ 3015 | mat4.translate = function (out, a, v) { 3016 | var x = v[0], y = v[1], z = v[2], 3017 | a00, a01, a02, a03, 3018 | a10, a11, a12, a13, 3019 | a20, a21, a22, a23; 3020 | 3021 | if (a === out) { 3022 | out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 3023 | out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 3024 | out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 3025 | out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 3026 | } else { 3027 | a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 3028 | a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 3029 | a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 3030 | 3031 | out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; 3032 | out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; 3033 | out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; 3034 | 3035 | out[12] = a00 * x + a10 * y + a20 * z + a[12]; 3036 | out[13] = a01 * x + a11 * y + a21 * z + a[13]; 3037 | out[14] = a02 * x + a12 * y + a22 * z + a[14]; 3038 | out[15] = a03 * x + a13 * y + a23 * z + a[15]; 3039 | } 3040 | 3041 | return out; 3042 | }; 3043 | 3044 | /** 3045 | * Scales the mat4 by the dimensions in the given vec3 3046 | * 3047 | * @param {mat4} out the receiving matrix 3048 | * @param {mat4} a the matrix to scale 3049 | * @param {vec3} v the vec3 to scale the matrix by 3050 | * @returns {mat4} out 3051 | **/ 3052 | mat4.scale = function(out, a, v) { 3053 | var x = v[0], y = v[1], z = v[2]; 3054 | 3055 | out[0] = a[0] * x; 3056 | out[1] = a[1] * x; 3057 | out[2] = a[2] * x; 3058 | out[3] = a[3] * x; 3059 | out[4] = a[4] * y; 3060 | out[5] = a[5] * y; 3061 | out[6] = a[6] * y; 3062 | out[7] = a[7] * y; 3063 | out[8] = a[8] * z; 3064 | out[9] = a[9] * z; 3065 | out[10] = a[10] * z; 3066 | out[11] = a[11] * z; 3067 | out[12] = a[12]; 3068 | out[13] = a[13]; 3069 | out[14] = a[14]; 3070 | out[15] = a[15]; 3071 | return out; 3072 | }; 3073 | 3074 | /** 3075 | * Rotates a mat4 by the given angle 3076 | * 3077 | * @param {mat4} out the receiving matrix 3078 | * @param {mat4} a the matrix to rotate 3079 | * @param {Number} rad the angle to rotate the matrix by 3080 | * @param {vec3} axis the axis to rotate around 3081 | * @returns {mat4} out 3082 | */ 3083 | mat4.rotate = function (out, a, rad, axis) { 3084 | var x = axis[0], y = axis[1], z = axis[2], 3085 | len = Math.sqrt(x * x + y * y + z * z), 3086 | s, c, t, 3087 | a00, a01, a02, a03, 3088 | a10, a11, a12, a13, 3089 | a20, a21, a22, a23, 3090 | b00, b01, b02, 3091 | b10, b11, b12, 3092 | b20, b21, b22; 3093 | 3094 | if (Math.abs(len) < GLMAT_EPSILON) { return null; } 3095 | 3096 | len = 1 / len; 3097 | x *= len; 3098 | y *= len; 3099 | z *= len; 3100 | 3101 | s = Math.sin(rad); 3102 | c = Math.cos(rad); 3103 | t = 1 - c; 3104 | 3105 | a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 3106 | a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 3107 | a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 3108 | 3109 | // Construct the elements of the rotation matrix 3110 | b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; 3111 | b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; 3112 | b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; 3113 | 3114 | // Perform rotation-specific matrix multiplication 3115 | out[0] = a00 * b00 + a10 * b01 + a20 * b02; 3116 | out[1] = a01 * b00 + a11 * b01 + a21 * b02; 3117 | out[2] = a02 * b00 + a12 * b01 + a22 * b02; 3118 | out[3] = a03 * b00 + a13 * b01 + a23 * b02; 3119 | out[4] = a00 * b10 + a10 * b11 + a20 * b12; 3120 | out[5] = a01 * b10 + a11 * b11 + a21 * b12; 3121 | out[6] = a02 * b10 + a12 * b11 + a22 * b12; 3122 | out[7] = a03 * b10 + a13 * b11 + a23 * b12; 3123 | out[8] = a00 * b20 + a10 * b21 + a20 * b22; 3124 | out[9] = a01 * b20 + a11 * b21 + a21 * b22; 3125 | out[10] = a02 * b20 + a12 * b21 + a22 * b22; 3126 | out[11] = a03 * b20 + a13 * b21 + a23 * b22; 3127 | 3128 | if (a !== out) { // If the source and destination differ, copy the unchanged last row 3129 | out[12] = a[12]; 3130 | out[13] = a[13]; 3131 | out[14] = a[14]; 3132 | out[15] = a[15]; 3133 | } 3134 | return out; 3135 | }; 3136 | 3137 | /** 3138 | * Rotates a matrix by the given angle around the X axis 3139 | * 3140 | * @param {mat4} out the receiving matrix 3141 | * @param {mat4} a the matrix to rotate 3142 | * @param {Number} rad the angle to rotate the matrix by 3143 | * @returns {mat4} out 3144 | */ 3145 | mat4.rotateX = function (out, a, rad) { 3146 | var s = Math.sin(rad), 3147 | c = Math.cos(rad), 3148 | a10 = a[4], 3149 | a11 = a[5], 3150 | a12 = a[6], 3151 | a13 = a[7], 3152 | a20 = a[8], 3153 | a21 = a[9], 3154 | a22 = a[10], 3155 | a23 = a[11]; 3156 | 3157 | if (a !== out) { // If the source and destination differ, copy the unchanged rows 3158 | out[0] = a[0]; 3159 | out[1] = a[1]; 3160 | out[2] = a[2]; 3161 | out[3] = a[3]; 3162 | out[12] = a[12]; 3163 | out[13] = a[13]; 3164 | out[14] = a[14]; 3165 | out[15] = a[15]; 3166 | } 3167 | 3168 | // Perform axis-specific matrix multiplication 3169 | out[4] = a10 * c + a20 * s; 3170 | out[5] = a11 * c + a21 * s; 3171 | out[6] = a12 * c + a22 * s; 3172 | out[7] = a13 * c + a23 * s; 3173 | out[8] = a20 * c - a10 * s; 3174 | out[9] = a21 * c - a11 * s; 3175 | out[10] = a22 * c - a12 * s; 3176 | out[11] = a23 * c - a13 * s; 3177 | return out; 3178 | }; 3179 | 3180 | /** 3181 | * Rotates a matrix by the given angle around the Y axis 3182 | * 3183 | * @param {mat4} out the receiving matrix 3184 | * @param {mat4} a the matrix to rotate 3185 | * @param {Number} rad the angle to rotate the matrix by 3186 | * @returns {mat4} out 3187 | */ 3188 | mat4.rotateY = function (out, a, rad) { 3189 | var s = Math.sin(rad), 3190 | c = Math.cos(rad), 3191 | a00 = a[0], 3192 | a01 = a[1], 3193 | a02 = a[2], 3194 | a03 = a[3], 3195 | a20 = a[8], 3196 | a21 = a[9], 3197 | a22 = a[10], 3198 | a23 = a[11]; 3199 | 3200 | if (a !== out) { // If the source and destination differ, copy the unchanged rows 3201 | out[4] = a[4]; 3202 | out[5] = a[5]; 3203 | out[6] = a[6]; 3204 | out[7] = a[7]; 3205 | out[12] = a[12]; 3206 | out[13] = a[13]; 3207 | out[14] = a[14]; 3208 | out[15] = a[15]; 3209 | } 3210 | 3211 | // Perform axis-specific matrix multiplication 3212 | out[0] = a00 * c - a20 * s; 3213 | out[1] = a01 * c - a21 * s; 3214 | out[2] = a02 * c - a22 * s; 3215 | out[3] = a03 * c - a23 * s; 3216 | out[8] = a00 * s + a20 * c; 3217 | out[9] = a01 * s + a21 * c; 3218 | out[10] = a02 * s + a22 * c; 3219 | out[11] = a03 * s + a23 * c; 3220 | return out; 3221 | }; 3222 | 3223 | /** 3224 | * Rotates a matrix by the given angle around the Z axis 3225 | * 3226 | * @param {mat4} out the receiving matrix 3227 | * @param {mat4} a the matrix to rotate 3228 | * @param {Number} rad the angle to rotate the matrix by 3229 | * @returns {mat4} out 3230 | */ 3231 | mat4.rotateZ = function (out, a, rad) { 3232 | var s = Math.sin(rad), 3233 | c = Math.cos(rad), 3234 | a00 = a[0], 3235 | a01 = a[1], 3236 | a02 = a[2], 3237 | a03 = a[3], 3238 | a10 = a[4], 3239 | a11 = a[5], 3240 | a12 = a[6], 3241 | a13 = a[7]; 3242 | 3243 | if (a !== out) { // If the source and destination differ, copy the unchanged last row 3244 | out[8] = a[8]; 3245 | out[9] = a[9]; 3246 | out[10] = a[10]; 3247 | out[11] = a[11]; 3248 | out[12] = a[12]; 3249 | out[13] = a[13]; 3250 | out[14] = a[14]; 3251 | out[15] = a[15]; 3252 | } 3253 | 3254 | // Perform axis-specific matrix multiplication 3255 | out[0] = a00 * c + a10 * s; 3256 | out[1] = a01 * c + a11 * s; 3257 | out[2] = a02 * c + a12 * s; 3258 | out[3] = a03 * c + a13 * s; 3259 | out[4] = a10 * c - a00 * s; 3260 | out[5] = a11 * c - a01 * s; 3261 | out[6] = a12 * c - a02 * s; 3262 | out[7] = a13 * c - a03 * s; 3263 | return out; 3264 | }; 3265 | 3266 | /** 3267 | * Creates a matrix from a quaternion rotation and vector translation 3268 | * This is equivalent to (but much faster than): 3269 | * 3270 | * mat4.identity(dest); 3271 | * mat4.translate(dest, vec); 3272 | * var quatMat = mat4.create(); 3273 | * quat4.toMat4(quat, quatMat); 3274 | * mat4.multiply(dest, quatMat); 3275 | * 3276 | * @param {mat4} out mat4 receiving operation result 3277 | * @param {quat4} q Rotation quaternion 3278 | * @param {vec3} v Translation vector 3279 | * @returns {mat4} out 3280 | */ 3281 | mat4.fromRotationTranslation = function (out, q, v) { 3282 | // Quaternion math 3283 | var x = q[0], y = q[1], z = q[2], w = q[3], 3284 | x2 = x + x, 3285 | y2 = y + y, 3286 | z2 = z + z, 3287 | 3288 | xx = x * x2, 3289 | xy = x * y2, 3290 | xz = x * z2, 3291 | yy = y * y2, 3292 | yz = y * z2, 3293 | zz = z * z2, 3294 | wx = w * x2, 3295 | wy = w * y2, 3296 | wz = w * z2; 3297 | 3298 | out[0] = 1 - (yy + zz); 3299 | out[1] = xy + wz; 3300 | out[2] = xz - wy; 3301 | out[3] = 0; 3302 | out[4] = xy - wz; 3303 | out[5] = 1 - (xx + zz); 3304 | out[6] = yz + wx; 3305 | out[7] = 0; 3306 | out[8] = xz + wy; 3307 | out[9] = yz - wx; 3308 | out[10] = 1 - (xx + yy); 3309 | out[11] = 0; 3310 | out[12] = v[0]; 3311 | out[13] = v[1]; 3312 | out[14] = v[2]; 3313 | out[15] = 1; 3314 | 3315 | return out; 3316 | }; 3317 | 3318 | /** 3319 | * Calculates a 4x4 matrix from the given quaternion 3320 | * 3321 | * @param {mat4} out mat4 receiving operation result 3322 | * @param {quat} q Quaternion to create matrix from 3323 | * 3324 | * @returns {mat4} out 3325 | */ 3326 | mat4.fromQuat = function (out, q) { 3327 | var x = q[0], y = q[1], z = q[2], w = q[3], 3328 | x2 = x + x, 3329 | y2 = y + y, 3330 | z2 = z + z, 3331 | 3332 | xx = x * x2, 3333 | xy = x * y2, 3334 | xz = x * z2, 3335 | yy = y * y2, 3336 | yz = y * z2, 3337 | zz = z * z2, 3338 | wx = w * x2, 3339 | wy = w * y2, 3340 | wz = w * z2; 3341 | 3342 | out[0] = 1 - (yy + zz); 3343 | out[1] = xy + wz; 3344 | out[2] = xz - wy; 3345 | out[3] = 0; 3346 | 3347 | out[4] = xy - wz; 3348 | out[5] = 1 - (xx + zz); 3349 | out[6] = yz + wx; 3350 | out[7] = 0; 3351 | 3352 | out[8] = xz + wy; 3353 | out[9] = yz - wx; 3354 | out[10] = 1 - (xx + yy); 3355 | out[11] = 0; 3356 | 3357 | out[12] = 0; 3358 | out[13] = 0; 3359 | out[14] = 0; 3360 | out[15] = 1; 3361 | 3362 | return out; 3363 | }; 3364 | 3365 | /** 3366 | * Generates a frustum matrix with the given bounds 3367 | * 3368 | * @param {mat4} out mat4 frustum matrix will be written into 3369 | * @param {Number} left Left bound of the frustum 3370 | * @param {Number} right Right bound of the frustum 3371 | * @param {Number} bottom Bottom bound of the frustum 3372 | * @param {Number} top Top bound of the frustum 3373 | * @param {Number} near Near bound of the frustum 3374 | * @param {Number} far Far bound of the frustum 3375 | * @returns {mat4} out 3376 | */ 3377 | mat4.frustum = function (out, left, right, bottom, top, near, far) { 3378 | var rl = 1 / (right - left), 3379 | tb = 1 / (top - bottom), 3380 | nf = 1 / (near - far); 3381 | out[0] = (near * 2) * rl; 3382 | out[1] = 0; 3383 | out[2] = 0; 3384 | out[3] = 0; 3385 | out[4] = 0; 3386 | out[5] = (near * 2) * tb; 3387 | out[6] = 0; 3388 | out[7] = 0; 3389 | out[8] = (right + left) * rl; 3390 | out[9] = (top + bottom) * tb; 3391 | out[10] = (far + near) * nf; 3392 | out[11] = -1; 3393 | out[12] = 0; 3394 | out[13] = 0; 3395 | out[14] = (far * near * 2) * nf; 3396 | out[15] = 0; 3397 | return out; 3398 | }; 3399 | 3400 | /** 3401 | * Generates a perspective projection matrix with the given bounds 3402 | * 3403 | * @param {mat4} out mat4 frustum matrix will be written into 3404 | * @param {number} fovy Vertical field of view in radians 3405 | * @param {number} aspect Aspect ratio. typically viewport width/height 3406 | * @param {number} near Near bound of the frustum 3407 | * @param {number} far Far bound of the frustum 3408 | * @returns {mat4} out 3409 | */ 3410 | mat4.perspective = function (out, fovy, aspect, near, far) { 3411 | var f = 1.0 / Math.tan(fovy / 2), 3412 | nf = 1 / (near - far); 3413 | out[0] = f / aspect; 3414 | out[1] = 0; 3415 | out[2] = 0; 3416 | out[3] = 0; 3417 | out[4] = 0; 3418 | out[5] = f; 3419 | out[6] = 0; 3420 | out[7] = 0; 3421 | out[8] = 0; 3422 | out[9] = 0; 3423 | out[10] = (far + near) * nf; 3424 | out[11] = -1; 3425 | out[12] = 0; 3426 | out[13] = 0; 3427 | out[14] = (2 * far * near) * nf; 3428 | out[15] = 0; 3429 | return out; 3430 | }; 3431 | 3432 | /** 3433 | * Generates a orthogonal projection matrix with the given bounds 3434 | * 3435 | * @param {mat4} out mat4 frustum matrix will be written into 3436 | * @param {number} left Left bound of the frustum 3437 | * @param {number} right Right bound of the frustum 3438 | * @param {number} bottom Bottom bound of the frustum 3439 | * @param {number} top Top bound of the frustum 3440 | * @param {number} near Near bound of the frustum 3441 | * @param {number} far Far bound of the frustum 3442 | * @returns {mat4} out 3443 | */ 3444 | mat4.ortho = function (out, left, right, bottom, top, near, far) { 3445 | var lr = 1 / (left - right), 3446 | bt = 1 / (bottom - top), 3447 | nf = 1 / (near - far); 3448 | out[0] = -2 * lr; 3449 | out[1] = 0; 3450 | out[2] = 0; 3451 | out[3] = 0; 3452 | out[4] = 0; 3453 | out[5] = -2 * bt; 3454 | out[6] = 0; 3455 | out[7] = 0; 3456 | out[8] = 0; 3457 | out[9] = 0; 3458 | out[10] = 2 * nf; 3459 | out[11] = 0; 3460 | out[12] = (left + right) * lr; 3461 | out[13] = (top + bottom) * bt; 3462 | out[14] = (far + near) * nf; 3463 | out[15] = 1; 3464 | return out; 3465 | }; 3466 | 3467 | /** 3468 | * Generates a look-at matrix with the given eye position, focal point, and up axis 3469 | * 3470 | * @param {mat4} out mat4 frustum matrix will be written into 3471 | * @param {vec3} eye Position of the viewer 3472 | * @param {vec3} center Point the viewer is looking at 3473 | * @param {vec3} up vec3 pointing up 3474 | * @returns {mat4} out 3475 | */ 3476 | mat4.lookAt = function (out, eye, center, up) { 3477 | var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, 3478 | eyex = eye[0], 3479 | eyey = eye[1], 3480 | eyez = eye[2], 3481 | upx = up[0], 3482 | upy = up[1], 3483 | upz = up[2], 3484 | centerx = center[0], 3485 | centery = center[1], 3486 | centerz = center[2]; 3487 | 3488 | if (Math.abs(eyex - centerx) < GLMAT_EPSILON && 3489 | Math.abs(eyey - centery) < GLMAT_EPSILON && 3490 | Math.abs(eyez - centerz) < GLMAT_EPSILON) { 3491 | return mat4.identity(out); 3492 | } 3493 | 3494 | z0 = eyex - centerx; 3495 | z1 = eyey - centery; 3496 | z2 = eyez - centerz; 3497 | 3498 | len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 3499 | z0 *= len; 3500 | z1 *= len; 3501 | z2 *= len; 3502 | 3503 | x0 = upy * z2 - upz * z1; 3504 | x1 = upz * z0 - upx * z2; 3505 | x2 = upx * z1 - upy * z0; 3506 | len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 3507 | if (!len) { 3508 | x0 = 0; 3509 | x1 = 0; 3510 | x2 = 0; 3511 | } else { 3512 | len = 1 / len; 3513 | x0 *= len; 3514 | x1 *= len; 3515 | x2 *= len; 3516 | } 3517 | 3518 | y0 = z1 * x2 - z2 * x1; 3519 | y1 = z2 * x0 - z0 * x2; 3520 | y2 = z0 * x1 - z1 * x0; 3521 | 3522 | len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 3523 | if (!len) { 3524 | y0 = 0; 3525 | y1 = 0; 3526 | y2 = 0; 3527 | } else { 3528 | len = 1 / len; 3529 | y0 *= len; 3530 | y1 *= len; 3531 | y2 *= len; 3532 | } 3533 | 3534 | out[0] = x0; 3535 | out[1] = y0; 3536 | out[2] = z0; 3537 | out[3] = 0; 3538 | out[4] = x1; 3539 | out[5] = y1; 3540 | out[6] = z1; 3541 | out[7] = 0; 3542 | out[8] = x2; 3543 | out[9] = y2; 3544 | out[10] = z2; 3545 | out[11] = 0; 3546 | out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 3547 | out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 3548 | out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 3549 | out[15] = 1; 3550 | 3551 | return out; 3552 | }; 3553 | 3554 | /** 3555 | * Returns a string representation of a mat4 3556 | * 3557 | * @param {mat4} mat matrix to represent as a string 3558 | * @returns {String} string representation of the matrix 3559 | */ 3560 | mat4.str = function (a) { 3561 | return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + 3562 | a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + 3563 | a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 3564 | a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; 3565 | }; 3566 | 3567 | if(typeof(exports) !== 'undefined') { 3568 | exports.mat4 = mat4; 3569 | } 3570 | ; 3571 | /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 3572 | 3573 | Redistribution and use in source and binary forms, with or without modification, 3574 | are permitted provided that the following conditions are met: 3575 | 3576 | * Redistributions of source code must retain the above copyright notice, this 3577 | list of conditions and the following disclaimer. 3578 | * Redistributions in binary form must reproduce the above copyright notice, 3579 | this list of conditions and the following disclaimer in the documentation 3580 | and/or other materials provided with the distribution. 3581 | 3582 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 3583 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3584 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 3585 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 3586 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3587 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 3588 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 3589 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3590 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3591 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 3592 | 3593 | /** 3594 | * @class Quaternion 3595 | * @name quat 3596 | */ 3597 | 3598 | var quat = {}; 3599 | 3600 | var quatIdentity = new Float32Array([0, 0, 0, 1]); 3601 | 3602 | /** 3603 | * Creates a new identity quat 3604 | * 3605 | * @returns {quat} a new quaternion 3606 | */ 3607 | quat.create = function() { 3608 | var out = new GLMAT_ARRAY_TYPE(4); 3609 | out[0] = 0; 3610 | out[1] = 0; 3611 | out[2] = 0; 3612 | out[3] = 1; 3613 | return out; 3614 | }; 3615 | 3616 | /** 3617 | * Creates a new quat initialized with values from an existing quaternion 3618 | * 3619 | * @param {quat} a quaternion to clone 3620 | * @returns {quat} a new quaternion 3621 | * @function 3622 | */ 3623 | quat.clone = vec4.clone; 3624 | 3625 | /** 3626 | * Creates a new quat initialized with the given values 3627 | * 3628 | * @param {Number} x X component 3629 | * @param {Number} y Y component 3630 | * @param {Number} z Z component 3631 | * @param {Number} w W component 3632 | * @returns {quat} a new quaternion 3633 | * @function 3634 | */ 3635 | quat.fromValues = vec4.fromValues; 3636 | 3637 | /** 3638 | * Copy the values from one quat to another 3639 | * 3640 | * @param {quat} out the receiving quaternion 3641 | * @param {quat} a the source quaternion 3642 | * @returns {quat} out 3643 | * @function 3644 | */ 3645 | quat.copy = vec4.copy; 3646 | 3647 | /** 3648 | * Set the components of a quat to the given values 3649 | * 3650 | * @param {quat} out the receiving quaternion 3651 | * @param {Number} x X component 3652 | * @param {Number} y Y component 3653 | * @param {Number} z Z component 3654 | * @param {Number} w W component 3655 | * @returns {quat} out 3656 | * @function 3657 | */ 3658 | quat.set = vec4.set; 3659 | 3660 | /** 3661 | * Set a quat to the identity quaternion 3662 | * 3663 | * @param {quat} out the receiving quaternion 3664 | * @returns {quat} out 3665 | */ 3666 | quat.identity = function(out) { 3667 | out[0] = 0; 3668 | out[1] = 0; 3669 | out[2] = 0; 3670 | out[3] = 1; 3671 | return out; 3672 | }; 3673 | 3674 | /** 3675 | * Sets a quat from the given angle and rotation axis, 3676 | * then returns it. 3677 | * 3678 | * @param {quat} out the receiving quaternion 3679 | * @param {vec3} axis the axis around which to rotate 3680 | * @param {Number} rad the angle in radians 3681 | * @returns {quat} out 3682 | **/ 3683 | quat.setAxisAngle = function(out, axis, rad) { 3684 | rad = rad * 0.5; 3685 | var s = Math.sin(rad); 3686 | out[0] = s * axis[0]; 3687 | out[1] = s * axis[1]; 3688 | out[2] = s * axis[2]; 3689 | out[3] = Math.cos(rad); 3690 | return out; 3691 | }; 3692 | 3693 | /** 3694 | * Adds two quat's 3695 | * 3696 | * @param {quat} out the receiving quaternion 3697 | * @param {quat} a the first operand 3698 | * @param {quat} b the second operand 3699 | * @returns {quat} out 3700 | * @function 3701 | */ 3702 | quat.add = vec4.add; 3703 | 3704 | /** 3705 | * Multiplies two quat's 3706 | * 3707 | * @param {quat} out the receiving quaternion 3708 | * @param {quat} a the first operand 3709 | * @param {quat} b the second operand 3710 | * @returns {quat} out 3711 | */ 3712 | quat.multiply = function(out, a, b) { 3713 | var ax = a[0], ay = a[1], az = a[2], aw = a[3], 3714 | bx = b[0], by = b[1], bz = b[2], bw = b[3]; 3715 | 3716 | out[0] = ax * bw + aw * bx + ay * bz - az * by; 3717 | out[1] = ay * bw + aw * by + az * bx - ax * bz; 3718 | out[2] = az * bw + aw * bz + ax * by - ay * bx; 3719 | out[3] = aw * bw - ax * bx - ay * by - az * bz; 3720 | return out; 3721 | }; 3722 | 3723 | /** 3724 | * Alias for {@link quat.multiply} 3725 | * @function 3726 | */ 3727 | quat.mul = quat.multiply; 3728 | 3729 | /** 3730 | * Scales a quat by a scalar number 3731 | * 3732 | * @param {quat} out the receiving vector 3733 | * @param {quat} a the vector to scale 3734 | * @param {Number} b amount to scale the vector by 3735 | * @returns {quat} out 3736 | * @function 3737 | */ 3738 | quat.scale = vec4.scale; 3739 | 3740 | /** 3741 | * Rotates a quaternion by the given angle around the X axis 3742 | * 3743 | * @param {quat} out quat receiving operation result 3744 | * @param {quat} a quat to rotate 3745 | * @param {number} rad angle (in radians) to rotate 3746 | * @returns {quat} out 3747 | */ 3748 | quat.rotateX = function (out, a, rad) { 3749 | rad *= 0.5; 3750 | 3751 | var ax = a[0], ay = a[1], az = a[2], aw = a[3], 3752 | bx = Math.sin(rad), bw = Math.cos(rad); 3753 | 3754 | out[0] = ax * bw + aw * bx; 3755 | out[1] = ay * bw + az * bx; 3756 | out[2] = az * bw - ay * bx; 3757 | out[3] = aw * bw - ax * bx; 3758 | return out; 3759 | }; 3760 | 3761 | /** 3762 | * Rotates a quaternion by the given angle around the Y axis 3763 | * 3764 | * @param {quat} out quat receiving operation result 3765 | * @param {quat} a quat to rotate 3766 | * @param {number} rad angle (in radians) to rotate 3767 | * @returns {quat} out 3768 | */ 3769 | quat.rotateY = function (out, a, rad) { 3770 | rad *= 0.5; 3771 | 3772 | var ax = a[0], ay = a[1], az = a[2], aw = a[3], 3773 | by = Math.sin(rad), bw = Math.cos(rad); 3774 | 3775 | out[0] = ax * bw - az * by; 3776 | out[1] = ay * bw + aw * by; 3777 | out[2] = az * bw + ax * by; 3778 | out[3] = aw * bw - ay * by; 3779 | return out; 3780 | }; 3781 | 3782 | /** 3783 | * Rotates a quaternion by the given angle around the Z axis 3784 | * 3785 | * @param {quat} out quat receiving operation result 3786 | * @param {quat} a quat to rotate 3787 | * @param {number} rad angle (in radians) to rotate 3788 | * @returns {quat} out 3789 | */ 3790 | quat.rotateZ = function (out, a, rad) { 3791 | rad *= 0.5; 3792 | 3793 | var ax = a[0], ay = a[1], az = a[2], aw = a[3], 3794 | bz = Math.sin(rad), bw = Math.cos(rad); 3795 | 3796 | out[0] = ax * bw + ay * bz; 3797 | out[1] = ay * bw - ax * bz; 3798 | out[2] = az * bw + aw * bz; 3799 | out[3] = aw * bw - az * bz; 3800 | return out; 3801 | }; 3802 | 3803 | /** 3804 | * Calculates the W component of a quat from the X, Y, and Z components. 3805 | * Assumes that quaternion is 1 unit in length. 3806 | * Any existing W component will be ignored. 3807 | * 3808 | * @param {quat} out the receiving quaternion 3809 | * @param {quat} a quat to calculate W component of 3810 | * @returns {quat} out 3811 | */ 3812 | quat.calculateW = function (out, a) { 3813 | var x = a[0], y = a[1], z = a[2]; 3814 | 3815 | out[0] = x; 3816 | out[1] = y; 3817 | out[2] = z; 3818 | out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); 3819 | return out; 3820 | }; 3821 | 3822 | /** 3823 | * Calculates the dot product of two quat's 3824 | * 3825 | * @param {quat} a the first operand 3826 | * @param {quat} b the second operand 3827 | * @returns {Number} dot product of a and b 3828 | * @function 3829 | */ 3830 | quat.dot = vec4.dot; 3831 | 3832 | /** 3833 | * Performs a linear interpolation between two quat's 3834 | * 3835 | * @param {quat} out the receiving quaternion 3836 | * @param {quat} a the first operand 3837 | * @param {quat} b the second operand 3838 | * @param {Number} t interpolation amount between the two inputs 3839 | * @returns {quat} out 3840 | * @function 3841 | */ 3842 | quat.lerp = vec4.lerp; 3843 | 3844 | /** 3845 | * Performs a spherical linear interpolation between two quat 3846 | * 3847 | * @param {quat} out the receiving quaternion 3848 | * @param {quat} a the first operand 3849 | * @param {quat} b the second operand 3850 | * @param {Number} t interpolation amount between the two inputs 3851 | * @returns {quat} out 3852 | */ 3853 | quat.slerp = function (out, a, b, t) { 3854 | var ax = a[0], ay = a[1], az = a[2], aw = a[3], 3855 | bx = b[0], by = b[1], bz = b[2], bw = b[3]; 3856 | 3857 | var cosHalfTheta = ax * bx + ay * by + az * bz + aw * bw, 3858 | halfTheta, 3859 | sinHalfTheta, 3860 | ratioA, 3861 | ratioB; 3862 | 3863 | if (Math.abs(cosHalfTheta) >= 1.0) { 3864 | if (out !== a) { 3865 | out[0] = ax; 3866 | out[1] = ay; 3867 | out[2] = az; 3868 | out[3] = aw; 3869 | } 3870 | return out; 3871 | } 3872 | 3873 | halfTheta = Math.acos(cosHalfTheta); 3874 | sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); 3875 | 3876 | if (Math.abs(sinHalfTheta) < 0.001) { 3877 | out[0] = (ax * 0.5 + bx * 0.5); 3878 | out[1] = (ay * 0.5 + by * 0.5); 3879 | out[2] = (az * 0.5 + bz * 0.5); 3880 | out[3] = (aw * 0.5 + bw * 0.5); 3881 | return out; 3882 | } 3883 | 3884 | ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta; 3885 | ratioB = Math.sin(t * halfTheta) / sinHalfTheta; 3886 | 3887 | out[0] = (ax * ratioA + bx * ratioB); 3888 | out[1] = (ay * ratioA + by * ratioB); 3889 | out[2] = (az * ratioA + bz * ratioB); 3890 | out[3] = (aw * ratioA + bw * ratioB); 3891 | 3892 | return out; 3893 | }; 3894 | 3895 | /** 3896 | * Calculates the inverse of a quat 3897 | * 3898 | * @param {quat} out the receiving quaternion 3899 | * @param {quat} a quat to calculate inverse of 3900 | * @returns {quat} out 3901 | */ 3902 | quat.invert = function(out, a) { 3903 | var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], 3904 | dot = a0*a0 + a1*a1 + a2*a2 + a3*a3, 3905 | invDot = dot ? 1.0/dot : 0; 3906 | 3907 | // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 3908 | 3909 | out[0] = -a0*invDot; 3910 | out[1] = -a1*invDot; 3911 | out[2] = -a2*invDot; 3912 | out[3] = a3*invDot; 3913 | return out; 3914 | }; 3915 | 3916 | /** 3917 | * Calculates the conjugate of a quat 3918 | * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. 3919 | * 3920 | * @param {quat} out the receiving quaternion 3921 | * @param {quat} a quat to calculate conjugate of 3922 | * @returns {quat} out 3923 | */ 3924 | quat.conjugate = function (out, a) { 3925 | out[0] = -a[0]; 3926 | out[1] = -a[1]; 3927 | out[2] = -a[2]; 3928 | out[3] = a[3]; 3929 | return out; 3930 | }; 3931 | 3932 | /** 3933 | * Calculates the length of a quat 3934 | * 3935 | * @param {quat} a vector to calculate length of 3936 | * @returns {Number} length of a 3937 | * @function 3938 | */ 3939 | quat.length = vec4.length; 3940 | 3941 | /** 3942 | * Alias for {@link quat.length} 3943 | * @function 3944 | */ 3945 | quat.len = quat.length; 3946 | 3947 | /** 3948 | * Calculates the squared length of a quat 3949 | * 3950 | * @param {quat} a vector to calculate squared length of 3951 | * @returns {Number} squared length of a 3952 | * @function 3953 | */ 3954 | quat.squaredLength = vec4.squaredLength; 3955 | 3956 | /** 3957 | * Alias for {@link quat.squaredLength} 3958 | * @function 3959 | */ 3960 | quat.sqrLen = quat.squaredLength; 3961 | 3962 | /** 3963 | * Normalize a quat 3964 | * 3965 | * @param {quat} out the receiving quaternion 3966 | * @param {quat} a quaternion to normalize 3967 | * @returns {quat} out 3968 | * @function 3969 | */ 3970 | quat.normalize = vec4.normalize; 3971 | 3972 | /** 3973 | * Creates a quaternion from the given 3x3 rotation matrix. 3974 | * 3975 | * @param {quat} out the receiving quaternion 3976 | * @param {mat3} m rotation matrix 3977 | * @returns {quat} out 3978 | * @function 3979 | */ 3980 | quat.fromMat3 = (function() { 3981 | var s_iNext = [1,2,0]; 3982 | return function(out, m) { 3983 | // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes 3984 | // article "Quaternion Calculus and Fast Animation". 3985 | var fTrace = m[0] + m[4] + m[8]; 3986 | var fRoot; 3987 | 3988 | if ( fTrace > 0.0 ) { 3989 | // |w| > 1/2, may as well choose w > 1/2 3990 | fRoot = Math.sqrt(fTrace + 1.0); // 2w 3991 | out[3] = 0.5 * fRoot; 3992 | fRoot = 0.5/fRoot; // 1/(4w) 3993 | out[0] = (m[7]-m[5])*fRoot; 3994 | out[1] = (m[2]-m[6])*fRoot; 3995 | out[2] = (m[3]-m[1])*fRoot; 3996 | } else { 3997 | // |w| <= 1/2 3998 | var i = 0; 3999 | if ( m[4] > m[0] ) 4000 | i = 1; 4001 | if ( m[8] > m[i*3+i] ) 4002 | i = 2; 4003 | var j = s_iNext[i]; 4004 | var k = s_iNext[j]; 4005 | 4006 | fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0); 4007 | out[i] = 0.5 * fRoot; 4008 | fRoot = 0.5 / fRoot; 4009 | out[3] = (m[k*3+j] - m[j*3+k]) * fRoot; 4010 | out[j] = (m[j*3+i] + m[i*3+j]) * fRoot; 4011 | out[k] = (m[k*3+i] + m[i*3+k]) * fRoot; 4012 | } 4013 | 4014 | return out; 4015 | }; 4016 | })(); 4017 | 4018 | /** 4019 | * Returns a string representation of a quatenion 4020 | * 4021 | * @param {quat} vec vector to represent as a string 4022 | * @returns {String} string representation of the vector 4023 | */ 4024 | quat.str = function (a) { 4025 | return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; 4026 | }; 4027 | 4028 | if(typeof(exports) !== 'undefined') { 4029 | exports.quat = quat; 4030 | } 4031 | ; 4032 | 4033 | 4034 | 4035 | 4036 | 4037 | 4038 | 4039 | 4040 | 4041 | 4042 | 4043 | 4044 | 4045 | })(shim.exports); 4046 | })(); 4047 | 4048 | },{}]},{},[1]); 4049 | -------------------------------------------------------------------------------- /examples/curves-graph/curves-graph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/curves-graph/curves-graph.js: -------------------------------------------------------------------------------- 1 | // An implementation of a curves graphing tool, very similar to the photoshop 2 | // curves tool. Control points are added via clicking on the canvas and the 3 | // animation loop will draw the interpolated points. 4 | var catRomSpline = require('../..'); 5 | 6 | window.canvas = document.createElement("canvas"); 7 | document.body.appendChild(canvas); 8 | var width = window.innerWidth; 9 | var height = window.innerHeight; 10 | var scaleX = 1; 11 | var scaleY = 1; 12 | var originalWidth = width; 13 | var originalHeight = height; 14 | canvas.width = width; 15 | canvas.height = height; 16 | var context = canvas.getContext('2d'); 17 | 18 | var p1 = [0, height]; 19 | var p2 = [width, 0]; 20 | 21 | var slope = (p2[0] - p1[0]) / (p2[1] - p1[1]); 22 | 23 | var p0 = [p1[0] - 10, p1[1] - (10 * 1/slope)]; 24 | var p3 = [p2[0] + 10, p2[1] + (10 * 1/slope)]; 25 | 26 | var points = [p0, p1, p2, p3]; 27 | 28 | var newPoint = []; 29 | 30 | window.onresize = function(event) { 31 | width = window.innerWidth; 32 | height = window.innerHeight; 33 | scaleX = width / originalWidth; 34 | scaleY = height / originalHeight; 35 | canvas.width = width; 36 | canvas.height = height; 37 | }; 38 | 39 | canvas.onmousedown = function(event) { 40 | newPoint = [event.layerX * (1/scaleX), event.layerY * (1/scaleY)]; 41 | points.push(newPoint); 42 | points.sort(function(a, b) { 43 | return a[0] - b[0]; 44 | }); 45 | }; 46 | 47 | canvas.onmousemove = function(event) { 48 | if (newPoint) { 49 | newPoint[0] = event.layerX * (1/scaleX); 50 | newPoint[1] = event.layerY * (1/scaleY); 51 | points.sort(function(a, b) { 52 | return a[0] - b[0]; 53 | }); 54 | } 55 | }; 56 | 57 | canvas.onmouseup = function(event) { 58 | newPoint = false; 59 | }; 60 | 61 | var frameLoop = function() { 62 | context.fillStyle = "black"; 63 | context.fillRect(0, 0, width, height); 64 | 65 | context.save(); 66 | context.scale(scaleX, scaleY); 67 | catRomSpline(points).forEach(function(point, index, array) { 68 | context.fillStyle = "white"; 69 | context.fillRect(point[0], point[1], 1, 1); 70 | }); 71 | 72 | context.restore(); 73 | requestAnimationFrame(frameLoop); 74 | }; 75 | 76 | requestAnimationFrame(frameLoop); 77 | -------------------------------------------------------------------------------- /examples/curves-graph/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var add = require('gl-vec2/add'); 2 | var scale = require('gl-vec2/scale'); 3 | var distance = require('gl-vec2/distance'); 4 | 5 | var interpolatePoint = function(p0, p1, p2, p3, t0, t1, t2, t3, t) { 6 | var a1, a2, a3, b1, b2, c; 7 | a1 = []; 8 | a2 = []; 9 | a3 = []; 10 | b1 = []; 11 | b2 = []; 12 | c = []; 13 | 14 | add(a1, scale([], p0, (t1 - t)/(t1 - t0)), scale([], p1, (t - t0)/(t1 - t0))); 15 | add(a2, scale([], p1, (t2 - t)/(t2 - t1)), scale([], p2, (t - t1)/(t2 - t1))); 16 | add(a3, scale([], p2, (t3 - t)/(t3 - t2)), scale([], p3, (t - t2)/(t3 - t2))); 17 | 18 | add(b1, scale([], a1, (t2 - t)/(t2 - t0)), scale([], a2, (t - t0)/(t2 - t0))); 19 | add(b2, scale([], a2, (t3 - t)/(t3 - t1)), scale([], a3, (t - t1)/(t3 - t1))); 20 | 21 | add(c, scale([], b1, (t2 - t)/(t2 - t1)), scale([], b2, (t - t1)/(t2 - t1))); 22 | 23 | return c; 24 | }; 25 | 26 | var catmullRomSplineSegment = function(p0, p1, p2, p3, samples, knot) { 27 | var t, t0, t1, t2, t3, segmentDist; 28 | var points = []; 29 | segmentDist = distance(p1, p2); 30 | 31 | t0 = 0; 32 | t1 = Math.pow(distance(p0, p1), knot); 33 | t2 = Math.pow(segmentDist, knot) + t1; 34 | t3 = Math.pow(distance(p2, p3), knot) + t2; 35 | 36 | if (!samples) { 37 | samples = segmentDist * 1.5; 38 | } 39 | 40 | var sampleStep = (t2 - t1) / samples; 41 | t = t1; 42 | while (t < t2) { 43 | t += sampleStep; 44 | points.push(interpolatePoint(p0, p1, p2, p3, t0, t1, t2, t3, t)); 45 | } 46 | 47 | return points; 48 | }; 49 | 50 | var catmullRomSpline = function(controlPoints, options) { 51 | if (controlPoints.length < 4) { 52 | throw "Must have at least 4 control points to generate catmull rom spline"; 53 | } 54 | var points = []; 55 | var p0, p1, p2, p3, offset; 56 | 57 | options = options || {}; 58 | var knot = options.knot || 0.5; 59 | var samples = options.samples; 60 | 61 | controlPoints.forEach(function(point, i) { 62 | offset = 1; 63 | p0 = point; 64 | 65 | do { 66 | p1 = controlPoints[i + offset]; 67 | offset++; 68 | } while (p0 && p1 && p0[0] === p1[0] && p0[1] === p1[1]); 69 | 70 | do { 71 | p2 = controlPoints[i + offset]; 72 | offset++; 73 | } while (p1 && p2 && p1[0] === p2[0] && p1[1] === p2[1]); 74 | 75 | do { 76 | p3 = controlPoints[i + offset]; 77 | offset++; 78 | } while (p2 && p3 && p2[0] === p3[0] && p2[1] === p3[1]); 79 | 80 | if (!(p1 && p2 && p3)) { 81 | return; 82 | } 83 | 84 | points.push(p1); 85 | points = points.concat(catmullRomSplineSegment(p0, p1, p2, p3, samples, knot)); 86 | if (!controlPoints[offset]) { 87 | points.push(p2); 88 | } 89 | }); 90 | 91 | return points; 92 | }; 93 | 94 | module.exports = catmullRomSpline; 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cat-rom-spline", 3 | "version": "0.1.3", 4 | "description": "Catmull Rom spline interpolation made easy.", 5 | "author": { 6 | "name": "Nick Schaubeck", 7 | "email": "nschaubeck@gmail.com", 8 | "url": "northofbrooklyn.nyc" 9 | }, 10 | "repository": "nschaubeck/cat-rom-spline", 11 | "license": "MIT", 12 | "files": [ 13 | "index.js" 14 | ], 15 | "keywords": [ 16 | "cat-rom-spline", 17 | "catmull", 18 | "rom", 19 | "spline", 20 | "interpolation" 21 | ], 22 | "dependencies": { 23 | "gl-vec2": "1.0.0" 24 | }, 25 | "devDependencies": { 26 | "browserify": "9.0.8", 27 | "grunt-browserify": "3.7.0", 28 | "grunt-cli": "0.1.13", 29 | "grunt-contrib-jshint": "0.11.0", 30 | "grunt-contrib-nodeunit": "0.4.1", 31 | "grunt-contrib-watch": "0.6.1", 32 | "grunt-mocha-cli": "1.12.0", 33 | "jshint-stylish": "1.0.1", 34 | "load-grunt-tasks": "3.1.0", 35 | "time-grunt": "1.1.0" 36 | }, 37 | "scripts": { 38 | "test": "grunt", 39 | "browser": "browserify index.js > browser.js" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var assert = require('assert'); 3 | var catRomSpline = require('../'); 4 | 5 | describe('cat-rom-spline node module', function () { 6 | it('must generate the correct amount of points', function () { 7 | var p0 = [0, 0]; 8 | var p1 = [5, 5]; 9 | var p2 = [5, 10]; 10 | var p3 = [15, 20]; 11 | var p4 = [0, 0]; 12 | var options = { 13 | samples: 10 14 | }; 15 | var points = [p0, p1, p2, p3, p4]; 16 | var interpolatedPoints = catRomSpline(points, options); 17 | assert.equal(interpolatedPoints.length, 23); 18 | }); 19 | 20 | it('must throw an error if not enough points are passed in', function () { 21 | try { 22 | catRomSpline([]); 23 | } catch(e) { 24 | assert(true); 25 | } 26 | }); 27 | }); 28 | --------------------------------------------------------------------------------