├── .gitignore ├── tests ├── Main.elm ├── elm-package.json └── Tests.elm ├── elm-package.json ├── CONTRIBUTING.md ├── README.md ├── LICENSE └── src ├── Math ├── Vector2.elm ├── Vector4.elm ├── Vector3.elm └── Matrix4.elm └── Native ├── Math ├── Vector2.js └── Vector4.js └── MJS.js /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff -------------------------------------------------------------------------------- /tests/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (main) 2 | 3 | import Json.Encode 4 | import Test.Runner.Node 5 | import Tests 6 | 7 | 8 | main = 9 | Test.Runner.Node.run emit Tests.suite 10 | 11 | 12 | port emit : ( String, Json.Encode.Value ) -> Cmd msg 13 | -------------------------------------------------------------------------------- /elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.5", 3 | "summary": "A linear algebra library for fast vector and matrix math", 4 | "repository": "https://github.com/elm-community/elm-linear-algebra.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "src" 8 | ], 9 | "exposed-modules": [ 10 | "Math.Vector2", 11 | "Math.Vector3", 12 | "Math.Vector4", 13 | "Math.Matrix4" 14 | ], 15 | "native-modules": true, 16 | "dependencies": { 17 | "elm-lang/core": "5.0.0 <= v < 6.0.0" 18 | }, 19 | "elm-version": "0.18.0 <= v < 0.19.0" 20 | } 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to elm-community/elm-linear-algebra 2 | 3 | This repository is kept for maintenance and does not accept most feature requests. In particular, 4 | [#5](https://github.com/elm-community/elm-linear-algebra/issues/5) requires that all 5 | changes be PATCH-level, meaning that the API cannot be modified. 6 | 7 | Any contribution should: 8 | * Compile using `elm make` 9 | * Be recognized as a PATCH change using `elm package diff` 10 | * Not introduce mutable variables 11 | * Justify why the change is needed and why it won't break anything already here 12 | 13 | Documentation improvements are welcome. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED: Renamed to [elm-community/linear-algebra](http://package.elm-lang.org/packages/elm-community/linear-algebra/latest) 2 | 3 | # Fast Linear Algebra for Elm 4 | 5 | A library for fast vector and matrix math. See the full docs [here][docs]. 6 | 7 | [docs]: http://package.elm-lang.org/packages/elm-community/elm-linear-algebra/latest/ 8 | 9 | This is needed for 3D rendering with [WebGL in Elm][webgl], but is useful for 10 | anything where fast linear algebra is needed. 11 | 12 | [webgl]: https://github.com/elm-community/elm-webgl 13 | 14 | It is based on [the MJS library](https://code.google.com/p/webgl-mjs/) for JavaScript. 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/elm-community/elm-linear-algebra.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "../src" 9 | ], 10 | "exposed-modules": [], 11 | "native-modules": true, 12 | "dependencies": { 13 | "elm-community/elm-test": "3.0.0 <= v < 4.0.0", 14 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 15 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 16 | "rtfeldman/node-test-runner": "3.0.1 <= v < 4.0.0" 17 | }, 18 | "elm-version": "0.18.0 <= v < 0.19.0" 19 | } 20 | -------------------------------------------------------------------------------- /tests/Tests.elm: -------------------------------------------------------------------------------- 1 | module Tests exposing (suite) 2 | 3 | import Test exposing (Test, describe, test) 4 | import Expect 5 | import Math.Vector2 as V2 6 | 7 | 8 | suite : Test 9 | suite = 10 | describe "Vector2 module" 11 | [ test "vec2" <| 12 | \() -> 13 | Expect.equal 14 | (V2.vec2 3 4) 15 | (V2.vec2 3 4) 16 | , test "setX" <| 17 | \() -> 18 | Expect.equal 19 | (V2.vec2 5 4) 20 | (V2.vec2 3 4 |> V2.setX 5) 21 | , test "setY" <| 22 | \() -> 23 | Expect.equal 24 | (V2.vec2 3 6) 25 | (V2.vec2 3 4 |> V2.setY 6) 26 | ] 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, John P Mayer, Jr 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/Math/Vector2.elm: -------------------------------------------------------------------------------- 1 | module Math.Vector2 exposing (..) 2 | {-| A high performance linear algebra library using native JS arrays. Geared 3 | towards 3D graphics and use with `Graphics.WebGL`. All vectors are immutable. 4 | 5 | # Create 6 | @docs Vec2, vec2 7 | 8 | # Get and Set 9 | The set functions create a new copy of the vector, updating a single field. 10 | 11 | @docs getX, getY, setX, setY 12 | 13 | # Operations 14 | @docs add, sub, negate, scale, dot, normalize, direction, 15 | length, lengthSquared, distance, distanceSquared 16 | 17 | # Conversions 18 | @docs toTuple, fromTuple, toRecord, fromRecord 19 | -} 20 | 21 | import Native.Math.Vector2 22 | 23 | {-| Two dimensional vector type -} 24 | type Vec2 = Vec2 25 | 26 | {-| Creates a new 2-element vector with the given values. -} 27 | vec2 : Float -> Float -> Vec2 28 | vec2 = Native.Math.Vector2.vec2 29 | 30 | {-| Extract the x component of a vector. -} 31 | getX : Vec2 -> Float 32 | getX = Native.Math.Vector2.getX 33 | 34 | {-| Extract the y component of a vector. -} 35 | getY : Vec2 -> Float 36 | getY = Native.Math.Vector2.getY 37 | 38 | {-| Update the x component of a vector, returning a new vector. -} 39 | setX : Float -> Vec2 -> Vec2 40 | setX = Native.Math.Vector2.setX 41 | 42 | {-| Update the y component of a vector, returning a new vector. -} 43 | setY : Float -> Vec2 -> Vec2 44 | setY = Native.Math.Vector2.setY 45 | 46 | {-| Convert a vector to a tuple. -} 47 | toTuple : Vec2 -> (Float,Float) 48 | toTuple = Native.Math.Vector2.toTuple 49 | 50 | {-| Convert a vector to a record. -} 51 | toRecord : Vec2 -> { x:Float, y:Float } 52 | toRecord = Native.Math.Vector2.toRecord 53 | 54 | {-| Convert a tuple to a vector. -} 55 | fromTuple : (Float,Float) -> Vec2 56 | fromTuple = Native.Math.Vector2.fromTuple 57 | 58 | {-| Convert a record to a vector. -} 59 | fromRecord : { x:Float, y:Float } -> Vec2 60 | fromRecord = Native.Math.Vector2.fromRecord 61 | 62 | {-| Vector addition: a + b -} 63 | add : Vec2 -> Vec2 -> Vec2 64 | add = Native.Math.Vector2.add 65 | 66 | {-| Vector subtraction: a - b -} 67 | sub : Vec2 -> Vec2 -> Vec2 68 | sub = Native.Math.Vector2.sub 69 | 70 | {-| Vector negation: -a -} 71 | negate : Vec2 -> Vec2 72 | negate = Native.Math.Vector2.neg 73 | 74 | {-| The normalized direction from b to a: (a - b) / |a - b| -} 75 | direction : Vec2 -> Vec2 -> Vec2 76 | direction = Native.Math.Vector2.direction 77 | 78 | {-| The length of the given vector: |a| -} 79 | length : Vec2 -> Float 80 | length = Native.Math.Vector2.length 81 | 82 | {-| The square of the length of the given vector: |a| * |a| -} 83 | lengthSquared : Vec2 -> Float 84 | lengthSquared = Native.Math.Vector2.lengthSquared 85 | 86 | {-| The distance between two vectors. -} 87 | distance : Vec2 -> Vec2 -> Float 88 | distance = Native.Math.Vector2.distance 89 | 90 | {-| The square of the distance between two vectors. -} 91 | distanceSquared : Vec2 -> Vec2 -> Float 92 | distanceSquared = Native.Math.Vector2.distanceSquared 93 | 94 | {-| A unit vector with the same direction as the given vector: a / |a| -} 95 | normalize : Vec2 -> Vec2 96 | normalize = Native.Math.Vector2.normalize 97 | 98 | {-| Multiply the vector by a scalar: s * v -} 99 | scale : Float -> Vec2 -> Vec2 100 | scale = Native.Math.Vector2.scale 101 | 102 | {-| The dot product of a and b -} 103 | dot : Vec2 -> Vec2 -> Float 104 | dot = Native.Math.Vector2.dot 105 | 106 | -------------------------------------------------------------------------------- /src/Math/Vector4.elm: -------------------------------------------------------------------------------- 1 | module Math.Vector4 exposing (..) 2 | {-| A high performance linear algebra library using native JS arrays. Geared 3 | towards 3D graphics and use with `Graphics.WebGL`. All vectors are immutable. 4 | 5 | # Create 6 | @docs Vec4, vec4 7 | 8 | # Get and Set 9 | The set functions create a new copy of the vector, updating a single field. 10 | 11 | @docs getX, getY, getZ, getW, setX, setY, setZ, setW 12 | 13 | # Operations 14 | @docs add, sub, negate, scale, dot, normalize, direction, 15 | length, lengthSquared, distance, distanceSquared 16 | 17 | # Conversions 18 | @docs toTuple, fromTuple, toRecord, fromRecord 19 | -} 20 | 21 | import Native.Math.Vector4 22 | 23 | {-| Four dimensional vector type -} 24 | type Vec4 = Vec4 25 | 26 | {-| Creates a new 4-element vector with the given x, y, z, and w values. -} 27 | vec4 : Float -> Float -> Float -> Float -> Vec4 28 | vec4 = Native.Math.Vector4.vec4 29 | 30 | {-| Extract the x component of a vector. -} 31 | getX : Vec4 -> Float 32 | getX = Native.Math.Vector4.getX 33 | 34 | {-| Extract the y component of a vector. -} 35 | getY : Vec4 -> Float 36 | getY = Native.Math.Vector4.getY 37 | 38 | {-| Extract the z component of a vector. -} 39 | getZ : Vec4 -> Float 40 | getZ = Native.Math.Vector4.getZ 41 | 42 | {-| Extract the w component of a vector. -} 43 | getW : Vec4 -> Float 44 | getW = Native.Math.Vector4.getW 45 | 46 | {-| Update the x component of a vector, returning a new vector. -} 47 | setX : Float -> Vec4 -> Vec4 48 | setX = Native.Math.Vector4.setX 49 | 50 | {-| Update the y component of a vector, returning a new vector. -} 51 | setY : Float -> Vec4 -> Vec4 52 | setY = Native.Math.Vector4.setY 53 | 54 | {-| Update the z component of a vector, returning a new vector. -} 55 | setZ : Float -> Vec4 -> Vec4 56 | setZ = Native.Math.Vector4.setZ 57 | 58 | {-| Update the w component of a vector, returning a new vector. -} 59 | setW : Float -> Vec4 -> Vec4 60 | setW = Native.Math.Vector4.setW 61 | 62 | {-| Convert a vector to a tuple. -} 63 | toTuple : Vec4 -> (Float,Float,Float,Float) 64 | toTuple = Native.Math.Vector4.toTuple 65 | 66 | {-| Convert a vector to a record. -} 67 | toRecord : Vec4 -> { x:Float, y:Float, z:Float, w:Float } 68 | toRecord = Native.Math.Vector4.toRecord 69 | 70 | {-| Convert a tuple to a vector. -} 71 | fromTuple : (Float,Float,Float,Float) -> Vec4 72 | fromTuple = Native.Math.Vector4.fromTuple 73 | 74 | {-| Convert a record to a vector. -} 75 | fromRecord : { x:Float, y:Float, z:Float, w:Float } -> Vec4 76 | fromRecord = Native.Math.Vector4.fromRecord 77 | 78 | {-| Vector addition: a + b -} 79 | add : Vec4 -> Vec4 -> Vec4 80 | add = Native.Math.Vector4.add 81 | 82 | {-| Vector subtraction: a - b -} 83 | sub : Vec4 -> Vec4 -> Vec4 84 | sub = Native.Math.Vector4.sub 85 | 86 | {-| Vector negation: -a -} 87 | negate : Vec4 -> Vec4 88 | negate = Native.Math.Vector4.neg 89 | 90 | {-| The normalized direction from b to a: (a - b) / |a - b| -} 91 | direction : Vec4 -> Vec4 -> Vec4 92 | direction = Native.Math.Vector4.direction 93 | 94 | {-| The length of the given vector: |a| -} 95 | length : Vec4 -> Float 96 | length = Native.Math.Vector4.length 97 | 98 | {-| The square of the length of the given vector: |a| * |a| -} 99 | lengthSquared : Vec4 -> Float 100 | lengthSquared = Native.Math.Vector4.lengthSquared 101 | 102 | {-| The distance between two vectors. -} 103 | distance : Vec4 -> Vec4 -> Float 104 | distance = Native.Math.Vector4.distance 105 | 106 | {-| The square of the distance between two vectors. -} 107 | distanceSquared : Vec4 -> Vec4 -> Float 108 | distanceSquared = Native.Math.Vector4.distanceSquared 109 | 110 | {-| A unit vector with the same direction as the given vector: a / |a| -} 111 | normalize : Vec4 -> Vec4 112 | normalize = Native.Math.Vector4.normalize 113 | 114 | {-| Multiply the vector by a scalar: s * v -} 115 | scale : Float -> Vec4 -> Vec4 116 | scale = Native.Math.Vector4.scale 117 | 118 | {-| The dot product of a and b -} 119 | dot : Vec4 -> Vec4 -> Float 120 | dot = Native.Math.Vector4.dot 121 | 122 | -------------------------------------------------------------------------------- /src/Math/Vector3.elm: -------------------------------------------------------------------------------- 1 | module Math.Vector3 exposing (..) 2 | {-| A high performance linear algebra library using native JS arrays. Geared 3 | towards 3D graphics and use with `Graphics.WebGL`. All vectors are immutable. 4 | 5 | # Create 6 | @docs Vec3, vec3, i, j, k 7 | 8 | # Get and Set 9 | The set functions create a new copy of the vector, updating a single field. 10 | 11 | @docs getX, getY, getZ, setX, setY, setZ 12 | 13 | # Operations 14 | @docs add, sub, negate, scale, dot, cross, normalize, direction, 15 | length, lengthSquared, distance, distanceSquared 16 | 17 | # Conversions 18 | @docs toTuple, fromTuple, toRecord, fromRecord 19 | -} 20 | 21 | import Native.MJS 22 | 23 | {-| Three dimensional vector type -} 24 | type Vec3 = Vec3 25 | 26 | {-| Creates a new 3-element vector with the given values. 27 | -} 28 | vec3 : Float -> Float -> Float -> Vec3 29 | vec3 = Native.MJS.vec3 30 | 31 | {-| The unit vector î which points in the x direction: `vec3 1 0 0` -} 32 | i : Vec3 33 | i = Native.MJS.vec3 1 0 0 34 | 35 | {-| The unit vector ĵ which points in the y direction: `vec3 0 1 0` -} 36 | j : Vec3 37 | j = Native.MJS.vec3 0 1 0 38 | 39 | {-| The unit vector k̂ which points in the z direction: `vec3 0 0 1` -} 40 | k : Vec3 41 | k = Native.MJS.vec3 0 0 1 42 | 43 | {-| Extract the x component of a vector. -} 44 | getX : Vec3 -> Float 45 | getX = Native.MJS.v3getX 46 | 47 | {-| Extract the y component of a vector. -} 48 | getY : Vec3 -> Float 49 | getY = Native.MJS.v3getY 50 | 51 | {-| Extract the z component of a vector. -} 52 | getZ : Vec3 -> Float 53 | getZ = Native.MJS.v3getZ 54 | 55 | {-| Update the x component of a vector, returning a new vector. -} 56 | setX : Float -> Vec3 -> Vec3 57 | setX = Native.MJS.v3setX 58 | 59 | {-| Update the y component of a vector, returning a new vector. -} 60 | setY : Float -> Vec3 -> Vec3 61 | setY = Native.MJS.v3setY 62 | 63 | {-| Update the z component of a vector, returning a new vector. -} 64 | setZ : Float -> Vec3 -> Vec3 65 | setZ = Native.MJS.v3setZ 66 | 67 | {-| Convert a vector to a tuple. -} 68 | toTuple : Vec3 -> (Float,Float,Float) 69 | toTuple = Native.MJS.toTuple3 70 | 71 | {-| Convert a vector to a record. -} 72 | toRecord : Vec3 -> { x:Float, y:Float, z:Float } 73 | toRecord = Native.MJS.toRecord3 74 | 75 | {-| Convert a tuple to a vector. -} 76 | fromTuple : (Float,Float,Float) -> Vec3 77 | fromTuple = Native.MJS.fromTuple3 78 | 79 | {-| Convert a record to a vector. -} 80 | fromRecord : { x:Float, y:Float, z:Float } -> Vec3 81 | fromRecord = Native.MJS.fromRecord3 82 | 83 | {-| Vector addition: a + b -} 84 | add : Vec3 -> Vec3 -> Vec3 85 | add = Native.MJS.v3add 86 | 87 | {-| Vector subtraction: a - b -} 88 | sub : Vec3 -> Vec3 -> Vec3 89 | sub = Native.MJS.v3sub 90 | 91 | {-| Vector negation: -a -} 92 | negate : Vec3 -> Vec3 93 | negate = Native.MJS.v3neg 94 | 95 | {-| The normalized direction from b to a: (a - b) / |a - b| -} 96 | direction : Vec3 -> Vec3 -> Vec3 97 | direction = Native.MJS.v3direction 98 | 99 | {-| The length of the given vector: |a| -} 100 | length : Vec3 -> Float 101 | length = Native.MJS.v3length 102 | 103 | {-| The square of the length of the given vector: |a| * |a| -} 104 | lengthSquared : Vec3 -> Float 105 | lengthSquared = Native.MJS.v3lengthSquared 106 | 107 | {-| The distance between two vectors. -} 108 | distance : Vec3 -> Vec3 -> Float 109 | distance = Native.MJS.v3distance 110 | 111 | {-| The square of the distance between two vectors. -} 112 | distanceSquared : Vec3 -> Vec3 -> Float 113 | distanceSquared = Native.MJS.v3distanceSquared 114 | 115 | {-| A unit vector with the same direction as the given vector: a / |a| -} 116 | normalize : Vec3 -> Vec3 117 | normalize = Native.MJS.v3normalize 118 | 119 | {-| Multiply the vector by a scalar: s * v -} 120 | scale : Float -> Vec3 -> Vec3 121 | scale = Native.MJS.v3scale 122 | 123 | {-| The dot product of a and b -} 124 | dot : Vec3 -> Vec3 -> Float 125 | dot = Native.MJS.v3dot 126 | 127 | {-| The cross product of a and b -} 128 | cross : Vec3 -> Vec3 -> Vec3 129 | cross = Native.MJS.v3cross 130 | -------------------------------------------------------------------------------- /src/Native/Math/Vector2.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (c) 2010 Mozilla Corporation 4 | * Copyright (c) 2010 Vladimir Vukicevic 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | /* 29 | * File: mjs 30 | * 31 | * Vector and Matrix math utilities for JavaScript, optimized for WebGL. 32 | * Edited to work with the Elm Programming Language 33 | */ 34 | 35 | var _elm_community$elm_linear_algebra$Native_Math_Vector2 = function() { 36 | 37 | var MJS_FLOAT_ARRAY_TYPE = Float32Array; 38 | 39 | var V2 = { }; 40 | 41 | if (MJS_FLOAT_ARRAY_TYPE == Array) { 42 | V2.$ = function V2_$(x, y) { 43 | return [x, y]; 44 | }; 45 | } else { 46 | V2.$ = function V2_$(x, y) { 47 | return new MJS_FLOAT_ARRAY_TYPE([x, y]); 48 | }; 49 | } 50 | 51 | V2.getX = function V2_getX(a) { 52 | return a[0]; 53 | } 54 | V2.getY = function V2_getY(a) { 55 | return a[1]; 56 | } 57 | V2.setX = function V2_setX(x, a) { 58 | return new MJS_FLOAT_ARRAY_TYPE([x, a[1]]); 59 | } 60 | V2.setY = function V2_setY(y, a) { 61 | return new MJS_FLOAT_ARRAY_TYPE([a[0], y]); 62 | } 63 | 64 | V2.toTuple = function V2_toTuple(a) { 65 | return { 66 | ctor:"_Tuple2", 67 | _0:a[0], 68 | _1:a[1] 69 | }; 70 | }; 71 | V2.fromTuple = function V2_fromTuple(t) { 72 | return new MJS_FLOAT_ARRAY_TYPE([t._0, t._1]); 73 | }; 74 | 75 | V2.toRecord = function V2_toRecord(a) { 76 | return { 77 | _:{}, 78 | x:a[0], 79 | y:a[1] 80 | }; 81 | }; 82 | V2.fromRecord = function V2_fromRecord(r) { 83 | return new MJS_FLOAT_ARRAY_TYPE([r.x, r.y]); 84 | }; 85 | 86 | V2.add = function V2_add(a, b) { 87 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 88 | r[0] = a[0] + b[0]; 89 | r[1] = a[1] + b[1]; 90 | return r; 91 | }; 92 | 93 | V2.sub = function V2_sub(a, b) { 94 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 95 | r[0] = a[0] - b[0]; 96 | r[1] = a[1] - b[1]; 97 | return r; 98 | }; 99 | 100 | V2.neg = function V2_neg(a) { 101 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 102 | r[0] = - a[0]; 103 | r[1] = - a[1]; 104 | return r; 105 | }; 106 | 107 | V2.direction = function V2_direction(a, b) { 108 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 109 | r[0] = a[0] - b[0]; 110 | r[1] = a[1] - b[1]; 111 | var im = 1.0 / V2.length(r); 112 | r[0] = r[0] * im; 113 | r[1] = r[1] * im; 114 | return r; 115 | }; 116 | 117 | V2.length = function V2_length(a) { 118 | return Math.sqrt(a[0]*a[0] + a[1]*a[1]); 119 | }; 120 | 121 | V2.lengthSquared = function V2_lengthSquared(a) { 122 | return a[0]*a[0] + a[1]*a[1]; 123 | }; 124 | 125 | V2.distance = function V2_distance(a, b) { 126 | var dx = a[0] - b[0]; 127 | var dy = a[1] - b[1]; 128 | return Math.sqrt(dx * dx + dy * dy); 129 | }; 130 | 131 | V2.distanceSquared = function V2_distanceSquared(a, b) { 132 | var dx = a[0] - b[0]; 133 | var dy = a[1] - b[1]; 134 | return dx * dx + dy * dy; 135 | }; 136 | 137 | V2.normalize = function V2_normalize(a) { 138 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 139 | var im = 1.0 / V2.length(a); 140 | r[0] = a[0] * im; 141 | r[1] = a[1] * im; 142 | return r; 143 | }; 144 | 145 | V2.scale = function V2_scale(k, a) { 146 | var r = new MJS_FLOAT_ARRAY_TYPE(2); 147 | r[0] = a[0] * k; 148 | r[1] = a[1] * k; 149 | return r; 150 | }; 151 | 152 | V2.dot = function V2_dot(a, b) { 153 | return a[0] * b[0] + a[1] * b[1]; 154 | }; 155 | 156 | return { 157 | vec2: F2(V2.$), 158 | getX: V2.getX, 159 | getY: V2.getY, 160 | setX: F2(V2.setX), 161 | setY: F2(V2.setY), 162 | toTuple: V2.toTuple, 163 | toRecord: V2.toRecord, 164 | fromTuple: V2.fromTuple, 165 | fromRecord: V2.fromRecord, 166 | add: F2(V2.add), 167 | sub: F2(V2.sub), 168 | neg: V2.neg, 169 | direction: F2(V2.direction), 170 | length: V2.length, 171 | lengthSquared: V2.lengthSquared, 172 | distance: F2(V2.distance), 173 | distanceSquared: F2(V2.distanceSquared), 174 | normalize: V2.normalize, 175 | scale: F2(V2.scale), 176 | dot: F2(V2.dot) 177 | }; 178 | 179 | }(); 180 | -------------------------------------------------------------------------------- /src/Math/Matrix4.elm: -------------------------------------------------------------------------------- 1 | module Math.Matrix4 exposing (..) 2 | 3 | {-| A high performance linear algebra library using native JS arrays. Geared 4 | towards 3D graphics and use with `Graphics.WebGL`. All matrices are immutable. 5 | 6 | This library uses the convention that the prefix `make` is creating a new 7 | array,as without the prefix, you are applying some transform to an 8 | existing matrix. 9 | 10 | # Create 11 | 12 | @docs Mat4, identity 13 | 14 | # Operations 15 | 16 | @docs inverseOrthonormal, mul, mulAffine, transpose, makeBasis, transform 17 | 18 | # Projections 19 | 20 | @docs makeFrustum, makePerspective, makeOrtho, makeOrtho2D, makeLookAt 21 | 22 | # Apply Transformations 23 | 24 | @docs rotate, scale, scale3, translate, translate3 25 | 26 | # Create Transformations 27 | 28 | @docs makeRotate, makeScale, makeScale3, makeTranslate, makeTranslate3 29 | 30 | -} 31 | 32 | import Native.MJS 33 | import Math.Vector3 exposing (Vec3) 34 | 35 | {-| 4x4 matrix type -} 36 | type Mat4 = Mat4 37 | 38 | {-| Multiply a vector by a 4x4 matrix: m * v 39 | -} 40 | transform : Mat4 -> Vec3 -> Vec3 41 | transform = Native.MJS.v3mul4x4 42 | 43 | {-| A matrix with all 0s, except 1s on the diagonal. 44 | -} 45 | identity : Mat4 46 | identity = Native.MJS.m4x4identity 47 | 48 | {-| Computes the inverse of the given matrix m, assuming that the matrix is 49 | orthonormal. 50 | -} 51 | inverseOrthonormal : Mat4 -> Mat4 52 | inverseOrthonormal = Native.MJS.m4x4inverseOrthonormal 53 | 54 | {-| Creates a matrix for a projection frustum with the given parameters. 55 | 56 | Parameters: 57 | 58 | * left - the left coordinate of the frustum 59 | * right- the right coordinate of the frustum 60 | * bottom - the bottom coordinate of the frustum 61 | * top - the top coordinate of the frustum 62 | * znear - the near z distance of the frustum 63 | * zfar - the far z distance of the frustum 64 | -} 65 | makeFrustum : Float -> Float -> Float -> Float -> Float -> Float -> Mat4 66 | makeFrustum = Native.MJS.m4x4makeFrustum 67 | 68 | {-| Creates a matrix for a perspective projection with the given parameters. 69 | 70 | Parameters: 71 | 72 | * fovy - field of view in the y axis, in degrees 73 | * aspect - aspect ratio 74 | * znear - the near z distance of the projection 75 | * zfar - the far z distance of the projection 76 | -} 77 | makePerspective : Float -> Float -> Float -> Float -> Mat4 78 | makePerspective = Native.MJS.m4x4makePerspective 79 | 80 | {-| 81 | Creates a matrix for an orthogonal frustum projection with the given parameters. 82 | 83 | Parameters: 84 | 85 | * left - the left coordinate of the frustum 86 | * right- the right coordinate of the frustum 87 | * bottom - the bottom coordinate of the frustum 88 | * top - the top coordinate of the frustum 89 | * znear - the near z distance of the frustum 90 | * zfar - the far z distance of the frustum 91 | -} 92 | makeOrtho : Float -> Float -> Float -> Float -> Float -> Float -> Mat4 93 | makeOrtho = Native.MJS.m4x4makeOrtho 94 | 95 | {-| Creates a matrix for a 2D orthogonal frustum projection with the given 96 | parameters. `znear` and `zfar` are assumed to be -1 and 1, respectively. 97 | 98 | Parameters: 99 | 100 | * left - the left coordinate of the frustum 101 | * right- the right coordinate of the frustum 102 | * bottom - the bottom coordinate of the frustum 103 | * top - the top coordinate of the frustum 104 | -} 105 | makeOrtho2D : Float -> Float -> Float -> Float -> Mat4 106 | makeOrtho2D = Native.MJS.m4x4makeOrtho2D 107 | 108 | {-| Matrix multiplcation: a * b 109 | -} 110 | mul : Mat4 -> Mat4 -> Mat4 111 | mul = Native.MJS.m4x4mul 112 | 113 | {-| Matrix multiplication, assuming a and b are affine: a * b 114 | -} 115 | mulAffine : Mat4 -> Mat4 -> Mat4 116 | mulAffine = Native.MJS.m4x4mulAffine 117 | 118 | {-| Creates a transformation matrix for rotation in radians about the 119 | 3-element vector axis. 120 | -} 121 | makeRotate : Float -> Vec3 -> Mat4 122 | makeRotate = Native.MJS.m4x4makeRotate 123 | 124 | {-| Concatenates a rotation in radians about an axis to the given matrix. 125 | -} 126 | rotate : Float -> Vec3 -> Mat4 -> Mat4 127 | rotate = Native.MJS.m4x4rotate 128 | 129 | {-| Creates a transformation matrix for scaling by 3 scalar values, one for 130 | each of the x, y, and z directions. 131 | -} 132 | makeScale3 : Float -> Float -> Float -> Mat4 133 | makeScale3 = Native.MJS.m4x4makeScale3 134 | 135 | {-| Creates a transformation matrix for scaling each of the x, y, and z axes by 136 | the amount given in the corresponding element of the 3-element vector. 137 | -} 138 | makeScale : Vec3 -> Mat4 139 | makeScale = Native.MJS.m4x4makeScale 140 | 141 | {-| Concatenates a scaling to the given matrix. 142 | -} 143 | scale3 : Float -> Float -> Float -> Mat4 -> Mat4 144 | scale3 = Native.MJS.m4x4scale3 145 | 146 | {-| Concatenates a scaling to the given matrix. 147 | -} 148 | scale : Vec3 -> Mat4 -> Mat4 149 | scale = Native.MJS.m4x4scale 150 | 151 | {-| 152 | Creates a transformation matrix for translating by 3 scalar values, one for 153 | each of the x, y, and z directions. 154 | -} 155 | makeTranslate3 : Float -> Float -> Float -> Mat4 156 | makeTranslate3 = Native.MJS.m4x4makeTranslate3 157 | 158 | {-| Creates a transformation matrix for translating each of the x, y, and z 159 | axes by the amount given in the corresponding element of the 3-element vector. 160 | -} 161 | makeTranslate : Vec3 -> Mat4 162 | makeTranslate = Native.MJS.m4x4makeTranslate 163 | 164 | {-| 165 | Concatenates a translation to the given matrix. 166 | -} 167 | translate3 : Float -> Float -> Float -> Mat4 -> Mat4 168 | translate3 = Native.MJS.m4x4translate3 169 | 170 | {-| 171 | Concatenates a translation to the given matrix. 172 | -} 173 | translate : Vec3 -> Mat4 -> Mat4 174 | translate = Native.MJS.m4x4translate 175 | 176 | {-| 177 | Creates a transformation matrix for a camera. 178 | 179 | Parameters: 180 | 181 | * eye - The location of the camera 182 | * center - The location of the focused object 183 | * up - The "up" direction according to the camera 184 | -} 185 | makeLookAt : Vec3 -> Vec3 -> Vec3 -> Mat4 186 | makeLookAt = Native.MJS.m4x4makeLookAt 187 | 188 | {-| "Flip" the matrix across the diagonal by swapping row index and column 189 | index. 190 | -} 191 | transpose : Mat4 -> Mat4 192 | transpose = Native.MJS.m4x4transpose 193 | 194 | {-| Creates a transform from a basis consisting of 3 linearly independent vectors. 195 | -} 196 | makeBasis : Vec3 -> Vec3 -> Vec3 -> Mat4 197 | makeBasis = Native.MJS.m4x4makeBasis 198 | -------------------------------------------------------------------------------- /src/Native/Math/Vector4.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (c) 2010 Mozilla Corporation 4 | * Copyright (c) 2010 Vladimir Vukicevic 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | /* 29 | * File: mjs 30 | * 31 | * Vector and Matrix math utilities for JavaScript, optimized for WebGL. 32 | * Edited to work with the Elm Programming Language 33 | */ 34 | 35 | var _elm_community$elm_linear_algebra$Native_Math_Vector4 = function() { 36 | 37 | var MJS_FLOAT_ARRAY_TYPE = Float32Array; 38 | 39 | var V4 = { }; 40 | 41 | if (MJS_FLOAT_ARRAY_TYPE == Array) { 42 | V4.$ = function V4_$(x, y, z, w) { 43 | return [x, y, z, w]; 44 | }; 45 | } else { 46 | V4.$ = function V4_$(x, y, z, w) { 47 | return new MJS_FLOAT_ARRAY_TYPE([x, y, z, w]); 48 | }; 49 | } 50 | 51 | V4.getX = function V4_getX(a) { 52 | return a[0]; 53 | } 54 | V4.getY = function V4_getY(a) { 55 | return a[1]; 56 | } 57 | V4.getZ = function V4_getZ(a) { 58 | return a[2]; 59 | } 60 | V4.getW = function V4_getW(a) { 61 | return a[3]; 62 | } 63 | V4.setX = function V4_setX(x, a) { 64 | return new MJS_FLOAT_ARRAY_TYPE(x, a[1], a[2], a[3]); 65 | } 66 | V4.setY = function V4_setY(y, a) { 67 | return new MJS_FLOAT_ARRAY_TYPE(a[0], y, a[2], a[3]); 68 | } 69 | V4.setZ = function V4_setZ(z, a) { 70 | return new MJS_FLOAT_ARRAY_TYPE(a[0], a[1], z, a[3]); 71 | } 72 | V4.setW = function V4_setW(w, a) { 73 | return new MJS_FLOAT_ARRAY_TYPE(a[0], a[1], a[2], w); 74 | } 75 | 76 | V4.toTuple = function V4_toTuple(a) { 77 | return { 78 | ctor:"_Tuple4", 79 | _0:a[0], 80 | _1:a[1], 81 | _2:a[2], 82 | _3:a[3] 83 | }; 84 | }; 85 | V4.fromTuple = function V4_fromTuple(t) { 86 | return new MJS_FLOAT_ARRAY_TYPE([t._0, t._1, t._2, t._3]); 87 | }; 88 | 89 | V4.toRecord = function V4_toRecord(a) { 90 | return { 91 | _:{}, 92 | x:a[0], 93 | y:a[1], 94 | z:a[2], 95 | w:a[3] 96 | }; 97 | }; 98 | V4.fromRecord = function V4_fromRecord(r) { 99 | return new MJS_FLOAT_ARRAY_TYPE([r.x, r.y, r.z, r.w]); 100 | }; 101 | 102 | V4.add = function V4_add(a, b) { 103 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 104 | r[0] = a[0] + b[0]; 105 | r[1] = a[1] + b[1]; 106 | r[2] = a[2] + b[2]; 107 | r[3] = a[3] + b[3]; 108 | return r; 109 | }; 110 | 111 | V4.sub = function V4_sub(a, b) { 112 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 113 | r[0] = a[0] - b[0]; 114 | r[1] = a[1] - b[1]; 115 | r[2] = a[2] - b[2]; 116 | r[3] = a[3] - b[3]; 117 | return r; 118 | }; 119 | 120 | V4.neg = function V4_neg(a) { 121 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 122 | r[0] = - a[0]; 123 | r[1] = - a[1]; 124 | r[2] = - a[2]; 125 | r[3] = - a[3]; 126 | return r; 127 | }; 128 | 129 | V4.direction = function V4_direction(a, b) { 130 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 131 | r[0] = a[0] - b[0]; 132 | r[1] = a[1] - b[1]; 133 | r[2] = a[2] - b[2]; 134 | r[3] = a[3] - b[3]; 135 | var im = 1.0 / V4.length(r); 136 | r[0] = r[0] * im; 137 | r[1] = r[1] * im; 138 | r[2] = r[2] * im; 139 | r[3] = r[3] * im; 140 | return r; 141 | }; 142 | 143 | V4.length = function V4_length(a) { 144 | return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3]); 145 | }; 146 | 147 | V4.lengthSquared = function V4_lengthSquared(a) { 148 | return a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3]; 149 | }; 150 | 151 | V4.distance = function V4_distance(a, b) { 152 | var dx = a[0] - b[0]; 153 | var dy = a[1] - b[1]; 154 | var dz = a[2] - b[2]; 155 | var dw = a[3] - b[3]; 156 | return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw); 157 | }; 158 | 159 | V4.distanceSquared = function V4_distanceSquared(a, b) { 160 | var dx = a[0] - b[0]; 161 | var dy = a[1] - b[1]; 162 | var dz = a[2] - b[2]; 163 | var dw = a[3] - b[3]; 164 | return dx * dx + dy * dy + dz * dz + dw * dw; 165 | }; 166 | 167 | V4.normalize = function V4_normalize(a) { 168 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 169 | var im = 1.0 / V4.length(a); 170 | r[0] = a[0] * im; 171 | r[1] = a[1] * im; 172 | r[2] = a[2] * im; 173 | r[3] = a[3] * im; 174 | return r; 175 | }; 176 | 177 | V4.scale = function V4_scale(k, a) { 178 | var r = new MJS_FLOAT_ARRAY_TYPE(4); 179 | r[0] = a[0] * k; 180 | r[1] = a[1] * k; 181 | r[2] = a[2] * k; 182 | r[3] = a[3] * k; 183 | return r; 184 | }; 185 | 186 | V4.dot = function V4_dot(a, b) { 187 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 188 | }; 189 | 190 | return { 191 | vec4: F4(V4.$), 192 | getX: V4.getX, 193 | getY: V4.getY, 194 | getZ: V4.getZ, 195 | getW: V4.getW, 196 | setX: F2(V4.setX), 197 | setY: F2(V4.setY), 198 | setZ: F2(V4.setZ), 199 | setW: F2(V4.setW), 200 | toTuple: V4.toTuple, 201 | toRecord: V4.toRecord, 202 | fromTuple: V4.fromTuple, 203 | fromRecord: V4.fromRecord, 204 | add: F2(V4.add), 205 | sub: F2(V4.sub), 206 | neg: V4.neg, 207 | direction: F2(V4.direction), 208 | length: V4.length, 209 | lengthSquared: V4.lengthSquared, 210 | distance: F2(V4.distance), 211 | distanceSquared: F2(V4.distanceSquared), 212 | normalize: V4.normalize, 213 | scale: F2(V4.scale), 214 | dot: F2(V4.dot) 215 | }; 216 | 217 | }(); 218 | -------------------------------------------------------------------------------- /src/Native/MJS.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (c) 2010 Mozilla Corporation 4 | * Copyright (c) 2010 Vladimir Vukicevic 5 | * Copyright (c) 2013 John Mayer 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | /* 30 | * File: mjs 31 | * 32 | * Vector and Matrix math utilities for JavaScript, optimized for WebGL. 33 | * Edited to work with the Elm Programming Language 34 | */ 35 | 36 | var _elm_community$elm_linear_algebra$Native_MJS = function() { 37 | 38 | 39 | /* 40 | * Constant: MJS_VERSION 41 | * 42 | * mjs version number aa.bb.cc, encoded as an integer of the form: 43 | * 0xaabbcc. 44 | */ 45 | var MJS_VERSION = 0x000000; 46 | 47 | /* 48 | * Constant: MJS_DO_ASSERT 49 | * 50 | * Enables or disables runtime assertions. 51 | * 52 | * For potentially more performance, the assert methods can be 53 | * commented out in each place where they are called. 54 | */ 55 | // var MJS_DO_ASSERT = false; 56 | 57 | /* 58 | * Constant: MJS_FLOAT_ARRAY_TYPE 59 | * 60 | * The base float array type. By default, WebGLFloatArray. 61 | * 62 | * mjs can work with any array-like elements, but if an array 63 | * creation is requested, it will create an array of the type 64 | * MJS_FLOAT_ARRAY_TYPE. Also, the builtin constants such as (M4x4.I) 65 | * will be of this type. 66 | */ 67 | //MJS_FLOAT_ARRAY_TYPE = WebGLFloatArray; 68 | var MJS_FLOAT_ARRAY_TYPE = Float32Array; 69 | //MJS_FLOAT_ARRAY_TYPE = Float64Array; 70 | //MJS_FLOAT_ARRAY_TYPE = Array; 71 | 72 | /* 73 | if (MJS_DO_ASSERT) { 74 | function MathUtils_assert(cond, msg) { 75 | if (!cond) { 76 | throw "Assertion failed: " + msg; 77 | } 78 | } 79 | } else { 80 | */ 81 | function MathUtils_assert() { } 82 | //} 83 | 84 | /* 85 | * Class: V3 86 | * 87 | * Methods for working with 3-element vectors. A vector is represented by a 3-element array. 88 | * Any valid JavaScript array type may be used, but if new 89 | * vectors are created they are created using the configured MJS_FLOAT_ARRAY_TYPE. 90 | */ 91 | 92 | var V3 = { }; 93 | 94 | V3._temp1 = new MJS_FLOAT_ARRAY_TYPE(3); 95 | V3._temp2 = new MJS_FLOAT_ARRAY_TYPE(3); 96 | V3._temp3 = new MJS_FLOAT_ARRAY_TYPE(3); 97 | 98 | if (MJS_FLOAT_ARRAY_TYPE == Array) { 99 | V3.x = [1.0, 0.0, 0.0]; 100 | V3.y = [0.0, 1.0, 0.0]; 101 | V3.z = [0.0, 0.0, 1.0]; 102 | 103 | V3.$ = function V3_$(x, y, z) { 104 | return [x, y, z]; 105 | }; 106 | } else { 107 | V3.x = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0]); 108 | V3.y = new MJS_FLOAT_ARRAY_TYPE([0.0, 1.0, 0.0]); 109 | V3.z = new MJS_FLOAT_ARRAY_TYPE([0.0, 0.0, 1.0]); 110 | 111 | /* 112 | * Function: V3.$ 113 | * 114 | * Creates a new 3-element vector with the given values. 115 | * 116 | * Parameters: 117 | * 118 | * x,y,z - the 3 elements of the new vector. 119 | * 120 | * Returns: 121 | * 122 | * A new vector containing with the given argument values. 123 | */ 124 | 125 | V3.$ = function V3_$(x, y, z) { 126 | return new MJS_FLOAT_ARRAY_TYPE([x, y, z]); 127 | }; 128 | } 129 | 130 | V3.u = V3.x; 131 | V3.v = V3.y; 132 | 133 | V3.getX = function V3_getX(a) { 134 | return a[0]; 135 | } 136 | V3.getY = function V3_getY(a) { 137 | return a[1]; 138 | } 139 | V3.getZ = function V3_getZ(a) { 140 | return a[2]; 141 | } 142 | V3.setX = function V3_setX(x, a) { 143 | return new MJS_FLOAT_ARRAY_TYPE([x, a[1], a[2]]); 144 | } 145 | V3.setY = function V3_setY(y, a) { 146 | return new MJS_FLOAT_ARRAY_TYPE([a[0], y, a[2]]); 147 | } 148 | V3.setZ = function V3_setZ(z, a) { 149 | return new MJS_FLOAT_ARRAY_TYPE([a[0], a[1], z]); 150 | } 151 | 152 | V3.toTuple3 = function V3_toTuple3(a) { 153 | return { 154 | ctor:"_Tuple3", 155 | _0:a[0], 156 | _1:a[1], 157 | _2:a[2] 158 | }; 159 | }; 160 | V3.fromTuple3 = function V3_fromTuple3(t) { 161 | return new MJS_FLOAT_ARRAY_TYPE([t._0, t._1, t._2]); 162 | }; 163 | 164 | V3.toRecord3 = function V3_toRecord3(a) { 165 | return { 166 | _:{}, 167 | x:a[0], 168 | y:a[1], 169 | z:a[2] 170 | }; 171 | }; 172 | V3.fromRecord3 = function V3_fromRecord3(r) { 173 | return new MJS_FLOAT_ARRAY_TYPE([r.x, r.y, r.z]); 174 | }; 175 | 176 | /* 177 | * Function: V3.add 178 | * 179 | * Perform r = a + b. 180 | * 181 | * Parameters: 182 | * 183 | * a - the first vector operand 184 | * b - the second vector operand 185 | * r - optional vector to store the result in 186 | * 187 | * Returns: 188 | * 189 | * If r is specified, returns r after performing the operation. 190 | * Otherwise, returns a new 3-element vector with the result. 191 | */ 192 | V3.add = function V3_add(a, b, r) { 193 | //MathUtils_assert(a.length == 3, "a.length == 3"); 194 | //MathUtils_assert(b.length == 3, "b.length == 3"); 195 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 196 | 197 | if (r == undefined) 198 | r = new MJS_FLOAT_ARRAY_TYPE(3); 199 | r[0] = a[0] + b[0]; 200 | r[1] = a[1] + b[1]; 201 | r[2] = a[2] + b[2]; 202 | return r; 203 | }; 204 | 205 | /* 206 | * Function: V3.sub 207 | * 208 | * Perform 209 | * r = a - b. 210 | * 211 | * Parameters: 212 | * 213 | * a - the first vector operand 214 | * b - the second vector operand 215 | * r - optional vector to store the result in 216 | * 217 | * Returns: 218 | * 219 | * If r is specified, returns r after performing the operation. 220 | * Otherwise, returns a new 3-element vector with the result. 221 | */ 222 | V3.sub = function V3_sub(a, b, r) { 223 | //MathUtils_assert(a.length == 3, "a.length == 3"); 224 | //MathUtils_assert(b.length == 3, "b.length == 3"); 225 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 226 | 227 | if (r == undefined) 228 | r = new MJS_FLOAT_ARRAY_TYPE(3); 229 | r[0] = a[0] - b[0]; 230 | r[1] = a[1] - b[1]; 231 | r[2] = a[2] - b[2]; 232 | return r; 233 | }; 234 | 235 | /* 236 | * Function: V3.neg 237 | * 238 | * Perform 239 | * r = - a. 240 | * 241 | * Parameters: 242 | * 243 | * a - the vector operand 244 | * r - optional vector to store the result in 245 | * 246 | * Returns: 247 | * 248 | * If r is specified, returns r after performing the operation. 249 | * Otherwise, returns a new 3-element vector with the result. 250 | */ 251 | V3.neg = function V3_neg(a, r) { 252 | //MathUtils_assert(a.length == 3, "a.length == 3"); 253 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 254 | 255 | if (r == undefined) 256 | r = new MJS_FLOAT_ARRAY_TYPE(3); 257 | r[0] = - a[0]; 258 | r[1] = - a[1]; 259 | r[2] = - a[2]; 260 | return r; 261 | }; 262 | 263 | /* 264 | * Function: V3.direction 265 | * 266 | * Perform 267 | * r = (a - b) / |a - b|. The result is the normalized 268 | * direction from a to b. 269 | * 270 | * Parameters: 271 | * 272 | * a - the first vector operand 273 | * b - the second vector operand 274 | * r - optional vector to store the result in 275 | * 276 | * Returns: 277 | * 278 | * If r is specified, returns r after performing the operation. 279 | * Otherwise, returns a new 3-element vector with the result. 280 | */ 281 | V3.direction = function V3_direction(a, b, r) { 282 | //MathUtils_assert(a.length == 3, "a.length == 3"); 283 | //MathUtils_assert(b.length == 3, "b.length == 3"); 284 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 285 | 286 | if (r == undefined) 287 | r = new MJS_FLOAT_ARRAY_TYPE(3); 288 | return V3.normalize(V3.sub(a, b, r), r); 289 | }; 290 | 291 | /* 292 | * Function: V3.length 293 | * 294 | * Perform r = |a|. 295 | * 296 | * Parameters: 297 | * 298 | * a - the vector operand 299 | * 300 | * Returns: 301 | * 302 | * The length of the given vector. 303 | */ 304 | V3.length = function V3_length(a) { 305 | //MathUtils_assert(a.length == 3, "a.length == 3"); 306 | 307 | return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); 308 | }; 309 | 310 | /* 311 | * Function: V3.lengthSquard 312 | * 313 | * Perform r = |a|*|a|. 314 | * 315 | * Parameters: 316 | * 317 | * a - the vector operand 318 | * 319 | * Returns: 320 | * 321 | * The square of the length of the given vector. 322 | */ 323 | V3.lengthSquared = function V3_lengthSquared(a) { 324 | //MathUtils_assert(a.length == 3, "a.length == 3"); 325 | 326 | return a[0]*a[0] + a[1]*a[1] + a[2]*a[2]; 327 | }; 328 | 329 | V3.distance = function V3_distance(a, b) { 330 | var dx = a[0] - b[0]; 331 | var dy = a[1] - b[1]; 332 | var dz = a[2] - b[2]; 333 | return Math.sqrt(dx * dx + dy * dy + dz * dz); 334 | }; 335 | 336 | V3.distanceSquared = function V3_distanceSquared(a, b) { 337 | var dx = a[0] - b[0]; 338 | var dy = a[1] - b[1]; 339 | var dz = a[2] - b[2]; 340 | return dx * dx + dy * dy + dz * dz; 341 | }; 342 | 343 | /* 344 | * Function: V3.normalize 345 | * 346 | * Perform r = a / |a|. 347 | * 348 | * Parameters: 349 | * 350 | * a - the vector operand 351 | * r - optional vector to store the result in 352 | * 353 | * Returns: 354 | * 355 | * If r is specified, returns r after performing the operation. 356 | * Otherwise, returns a new 3-element vector with the result. 357 | */ 358 | V3.normalize = function V3_normalize(a, r) { 359 | //MathUtils_assert(a.length == 3, "a.length == 3"); 360 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 361 | 362 | if (r == undefined) 363 | r = new MJS_FLOAT_ARRAY_TYPE(3); 364 | var im = 1.0 / V3.length(a); 365 | r[0] = a[0] * im; 366 | r[1] = a[1] * im; 367 | r[2] = a[2] * im; 368 | return r; 369 | }; 370 | 371 | /* 372 | * Function: V3.scale 373 | * 374 | * Perform r = k * a. 375 | * 376 | * Parameters: 377 | * 378 | * a - the vector operand 379 | * k - a scalar value 380 | * r - optional vector to store the result in 381 | * 382 | * Returns: 383 | * 384 | * If r is specified, returns r after performing the operation. 385 | * Otherwise, returns a new 3-element vector with the result. 386 | */ 387 | V3.scale = function V3_scale(k, a, r) { 388 | //MathUtils_assert(a.length == 3, "a.length == 3"); 389 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 390 | 391 | if (r == undefined) 392 | r = new MJS_FLOAT_ARRAY_TYPE(3); 393 | r[0] = a[0] * k; 394 | r[1] = a[1] * k; 395 | r[2] = a[2] * k; 396 | return r; 397 | }; 398 | 399 | /* 400 | * Function: V3.dot 401 | * 402 | * Perform 403 | * r = dot(a, b). 404 | * 405 | * Parameters: 406 | * 407 | * a - the first vector operand 408 | * b - the second vector operand 409 | * 410 | * Returns: 411 | * 412 | * The dot product of a and b. 413 | */ 414 | V3.dot = function V3_dot(a, b) { 415 | //MathUtils_assert(a.length == 3, "a.length == 3"); 416 | //MathUtils_assert(b.length == 3, "b.length == 3"); 417 | 418 | return a[0] * b[0] + 419 | a[1] * b[1] + 420 | a[2] * b[2]; 421 | }; 422 | 423 | /* 424 | * Function: V3.cross 425 | * 426 | * Perform r = a x b. 427 | * 428 | * Parameters: 429 | * 430 | * a - the first vector operand 431 | * b - the second vector operand 432 | * r - optional vector to store the result in 433 | * 434 | * Returns: 435 | * 436 | * If r is specified, returns r after performing the operation. 437 | * Otherwise, returns a new 3-element vector with the result. 438 | */ 439 | V3.cross = function V3_cross(a, b, r) { 440 | //MathUtils_assert(a.length == 3, "a.length == 3"); 441 | //MathUtils_assert(b.length == 3, "b.length == 3"); 442 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 443 | 444 | if (r == undefined) 445 | r = new MJS_FLOAT_ARRAY_TYPE(3); 446 | r[0] = a[1]*b[2] - a[2]*b[1]; 447 | r[1] = a[2]*b[0] - a[0]*b[2]; 448 | r[2] = a[0]*b[1] - a[1]*b[0]; 449 | return r; 450 | }; 451 | 452 | /* 453 | * Function: V3.mul4x4 454 | * 455 | * Perform 456 | * r = m * v. 457 | * 458 | * Parameters: 459 | * 460 | * m - the 4x4 matrix operand 461 | * v - the 3-element vector operand 462 | * r - optional vector to store the result in 463 | * 464 | * Returns: 465 | * 466 | * If r is specified, returns r after performing the operation. 467 | * Otherwise, returns a new 3-element vector with the result. 468 | * The 4-element result vector is divided by the w component 469 | * and returned as a 3-element vector. 470 | */ 471 | V3.mul4x4 = function V3_mul4x4(m, v, r) { 472 | //MathUtils_assert(m.length == 16, "m.length == 16"); 473 | //MathUtils_assert(v.length == 3, "v.length == 3"); 474 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 475 | 476 | var w; 477 | var tmp = V3._temp1; 478 | if (r == undefined) 479 | r = new MJS_FLOAT_ARRAY_TYPE(3); 480 | tmp[0] = m[ 3]; 481 | tmp[1] = m[ 7]; 482 | tmp[2] = m[11]; 483 | w = V3.dot(v, tmp) + m[15]; 484 | tmp[0] = m[ 0]; 485 | tmp[1] = m[ 4]; 486 | tmp[2] = m[ 8]; 487 | r[0] = (V3.dot(v, tmp) + m[12])/w; 488 | tmp[0] = m[ 1]; 489 | tmp[1] = m[ 5]; 490 | tmp[2] = m[ 9]; 491 | r[1] = (V3.dot(v, tmp) + m[13])/w; 492 | tmp[0] = m[ 2]; 493 | tmp[1] = m[ 6]; 494 | tmp[2] = m[10]; 495 | r[2] = (V3.dot(v, tmp) + m[14])/w; 496 | return r; 497 | }; 498 | 499 | /* 500 | * Class: M4x4 501 | * 502 | * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array 503 | * in column-major order. Any valid JavaScript array type may be used, but if new 504 | * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE. 505 | */ 506 | 507 | var M4x4 = { }; 508 | 509 | M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16); 510 | M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16); 511 | 512 | if (MJS_FLOAT_ARRAY_TYPE == Array) { 513 | M4x4.I = [1.0, 0.0, 0.0, 0.0, 514 | 0.0, 1.0, 0.0, 0.0, 515 | 0.0, 0.0, 1.0, 0.0, 516 | 0.0, 0.0, 0.0, 1.0]; 517 | 518 | M4x4.$ = function M4x4_$(m00, m01, m02, m03, 519 | m04, m05, m06, m07, 520 | m08, m09, m10, m11, 521 | m12, m13, m14, m15) 522 | { 523 | return [m00, m01, m02, m03, 524 | m04, m05, m06, m07, 525 | m08, m09, m10, m11, 526 | m12, m13, m14, m15]; 527 | }; 528 | } else { 529 | M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0, 530 | 0.0, 1.0, 0.0, 0.0, 531 | 0.0, 0.0, 1.0, 0.0, 532 | 0.0, 0.0, 0.0, 1.0]); 533 | 534 | /* 535 | * Function: M4x4.$ 536 | * 537 | * Creates a new 4x4 matrix with the given values. 538 | * 539 | * Parameters: 540 | * 541 | * m00..m15 - the 16 elements of the new matrix. 542 | * 543 | * Returns: 544 | * 545 | * A new matrix filled with the given argument values. 546 | */ 547 | M4x4.$ = function M4x4_$(m00, m01, m02, m03, 548 | m04, m05, m06, m07, 549 | m08, m09, m10, m11, 550 | m12, m13, m14, m15) 551 | { 552 | return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03, 553 | m04, m05, m06, m07, 554 | m08, m09, m10, m11, 555 | m12, m13, m14, m15]); 556 | }; 557 | } 558 | 559 | M4x4.identity = M4x4.I; 560 | 561 | /* 562 | * Function: M4x4.topLeft3x3 563 | * 564 | * Return the top left 3x3 matrix from the given 4x4 matrix m. 565 | * 566 | * Parameters: 567 | * 568 | * m - the matrix 569 | * r - optional 3x3 matrix to store the result in 570 | * 571 | * Returns: 572 | * 573 | * If r is specified, returns r after performing the operation. 574 | * Otherwise, returns a new 3x3 matrix with the result. 575 | */ 576 | M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) { 577 | //MathUtils_assert(m.length == 16, "m.length == 16"); 578 | //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9"); 579 | 580 | if (r == undefined) 581 | r = new MJS_FLOAT_ARRAY_TYPE(9); 582 | r[0] = m[0]; r[1] = m[1]; r[2] = m[2]; 583 | r[3] = m[4]; r[4] = m[5]; r[5] = m[6]; 584 | r[6] = m[8]; r[7] = m[9]; r[8] = m[10]; 585 | return r; 586 | }; 587 | 588 | /* 589 | * Function: M4x4.inverseOrthonormal 590 | * 591 | * Computes the inverse of the given matrix m, assuming that 592 | * the matrix is orthonormal. 593 | * 594 | * Parameters: 595 | * 596 | * m - the matrix 597 | * r - optional 4x4 matrix to store the result in 598 | * 599 | * Returns: 600 | * 601 | * If r is specified, returns r after performing the operation. 602 | * Otherwise, returns a new 4x4 matrix with the result. 603 | */ 604 | M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) { 605 | //MathUtils_assert(m.length == 16, "m.length == 16"); 606 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 607 | //MathUtils_assert(m != r, "m != r"); 608 | 609 | if (r == undefined) 610 | r = new MJS_FLOAT_ARRAY_TYPE(16); 611 | M4x4.transpose(m, r); 612 | var t = [m[12], m[13], m[14]]; 613 | r[3] = r[7] = r[11] = 0; 614 | r[12] = -V3.dot([r[0], r[4], r[8]], t); 615 | r[13] = -V3.dot([r[1], r[5], r[9]], t); 616 | r[14] = -V3.dot([r[2], r[6], r[10]], t); 617 | return r; 618 | }; 619 | 620 | /* 621 | * Function: M4x4.inverseTo3x3 622 | * 623 | * Computes the inverse of the given matrix m, but calculates 624 | * only the top left 3x3 values of the result. 625 | * 626 | * Parameters: 627 | * 628 | * m - the matrix 629 | * r - optional 3x3 matrix to store the result in 630 | * 631 | * Returns: 632 | * 633 | * If r is specified, returns r after performing the operation. 634 | * Otherwise, returns a new 3x3 matrix with the result. 635 | */ 636 | M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) { 637 | //MathUtils_assert(m.length == 16, "m.length == 16"); 638 | //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9"); 639 | 640 | if (r == undefined) 641 | r = new MJS_FLOAT_ARRAY_TYPE(9); 642 | 643 | var a11 = m[10]*m[5]-m[6]*m[9], 644 | a21 = -m[10]*m[1]+m[2]*m[9], 645 | a31 = m[6]*m[1]-m[2]*m[5], 646 | a12 = -m[10]*m[4]+m[6]*m[8], 647 | a22 = m[10]*m[0]-m[2]*m[8], 648 | a32 = -m[6]*m[0]+m[2]*m[4], 649 | a13 = m[9]*m[4]-m[5]*m[8], 650 | a23 = -m[9]*m[0]+m[1]*m[8], 651 | a33 = m[5]*m[0]-m[1]*m[4]; 652 | var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13); 653 | if (det == 0) // no inverse 654 | throw "matrix not invertible"; 655 | var idet = 1.0 / det; 656 | 657 | r[0] = idet*a11; 658 | r[1] = idet*a21; 659 | r[2] = idet*a31; 660 | r[3] = idet*a12; 661 | r[4] = idet*a22; 662 | r[5] = idet*a32; 663 | r[6] = idet*a13; 664 | r[7] = idet*a23; 665 | r[8] = idet*a33; 666 | 667 | return r; 668 | }; 669 | 670 | /* 671 | * Function: M4x4.makeFrustum 672 | * 673 | * Creates a matrix for a projection frustum with the given parameters. 674 | * 675 | * Parameters: 676 | * 677 | * left - the left coordinate of the frustum 678 | * right- the right coordinate of the frustum 679 | * bottom - the bottom coordinate of the frustum 680 | * top - the top coordinate of the frustum 681 | * znear - the near z distance of the frustum 682 | * zfar - the far z distance of the frustum 683 | * r - optional 4x4 matrix to store the result in 684 | * 685 | * Returns: 686 | * 687 | * If r is specified, returns r after creating the projection matrix. 688 | * Otherwise, returns a new 4x4 matrix. 689 | */ 690 | M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) { 691 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 692 | 693 | if (r == undefined) 694 | r = new MJS_FLOAT_ARRAY_TYPE(16); 695 | 696 | var X = 2*znear/(right-left); 697 | var Y = 2*znear/(top-bottom); 698 | var A = (right+left)/(right-left); 699 | var B = (top+bottom)/(top-bottom); 700 | var C = -(zfar+znear)/(zfar-znear); 701 | var D = -2*zfar*znear/(zfar-znear); 702 | 703 | r[0] = 2*znear/(right-left); 704 | r[1] = 0; 705 | r[2] = 0; 706 | r[3] = 0; 707 | r[4] = 0; 708 | r[5] = 2*znear/(top-bottom); 709 | r[6] = 0; 710 | r[7] = 0; 711 | r[8] = (right+left)/(right-left); 712 | r[9] = (top+bottom)/(top-bottom); 713 | r[10] = -(zfar+znear)/(zfar-znear); 714 | r[11] = -1; 715 | r[12] = 0; 716 | r[13] = 0; 717 | r[14] = -2*zfar*znear/(zfar-znear); 718 | r[15] = 0; 719 | 720 | return r; 721 | }; 722 | 723 | /* 724 | * Function: M4x4.makePerspective 725 | * 726 | * Creates a matrix for a perspective projection with the given parameters. 727 | * 728 | * Parameters: 729 | * 730 | * fovy - field of view in the y axis, in degrees 731 | * aspect - aspect ratio 732 | * znear - the near z distance of the projection 733 | * zfar - the far z distance of the projection 734 | * r - optional 4x4 matrix to store the result in 735 | * 736 | * Returns: 737 | * 738 | * If r is specified, returns r after creating the projection matrix. 739 | * Otherwise, returns a new 4x4 matrix. 740 | */ 741 | M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) { 742 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 743 | 744 | var ymax = znear * Math.tan(fovy * Math.PI / 360.0); 745 | var ymin = -ymax; 746 | var xmin = ymin * aspect; 747 | var xmax = ymax * aspect; 748 | 749 | return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r); 750 | }; 751 | 752 | /* 753 | * Function: M4x4.makeOrtho 754 | * 755 | * Creates a matrix for an orthogonal frustum projection with the given parameters. 756 | * 757 | * Parameters: 758 | * 759 | * left - the left coordinate of the frustum 760 | * right- the right coordinate of the frustum 761 | * bottom - the bottom coordinate of the frustum 762 | * top - the top coordinate of the frustum 763 | * znear - the near z distance of the frustum 764 | * zfar - the far z distance of the frustum 765 | * r - optional 4x4 matrix to store the result in 766 | * 767 | * Returns: 768 | * 769 | * If r is specified, returns r after creating the projection matrix. 770 | * Otherwise, returns a new 4x4 matrix. 771 | */ 772 | M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) { 773 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 774 | 775 | if (r == undefined) 776 | r = new MJS_FLOAT_ARRAY_TYPE(16); 777 | 778 | var tX = -(right+left)/(right-left); 779 | var tY = -(top+bottom)/(top-bottom); 780 | var tZ = -(zfar+znear)/(zfar-znear); 781 | var X = 2 / (right-left); 782 | var Y = 2 / (top-bottom); 783 | var Z = -2 / (zfar-znear); 784 | 785 | r[0] = 2 / (right-left); 786 | r[1] = 0; 787 | r[2] = 0; 788 | r[3] = 0; 789 | r[4] = 0; 790 | r[5] = 2 / (top-bottom); 791 | r[6] = 0; 792 | r[7] = 0; 793 | r[8] = 0; 794 | r[9] = 0; 795 | r[10] = -2 / (zfar-znear); 796 | r[11] = 0; 797 | r[12] = -(right+left)/(right-left); 798 | r[13] = -(top+bottom)/(top-bottom); 799 | r[14] = -(zfar+znear)/(zfar-znear); 800 | r[15] = 1; 801 | 802 | return r; 803 | }; 804 | 805 | /* 806 | * Function: M4x4.makeOrtho2D 807 | * 808 | * Creates a matrix for a 2D orthogonal frustum projection with the given parameters. 809 | * znear and zfar are assumed to be -1 and 1, respectively. 810 | * 811 | * Parameters: 812 | * 813 | * left - the left coordinate of the frustum 814 | * right- the right coordinate of the frustum 815 | * bottom - the bottom coordinate of the frustum 816 | * top - the top coordinate of the frustum 817 | * r - optional 4x4 matrix to store the result in 818 | * 819 | * Returns: 820 | * 821 | * If r is specified, returns r after creating the projection matrix. 822 | * Otherwise, returns a new 4x4 matrix. 823 | */ 824 | M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) { 825 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 826 | 827 | return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r); 828 | }; 829 | 830 | /* 831 | * Function: M4x4.mul 832 | * 833 | * Performs r = a * b. 834 | * 835 | * Parameters: 836 | * 837 | * a - the first matrix operand 838 | * b - the second matrix operand 839 | * r - optional 4x4 matrix to store the result in 840 | * 841 | * Returns: 842 | * 843 | * If r is specified, returns r after performing the operation. 844 | * Otherwise, returns a new 4x4 matrix with the result. 845 | */ 846 | M4x4.mul = function M4x4_mul(a, b, r) { 847 | //MathUtils_assert(a.length == 16, "a.length == 16"); 848 | //MathUtils_assert(b.length == 16, "b.length == 16"); 849 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 850 | //MathUtils_assert(a != r && b != r, "a != r && b != r"); 851 | 852 | if (r == undefined) 853 | r = new MJS_FLOAT_ARRAY_TYPE(16); 854 | 855 | var a11 = a[0]; 856 | var a21 = a[1]; 857 | var a31 = a[2]; 858 | var a41 = a[3]; 859 | var a12 = a[4]; 860 | var a22 = a[5]; 861 | var a32 = a[6]; 862 | var a42 = a[7]; 863 | var a13 = a[8]; 864 | var a23 = a[9]; 865 | var a33 = a[10]; 866 | var a43 = a[11]; 867 | var a14 = a[12]; 868 | var a24 = a[13]; 869 | var a34 = a[14]; 870 | var a44 = a[15]; 871 | 872 | var b11 = b[0]; 873 | var b21 = b[1]; 874 | var b31 = b[2]; 875 | var b41 = b[3]; 876 | var b12 = b[4]; 877 | var b22 = b[5]; 878 | var b32 = b[6]; 879 | var b42 = b[7]; 880 | var b13 = b[8]; 881 | var b23 = b[9]; 882 | var b33 = b[10]; 883 | var b43 = b[11]; 884 | var b14 = b[12]; 885 | var b24 = b[13]; 886 | var b34 = b[14]; 887 | var b44 = b[15]; 888 | 889 | r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 890 | r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 891 | r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 892 | r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 893 | r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 894 | r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 895 | r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 896 | r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 897 | r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 898 | r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 899 | r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 900 | r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 901 | r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 902 | r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 903 | r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 904 | r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 905 | 906 | return r; 907 | }; 908 | 909 | /* 910 | * Function: M4x4.mulAffine 911 | * 912 | * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1) 913 | * 914 | * Parameters: 915 | * 916 | * a - the first matrix operand 917 | * b - the second matrix operand 918 | * r - optional 4x4 matrix to store the result in 919 | * 920 | * Returns: 921 | * 922 | * If r is specified, returns r after performing the operation. 923 | * Otherwise, returns a new 4x4 matrix with the result. 924 | */ 925 | M4x4.mulAffine = function M4x4_mulAffine(a, b, r) { 926 | //MathUtils_assert(a.length == 16, "a.length == 16"); 927 | //MathUtils_assert(b.length == 16, "b.length == 16"); 928 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 929 | //MathUtils_assert(a != r && b != r, "a != r && b != r"); 930 | 931 | if (r == undefined) 932 | r = new MJS_FLOAT_ARRAY_TYPE(16); 933 | var a11 = a[0]; 934 | var a21 = a[1]; 935 | var a31 = a[2]; 936 | var a12 = a[4]; 937 | var a22 = a[5]; 938 | var a32 = a[6]; 939 | var a13 = a[8]; 940 | var a23 = a[9]; 941 | var a33 = a[10]; 942 | var a14 = a[12]; 943 | var a24 = a[13]; 944 | var a34 = a[14]; 945 | 946 | var b11 = b[0]; 947 | var b21 = b[1]; 948 | var b31 = b[2]; 949 | var b12 = b[4]; 950 | var b22 = b[5]; 951 | var b32 = b[6]; 952 | var b13 = b[8]; 953 | var b23 = b[9]; 954 | var b33 = b[10]; 955 | var b14 = b[12]; 956 | var b24 = b[13]; 957 | var b34 = b[14]; 958 | 959 | r[0] = a11 * b11 + a12 * b21 + a13 * b31; 960 | r[1] = a21 * b11 + a22 * b21 + a23 * b31; 961 | r[2] = a31 * b11 + a32 * b21 + a33 * b31; 962 | r[3] = 0; 963 | r[4] = a11 * b12 + a12 * b22 + a13 * b32; 964 | r[5] = a21 * b12 + a22 * b22 + a23 * b32; 965 | r[6] = a31 * b12 + a32 * b22 + a33 * b32; 966 | r[7] = 0; 967 | r[8] = a11 * b13 + a12 * b23 + a13 * b33; 968 | r[9] = a21 * b13 + a22 * b23 + a23 * b33; 969 | r[10] = a31 * b13 + a32 * b23 + a33 * b33; 970 | r[11] = 0; 971 | r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14; 972 | r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24; 973 | r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34; 974 | r[15] = 1; 975 | 976 | return r; 977 | }; 978 | 979 | /* 980 | * Function: M4x4.makeRotate 981 | * 982 | * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis. 983 | * 984 | * Parameters: 985 | * 986 | * angle - the angle of rotation, in radians 987 | * axis - the axis around which the rotation is performed, a 3-element vector 988 | * r - optional 4x4 matrix to store the result in 989 | * 990 | * Returns: 991 | * 992 | * If r is specified, returns r after creating the matrix. 993 | * Otherwise, returns a new 4x4 matrix with the result. 994 | */ 995 | M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) { 996 | //MathUtils_assert(angle.length == 3, "angle.length == 3"); 997 | //MathUtils_assert(axis.length == 3, "axis.length == 3"); 998 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 999 | 1000 | if (r == undefined) 1001 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1002 | 1003 | axis = V3.normalize(axis, V3._temp1); 1004 | var x = axis[0], y = axis[1], z = axis[2]; 1005 | var c = Math.cos(angle); 1006 | var c1 = 1-c; 1007 | var s = Math.sin(angle); 1008 | 1009 | r[0] = x*x*c1+c; 1010 | r[1] = y*x*c1+z*s; 1011 | r[2] = z*x*c1-y*s; 1012 | r[3] = 0; 1013 | r[4] = x*y*c1-z*s; 1014 | r[5] = y*y*c1+c; 1015 | r[6] = y*z*c1+x*s; 1016 | r[7] = 0; 1017 | r[8] = x*z*c1+y*s; 1018 | r[9] = y*z*c1-x*s; 1019 | r[10] = z*z*c1+c; 1020 | r[11] = 0; 1021 | r[12] = 0; 1022 | r[13] = 0; 1023 | r[14] = 0; 1024 | r[15] = 1; 1025 | 1026 | return r; 1027 | }; 1028 | 1029 | /* 1030 | * Function: M4x4.rotate 1031 | * 1032 | * Concatenates a rotation of angle radians about the axis to the give matrix m. 1033 | * 1034 | * Parameters: 1035 | * 1036 | * angle - the angle of rotation, in radians 1037 | * axis - the axis around which the rotation is performed, a 3-element vector 1038 | * m - the matrix to concatenate the rotation to 1039 | * r - optional 4x4 matrix to store the result in 1040 | * 1041 | * Returns: 1042 | * 1043 | * If r is specified, returns r after performing the operation. 1044 | * Otherwise, returns a new 4x4 matrix with the result. 1045 | */ 1046 | M4x4.rotate = function M4x4_rotate(angle, axis, m, r) { 1047 | //MathUtils_assert(angle.length == 3, "angle.length == 3"); 1048 | //MathUtils_assert(axis.length == 3, "axis.length == 3"); 1049 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1050 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1051 | 1052 | if (r == undefined) 1053 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1054 | var a0=axis [0], a1=axis [1], a2=axis [2]; 1055 | var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2); 1056 | var x = a0, y = a1, z = a2; 1057 | if (l != 1.0) { 1058 | var im = 1.0 / l; 1059 | x *= im; 1060 | y *= im; 1061 | z *= im; 1062 | } 1063 | var c = Math.cos(angle); 1064 | var c1 = 1-c; 1065 | var s = Math.sin(angle); 1066 | var xs = x*s; 1067 | var ys = y*s; 1068 | var zs = z*s; 1069 | var xyc1 = x * y * c1; 1070 | var xzc1 = x * z * c1; 1071 | var yzc1 = y * z * c1; 1072 | 1073 | var m11 = m[0]; 1074 | var m21 = m[1]; 1075 | var m31 = m[2]; 1076 | var m41 = m[3]; 1077 | var m12 = m[4]; 1078 | var m22 = m[5]; 1079 | var m32 = m[6]; 1080 | var m42 = m[7]; 1081 | var m13 = m[8]; 1082 | var m23 = m[9]; 1083 | var m33 = m[10]; 1084 | var m43 = m[11]; 1085 | 1086 | var t11 = x * x * c1 + c; 1087 | var t21 = xyc1 + zs; 1088 | var t31 = xzc1 - ys; 1089 | var t12 = xyc1 - zs; 1090 | var t22 = y * y * c1 + c; 1091 | var t32 = yzc1 + xs; 1092 | var t13 = xzc1 + ys; 1093 | var t23 = yzc1 - xs; 1094 | var t33 = z * z * c1 + c; 1095 | 1096 | r[0] = m11 * t11 + m12 * t21 + m13 * t31; 1097 | r[1] = m21 * t11 + m22 * t21 + m23 * t31; 1098 | r[2] = m31 * t11 + m32 * t21 + m33 * t31; 1099 | r[3] = m41 * t11 + m42 * t21 + m43 * t31; 1100 | r[4] = m11 * t12 + m12 * t22 + m13 * t32; 1101 | r[5] = m21 * t12 + m22 * t22 + m23 * t32; 1102 | r[6] = m31 * t12 + m32 * t22 + m33 * t32; 1103 | r[7] = m41 * t12 + m42 * t22 + m43 * t32; 1104 | r[8] = m11 * t13 + m12 * t23 + m13 * t33; 1105 | r[9] = m21 * t13 + m22 * t23 + m23 * t33; 1106 | r[10] = m31 * t13 + m32 * t23 + m33 * t33; 1107 | r[11] = m41 * t13 + m42 * t23 + m43 * t33; 1108 | if (r != m) { 1109 | r[12] = m[12]; 1110 | r[13] = m[13]; 1111 | r[14] = m[14]; 1112 | r[15] = m[15]; 1113 | } 1114 | return r; 1115 | }; 1116 | 1117 | /* 1118 | * Function: M4x4.makeScale3 1119 | * 1120 | * Creates a transformation matrix for scaling by 3 scalar values, one for 1121 | * each of the x, y, and z directions. 1122 | * 1123 | * Parameters: 1124 | * 1125 | * x - the scale for the x axis 1126 | * y - the scale for the y axis 1127 | * z - the scale for the z axis 1128 | * r - optional 4x4 matrix to store the result in 1129 | * 1130 | * Returns: 1131 | * 1132 | * If r is specified, returns r after creating the matrix. 1133 | * Otherwise, returns a new 4x4 matrix with the result. 1134 | */ 1135 | M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) { 1136 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1137 | 1138 | if (r == undefined) 1139 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1140 | 1141 | r[0] = x; 1142 | r[1] = 0; 1143 | r[2] = 0; 1144 | r[3] = 0; 1145 | r[4] = 0; 1146 | r[5] = y; 1147 | r[6] = 0; 1148 | r[7] = 0; 1149 | r[8] = 0; 1150 | r[9] = 0; 1151 | r[10] = z; 1152 | r[11] = 0; 1153 | r[12] = 0; 1154 | r[13] = 0; 1155 | r[14] = 0; 1156 | r[15] = 1; 1157 | 1158 | return r; 1159 | }; 1160 | 1161 | /* 1162 | * Function: M4x4.makeScale1 1163 | * 1164 | * Creates a transformation matrix for a uniform scale by a single scalar value. 1165 | * 1166 | * Parameters: 1167 | * 1168 | * k - the scale factor 1169 | * r - optional 4x4 matrix to store the result in 1170 | * 1171 | * Returns: 1172 | * 1173 | * If r is specified, returns r after creating the matrix. 1174 | * Otherwise, returns a new 4x4 matrix with the result. 1175 | */ 1176 | M4x4.makeScale1 = function M4x4_makeScale1(k, r) { 1177 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1178 | 1179 | return M4x4.makeScale3(k, k, k, r); 1180 | }; 1181 | 1182 | /* 1183 | * Function: M4x4.makeScale 1184 | * 1185 | * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount 1186 | * given in the corresponding element of the 3-element vector. 1187 | * 1188 | * Parameters: 1189 | * 1190 | * v - the 3-element vector containing the scale factors 1191 | * r - optional 4x4 matrix to store the result in 1192 | * 1193 | * Returns: 1194 | * 1195 | * If r is specified, returns r after creating the matrix. 1196 | * Otherwise, returns a new 4x4 matrix with the result. 1197 | */ 1198 | M4x4.makeScale = function M4x4_makeScale(v, r) { 1199 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1200 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1201 | 1202 | return M4x4.makeScale3(v[0], v[1], v[2], r); 1203 | }; 1204 | 1205 | /* 1206 | * Function: M4x4.scale3 1207 | */ 1208 | M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) { 1209 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1210 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1211 | 1212 | if (r == m) { 1213 | m[0] *= x; 1214 | m[1] *= x; 1215 | m[2] *= x; 1216 | m[3] *= x; 1217 | m[4] *= y; 1218 | m[5] *= y; 1219 | m[6] *= y; 1220 | m[7] *= y; 1221 | m[8] *= z; 1222 | m[9] *= z; 1223 | m[10] *= z; 1224 | m[11] *= z; 1225 | return m; 1226 | } 1227 | 1228 | if (r == undefined) 1229 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1230 | 1231 | r[0] = m[0] * x; 1232 | r[1] = m[1] * x; 1233 | r[2] = m[2] * x; 1234 | r[3] = m[3] * x; 1235 | r[4] = m[4] * y; 1236 | r[5] = m[5] * y; 1237 | r[6] = m[6] * y; 1238 | r[7] = m[7] * y; 1239 | r[8] = m[8] * z; 1240 | r[9] = m[9] * z; 1241 | r[10] = m[10] * z; 1242 | r[11] = m[11] * z; 1243 | r[12] = m[12]; 1244 | r[13] = m[13]; 1245 | r[14] = m[14]; 1246 | r[15] = m[15]; 1247 | 1248 | return r; 1249 | }; 1250 | 1251 | /* 1252 | * Function: M4x4.scale1 1253 | */ 1254 | M4x4.scale1 = function M4x4_scale1(k, m, r) { 1255 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1256 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1257 | if (r == m) { 1258 | m[0] *= k; 1259 | m[1] *= k; 1260 | m[2] *= k; 1261 | m[3] *= k; 1262 | m[4] *= k; 1263 | m[5] *= k; 1264 | m[6] *= k; 1265 | m[7] *= k; 1266 | m[8] *= k; 1267 | m[9] *= k; 1268 | m[10] *= k; 1269 | m[11] *= k; 1270 | return m; 1271 | } 1272 | 1273 | 1274 | if (r == undefined) 1275 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1276 | 1277 | r[0] = m[0] * k; 1278 | r[1] = m[1] * k; 1279 | r[2] = m[2] * k; 1280 | r[3] = m[3] * k; 1281 | r[4] = m[4] * k; 1282 | r[5] = m[5] * k; 1283 | r[6] = m[6] * k; 1284 | r[7] = m[7] * k; 1285 | r[8] = m[8] * k; 1286 | r[9] = m[9] * k; 1287 | r[10] = m[10] * k; 1288 | r[11] = m[11] * k; 1289 | r[12] = m[12]; 1290 | r[13] = m[13]; 1291 | r[14] = m[14]; 1292 | r[15] = m[15]; 1293 | 1294 | return r; 1295 | }; 1296 | 1297 | /* 1298 | * Function: M4x4.scale1 1299 | */ 1300 | M4x4.scale = function M4x4_scale(v, m, r) { 1301 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1302 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1303 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1304 | var x = v[0], y = v[1], z = v[2]; 1305 | 1306 | if (r == m) { 1307 | m[0] *= x; 1308 | m[1] *= x; 1309 | m[2] *= x; 1310 | m[3] *= x; 1311 | m[4] *= y; 1312 | m[5] *= y; 1313 | m[6] *= y; 1314 | m[7] *= y; 1315 | m[8] *= z; 1316 | m[9] *= z; 1317 | m[10] *= z; 1318 | m[11] *= z; 1319 | return m; 1320 | } 1321 | 1322 | if (r == undefined) 1323 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1324 | 1325 | 1326 | r[0] = m[0] * x; 1327 | r[1] = m[1] * x; 1328 | r[2] = m[2] * x; 1329 | r[3] = m[3] * x; 1330 | r[4] = m[4] * y; 1331 | r[5] = m[5] * y; 1332 | r[6] = m[6] * y; 1333 | r[7] = m[7] * y; 1334 | r[8] = m[8] * z; 1335 | r[9] = m[9] * z; 1336 | r[10] = m[10] * z; 1337 | r[11] = m[11] * z; 1338 | r[12] = m[12]; 1339 | r[13] = m[13]; 1340 | r[14] = m[14]; 1341 | r[15] = m[15]; 1342 | 1343 | return r; 1344 | }; 1345 | 1346 | /* 1347 | * Function: M4x4.makeTranslate3 1348 | */ 1349 | M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) { 1350 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1351 | 1352 | if (r == undefined) 1353 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1354 | 1355 | r[0] = 1; 1356 | r[1] = 0; 1357 | r[2] = 0; 1358 | r[3] = 0; 1359 | r[4] = 0; 1360 | r[5] = 1; 1361 | r[6] = 0; 1362 | r[7] = 0; 1363 | r[8] = 0; 1364 | r[9] = 0; 1365 | r[10] = 1; 1366 | r[11] = 0; 1367 | r[12] = x; 1368 | r[13] = y; 1369 | r[14] = z; 1370 | r[15] = 1; 1371 | 1372 | return r; 1373 | }; 1374 | 1375 | /* 1376 | * Function: M4x4.makeTranslate1 1377 | */ 1378 | M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) { 1379 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1380 | 1381 | return M4x4.makeTranslate3(k, k, k, r); 1382 | }; 1383 | 1384 | /* 1385 | * Function: M4x4.makeTranslate 1386 | */ 1387 | M4x4.makeTranslate = function M4x4_makeTranslate (v, r) { 1388 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1389 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1390 | 1391 | return M4x4.makeTranslate3(v[0], v[1], v[2], r); 1392 | }; 1393 | 1394 | /* 1395 | * Function: M4x4.translate3Self 1396 | */ 1397 | M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) { 1398 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1399 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1400 | m[12] += m[0] * x + m[4] * y + m[8] * z; 1401 | m[13] += m[1] * x + m[5] * y + m[9] * z; 1402 | m[14] += m[2] * x + m[6] * y + m[10] * z; 1403 | m[15] += m[3] * x + m[7] * y + m[11] * z; 1404 | return m; 1405 | }; 1406 | 1407 | /* 1408 | * Function: M4x4.translate3 1409 | */ 1410 | M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) { 1411 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1412 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1413 | 1414 | if (r == m) { 1415 | m[12] += m[0] * x + m[4] * y + m[8] * z; 1416 | m[13] += m[1] * x + m[5] * y + m[9] * z; 1417 | m[14] += m[2] * x + m[6] * y + m[10] * z; 1418 | m[15] += m[3] * x + m[7] * y + m[11] * z; 1419 | return m; 1420 | } 1421 | 1422 | if (r == undefined) 1423 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1424 | 1425 | var m11 = m[0]; 1426 | var m21 = m[1]; 1427 | var m31 = m[2]; 1428 | var m41 = m[3]; 1429 | var m12 = m[4]; 1430 | var m22 = m[5]; 1431 | var m32 = m[6]; 1432 | var m42 = m[7]; 1433 | var m13 = m[8]; 1434 | var m23 = m[9]; 1435 | var m33 = m[10]; 1436 | var m43 = m[11]; 1437 | 1438 | 1439 | r[0] = m11; 1440 | r[1] = m21; 1441 | r[2] = m31; 1442 | r[3] = m41; 1443 | r[4] = m12; 1444 | r[5] = m22; 1445 | r[6] = m32; 1446 | r[7] = m42; 1447 | r[8] = m13; 1448 | r[9] = m23; 1449 | r[10] = m33; 1450 | r[11] = m43; 1451 | r[12] = m11 * x + m12 * y + m13 * z + m[12]; 1452 | r[13] = m21 * x + m22 * y + m23 * z + m[13]; 1453 | r[14] = m31 * x + m32 * y + m33 * z + m[14]; 1454 | r[15] = m41 * x + m42 * y + m43 * z + m[15]; 1455 | 1456 | return r; 1457 | }; 1458 | 1459 | /* 1460 | * Function: M4x4.translate1 1461 | */ 1462 | M4x4.translate1 = function M4x4_translate1 (k, m, r) { 1463 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1464 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1465 | 1466 | return M4x4.translate3(k, k, k, m, r); 1467 | }; 1468 | /* 1469 | * Function: M4x4.translateSelf 1470 | */ 1471 | M4x4.translateSelf = function M4x4_translateSelf (v, m) { 1472 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1473 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1474 | var x=v[0], y=v[1], z=v[2]; 1475 | m[12] += m[0] * x + m[4] * y + m[8] * z; 1476 | m[13] += m[1] * x + m[5] * y + m[9] * z; 1477 | m[14] += m[2] * x + m[6] * y + m[10] * z; 1478 | m[15] += m[3] * x + m[7] * y + m[11] * z; 1479 | return m; 1480 | }; 1481 | /* 1482 | * Function: M4x4.translate 1483 | */ 1484 | M4x4.translate = function M4x4_translate (v, m, r) { 1485 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1486 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1487 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1488 | var x=v[0], y=v[1], z=v[2]; 1489 | if (r == m) { 1490 | m[12] += m[0] * x + m[4] * y + m[8] * z; 1491 | m[13] += m[1] * x + m[5] * y + m[9] * z; 1492 | m[14] += m[2] * x + m[6] * y + m[10] * z; 1493 | m[15] += m[3] * x + m[7] * y + m[11] * z; 1494 | return m; 1495 | } 1496 | 1497 | if (r == undefined) 1498 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1499 | 1500 | var m11 = m[0]; 1501 | var m21 = m[1]; 1502 | var m31 = m[2]; 1503 | var m41 = m[3]; 1504 | var m12 = m[4]; 1505 | var m22 = m[5]; 1506 | var m32 = m[6]; 1507 | var m42 = m[7]; 1508 | var m13 = m[8]; 1509 | var m23 = m[9]; 1510 | var m33 = m[10]; 1511 | var m43 = m[11]; 1512 | 1513 | r[0] = m11; 1514 | r[1] = m21; 1515 | r[2] = m31; 1516 | r[3] = m41; 1517 | r[4] = m12; 1518 | r[5] = m22; 1519 | r[6] = m32; 1520 | r[7] = m42; 1521 | r[8] = m13; 1522 | r[9] = m23; 1523 | r[10] = m33; 1524 | r[11] = m43; 1525 | r[12] = m11 * x + m12 * y + m13 * z + m[12]; 1526 | r[13] = m21 * x + m22 * y + m23 * z + m[13]; 1527 | r[14] = m31 * x + m32 * y + m33 * z + m[14]; 1528 | r[15] = m41 * x + m42 * y + m43 * z + m[15]; 1529 | 1530 | return r; 1531 | }; 1532 | 1533 | /* 1534 | * Function: M4x4.makeLookAt 1535 | */ 1536 | M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) { 1537 | //MathUtils_assert(eye.length == 3, "eye.length == 3"); 1538 | //MathUtils_assert(center.length == 3, "center.length == 3"); 1539 | //MathUtils_assert(up.length == 3, "up.length == 3"); 1540 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1541 | 1542 | var z = V3.direction(eye, center, V3._temp1); 1543 | var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2); 1544 | var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3); 1545 | 1546 | var tm1 = M4x4._temp1; 1547 | var tm2 = M4x4._temp2; 1548 | 1549 | tm1[0] = x[0]; 1550 | tm1[1] = y[0]; 1551 | tm1[2] = z[0]; 1552 | tm1[3] = 0; 1553 | tm1[4] = x[1]; 1554 | tm1[5] = y[1]; 1555 | tm1[6] = z[1]; 1556 | tm1[7] = 0; 1557 | tm1[8] = x[2]; 1558 | tm1[9] = y[2]; 1559 | tm1[10] = z[2]; 1560 | tm1[11] = 0; 1561 | tm1[12] = 0; 1562 | tm1[13] = 0; 1563 | tm1[14] = 0; 1564 | tm1[15] = 1; 1565 | 1566 | tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0; 1567 | tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0; 1568 | tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0; 1569 | tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1; 1570 | 1571 | if (r == undefined) 1572 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1573 | return M4x4.mul(tm1, tm2, r); 1574 | }; 1575 | 1576 | /* 1577 | * Function: M4x4.transposeSelf 1578 | */ 1579 | M4x4.transposeSelf = function M4x4_transposeSelf (m) { 1580 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1581 | var tmp = m[1]; m[1] = m[4]; m[4] = tmp; 1582 | tmp = m[2]; m[2] = m[8]; m[8] = tmp; 1583 | tmp = m[3]; m[3] = m[12]; m[12] = tmp; 1584 | tmp = m[6]; m[6] = m[9]; m[9] = tmp; 1585 | tmp = m[7]; m[7] = m[13]; m[13] = tmp; 1586 | tmp = m[11]; m[11] = m[14]; m[14] = tmp; 1587 | return m; 1588 | }; 1589 | /* 1590 | * Function: M4x4.transpose 1591 | */ 1592 | M4x4.transpose = function M4x4_transpose (m, r) { 1593 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1594 | //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16"); 1595 | 1596 | if (m == r) { 1597 | var tmp = 0.0; 1598 | tmp = m[1]; m[1] = m[4]; m[4] = tmp; 1599 | tmp = m[2]; m[2] = m[8]; m[8] = tmp; 1600 | tmp = m[3]; m[3] = m[12]; m[12] = tmp; 1601 | tmp = m[6]; m[6] = m[9]; m[9] = tmp; 1602 | tmp = m[7]; m[7] = m[13]; m[13] = tmp; 1603 | tmp = m[11]; m[11] = m[14]; m[14] = tmp; 1604 | return m; 1605 | } 1606 | 1607 | if (r == undefined) 1608 | r = new MJS_FLOAT_ARRAY_TYPE(16); 1609 | 1610 | r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12]; 1611 | r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13]; 1612 | r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14]; 1613 | r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15]; 1614 | 1615 | return r; 1616 | }; 1617 | 1618 | 1619 | /* 1620 | * Function: M4x4.transformPoint 1621 | */ 1622 | M4x4.transformPoint = function M4x4_transformPoint (m, v, r) { 1623 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1624 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1625 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 1626 | if (r == undefined) 1627 | r = new MJS_FLOAT_ARRAY_TYPE(3); 1628 | 1629 | var v0 = v[0], v1 = v[1], v2 = v[2]; 1630 | 1631 | r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12]; 1632 | r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13]; 1633 | r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14]; 1634 | var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15]; 1635 | 1636 | if (w != 1.0) { 1637 | r[0] /= w; 1638 | r[1] /= w; 1639 | r[2] /= w; 1640 | } 1641 | 1642 | return r; 1643 | }; 1644 | 1645 | /* 1646 | * Function: M4x4.transformLine 1647 | */ 1648 | M4x4.transformLine = function M4x4_transformLine(m, v, r) { 1649 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1650 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1651 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 1652 | if (r == undefined) 1653 | r = new MJS_FLOAT_ARRAY_TYPE(3); 1654 | 1655 | var v0 = v[0], v1 = v[1], v2 = v[2]; 1656 | r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2; 1657 | r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2; 1658 | r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2; 1659 | var w = m[3] * v0 + m[7] * v1 + m[11] * v2; 1660 | 1661 | if (w != 1.0) { 1662 | r[0] /= w; 1663 | r[1] /= w; 1664 | r[2] /= w; 1665 | } 1666 | 1667 | return r; 1668 | }; 1669 | 1670 | 1671 | /* 1672 | * Function: M4x4.transformPointAffine 1673 | */ 1674 | M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) { 1675 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1676 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1677 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 1678 | if (r == undefined) 1679 | r = new MJS_FLOAT_ARRAY_TYPE(3); 1680 | 1681 | var v0 = v[0], v1 = v[1], v2 = v[2]; 1682 | 1683 | r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12]; 1684 | r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13]; 1685 | r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14]; 1686 | 1687 | return r; 1688 | }; 1689 | 1690 | /* 1691 | * Function: M4x4.transformLineAffine 1692 | */ 1693 | M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) { 1694 | //MathUtils_assert(m.length == 16, "m.length == 16"); 1695 | //MathUtils_assert(v.length == 3, "v.length == 3"); 1696 | //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3"); 1697 | if (r == undefined) 1698 | r = new MJS_FLOAT_ARRAY_TYPE(3); 1699 | 1700 | var v0 = v[0], v1 = v[1], v2 = v[2]; 1701 | r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2; 1702 | r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2; 1703 | r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2; 1704 | 1705 | return r; 1706 | }; 1707 | 1708 | M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) { 1709 | 1710 | var r = new MJS_FLOAT_ARRAY_TYPE(16); 1711 | 1712 | r[0] = vx[0]; 1713 | r[1] = vx[1]; 1714 | r[2] = vx[2]; 1715 | r[3] = 0; 1716 | r[4] = vy[0]; 1717 | r[5] = vy[1]; 1718 | r[6] = vy[2]; 1719 | r[7] = 0; 1720 | r[8] = vz[0]; 1721 | r[9] = vz[1]; 1722 | r[10] = vz[2]; 1723 | r[11] = 0; 1724 | r[12] = 0; 1725 | r[13] = 0; 1726 | r[14] = 0; 1727 | r[15] = 1; 1728 | 1729 | return r; 1730 | 1731 | }; 1732 | 1733 | return { 1734 | vec3: F3(V3.$), 1735 | v3getX: V3.getX, 1736 | v3getY: V3.getY, 1737 | v3getZ: V3.getZ, 1738 | v3setX: F2(V3.setX), 1739 | v3setY: F2(V3.setY), 1740 | v3setZ: F2(V3.setZ), 1741 | toTuple3: V3.toTuple3, 1742 | toRecord3: V3.toRecord3, 1743 | fromTuple3: V3.fromTuple3, 1744 | fromRecord3: V3.fromRecord3, 1745 | v3add: F2(V3.add), 1746 | v3sub: F2(V3.sub), 1747 | v3neg: V3.neg, 1748 | v3direction: F2(V3.direction), 1749 | v3length: V3.length, 1750 | v3lengthSquared: V3.lengthSquared, 1751 | v3distance: F2(V3.distance), 1752 | v3distanceSquared: F2(V3.distanceSquared), 1753 | v3normalize: V3.normalize, 1754 | v3scale: F2(V3.scale), 1755 | v3dot: F2(V3.dot), 1756 | v3cross: F2(V3.cross), 1757 | v3mul4x4: F2(V3.mul4x4), 1758 | m4x4identity: M4x4.identity, 1759 | m4x4topLeft3x3: M4x4.topLeft3x3, 1760 | m4x4inverseOrthonormal: M4x4.inverseOrthonormal, 1761 | m4x4inverseTo3x3: M4x4.inverseTo3x3, 1762 | m4x4makeFrustum: F6(M4x4.makeFrustum), 1763 | m4x4makePerspective: F4(M4x4.makePerspective), 1764 | m4x4makeOrtho: F6(M4x4.makeOrtho), 1765 | m4x4makeOrtho2D: F4(M4x4.makeOrtho2D), 1766 | m4x4mul: F2(M4x4.mul), 1767 | m4x4Affine: F2(M4x4.mulAffine), 1768 | m4x4makeRotate: F2(M4x4.makeRotate), 1769 | m4x4rotate: F3(M4x4.rotate), 1770 | m4x4makeScale3: F3(M4x4.makeScale3), 1771 | m4x4makeScale1: M4x4.makeScale1, 1772 | m4x4makeScale: M4x4.makeScale, 1773 | m4x4scale3: F4(M4x4.scale3), 1774 | m4x4scale: F2(M4x4.scale), 1775 | m4x4makeTranslate3: F3(M4x4.makeTranslate3), 1776 | m4x4makeTranslate: M4x4.makeTranslate, 1777 | m4x4translate3: F4(M4x4.translate3), 1778 | m4x4translate: F2(M4x4.translate), 1779 | m4x4makeLookAt: F3(M4x4.makeLookAt), 1780 | m4x4transpose: M4x4.transpose, 1781 | m4x4transformPoint: F2(M4x4.transformPoint), 1782 | m4x4makeBasis: F3(M4x4.makeBasis) 1783 | }; 1784 | 1785 | }(); 1786 | --------------------------------------------------------------------------------