├── .editorconfig
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── __tests__
├── browser
│ └── test.html
├── float32vector.test.ts
├── lib
│ └── close_to.ts
├── matrix.test.ts
└── quaternion.test.ts
├── build
└── matrixgl.min.js
├── docs
├── .nojekyll
├── assets
│ ├── highlight.css
│ ├── icons.css
│ ├── icons.png
│ ├── icons@2x.png
│ ├── main.js
│ ├── search.js
│ ├── style.css
│ ├── widgets.png
│ └── widgets@2x.png
├── classes
│ ├── Float32Vector2.html
│ ├── Float32Vector3.html
│ ├── Float32Vector4.html
│ ├── Matrix2x2.html
│ ├── Matrix3x3.html
│ ├── Matrix4x4.html
│ └── Quaternion.html
├── index.html
├── interfaces
│ └── Matrix.html
└── modules.html
├── lib
├── cjs
│ ├── float32vector.d.ts
│ ├── float32vector.js
│ ├── index.d.ts
│ ├── index.js
│ ├── matrix.d.ts
│ ├── matrix.js
│ ├── quaternion.d.ts
│ ├── quaternion.js
│ ├── vector_base.d.ts
│ └── vector_base.js
└── esm
│ ├── float32vector.d.ts
│ ├── float32vector.js
│ ├── index.d.ts
│ ├── index.js
│ ├── matrix.d.ts
│ ├── matrix.js
│ ├── quaternion.d.ts
│ ├── quaternion.js
│ ├── vector_base.d.ts
│ └── vector_base.js
├── package-lock.json
├── package.json
├── src
├── float32vector.ts
├── index.ts
├── matrix.ts
├── quaternion.ts
└── vector_base.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 |
6 | charset = utf-8
7 |
8 | indent_style = space
9 | indent_size = 2
10 |
11 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, reopened]
6 |
7 | jobs:
8 | test:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: actions/setup-node@v2
13 | with:
14 | node-version: '16'
15 | - run: npm ci
16 | - run: npm run test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | *~
3 | .fuse_hidden*
4 | .directory
5 | .Trash-*
6 | .nfs*
7 | .idea
8 | *.iml
9 | out
10 | gen
11 | logs
12 | *.log
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | pids
17 | *.pid
18 | *.seed
19 | *.pid.lock
20 | lib-cov
21 | coverage
22 | .nyc_output
23 | .grunt
24 | bower_components
25 | .lock-wscript
26 | build/Release
27 | node_modules/
28 | jspm_packages/
29 | typings/
30 | .npm
31 | .eslintcache
32 | .node_repl_history
33 | *.tgz
34 | .yarn-integrity
35 | .env
36 | .idea
37 | *.iml
38 | out
39 | gen
40 | Thumbs.db
41 | ehthumbs.db
42 | ehthumbs_vista.db
43 | *.stackdump
44 | [Dd]esktop.ini
45 | $RECYCLE.BIN/
46 | *.cab
47 | *.msi
48 | *.msm
49 | *.msp
50 | *.lnk
51 | .DS_Store
52 | .AppleDouble
53 | .LSOverride
54 | Icon
55 | ._*
56 | .DocumentRevisions-V100
57 | .fseventsd
58 | .Spotlight-V100
59 | .TemporaryItems
60 | .Trashes
61 | .VolumeIcon.icns
62 | .com.apple.timemachine.donotpresent
63 | .AppleDB
64 | .AppleDesktop
65 | Network Trash Folder
66 | Temporary Items
67 | .apdisk
68 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 2.0.0
4 |
5 | * **\[Breaking Change\]** Add ESM support for Node.js. CommonJS is supported too, but this change may break some build system.
6 | * **\[Breaking Change\]** Change compatibility to ES2020 and drop ES5 support for Node.js.
7 | * **\[Breaking Change\]** Change compatibility to ES2020 and drop ES5 support for browsers.
8 | * Change license to Zlib License which is looser than MIT license. Zlib license doesn't require license terms in your code.
9 |
10 | ## 1.0.1
11 |
12 | * Fix v1.0.0 did not apply changes to `matrixgl.min.js` and documents.
13 |
14 | ## 1.0.0
15 |
16 | * **\[Breaking Change\]** Rename `perspective` to `frustum`.
17 | * Add new `Matrix4.perspective()`.
18 |
19 | ## 0.2.0
20 |
21 | * Add `xy` to `Vector3` and `xyz` to `Vector4`, that return the part of the vector.
22 | * Add `rotateAround(axis, radian)` to `Matrix4` and static `Matrix4.rotationAround(axis, radian)`.
23 | * Improve `toString()` of vectors.
24 |
25 | ## 0.1.0
26 |
27 | * Add a Quaternion class.
28 |
29 | ## 0.0.3
30 |
31 | * Fix Vector3.normalize() returns NaN if its magnitude is zero.
32 |
33 | ## 0.0.2
34 |
35 | * orthogonal -> orthographic
36 |
37 | ## 0.0.1
38 |
39 | * Initial release with minimal implementation.
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Koto Furumiya
2 |
3 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
4 |
5 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
6 |
7 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
8 |
9 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
10 |
11 | 3. This notice may not be removed or altered from any source distribution.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MatrixGL
2 |
3 | MatrixGL is yet another matrix library for WebGL.
4 |
5 | ## Install without Node.js
6 |
7 | Download the zip file from [Releases page on GitHub](https://github.com/kotofurumiya/matrixgl/releases), and unzip the file.
8 |
9 | You will see **matrixgl.min.js** file in the **build** directory. Copy the file(matrixgl.min.js) into your directory. You can ignore all other files(These files are for Node.js).
10 |
11 | Then add below code to your HTML file.
12 |
13 | ```html
14 |
15 |
18 | ```
19 |
20 | ## Install with Node.js
21 |
22 | Run the install command.
23 |
24 | ```
25 | $ npm install matrixgl
26 | ```
27 |
28 | Then, import MatrixGL in your script.
29 |
30 | ```typescript
31 | // JavaScript(CommonJS)
32 | const { Vector3, Vector4, Matrix4, Quaternion } = require('matrixgl');
33 |
34 | // TypeScript or Modern JavaScript(ES Modules)
35 | import { Vector3, Vector4, Matrix4, Quaternion } from 'matrixgl';
36 | ```
37 |
38 | ## Basic Usage
39 |
40 | MatrixGL has Vector, Matrix and Quaternion class.
41 |
42 | You can use it simply. For example:
43 |
44 | ```javascript
45 | // create 4-dimensional vector.
46 | const vec = new Vector4(1, 2, 3, 4);
47 |
48 | // display elements.
49 | console.log(vec.x); // 1
50 | console.log(vec.y); // 2
51 | console.log(vec.z); // 3
52 | console.log(vec.w); // 4
53 |
54 | // all values
55 | console.log(vec.values);
56 | ```
57 |
58 | Vector classes also have some operation.
59 |
60 | ```javascript
61 | const vec1 = new Vector4(1, 2, 3, 4);
62 | const vec2 = new Vector4(5, 6, 7, 8);
63 | const scalar = 5;
64 |
65 | // calculate
66 | const vecSum = vec1.add(vec2);
67 | const vecDiff = vec1.sub(vec2);
68 | const vecProd = vec1.mulByScalar(scalar);
69 | const vecMag = vec1.magnitude;
70 | ```
71 |
72 | **Note: MatrixGL's API does not modify the original vector/matrix unlike ordinary OpenGL matrix libraries. So you should assign the result to variables**
73 |
74 | There are also Matrix classes.
75 |
76 | ```javascript
77 | const mat = new Matrix2(1, 2, 3, 4);
78 | console.log(mat.values);
79 | ```
80 |
81 | Matrices' values are stored in "column major order" which is the default order of WebGL. This means `new Matrix(1, 2, 3, 4);` represents the first row is `[1, 3]` and second row is `[2, 4]`.
82 |
83 | If you are bored with enumerating numbers 16 times to create a Matrix4, please use a spread operator.
84 |
85 | ```javascript
86 | const values = new Array(16);
87 | values.fill(0);
88 |
89 | const matrix = new Matrix4(...values);
90 | ```
91 |
92 | In addition to basic methods, `Matrix4` class has special methods. You can generate a model matrix easily with these methods.
93 |
94 | ```javascript
95 | const model = Matrix4.identity()
96 | .translate(1, 2, 3)
97 | .rotateX(Math.PI)
98 | .scale(5, 5, 5);
99 | ```
100 |
101 | Or you can build a model matrix manually.
102 |
103 | ```javascript
104 | const identity = Matrix4.identity();
105 | const scaling = Matrix4.scaling(5, 5, 5);
106 | const rotation = Matrix4.rotationX(Math.PI);
107 | const translation = Matrix4.translation(1, 2, 3);
108 |
109 | const model = identity.mulByMatrix4(translation)
110 | .mulByMatrix4(rotation)
111 | .mulByMatrix4(scaling);
112 | ```
113 |
114 | If you want a rotation matrix about an arbitrary axis, use `rotateAround(axis, radian)` .
115 | ```javascript
116 | // An axis vector must be normalized.
117 | const axis = new Vector3(1, 2, 3).normalize();
118 | const rotation = Matrix4.identity()
119 | .rotateAround(axis, Math.PI);
120 | ```
121 |
122 | or use `Matrix4.rotationAround(axis, radian)`.
123 |
124 | ```javascript
125 | const rotation = Matrix4.rotationAround(axis, Math.PI);
126 | ```
127 |
128 | To build a "look at" matrix, use `lookAt` method.
129 |
130 | ```javascript
131 | const camera = new Vector3(1, 2, 3);
132 | const lookAt = new Vector3(4, 5, 6);
133 | const cameraUpDirection = new Vector3(7, 8, 9);
134 |
135 | const view = Matrix4.lookAt(camera, lookAt, cameraUpDirection);
136 | ```
137 |
138 | If you need a projection matrix, use `Matrix4.orthographic` or `Matrix4.perspective` method.
139 |
140 | ```javascript
141 | const orthographic = Matrix4.orthographic({
142 | top: 1,
143 | bottom: -1,
144 | left: -1,
145 | right: 1,
146 | near: 1,
147 | far: 2
148 | });
149 |
150 | const perspective = Matrix4.perspective({
151 | fovYRadian: 60 * Math.PI / 180,
152 | aspectRatio: 1,
153 | near: 1,
154 | far: 2
155 | });
156 | ```
157 |
158 | And combine all above matrices to build a ModelViewProjection matrix.
159 |
160 | ```javascript
161 | const mvp = perspective.mulByMatrix4(view)
162 | .mulByMatrix4(model);
163 | ```
164 |
165 | ## Quaternion
166 |
167 | MatrixGL supports quaternions for rotation.
168 |
169 | ```javascript
170 | // Create a quaternion.
171 | const q = new Quaternion(1, 2, 3, 4);
172 | ```
173 |
174 | To create a rotation matrix from a quaternion, use `Quaternion.rotationAround(axis, rad)` and `toRotationMatrix4()`.
175 |
176 | ```javascript
177 | // An axis must be normalized.
178 | const axis = new Vector3(1, 2, 3).normalize();
179 | const radian = 45 * Math.PI / 180;
180 |
181 | // Create a quaternion from the axis and radian.
182 | const q = Quaternion.rotationAround(axis, radian);
183 |
184 | // Convert the rotation quaternion to a rotation matrix.
185 | const rotation = q.toRotationMatrix4();
186 | ```
187 |
188 | To interpolate between two quaternions, use `slerp(other, t)`.
189 |
190 | ```javascript
191 | // To interpolate quaternions, they must be normalized.
192 | const q1 = new Quaternion(1, 2, 3, 4).normalize();
193 | const q2 = new Quaternion(5, 6, 7, 8).normalize();
194 |
195 | // interpolate with t = 0.5.
196 | // t is from 0.0 to 1.0.
197 | const interpolated = q1.slerp(q2, 0.5);
198 | ```
199 |
200 | ## Usage with WebGL
201 |
202 | You can get `Float32Array` from `values` property of vectors, matrices or quaternions.
203 |
204 | So if you use MatrixGL with WebGL, just pass the vector's(or matrix's) `values`.
205 |
206 | ```javascript
207 | // Buffer
208 | gl.bufferData(gl.ARRAY_BUFFER, vec1.values, gl.STATIC_DRAW);
209 |
210 | // Uniform Variable
211 | gl.uniformMatrix4fv(mvpLocation, false, mvp.values);
212 | ```
213 |
214 | ## API Document
215 |
216 | For more information, see also [API Document](https://kotofurumiya.github.io/matrixgl).
217 |
218 | ## How to Build from Source
219 |
220 | Install dependencies.
221 |
222 | ```
223 | $ npm install
224 | ```
225 |
226 | Build.
227 |
228 | ```
229 | $ npm run build
230 | ```
231 |
232 | ## License
233 |
234 | Zlib License. See [LICENSE.md](https://github.com/kotofurumiya/matrixgl/blob/master/LICENSE.md).
--------------------------------------------------------------------------------
/__tests__/browser/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | matrixgl Test
6 |
7 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/__tests__/float32vector.test.ts:
--------------------------------------------------------------------------------
1 | import { suite } from 'uvu';
2 | import { Vector2, Vector3, Vector4 } from '../';
3 | import { toBeCloseTo, arrayToBeCloseTo } from './lib/close_to';
4 |
5 | const Vector2Suite = suite('Vector2');
6 | const Vector3Suite = suite('Vector3');
7 | const Vector4Suite = suite('Vector4');
8 | const delta = 0.001;
9 |
10 | //
11 | // Vector2
12 | //
13 | Vector2Suite('Add Vector2', () => {
14 | const vec1 = new Vector2(1, 2);
15 | const vec2 = new Vector2(3, 4);
16 |
17 | arrayToBeCloseTo(vec1.add(vec2).values, [4, 6], delta);
18 | });
19 |
20 | Vector2Suite('Sub Vector2', () => {
21 | const vec1 = new Vector2(1, 2);
22 | const vec2 = new Vector2(3, 4);
23 |
24 | arrayToBeCloseTo(vec1.sub(vec2).values, [-2, -2], delta);
25 | });
26 |
27 | Vector2Suite('Mul Vector2', () => {
28 | const vec1 = new Vector2(1, 2);
29 |
30 | arrayToBeCloseTo(vec1.mulByScalar(5).values, [5, 10], delta);
31 | });
32 |
33 | //
34 | // Vector3
35 | //
36 | Vector3Suite('Add Vector3', () => {
37 | const vec1 = new Vector3(1, 2, 3);
38 | const vec2 = new Vector3(4, 5, 6);
39 |
40 | arrayToBeCloseTo(vec1.add(vec2).values, [5, 7, 9], delta);
41 | });
42 |
43 | Vector3Suite('Sub Vector3', () => {
44 | const vec1 = new Vector3(1, 2, 3);
45 | const vec2 = new Vector3(4, 5, 6);
46 |
47 | arrayToBeCloseTo(vec1.sub(vec2).values, [-3, -3, -3], delta);
48 | });
49 |
50 | Vector3Suite('Mul Vector3', () => {
51 | const vec1 = new Vector3(1, 2, 3);
52 |
53 | arrayToBeCloseTo(vec1.mulByScalar(5).values, [5, 10, 15], delta);
54 | });
55 |
56 | Vector3Suite('Dot Vector3', () => {
57 | const vec1 = new Vector3(1, 2, 3);
58 | const vec2 = new Vector3(4, 5, 6);
59 |
60 | toBeCloseTo(vec1.dot(vec2), 32, delta);
61 | });
62 |
63 | Vector3Suite('Cross Vector3', () => {
64 | const vec1 = new Vector3(1, 2, 3);
65 | const vec2 = new Vector3(4, 5, 6);
66 |
67 | arrayToBeCloseTo(vec1.cross(vec2).values, [-3, 6, -3], delta);
68 | });
69 |
70 | Vector3Suite('Magnitude of Vector3', () => {
71 | const vec = new Vector3(1.23 , 4.56, 7.89);
72 |
73 | toBeCloseTo(vec.magnitude, 9.19558, delta);
74 | });
75 |
76 | Vector3Suite('Normal Vector3', () => {
77 | const vec = new Vector3(1.05, 3.47, 7.43);
78 | arrayToBeCloseTo(vec.normalize().values, [0.127006, 0.419726, 0.898721], delta);
79 | });
80 |
81 | Vector3Suite('Normal Zero Vector3', () => {
82 | const vec = new Vector3(0.0, 0.0, 0.0);
83 | arrayToBeCloseTo(vec.normalize().values, [0.0, 0.0, 0.0], delta);
84 | });
85 |
86 | Vector3Suite('Get xy', () => {
87 | const vec = new Vector3(1, 2, 3);
88 | arrayToBeCloseTo(vec.xy.values, [1, 2], delta);
89 | });
90 |
91 | //
92 | // Vector4
93 | //
94 | Vector4Suite('Add Vector4', () => {
95 | const vec1 = new Vector4(1, 2, 3, 4);
96 | const vec2 = new Vector4(5, 6, 7, 8);
97 |
98 | arrayToBeCloseTo(vec1.add(vec2).values, [6, 8, 10, 12], delta);
99 | });
100 |
101 | Vector4Suite('Sub Vector4', () => {
102 | const vec1 = new Vector4(1, 2, 3, 4);
103 | const vec2 = new Vector4(5, 6, 7, 8);
104 |
105 | arrayToBeCloseTo(vec1.sub(vec2).values, [-4, -4, -4, -4], delta);
106 | });
107 |
108 | Vector4Suite('Mul Vector4', () => {
109 | const vec1 = new Vector4(1, 2, 3, 4);
110 |
111 | arrayToBeCloseTo(vec1.mulByScalar(5).values, [5, 10, 15, 20], delta);
112 | });
113 |
114 | Vector4Suite('Get xyz', () => {
115 | const vec = new Vector4(1, 2, 3, 4);
116 | arrayToBeCloseTo(vec.xyz.values, [1, 2, 3], delta);
117 | });
118 |
119 | Vector2Suite.run();
120 | Vector3Suite.run();
121 | Vector4Suite.run();
--------------------------------------------------------------------------------
/__tests__/lib/close_to.ts:
--------------------------------------------------------------------------------
1 | import { Assertion } from "uvu/assert";
2 | import { compare } from 'uvu/diff';
3 |
4 | export const toBeCloseTo = (actual: number, expected: number, delta: number) => {
5 | const diff = Math.abs(actual - expected);
6 | if(diff > delta) {
7 | throw new Assertion({
8 | message: `unacceptable diff with delta=${delta}`,
9 | operator: 'toBeCloseTo',
10 | details: compare(actual, expected),
11 | expects: expected,
12 | actual
13 | });
14 | }
15 | }
16 |
17 | export const arrayToBeCloseTo = (actual: ArrayLike, expected: ArrayLike, delta: number) => {
18 | if(actual.length !== expected.length) {
19 | throw new Assertion({
20 | message: 'incompatible length',
21 | operator: 'arrayToBeCloseTo',
22 | details: compare(actual.length, expected.length),
23 | expects: expected,
24 | actual
25 | });
26 | }
27 |
28 | type Difference = {
29 | index: number,
30 | diff: number
31 | };
32 | const differenceList: Difference[] = [];
33 | for(let i=0; i delta) {
36 | differenceList.push({
37 | index: i,
38 | diff
39 | });
40 | }
41 | }
42 |
43 | if(differenceList.length > 0) {
44 | throw new Assertion({
45 | message: `unacceptable diffs with delta=${delta}`,
46 | operator: 'arrayCloseTo',
47 | details: compare(differenceList, []),
48 | expects: expected,
49 | actual
50 | });
51 | }
52 | };
53 |
--------------------------------------------------------------------------------
/__tests__/matrix.test.ts:
--------------------------------------------------------------------------------
1 | import { suite } from 'uvu';
2 | import { Matrix4, Vector3 } from '../';
3 | import { arrayToBeCloseTo } from './lib/close_to';
4 |
5 | const Matrix4Suite = suite('Matrix4');
6 | const delta = 0.001;
7 |
8 | //
9 | // Matrix4
10 | //
11 | Matrix4Suite('Model Matrix', () => {
12 | const model = Matrix4.identity()
13 | .translate(40, 0, -20)
14 | .rotateZ(Math.PI / 8)
15 | .scale(1, 2,3)
16 |
17 | arrayToBeCloseTo(model.values, [
18 | 0.9238795042037964,0.3826834261417389,0,0,
19 | -0.7653668522834778,1.8477590084075928,0,0,
20 | 0,0,3,0,
21 | 40,0,-20,1
22 | ], delta);
23 | });
24 |
25 | Matrix4Suite('View Matrix', () => {
26 | const cameraPosition = new Vector3(0, 60, 90);
27 | const lookAtPosition = new Vector3(0, 0, 0);
28 | const upDirection = new Vector3(0, 1, 0);
29 | const view = Matrix4.lookAt(cameraPosition, lookAtPosition, upDirection);
30 |
31 | arrayToBeCloseTo(view.values, [
32 | 1,0,0,0,
33 | 0,0.8320503234863281,0.5547001957893372,0,
34 | 0,-0.5547001957893372,0.8320503234863281,0,
35 | 0,0,-108.16654205322266,1
36 | ], delta);
37 | });
38 |
39 | Matrix4Suite('Projection Matrix Orthographic', () => {
40 | const left = -40;
41 | const right = 40;
42 | const top = 40;
43 | const bottom = -40;
44 | const near = 30;
45 | const far = 150;
46 | const projection = Matrix4.orthographic({ top, right, left, bottom, near, far });
47 |
48 | arrayToBeCloseTo(projection.values, [
49 | 0.02500000037252903,0,0,0,
50 | 0,0.02500000037252903,0,
51 | 0,0,0,-0.01666666753590107,
52 | 0,0,0,-1.5,1
53 | ], delta);
54 | });
55 |
56 | Matrix4Suite('Projection Matrix Frustum', () => {
57 | const left = -40;
58 | const right = 40;
59 | const top = 40;
60 | const bottom = -40;
61 | const near = 30;
62 | const far = 150;
63 | const frustum = Matrix4.frustum({ top, right, left, bottom, near, far });
64 |
65 | arrayToBeCloseTo(frustum.values, [
66 | 0.75,0,0,0,
67 | 0,0.75,0,0,
68 | 0,0,-1.5,-1,
69 | 0,0,-75,0
70 | ], delta);
71 | });
72 |
73 | Matrix4Suite('Projection Matrix Perspective', () => {
74 | const fovY = 60 * Math.PI / 180;
75 | const aspectRatio = 500 / 500;
76 | const near = 30;
77 | const far = 300;
78 | const projection = Matrix4.perspective({ fovYRadian: fovY, aspectRatio, near, far });
79 |
80 | arrayToBeCloseTo(projection.values, [
81 | 1.7320507764816284,0,0,0,
82 | 0,1.7320507764816284,0,0,
83 | 0,0,-1.2222222089767456,-1,
84 | 0,0,-66.66666412353516,0
85 | ], delta);
86 | });
87 |
88 | Matrix4Suite.run();
--------------------------------------------------------------------------------
/__tests__/quaternion.test.ts:
--------------------------------------------------------------------------------
1 | import { suite } from 'uvu';
2 | import { Quaternion, Vector3 } from '../';
3 | import { arrayToBeCloseTo } from './lib/close_to';
4 |
5 | const QuaternionSuite = suite('Matrix4');
6 | const delta = 0.001;
7 |
8 | QuaternionSuite('toRotationMatrix4', () => {
9 | const axis = new Vector3(1, 2, 3).normalize();
10 | const rad = 45.6 * Math.PI / 180;
11 | const quaternion = Quaternion.rotationAround(axis, rad);
12 | const rotationMatrix = quaternion.toRotationMatrix4();
13 | const expected = [
14 | 0.7211159467697144, 0.6157578229904175, -0.3175438642501831, 0,
15 | -0.5299473404884338, 0.7854738235473633, 0.3196665644645691, 0,
16 | 0.4462595582008362, -0.062235139310359955, 0.8927369117736816, 0,
17 | 0, 0, 0, 1
18 | ];
19 |
20 | arrayToBeCloseTo(rotationMatrix.values, expected, delta);
21 | });
22 |
23 | QuaternionSuite('normalize', () => {
24 | const normalized = new Quaternion(1, 2, 3, 4).normalize();
25 | const expected = [0.18257418583505536, 0.3651483716701107, 0.5477225575051661, 0.7302967433402214];
26 |
27 | arrayToBeCloseTo(normalized.values, expected, delta);
28 | });
29 |
30 | QuaternionSuite('normalize with zero norm', () => {
31 | const normalized = new Quaternion(0, 0, 0, 0).normalize();
32 | arrayToBeCloseTo(normalized.values, [0, 0, 0, 0], delta);
33 | });
34 |
35 | QuaternionSuite('slerp', () => {
36 | const q1 = new Quaternion(1, 2, 3, 4).normalize();
37 | const q2 = new Quaternion(5, 6, 7, 8).normalize();
38 | const s = q1.slerp(q2, 0.123);
39 | const expected = [0.20761071976221868, 0.37753696937382647, 0.5474632189854343, 0.717389468597042];
40 |
41 | arrayToBeCloseTo(s.values, expected, delta);
42 | });
43 |
44 | QuaternionSuite.run();
--------------------------------------------------------------------------------
/build/matrixgl.min.js:
--------------------------------------------------------------------------------
1 | (()=>{var U=class{get values(){return this._values}get magnitude(){let t=0;for(let r of this._values)t+=r**2;return Math.sqrt(t)}toString(){return`Vector${this._values.length}(${this._values.join(", ")})`}},C=class extends U{get x(){return this._values[0]}get y(){return this._values[1]}set x(t){this._values[0]=t}set y(t){this._values[1]=t}},D=class extends U{get x(){return this._values[0]}get y(){return this._values[1]}get z(){return this._values[2]}set x(t){this._values[0]=t}set y(t){this._values[1]=t}set z(t){this._values[2]=t}},E=class extends U{get x(){return this._values[0]}get y(){return this._values[1]}get z(){return this._values[2]}get w(){return this._values[3]}set x(t){this._values[0]=t}set y(t){this._values[1]=t}set z(t){this._values[2]=t}set w(t){this._values[3]=t}};var d=class extends C{constructor(t,r){super();this._values=new Float32Array([t,r])}add(t){return new d(this.x+t.x,this.y+t.y)}sub(t){return new d(this.x-t.x,this.y-t.y)}mulByScalar(t){return new d(this.x*t,this.y*t)}},c=class extends D{constructor(t,r,e){super();this._values=new Float32Array([t,r,e])}add(t){return new c(this.x+t.x,this.y+t.y,this.z+t.z)}sub(t){return new c(this.x-t.x,this.y-t.y,this.z-t.z)}mulByScalar(t){return new c(this.x*t,this.y*t,this.z*t)}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}cross(t){let r=this.y*t.z-this.z*t.y,e=this.z*t.x-this.x*t.z,n=this.x*t.y-this.y*t.x;return new c(r,e,n)}normalize(){let t=this.magnitude;return t===0?this:new c(this.x/t,this.y/t,this.z/t)}get xy(){return new d(this.x,this.y)}},F=class extends E{constructor(t,r,e,n){super();this._values=new Float32Array([t,r,e,n])}add(t){return new F(this.x+t.x,this.y+t.y,this.z+t.z,this.w+t.w)}sub(t){return new F(this.x-t.x,this.y-t.y,this.z-t.z,this.w-t.w)}mulByScalar(t){return new F(this.x*t,this.y*t,this.z*t,this.w*t)}get xyz(){return new c(this.x,this.y,this.z)}},mt=d,ct=c,lt=F;var w=class{constructor(t,r,e,n){this._values=new Float32Array([t,r,e,n])}static rotationAround(t,r){let e=Math.sin(r/2),n=Math.cos(r/2);return new w(t.x*e,t.y*e,t.z*e,n)}normalize(){let t=this.magnitude;if(t===0)return this;let r=1/t;return new w(this.x*r,this.y*r,this.z*r,this.w*r)}add(t){return new w(this.x+t.x,this.y+t.y,this.z+t.z,this.w+t.w)}mulByScalar(t){return new w(this.x*t,this.y*t,this.z*t,this.w*t)}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}slerp(t,r,e={chooseShorterAngle:!0}){let n=this.dot(t),u=t;n<0&&(n=-n,u=t.mulByScalar(-1));let s=Math.acos(n),o=Math.sin(s),i=this.mulByScalar(Math.sin((1-r)*s)/o),m=u.mulByScalar(Math.sin(r*s)/o);return i.add(m)}get magnitude(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}get norm(){return this.magnitude}get x(){return this._values[0]}get y(){return this._values[1]}get z(){return this._values[2]}get w(){return this._values[3]}set x(t){this._values[0]=t}set y(t){this._values[1]=t}set z(t){this._values[2]=t}set w(t){this._values[3]=t}get values(){return this._values}toRotationMatrix4(){let t=this.x,r=this.y,e=this.z,n=this.w,u=1-2*r*r-2*e*e,s=2*t*r-2*n*e,o=2*t*e+2*n*r,i=0,m=2*t*r+2*n*e,l=1-2*t*t-2*e*e,b=2*r*e-2*n*t,h=0,x=2*t*e-2*n*r,y=2*r*e+2*n*t,v=1-2*t*t-2*r*r,p=0,g=0,z=0,M=0,A=1;return new a(u,m,x,g,s,l,y,z,o,b,v,M,i,h,p,A)}toString(){return`Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`}};var I=class{constructor(t,r,e,n){this._values=new Float32Array([t,r,e,n])}static identity(){return new I(1,0,0,1)}get values(){return this._values}toString(){return this._values.toString()}},X=class{constructor(t,r,e,n,u,s,o,i,m){this._values=new Float32Array([t,r,e,n,u,s,o,i,m])}static identity(){return new X(1,0,0,0,1,0,0,0,1)}get values(){return this._values}toString(){return this._values.toString()}},a=class{constructor(t,r,e,n,u,s,o,i,m,l,b,h,x,y,v,p){this._values=new Float32Array([t,r,e,n,u,s,o,i,m,l,b,h,x,y,v,p])}static identity(){return new a(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)}static translation(t,r,e){return new a(1,0,0,0,0,1,0,0,0,0,1,0,t,r,e,1)}static scaling(t,r,e){return new a(t,0,0,0,0,r,0,0,0,0,e,0,0,0,0,1)}static rotationX(t){let r=Math.sin(t),e=Math.cos(t);return new a(1,0,0,0,0,e,r,0,0,-r,e,0,0,0,0,1)}static rotationY(t){let r=Math.sin(t),e=Math.cos(t);return new a(e,0,-r,0,0,1,0,0,r,0,e,0,0,0,0,1)}static rotationZ(t){let r=Math.sin(t),e=Math.cos(t);return new a(e,r,0,0,-r,e,0,0,0,0,1,0,0,0,0,1)}static rotationAround(t,r){return w.rotationAround(t,r).toRotationMatrix4()}static lookAt(t,r,e){let n=t.sub(r).normalize(),u=e.cross(n).normalize(),s=n.cross(u).normalize();return new a(u.x,s.x,n.x,0,u.y,s.y,n.y,0,u.z,s.z,n.z,0,-t.dot(u),-t.dot(s),-t.dot(n),1)}static orthographic(t){let r=t.top,e=t.bottom,n=t.left,u=t.right,s=t.near,o=t.far;return new a(2/(u-n),0,0,0,0,2/(r-e),0,0,0,0,-2/(o-s),0,-(u+n)/(u-n),-(r+e)/(r-e),-(o+s)/(o-s),1)}static frustum(t){let r=t.top,e=t.bottom,n=t.left,u=t.right,s=t.near,o=t.far;return new a(2*s/(u-n),0,0,0,0,2*s/(r-e),0,0,(u+n)/(u-n),(r+e)/(r-e),-(o+s)/(o-s),-1,0,0,-2*o*s/(o-s),0)}static perspective(t){let r=t.near*Math.tan(t.fovYRadian*.5),e=r*2,n=t.aspectRatio*e,u=-.5*n,s=u+n,o=r-e;return a.frustum({top:r,bottom:o,left:u,right:s,near:t.near,far:t.far})}mulByMatrix4x4(t){let r=this._values[0],e=this._values[4],n=this._values[8],u=this._values[12],s=this._values[1],o=this._values[5],i=this._values[9],m=this._values[13],l=this._values[2],b=this._values[6],h=this._values[10],x=this._values[14],y=this._values[3],v=this._values[7],p=this._values[11],g=this._values[15],z=t.values[0],M=t.values[4],A=t.values[8],f=t.values[12],_=t.values[1],V=t.values[5],S=t.values[9],B=t.values[13],T=t.values[2],Q=t.values[6],q=t.values[10],k=t.values[14],L=t.values[3],R=t.values[7],$=t.values[11],Y=t.values[15],G=r*z+e*_+n*T+u*L,H=r*M+e*V+n*Q+u*R,J=r*A+e*S+n*q+u*$,K=r*f+e*B+n*k+u*Y,N=s*z+o*_+i*T+m*L,W=s*M+o*V+i*Q+m*R,P=s*A+o*S+i*q+m*$,j=s*f+o*B+i*k+m*Y,O=l*z+b*_+h*T+x*L,tt=l*M+b*V+h*Q+x*R,rt=l*A+b*S+h*q+x*$,et=l*f+b*B+h*k+x*Y,nt=y*z+v*_+p*T+g*L,st=y*M+v*V+p*Q+g*R,ut=y*A+v*S+p*q+g*$,ot=y*f+v*B+p*k+g*Y;return new a(G,N,O,nt,H,W,tt,st,J,P,rt,ut,K,j,et,ot)}mulByMatrix4(t){return this.mulByMatrix4x4(t)}translate(t,r,e){let n=a.translation(t,r,e);return this.mulByMatrix4x4(n)}scale(t,r,e){let n=a.scaling(t,r,e);return this.mulByMatrix4x4(n)}rotateX(t){let r=a.rotationX(t);return this.mulByMatrix4x4(r)}rotateY(t){let r=a.rotationY(t);return this.mulByMatrix4x4(r)}rotateZ(t){let r=a.rotationZ(t);return this.mulByMatrix4x4(r)}rotateAround(t,r){let e=a.rotationAround(t,r);return this.mulByMatrix4x4(e)}get values(){return this._values}toString(){return this._values.toString()}},vt=I,pt=X,wt=a;})();
2 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/assets/highlight.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --light-hl-0: #800000;
3 | --dark-hl-0: #808080;
4 | --light-hl-1: #800000;
5 | --dark-hl-1: #569CD6;
6 | --light-hl-2: #000000FF;
7 | --dark-hl-2: #D4D4D4;
8 | --light-hl-3: #FF0000;
9 | --dark-hl-3: #9CDCFE;
10 | --light-hl-4: #0000FF;
11 | --dark-hl-4: #CE9178;
12 | --light-hl-5: #008000;
13 | --dark-hl-5: #6A9955;
14 | --light-hl-6: #001080;
15 | --dark-hl-6: #9CDCFE;
16 | --light-hl-7: #000000;
17 | --dark-hl-7: #D4D4D4;
18 | --light-hl-8: #0000FF;
19 | --dark-hl-8: #569CD6;
20 | --light-hl-9: #0070C1;
21 | --dark-hl-9: #4FC1FF;
22 | --light-hl-10: #795E26;
23 | --dark-hl-10: #DCDCAA;
24 | --light-hl-11: #A31515;
25 | --dark-hl-11: #CE9178;
26 | --light-hl-12: #AF00DB;
27 | --dark-hl-12: #C586C0;
28 | --light-hl-13: #098658;
29 | --dark-hl-13: #B5CEA8;
30 | --light-hl-14: #267F99;
31 | --dark-hl-14: #4EC9B0;
32 | --light-code-background: #FFFFFF;
33 | --dark-code-background: #1E1E1E;
34 | }
35 |
36 | @media (prefers-color-scheme: light) { :root {
37 | --hl-0: var(--light-hl-0);
38 | --hl-1: var(--light-hl-1);
39 | --hl-2: var(--light-hl-2);
40 | --hl-3: var(--light-hl-3);
41 | --hl-4: var(--light-hl-4);
42 | --hl-5: var(--light-hl-5);
43 | --hl-6: var(--light-hl-6);
44 | --hl-7: var(--light-hl-7);
45 | --hl-8: var(--light-hl-8);
46 | --hl-9: var(--light-hl-9);
47 | --hl-10: var(--light-hl-10);
48 | --hl-11: var(--light-hl-11);
49 | --hl-12: var(--light-hl-12);
50 | --hl-13: var(--light-hl-13);
51 | --hl-14: var(--light-hl-14);
52 | --code-background: var(--light-code-background);
53 | } }
54 |
55 | @media (prefers-color-scheme: dark) { :root {
56 | --hl-0: var(--dark-hl-0);
57 | --hl-1: var(--dark-hl-1);
58 | --hl-2: var(--dark-hl-2);
59 | --hl-3: var(--dark-hl-3);
60 | --hl-4: var(--dark-hl-4);
61 | --hl-5: var(--dark-hl-5);
62 | --hl-6: var(--dark-hl-6);
63 | --hl-7: var(--dark-hl-7);
64 | --hl-8: var(--dark-hl-8);
65 | --hl-9: var(--dark-hl-9);
66 | --hl-10: var(--dark-hl-10);
67 | --hl-11: var(--dark-hl-11);
68 | --hl-12: var(--dark-hl-12);
69 | --hl-13: var(--dark-hl-13);
70 | --hl-14: var(--dark-hl-14);
71 | --code-background: var(--dark-code-background);
72 | } }
73 |
74 | body.light {
75 | --hl-0: var(--light-hl-0);
76 | --hl-1: var(--light-hl-1);
77 | --hl-2: var(--light-hl-2);
78 | --hl-3: var(--light-hl-3);
79 | --hl-4: var(--light-hl-4);
80 | --hl-5: var(--light-hl-5);
81 | --hl-6: var(--light-hl-6);
82 | --hl-7: var(--light-hl-7);
83 | --hl-8: var(--light-hl-8);
84 | --hl-9: var(--light-hl-9);
85 | --hl-10: var(--light-hl-10);
86 | --hl-11: var(--light-hl-11);
87 | --hl-12: var(--light-hl-12);
88 | --hl-13: var(--light-hl-13);
89 | --hl-14: var(--light-hl-14);
90 | --code-background: var(--light-code-background);
91 | }
92 |
93 | body.dark {
94 | --hl-0: var(--dark-hl-0);
95 | --hl-1: var(--dark-hl-1);
96 | --hl-2: var(--dark-hl-2);
97 | --hl-3: var(--dark-hl-3);
98 | --hl-4: var(--dark-hl-4);
99 | --hl-5: var(--dark-hl-5);
100 | --hl-6: var(--dark-hl-6);
101 | --hl-7: var(--dark-hl-7);
102 | --hl-8: var(--dark-hl-8);
103 | --hl-9: var(--dark-hl-9);
104 | --hl-10: var(--dark-hl-10);
105 | --hl-11: var(--dark-hl-11);
106 | --hl-12: var(--dark-hl-12);
107 | --hl-13: var(--dark-hl-13);
108 | --hl-14: var(--dark-hl-14);
109 | --code-background: var(--dark-code-background);
110 | }
111 |
112 | .hl-0 { color: var(--hl-0); }
113 | .hl-1 { color: var(--hl-1); }
114 | .hl-2 { color: var(--hl-2); }
115 | .hl-3 { color: var(--hl-3); }
116 | .hl-4 { color: var(--hl-4); }
117 | .hl-5 { color: var(--hl-5); }
118 | .hl-6 { color: var(--hl-6); }
119 | .hl-7 { color: var(--hl-7); }
120 | .hl-8 { color: var(--hl-8); }
121 | .hl-9 { color: var(--hl-9); }
122 | .hl-10 { color: var(--hl-10); }
123 | .hl-11 { color: var(--hl-11); }
124 | .hl-12 { color: var(--hl-12); }
125 | .hl-13 { color: var(--hl-13); }
126 | .hl-14 { color: var(--hl-14); }
127 | pre, code { background: var(--code-background); }
128 |
--------------------------------------------------------------------------------
/docs/assets/icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/matrixgl/cba6203ad2d8f5179aa48d457d76a343bc25da91/docs/assets/icons.png
--------------------------------------------------------------------------------
/docs/assets/icons@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/matrixgl/cba6203ad2d8f5179aa48d457d76a343bc25da91/docs/assets/icons@2x.png
--------------------------------------------------------------------------------
/docs/assets/widgets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/matrixgl/cba6203ad2d8f5179aa48d457d76a343bc25da91/docs/assets/widgets.png
--------------------------------------------------------------------------------
/docs/assets/widgets@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/matrixgl/cba6203ad2d8f5179aa48d457d76a343bc25da91/docs/assets/widgets@2x.png
--------------------------------------------------------------------------------
/docs/classes/Matrix2x2.html:
--------------------------------------------------------------------------------
1 | Matrix2x2 | matrixglConstructors
constructor
- new Matrix2x2(m11: number, m21: number, m12: number, m22: number): Matrix2x2
Parameters
m11: number
m21: number
m12: number
m22: number
Properties
Protected _values
_values: Float32Array
Accessors
values
- get values(): Float32Array
--------------------------------------------------------------------------------
/docs/classes/Matrix3x3.html:
--------------------------------------------------------------------------------
1 | Matrix3x3 | matrixglConstructors
constructor
- new Matrix3x3(m11: number, m21: number, m31: number, m12: number, m22: number, m32: number, m13: number, m23: number, m33: number): Matrix3x3
Parameters
m11: number
m21: number
m31: number
m12: number
m22: number
m32: number
m13: number
m23: number
m33: number
Properties
Protected _values
_values: Float32Array
Accessors
values
- get values(): Float32Array
--------------------------------------------------------------------------------
/docs/interfaces/Matrix.html:
--------------------------------------------------------------------------------
1 | Matrix | matrixglProperties
Readonly values
values: Float32Array
--------------------------------------------------------------------------------
/docs/modules.html:
--------------------------------------------------------------------------------
1 | matrixgl
--------------------------------------------------------------------------------
/lib/cjs/float32vector.d.ts:
--------------------------------------------------------------------------------
1 | import { Vector2Base, Vector3Base, Vector4Base } from './vector_base';
2 | /**
3 | * A 2-dimensional vector of single-precision float numbers.
4 | */
5 | export declare class Float32Vector2 extends Vector2Base {
6 | constructor(x: number, y: number);
7 | /**
8 | * Add `other` to the vector and returns new `Float32Vector2`.
9 | *
10 | * This method does not mutate the vector.
11 | * @param {Float32Vector2} other
12 | * @returns {Float32Vector2}
13 | */
14 | add(other: Float32Vector2): Float32Vector2;
15 | /**
16 | * Subtract `other` from the vector and returns new `Float32Vector2`.
17 | *
18 | * This method does not mutate the vector.
19 | * @param {Float32Vector2} other
20 | * @returns {Float32Vector2}
21 | */
22 | sub(other: Float32Vector2): Float32Vector2;
23 | /**
24 | * Multiply the vector by `scalar` and returns new `Float32Vector2`.
25 | *
26 | * This method does not mutate the vector.
27 | * @param {number} scalar
28 | * @returns {Float32Vector2}
29 | */
30 | mulByScalar(scalar: number): Float32Vector2;
31 | }
32 | /**
33 | * A 3-dimensional vector of single-precision float numbers.
34 | */
35 | export declare class Float32Vector3 extends Vector3Base {
36 | constructor(x: number, y: number, z: number);
37 | /**
38 | * Add `other` to the vector and returns new `Float32Vector3`.
39 | *
40 | * This method does not mutate the vector.
41 | * @param {Float32Vector3} other
42 | * @returns {Float32Vector3}
43 | */
44 | add(other: Float32Vector3): Float32Vector3;
45 | /**
46 | * Subtract `other` from the vector and returns new `Float32Vector3`.
47 | *
48 | * This method does not mutate the vector.
49 | * @param {Float32Vector3} other
50 | * @returns {Float32Vector3}
51 | */
52 | sub(other: Float32Vector3): Float32Vector3;
53 | /**
54 | * Multiply the vector by `scalar` and returns new `Float32Vector3`.
55 | *
56 | * This method does not mutate the vector.
57 | * @param {number} scalar
58 | * @returns {Float32Vector3}
59 | */
60 | mulByScalar(scalar: number): Float32Vector3;
61 | /**
62 | * Calculate dot product.
63 | * @param {Float32Vector3} other
64 | * @returns {number}
65 | */
66 | dot(other: Float32Vector3): number;
67 | /**
68 | * Calculate cross product.
69 | * @param {Float32Vector3} other
70 | * @returns {Float32Vector3}
71 | */
72 | cross(other: Float32Vector3): Float32Vector3;
73 | /**
74 | * Normalize the vector and returns new `Float32Vector3`.
75 | *
76 | * This method does not mutate the vector.
77 | * @returns {Float32Vector3}
78 | */
79 | normalize(): Float32Vector3;
80 | /**
81 | * Returns xy values of the vector as `Float32Vector2`.
82 | * @returns {Float32Vector2}
83 | */
84 | get xy(): Float32Vector2;
85 | }
86 | /**
87 | * A 4-dimensional vector of single-precision float numbers.
88 | */
89 | export declare class Float32Vector4 extends Vector4Base {
90 | constructor(x: number, y: number, z: number, w: number);
91 | /**
92 | * Add `other` to the vector and returns new `Float32Vector4`.
93 | *
94 | * This method does not mutate the vector.
95 | * @param {Float32Vector4} other
96 | * @returns {Float32Vector4}
97 | */
98 | add(other: Float32Vector4): Float32Vector4;
99 | /**
100 | * Subtract `other` from the vector and returns new `Float32Vector4`.
101 | *
102 | * This method does not mutate the vector.
103 | * @param {Float32Vector4} other
104 | * @returns {Float32Vector4}
105 | */
106 | sub(other: Float32Vector4): Float32Vector4;
107 | /**
108 | * Multiply the vector by `scalar` and returns new `Float32Vector4`.
109 | *
110 | * This method does not mutate the vector.
111 | * @param {number} scalar
112 | * @returns {Float32Vector4}
113 | */
114 | mulByScalar(scalar: number): Float32Vector4;
115 | /**
116 | * Returns xyz values of the vector as `Float32Vector3`.
117 | * @returns {Float32Vector3}
118 | */
119 | get xyz(): Float32Vector3;
120 | }
121 | /**
122 | * An alias for `Float32Vector2`.
123 | * @type {Float32Vector2}
124 | */
125 | export declare const Vector2: typeof Float32Vector2;
126 | /**
127 | * An alias for `Float32Vector3`.
128 | * @type {Float32Vector3}
129 | */
130 | export declare const Vector3: typeof Float32Vector3;
131 | /**
132 | * An alias for `Float32Vector4`.
133 | * @type {Float32Vector4}
134 | */
135 | export declare const Vector4: typeof Float32Vector4;
136 |
--------------------------------------------------------------------------------
/lib/cjs/float32vector.js:
--------------------------------------------------------------------------------
1 | var __defProp = Object.defineProperty;
2 | var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
3 | var __export = (target, all) => {
4 | __markAsModule(target);
5 | for (var name in all)
6 | __defProp(target, name, { get: all[name], enumerable: true });
7 | };
8 |
9 | // src/float32vector.ts
10 | __export(exports, {
11 | Float32Vector2: () => Float32Vector2,
12 | Float32Vector3: () => Float32Vector3,
13 | Float32Vector4: () => Float32Vector4,
14 | Vector2: () => Vector2,
15 | Vector3: () => Vector3,
16 | Vector4: () => Vector4
17 | });
18 |
19 | // src/vector_base.ts
20 | var VectorBase = class {
21 | get values() {
22 | return this._values;
23 | }
24 | get magnitude() {
25 | let sumSq = 0;
26 | for (const val of this._values) {
27 | sumSq += val ** 2;
28 | }
29 | return Math.sqrt(sumSq);
30 | }
31 | toString() {
32 | const dimension = this._values.length;
33 | return `Vector${dimension}(${this._values.join(", ")})`;
34 | }
35 | };
36 | var Vector2Base = class extends VectorBase {
37 | get x() {
38 | return this._values[0];
39 | }
40 | get y() {
41 | return this._values[1];
42 | }
43 | set x(value) {
44 | this._values[0] = value;
45 | }
46 | set y(value) {
47 | this._values[1] = value;
48 | }
49 | };
50 | var Vector3Base = class extends VectorBase {
51 | get x() {
52 | return this._values[0];
53 | }
54 | get y() {
55 | return this._values[1];
56 | }
57 | get z() {
58 | return this._values[2];
59 | }
60 | set x(value) {
61 | this._values[0] = value;
62 | }
63 | set y(value) {
64 | this._values[1] = value;
65 | }
66 | set z(value) {
67 | this._values[2] = value;
68 | }
69 | };
70 | var Vector4Base = class extends VectorBase {
71 | get x() {
72 | return this._values[0];
73 | }
74 | get y() {
75 | return this._values[1];
76 | }
77 | get z() {
78 | return this._values[2];
79 | }
80 | get w() {
81 | return this._values[3];
82 | }
83 | set x(value) {
84 | this._values[0] = value;
85 | }
86 | set y(value) {
87 | this._values[1] = value;
88 | }
89 | set z(value) {
90 | this._values[2] = value;
91 | }
92 | set w(value) {
93 | this._values[3] = value;
94 | }
95 | };
96 |
97 | // src/float32vector.ts
98 | var Float32Vector2 = class extends Vector2Base {
99 | constructor(x, y) {
100 | super();
101 | this._values = new Float32Array([x, y]);
102 | }
103 | add(other) {
104 | return new Float32Vector2(this.x + other.x, this.y + other.y);
105 | }
106 | sub(other) {
107 | return new Float32Vector2(this.x - other.x, this.y - other.y);
108 | }
109 | mulByScalar(scalar) {
110 | return new Float32Vector2(this.x * scalar, this.y * scalar);
111 | }
112 | };
113 | var Float32Vector3 = class extends Vector3Base {
114 | constructor(x, y, z) {
115 | super();
116 | this._values = new Float32Array([x, y, z]);
117 | }
118 | add(other) {
119 | return new Float32Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
120 | }
121 | sub(other) {
122 | return new Float32Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
123 | }
124 | mulByScalar(scalar) {
125 | return new Float32Vector3(this.x * scalar, this.y * scalar, this.z * scalar);
126 | }
127 | dot(other) {
128 | return this.x * other.x + this.y * other.y + this.z * other.z;
129 | }
130 | cross(other) {
131 | const cx = this.y * other.z - this.z * other.y;
132 | const cy = this.z * other.x - this.x * other.z;
133 | const cz = this.x * other.y - this.y * other.x;
134 | return new Float32Vector3(cx, cy, cz);
135 | }
136 | normalize() {
137 | const mag = this.magnitude;
138 | if (mag === 0) {
139 | return this;
140 | }
141 | return new Float32Vector3(this.x / mag, this.y / mag, this.z / mag);
142 | }
143 | get xy() {
144 | return new Float32Vector2(this.x, this.y);
145 | }
146 | };
147 | var Float32Vector4 = class extends Vector4Base {
148 | constructor(x, y, z, w) {
149 | super();
150 | this._values = new Float32Array([x, y, z, w]);
151 | }
152 | add(other) {
153 | return new Float32Vector4(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
154 | }
155 | sub(other) {
156 | return new Float32Vector4(this.x - other.x, this.y - other.y, this.z - other.z, this.w - other.w);
157 | }
158 | mulByScalar(scalar) {
159 | return new Float32Vector4(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
160 | }
161 | get xyz() {
162 | return new Float32Vector3(this.x, this.y, this.z);
163 | }
164 | };
165 | var Vector2 = Float32Vector2;
166 | var Vector3 = Float32Vector3;
167 | var Vector4 = Float32Vector4;
168 | // Annotate the CommonJS export names for ESM import in node:
169 | 0 && (module.exports = {
170 | Float32Vector2,
171 | Float32Vector3,
172 | Float32Vector4,
173 | Vector2,
174 | Vector3,
175 | Vector4
176 | });
177 |
--------------------------------------------------------------------------------
/lib/cjs/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './float32vector';
2 | export * from './matrix';
3 | export * from './quaternion';
4 |
--------------------------------------------------------------------------------
/lib/cjs/matrix.d.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3 } from './float32vector';
2 | /**
3 | * An interface for matrices;
4 | */
5 | export interface Matrix {
6 | /**
7 | * Values of the matrix, that is stored in column major order.
8 | */
9 | readonly values: Float32Array;
10 | /**
11 | * Returns `values` as string.
12 | * @returns {string}
13 | */
14 | toString(): string;
15 | }
16 | /**
17 | * 2x2 Matrix of single-precision float numbers.
18 | *
19 | * Values are stored in column major order.
20 | */
21 | export declare class Matrix2x2 implements Matrix {
22 | protected _values: Float32Array;
23 | constructor(m11: number, m21: number, m12: number, m22: number);
24 | /**
25 | * Returns an identity matrix.
26 | * @returns {Matrix2x2}
27 | */
28 | static identity(): Matrix2x2;
29 | get values(): Float32Array;
30 | toString(): string;
31 | }
32 | /**
33 | * 3x3 Matrix of single-precision float numbers.
34 | *
35 | * Values are stored in column major order.
36 | */
37 | export declare class Matrix3x3 implements Matrix {
38 | protected _values: Float32Array;
39 | constructor(m11: number, m21: number, m31: number, m12: number, m22: number, m32: number, m13: number, m23: number, m33: number);
40 | /**
41 | * Returns an identity matrix.
42 | * @returns {Matrix3x3}
43 | */
44 | static identity(): Matrix3x3;
45 | get values(): Float32Array;
46 | toString(): string;
47 | }
48 | /**
49 | * 4x4 Matrix of single-precision float numbers.
50 | *
51 | * Values are stored in column major order.
52 | */
53 | export declare class Matrix4x4 implements Matrix {
54 | protected _values: Float32Array;
55 | constructor(m11: number, m21: number, m31: number, m41: number, m12: number, m22: number, m32: number, m42: number, m13: number, m23: number, m33: number, m43: number, m14: number, m24: number, m34: number, m44: number);
56 | /**
57 | * Returns an identity matrix.
58 | * @returns {Matrix4x4}
59 | */
60 | static identity(): Matrix4x4;
61 | /**
62 | * Returns translation matrix.
63 | * @param {number} tx
64 | * @param {number} ty
65 | * @param {number} tz
66 | * @returns {Matrix4x4}
67 | */
68 | static translation(tx: number, ty: number, tz: number): Matrix4x4;
69 | /**
70 | * Returns scaling matrix.
71 | * @param {number} sx
72 | * @param {number} sy
73 | * @param {number} sz
74 | * @returns {Matrix4x4}
75 | */
76 | static scaling(sx: number, sy: number, sz: number): Matrix4x4;
77 | /**
78 | * Returns rotation matrix around x-axis.
79 | * @param {number} radian
80 | * @returns {Matrix4x4}
81 | */
82 | static rotationX(radian: number): Matrix4x4;
83 | /**
84 | * Returns rotation matrix around y-axis.
85 | * @param {number} radian
86 | * @returns {Matrix4x4}
87 | */
88 | static rotationY(radian: number): Matrix4x4;
89 | /**
90 | * Returns rotation matrix around z-axis.
91 | * @param {number} radian
92 | * @returns {Matrix4x4}
93 | */
94 | static rotationZ(radian: number): Matrix4x4;
95 | /**
96 | * Returns rotation matrix around `normalizedAxis`. `normalizedAxis` must be normalized.
97 | * @param {Float32Vector3} normalizedAxis
98 | * @param {number} radian
99 | * @returns {Matrix4x4}
100 | */
101 | static rotationAround(normalizedAxis: Float32Vector3, radian: number): Matrix4x4;
102 | /**
103 | * Returns "look at" matrix.
104 | * @param {Float32Vector3} cameraPosition
105 | * @param {Float32Vector3} lookAtPosition
106 | * @param {Float32Vector3} cameraUp
107 | * @returns {Matrix4x4}
108 | */
109 | static lookAt(cameraPosition: Float32Vector3, lookAtPosition: Float32Vector3, cameraUp: Float32Vector3): Matrix4x4;
110 | /**
111 | * Returns an orthographic projection matrix.
112 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
113 | * @returns {Matrix4x4}
114 | */
115 | static orthographic(argsObject: {
116 | top: number;
117 | bottom: number;
118 | left: number;
119 | right: number;
120 | near: number;
121 | far: number;
122 | }): Matrix4x4;
123 | /**
124 | * Returns a frustrum projection matrix.
125 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
126 | * @returns {Matrix4x4}
127 | */
128 | static frustum(argsObject: {
129 | top: number;
130 | bottom: number;
131 | left: number;
132 | right: number;
133 | near: number;
134 | far: number;
135 | }): Matrix4x4;
136 | /**
137 | * Returns a perspective projection matrix.
138 | * @param {{fovY: number; aspect: number; near: number; far: number}} argsObject
139 | * @returns {Matrix4x4}
140 | */
141 | static perspective(argsObject: {
142 | fovYRadian: number;
143 | aspectRatio: number;
144 | near: number;
145 | far: number;
146 | }): Matrix4x4;
147 | /**
148 | * Multiply by `other` matrix and returns a product.
149 | *
150 | * This method does not mutate the matrix.
151 | * @param {Matrix4x4} other
152 | * @returns {Matrix4x4}
153 | */
154 | mulByMatrix4x4(other: Matrix4x4): Matrix4x4;
155 | /**
156 | * An alias for `mulByMatrix4x4`.
157 | * @param {Matrix4x4} other
158 | * @returns {Matrix4x4}
159 | */
160 | mulByMatrix4(other: Matrix4x4): Matrix4x4;
161 | /**
162 | * Translate the matrix and returns new `Matrix4x4`.
163 | *
164 | * This method does not mutate the matrix.
165 | * @param {number} tx
166 | * @param {number} ty
167 | * @param {number} tz
168 | * @returns {Matrix4x4}
169 | */
170 | translate(tx: number, ty: number, tz: number): Matrix4x4;
171 | /**
172 | * Scale the matrix and returns new `Matrix4x4`.
173 | * @param {number} sx
174 | * @param {number} sy
175 | * @param {number} sz
176 | * @returns {Matrix4x4}
177 | */
178 | scale(sx: number, sy: number, sz: number): Matrix4x4;
179 | /**
180 | * Rotate the matrix around x-axis and returns new `Matrix4x4`.
181 | *
182 | * This method does not mutate the matrix.
183 | * @param {number} radian
184 | * @returns {Matrix4x4}
185 | */
186 | rotateX(radian: number): Matrix4x4;
187 | /**
188 | * Rotate the matrix around y-axis and returns new `Matrix4x4`.
189 | *
190 | * This method does not mutate the matrix.
191 | * @param {number} radian
192 | * @returns {Matrix4x4}
193 | */
194 | rotateY(radian: number): Matrix4x4;
195 | /**
196 | * Rotate the matrix around z-axis and returns new `Matrix4x4`.
197 | *
198 | * This method does not mutate the matrix.
199 | * @param {number} radian
200 | * @returns {Matrix4x4}
201 | */
202 | rotateZ(radian: number): Matrix4x4;
203 | /**
204 | * Rotate the matrix around the `normalizedAxis` and return new Matrix4x4.
205 | *
206 | * This method does not mutate the matrix.
207 | * @param {Float32Vector3} normalizedAxis
208 | * @param {number} radian
209 | * @returns {Matrix4x4}
210 | */
211 | rotateAround(normalizedAxis: Float32Vector3, radian: number): Matrix4x4;
212 | get values(): Float32Array;
213 | toString(): string;
214 | }
215 | /**
216 | * An alias for `Matrix2x2`.
217 | * @type {Matrix2x2}
218 | */
219 | export declare const Matrix2: typeof Matrix2x2;
220 | /**
221 | * An alias for `Matrix3x3`.
222 | * @type {Matrix3x3}
223 | */
224 | export declare const Matrix3: typeof Matrix3x3;
225 | /**
226 | * An alias for `Matrix4x4`.
227 | * @type {Matrix4x4}
228 | */
229 | export declare const Matrix4: typeof Matrix4x4;
230 |
--------------------------------------------------------------------------------
/lib/cjs/matrix.js:
--------------------------------------------------------------------------------
1 | var __defProp = Object.defineProperty;
2 | var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
3 | var __export = (target, all) => {
4 | __markAsModule(target);
5 | for (var name in all)
6 | __defProp(target, name, { get: all[name], enumerable: true });
7 | };
8 |
9 | // src/matrix.ts
10 | __export(exports, {
11 | Matrix2: () => Matrix2,
12 | Matrix2x2: () => Matrix2x2,
13 | Matrix3: () => Matrix3,
14 | Matrix3x3: () => Matrix3x3,
15 | Matrix4: () => Matrix4,
16 | Matrix4x4: () => Matrix4x4
17 | });
18 |
19 | // src/quaternion.ts
20 | var Quaternion = class {
21 | constructor(x, y, z, w) {
22 | this._values = new Float32Array([x, y, z, w]);
23 | }
24 | static rotationAround(normalizedAxis, radian) {
25 | const sin = Math.sin(radian / 2);
26 | const cos = Math.cos(radian / 2);
27 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
28 | }
29 | normalize() {
30 | const mag = this.magnitude;
31 | if (mag === 0) {
32 | return this;
33 | }
34 | const r = 1 / mag;
35 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
36 | }
37 | add(other) {
38 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
39 | }
40 | mulByScalar(scalar) {
41 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
42 | }
43 | dot(other) {
44 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
45 | }
46 | slerp(other, t, options = { chooseShorterAngle: true }) {
47 | let dotProd = this.dot(other);
48 | let otherQuaternion = other;
49 | if (dotProd < 0) {
50 | dotProd = -dotProd;
51 | otherQuaternion = other.mulByScalar(-1);
52 | }
53 | const omega = Math.acos(dotProd);
54 | const sinOmega = Math.sin(omega);
55 | const q1 = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
56 | const q2 = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
57 | return q1.add(q2);
58 | }
59 | get magnitude() {
60 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
61 | }
62 | get norm() {
63 | return this.magnitude;
64 | }
65 | get x() {
66 | return this._values[0];
67 | }
68 | get y() {
69 | return this._values[1];
70 | }
71 | get z() {
72 | return this._values[2];
73 | }
74 | get w() {
75 | return this._values[3];
76 | }
77 | set x(value) {
78 | this._values[0] = value;
79 | }
80 | set y(value) {
81 | this._values[1] = value;
82 | }
83 | set z(value) {
84 | this._values[2] = value;
85 | }
86 | set w(value) {
87 | this._values[3] = value;
88 | }
89 | get values() {
90 | return this._values;
91 | }
92 | toRotationMatrix4() {
93 | const x = this.x;
94 | const y = this.y;
95 | const z = this.z;
96 | const w = this.w;
97 | const m11 = 1 - 2 * y * y - 2 * z * z;
98 | const m12 = 2 * x * y - 2 * w * z;
99 | const m13 = 2 * x * z + 2 * w * y;
100 | const m14 = 0;
101 | const m21 = 2 * x * y + 2 * w * z;
102 | const m22 = 1 - 2 * x * x - 2 * z * z;
103 | const m23 = 2 * y * z - 2 * w * x;
104 | const m24 = 0;
105 | const m31 = 2 * x * z - 2 * w * y;
106 | const m32 = 2 * y * z + 2 * w * x;
107 | const m33 = 1 - 2 * x * x - 2 * y * y;
108 | const m34 = 0;
109 | const m41 = 0;
110 | const m42 = 0;
111 | const m43 = 0;
112 | const m44 = 1;
113 | return new Matrix4x4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44);
114 | }
115 | toString() {
116 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
117 | }
118 | };
119 |
120 | // src/matrix.ts
121 | var Matrix2x2 = class {
122 | constructor(m11, m21, m12, m22) {
123 | this._values = new Float32Array([
124 | m11,
125 | m21,
126 | m12,
127 | m22
128 | ]);
129 | }
130 | static identity() {
131 | return new Matrix2x2(1, 0, 0, 1);
132 | }
133 | get values() {
134 | return this._values;
135 | }
136 | toString() {
137 | return this._values.toString();
138 | }
139 | };
140 | var Matrix3x3 = class {
141 | constructor(m11, m21, m31, m12, m22, m32, m13, m23, m33) {
142 | this._values = new Float32Array([
143 | m11,
144 | m21,
145 | m31,
146 | m12,
147 | m22,
148 | m32,
149 | m13,
150 | m23,
151 | m33
152 | ]);
153 | }
154 | static identity() {
155 | return new Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
156 | }
157 | get values() {
158 | return this._values;
159 | }
160 | toString() {
161 | return this._values.toString();
162 | }
163 | };
164 | var Matrix4x4 = class {
165 | constructor(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44) {
166 | this._values = new Float32Array([
167 | m11,
168 | m21,
169 | m31,
170 | m41,
171 | m12,
172 | m22,
173 | m32,
174 | m42,
175 | m13,
176 | m23,
177 | m33,
178 | m43,
179 | m14,
180 | m24,
181 | m34,
182 | m44
183 | ]);
184 | }
185 | static identity() {
186 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
187 | }
188 | static translation(tx, ty, tz) {
189 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
190 | }
191 | static scaling(sx, sy, sz) {
192 | return new Matrix4x4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
193 | }
194 | static rotationX(radian) {
195 | const sin = Math.sin(radian);
196 | const cos = Math.cos(radian);
197 | return new Matrix4x4(1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1);
198 | }
199 | static rotationY(radian) {
200 | const sin = Math.sin(radian);
201 | const cos = Math.cos(radian);
202 | return new Matrix4x4(cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1);
203 | }
204 | static rotationZ(radian) {
205 | const sin = Math.sin(radian);
206 | const cos = Math.cos(radian);
207 | return new Matrix4x4(cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
208 | }
209 | static rotationAround(normalizedAxis, radian) {
210 | const q = Quaternion.rotationAround(normalizedAxis, radian);
211 | return q.toRotationMatrix4();
212 | }
213 | static lookAt(cameraPosition, lookAtPosition, cameraUp) {
214 | const zAxis = cameraPosition.sub(lookAtPosition).normalize();
215 | const xAxis = cameraUp.cross(zAxis).normalize();
216 | const yAxis = zAxis.cross(xAxis).normalize();
217 | return new Matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1);
218 | }
219 | static orthographic(argsObject) {
220 | const top = argsObject.top;
221 | const bottom = argsObject.bottom;
222 | const left = argsObject.left;
223 | const right = argsObject.right;
224 | const near = argsObject.near;
225 | const far = argsObject.far;
226 | return new Matrix4x4(2 / (right - left), 0, 0, 0, 0, 2 / (top - bottom), 0, 0, 0, 0, -2 / (far - near), 0, -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1);
227 | }
228 | static frustum(argsObject) {
229 | const top = argsObject.top;
230 | const bottom = argsObject.bottom;
231 | const left = argsObject.left;
232 | const right = argsObject.right;
233 | const near = argsObject.near;
234 | const far = argsObject.far;
235 | return new Matrix4x4(2 * near / (right - left), 0, 0, 0, 0, 2 * near / (top - bottom), 0, 0, (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0);
236 | }
237 | static perspective(argsObject) {
238 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
239 | const height = top * 2;
240 | const width = argsObject.aspectRatio * height;
241 | const left = -0.5 * width;
242 | const right = left + width;
243 | const bottom = top - height;
244 | return Matrix4x4.frustum({
245 | top,
246 | bottom,
247 | left,
248 | right,
249 | near: argsObject.near,
250 | far: argsObject.far
251 | });
252 | }
253 | mulByMatrix4x4(other) {
254 | const m11 = this._values[0];
255 | const m12 = this._values[4];
256 | const m13 = this._values[8];
257 | const m14 = this._values[12];
258 | const m21 = this._values[1];
259 | const m22 = this._values[5];
260 | const m23 = this._values[9];
261 | const m24 = this._values[13];
262 | const m31 = this._values[2];
263 | const m32 = this._values[6];
264 | const m33 = this._values[10];
265 | const m34 = this._values[14];
266 | const m41 = this._values[3];
267 | const m42 = this._values[7];
268 | const m43 = this._values[11];
269 | const m44 = this._values[15];
270 | const o11 = other.values[0];
271 | const o12 = other.values[4];
272 | const o13 = other.values[8];
273 | const o14 = other.values[12];
274 | const o21 = other.values[1];
275 | const o22 = other.values[5];
276 | const o23 = other.values[9];
277 | const o24 = other.values[13];
278 | const o31 = other.values[2];
279 | const o32 = other.values[6];
280 | const o33 = other.values[10];
281 | const o34 = other.values[14];
282 | const o41 = other.values[3];
283 | const o42 = other.values[7];
284 | const o43 = other.values[11];
285 | const o44 = other.values[15];
286 | const p11 = m11 * o11 + m12 * o21 + m13 * o31 + m14 * o41;
287 | const p12 = m11 * o12 + m12 * o22 + m13 * o32 + m14 * o42;
288 | const p13 = m11 * o13 + m12 * o23 + m13 * o33 + m14 * o43;
289 | const p14 = m11 * o14 + m12 * o24 + m13 * o34 + m14 * o44;
290 | const p21 = m21 * o11 + m22 * o21 + m23 * o31 + m24 * o41;
291 | const p22 = m21 * o12 + m22 * o22 + m23 * o32 + m24 * o42;
292 | const p23 = m21 * o13 + m22 * o23 + m23 * o33 + m24 * o43;
293 | const p24 = m21 * o14 + m22 * o24 + m23 * o34 + m24 * o44;
294 | const p31 = m31 * o11 + m32 * o21 + m33 * o31 + m34 * o41;
295 | const p32 = m31 * o12 + m32 * o22 + m33 * o32 + m34 * o42;
296 | const p33 = m31 * o13 + m32 * o23 + m33 * o33 + m34 * o43;
297 | const p34 = m31 * o14 + m32 * o24 + m33 * o34 + m34 * o44;
298 | const p41 = m41 * o11 + m42 * o21 + m43 * o31 + m44 * o41;
299 | const p42 = m41 * o12 + m42 * o22 + m43 * o32 + m44 * o42;
300 | const p43 = m41 * o13 + m42 * o23 + m43 * o33 + m44 * o43;
301 | const p44 = m41 * o14 + m42 * o24 + m43 * o34 + m44 * o44;
302 | return new Matrix4x4(p11, p21, p31, p41, p12, p22, p32, p42, p13, p23, p33, p43, p14, p24, p34, p44);
303 | }
304 | mulByMatrix4(other) {
305 | return this.mulByMatrix4x4(other);
306 | }
307 | translate(tx, ty, tz) {
308 | const t = Matrix4x4.translation(tx, ty, tz);
309 | return this.mulByMatrix4x4(t);
310 | }
311 | scale(sx, sy, sz) {
312 | const s = Matrix4x4.scaling(sx, sy, sz);
313 | return this.mulByMatrix4x4(s);
314 | }
315 | rotateX(radian) {
316 | const rx = Matrix4x4.rotationX(radian);
317 | return this.mulByMatrix4x4(rx);
318 | }
319 | rotateY(radian) {
320 | const ry = Matrix4x4.rotationY(radian);
321 | return this.mulByMatrix4x4(ry);
322 | }
323 | rotateZ(radian) {
324 | const rz = Matrix4x4.rotationZ(radian);
325 | return this.mulByMatrix4x4(rz);
326 | }
327 | rotateAround(normalizedAxis, radian) {
328 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
329 | return this.mulByMatrix4x4(r);
330 | }
331 | get values() {
332 | return this._values;
333 | }
334 | toString() {
335 | return this._values.toString();
336 | }
337 | };
338 | var Matrix2 = Matrix2x2;
339 | var Matrix3 = Matrix3x3;
340 | var Matrix4 = Matrix4x4;
341 | // Annotate the CommonJS export names for ESM import in node:
342 | 0 && (module.exports = {
343 | Matrix2,
344 | Matrix2x2,
345 | Matrix3,
346 | Matrix3x3,
347 | Matrix4,
348 | Matrix4x4
349 | });
350 |
--------------------------------------------------------------------------------
/lib/cjs/quaternion.d.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3 } from './float32vector';
2 | import { Matrix4x4 } from './matrix';
3 | /**
4 | * Quaternion which is 4-dimensional complex number.
5 | * See [Wikipedia](https://en.wikipedia.org/wiki/Quaternion).
6 | */
7 | export declare class Quaternion {
8 | protected _values: Float32Array;
9 | constructor(x: number, y: number, z: number, w: number);
10 | /**
11 | * Create a rotation quaternion around `normalizedAxis`.
12 | * `normalizedAxis` must be normalized.
13 | * @param {Float32Vector3} normalizedAxis
14 | * @param {number} radian
15 | * @returns {Quaternion}
16 | */
17 | static rotationAround(normalizedAxis: Float32Vector3, radian: number): Quaternion;
18 | /**
19 | * Returns a normalized quaternion.
20 | * @returns {Quaternion}
21 | */
22 | normalize(): Quaternion;
23 | /**
24 | * Adds the `other` to the quaternion and returns the sum.
25 | *
26 | * This method does not mutate the quaternion.
27 | * @param {Quaternion} other
28 | * @returns {Quaternion}
29 | */
30 | add(other: Quaternion): Quaternion;
31 | /**
32 | * Multiplies the quaternion by `scalar` and returns the product.
33 | *
34 | * This method does not mutate the quaternion.
35 | * @param {number} scalar
36 | * @returns {Quaternion}
37 | */
38 | mulByScalar(scalar: number): Quaternion;
39 | /**
40 | * Calculates dot product.
41 | * @param {Quaternion} other
42 | * @returns {number}
43 | */
44 | dot(other: Quaternion): number;
45 | /**
46 | * Calculates spherical linear interpolation(also known as Slerp) and returns new `Quaternion` between the quaternion and the other.
47 | * @param {Quaternion} other
48 | * @param {number} t 0.0 <= t <= 1.0
49 | * @param {{chooseShorterAngle: boolean}} options Does not work currently. slerp chooses shorter angle regardless of this value.
50 | * @returns {Quaternion}
51 | */
52 | slerp(other: Quaternion, t: number, options?: {
53 | chooseShorterAngle: boolean;
54 | }): Quaternion;
55 | /**
56 | * Calc magnitude of the quaternion.
57 | * @returns {number}
58 | */
59 | get magnitude(): number;
60 | /**
61 | * Calc norm of the quaternion.
62 | * An alias for `magnitude`.
63 | * @returns {number}
64 | */
65 | get norm(): number;
66 | /**
67 | * Returns x value of the vector.
68 | * @returns {number}
69 | */
70 | get x(): number;
71 | /**
72 | * Returns y value of the vector.
73 | * @returns {number}
74 | */
75 | get y(): number;
76 | /**
77 | * Returns z value of the vector.
78 | * @returns {number}
79 | */
80 | get z(): number;
81 | /**
82 | * Returns w value of the vector.
83 | * @returns {number}
84 | */
85 | get w(): number;
86 | /**
87 | * Set the `value` as new x.
88 | * @param {number} value
89 | */
90 | set x(value: number);
91 | /**
92 | * Set the `value` as new y.
93 | * @param {number} value
94 | */
95 | set y(value: number);
96 | /**
97 | * Set the `value` as new z.
98 | * @param {number} value
99 | */
100 | set z(value: number);
101 | /**
102 | * Set the `value` as new w.
103 | * @param {number} value
104 | */
105 | set w(value: number);
106 | /**
107 | * Returns values of the quaternion.
108 | * @returns {Float32Array}
109 | */
110 | get values(): Float32Array;
111 | /**
112 | * Convert the quaternion to a rotation matrix.
113 | * @returns {Matrix4x4}
114 | */
115 | toRotationMatrix4(): Matrix4x4;
116 | /**
117 | * Returns values as `String`.
118 | * @returns {string}
119 | */
120 | toString(): string;
121 | }
122 |
--------------------------------------------------------------------------------
/lib/cjs/quaternion.js:
--------------------------------------------------------------------------------
1 | var __defProp = Object.defineProperty;
2 | var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
3 | var __export = (target, all) => {
4 | __markAsModule(target);
5 | for (var name in all)
6 | __defProp(target, name, { get: all[name], enumerable: true });
7 | };
8 |
9 | // src/quaternion.ts
10 | __export(exports, {
11 | Quaternion: () => Quaternion
12 | });
13 |
14 | // src/matrix.ts
15 | var Matrix4x4 = class {
16 | constructor(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44) {
17 | this._values = new Float32Array([
18 | m11,
19 | m21,
20 | m31,
21 | m41,
22 | m12,
23 | m22,
24 | m32,
25 | m42,
26 | m13,
27 | m23,
28 | m33,
29 | m43,
30 | m14,
31 | m24,
32 | m34,
33 | m44
34 | ]);
35 | }
36 | static identity() {
37 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
38 | }
39 | static translation(tx, ty, tz) {
40 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
41 | }
42 | static scaling(sx, sy, sz) {
43 | return new Matrix4x4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
44 | }
45 | static rotationX(radian) {
46 | const sin = Math.sin(radian);
47 | const cos = Math.cos(radian);
48 | return new Matrix4x4(1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1);
49 | }
50 | static rotationY(radian) {
51 | const sin = Math.sin(radian);
52 | const cos = Math.cos(radian);
53 | return new Matrix4x4(cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1);
54 | }
55 | static rotationZ(radian) {
56 | const sin = Math.sin(radian);
57 | const cos = Math.cos(radian);
58 | return new Matrix4x4(cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
59 | }
60 | static rotationAround(normalizedAxis, radian) {
61 | const q = Quaternion.rotationAround(normalizedAxis, radian);
62 | return q.toRotationMatrix4();
63 | }
64 | static lookAt(cameraPosition, lookAtPosition, cameraUp) {
65 | const zAxis = cameraPosition.sub(lookAtPosition).normalize();
66 | const xAxis = cameraUp.cross(zAxis).normalize();
67 | const yAxis = zAxis.cross(xAxis).normalize();
68 | return new Matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1);
69 | }
70 | static orthographic(argsObject) {
71 | const top = argsObject.top;
72 | const bottom = argsObject.bottom;
73 | const left = argsObject.left;
74 | const right = argsObject.right;
75 | const near = argsObject.near;
76 | const far = argsObject.far;
77 | return new Matrix4x4(2 / (right - left), 0, 0, 0, 0, 2 / (top - bottom), 0, 0, 0, 0, -2 / (far - near), 0, -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1);
78 | }
79 | static frustum(argsObject) {
80 | const top = argsObject.top;
81 | const bottom = argsObject.bottom;
82 | const left = argsObject.left;
83 | const right = argsObject.right;
84 | const near = argsObject.near;
85 | const far = argsObject.far;
86 | return new Matrix4x4(2 * near / (right - left), 0, 0, 0, 0, 2 * near / (top - bottom), 0, 0, (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0);
87 | }
88 | static perspective(argsObject) {
89 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
90 | const height = top * 2;
91 | const width = argsObject.aspectRatio * height;
92 | const left = -0.5 * width;
93 | const right = left + width;
94 | const bottom = top - height;
95 | return Matrix4x4.frustum({
96 | top,
97 | bottom,
98 | left,
99 | right,
100 | near: argsObject.near,
101 | far: argsObject.far
102 | });
103 | }
104 | mulByMatrix4x4(other) {
105 | const m11 = this._values[0];
106 | const m12 = this._values[4];
107 | const m13 = this._values[8];
108 | const m14 = this._values[12];
109 | const m21 = this._values[1];
110 | const m22 = this._values[5];
111 | const m23 = this._values[9];
112 | const m24 = this._values[13];
113 | const m31 = this._values[2];
114 | const m32 = this._values[6];
115 | const m33 = this._values[10];
116 | const m34 = this._values[14];
117 | const m41 = this._values[3];
118 | const m42 = this._values[7];
119 | const m43 = this._values[11];
120 | const m44 = this._values[15];
121 | const o11 = other.values[0];
122 | const o12 = other.values[4];
123 | const o13 = other.values[8];
124 | const o14 = other.values[12];
125 | const o21 = other.values[1];
126 | const o22 = other.values[5];
127 | const o23 = other.values[9];
128 | const o24 = other.values[13];
129 | const o31 = other.values[2];
130 | const o32 = other.values[6];
131 | const o33 = other.values[10];
132 | const o34 = other.values[14];
133 | const o41 = other.values[3];
134 | const o42 = other.values[7];
135 | const o43 = other.values[11];
136 | const o44 = other.values[15];
137 | const p11 = m11 * o11 + m12 * o21 + m13 * o31 + m14 * o41;
138 | const p12 = m11 * o12 + m12 * o22 + m13 * o32 + m14 * o42;
139 | const p13 = m11 * o13 + m12 * o23 + m13 * o33 + m14 * o43;
140 | const p14 = m11 * o14 + m12 * o24 + m13 * o34 + m14 * o44;
141 | const p21 = m21 * o11 + m22 * o21 + m23 * o31 + m24 * o41;
142 | const p22 = m21 * o12 + m22 * o22 + m23 * o32 + m24 * o42;
143 | const p23 = m21 * o13 + m22 * o23 + m23 * o33 + m24 * o43;
144 | const p24 = m21 * o14 + m22 * o24 + m23 * o34 + m24 * o44;
145 | const p31 = m31 * o11 + m32 * o21 + m33 * o31 + m34 * o41;
146 | const p32 = m31 * o12 + m32 * o22 + m33 * o32 + m34 * o42;
147 | const p33 = m31 * o13 + m32 * o23 + m33 * o33 + m34 * o43;
148 | const p34 = m31 * o14 + m32 * o24 + m33 * o34 + m34 * o44;
149 | const p41 = m41 * o11 + m42 * o21 + m43 * o31 + m44 * o41;
150 | const p42 = m41 * o12 + m42 * o22 + m43 * o32 + m44 * o42;
151 | const p43 = m41 * o13 + m42 * o23 + m43 * o33 + m44 * o43;
152 | const p44 = m41 * o14 + m42 * o24 + m43 * o34 + m44 * o44;
153 | return new Matrix4x4(p11, p21, p31, p41, p12, p22, p32, p42, p13, p23, p33, p43, p14, p24, p34, p44);
154 | }
155 | mulByMatrix4(other) {
156 | return this.mulByMatrix4x4(other);
157 | }
158 | translate(tx, ty, tz) {
159 | const t = Matrix4x4.translation(tx, ty, tz);
160 | return this.mulByMatrix4x4(t);
161 | }
162 | scale(sx, sy, sz) {
163 | const s = Matrix4x4.scaling(sx, sy, sz);
164 | return this.mulByMatrix4x4(s);
165 | }
166 | rotateX(radian) {
167 | const rx = Matrix4x4.rotationX(radian);
168 | return this.mulByMatrix4x4(rx);
169 | }
170 | rotateY(radian) {
171 | const ry = Matrix4x4.rotationY(radian);
172 | return this.mulByMatrix4x4(ry);
173 | }
174 | rotateZ(radian) {
175 | const rz = Matrix4x4.rotationZ(radian);
176 | return this.mulByMatrix4x4(rz);
177 | }
178 | rotateAround(normalizedAxis, radian) {
179 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
180 | return this.mulByMatrix4x4(r);
181 | }
182 | get values() {
183 | return this._values;
184 | }
185 | toString() {
186 | return this._values.toString();
187 | }
188 | };
189 |
190 | // src/quaternion.ts
191 | var Quaternion = class {
192 | constructor(x, y, z, w) {
193 | this._values = new Float32Array([x, y, z, w]);
194 | }
195 | static rotationAround(normalizedAxis, radian) {
196 | const sin = Math.sin(radian / 2);
197 | const cos = Math.cos(radian / 2);
198 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
199 | }
200 | normalize() {
201 | const mag = this.magnitude;
202 | if (mag === 0) {
203 | return this;
204 | }
205 | const r = 1 / mag;
206 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
207 | }
208 | add(other) {
209 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
210 | }
211 | mulByScalar(scalar) {
212 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
213 | }
214 | dot(other) {
215 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
216 | }
217 | slerp(other, t, options = { chooseShorterAngle: true }) {
218 | let dotProd = this.dot(other);
219 | let otherQuaternion = other;
220 | if (dotProd < 0) {
221 | dotProd = -dotProd;
222 | otherQuaternion = other.mulByScalar(-1);
223 | }
224 | const omega = Math.acos(dotProd);
225 | const sinOmega = Math.sin(omega);
226 | const q1 = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
227 | const q2 = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
228 | return q1.add(q2);
229 | }
230 | get magnitude() {
231 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
232 | }
233 | get norm() {
234 | return this.magnitude;
235 | }
236 | get x() {
237 | return this._values[0];
238 | }
239 | get y() {
240 | return this._values[1];
241 | }
242 | get z() {
243 | return this._values[2];
244 | }
245 | get w() {
246 | return this._values[3];
247 | }
248 | set x(value) {
249 | this._values[0] = value;
250 | }
251 | set y(value) {
252 | this._values[1] = value;
253 | }
254 | set z(value) {
255 | this._values[2] = value;
256 | }
257 | set w(value) {
258 | this._values[3] = value;
259 | }
260 | get values() {
261 | return this._values;
262 | }
263 | toRotationMatrix4() {
264 | const x = this.x;
265 | const y = this.y;
266 | const z = this.z;
267 | const w = this.w;
268 | const m11 = 1 - 2 * y * y - 2 * z * z;
269 | const m12 = 2 * x * y - 2 * w * z;
270 | const m13 = 2 * x * z + 2 * w * y;
271 | const m14 = 0;
272 | const m21 = 2 * x * y + 2 * w * z;
273 | const m22 = 1 - 2 * x * x - 2 * z * z;
274 | const m23 = 2 * y * z - 2 * w * x;
275 | const m24 = 0;
276 | const m31 = 2 * x * z - 2 * w * y;
277 | const m32 = 2 * y * z + 2 * w * x;
278 | const m33 = 1 - 2 * x * x - 2 * y * y;
279 | const m34 = 0;
280 | const m41 = 0;
281 | const m42 = 0;
282 | const m43 = 0;
283 | const m44 = 1;
284 | return new Matrix4x4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44);
285 | }
286 | toString() {
287 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
288 | }
289 | };
290 | // Annotate the CommonJS export names for ESM import in node:
291 | 0 && (module.exports = {
292 | Quaternion
293 | });
294 |
--------------------------------------------------------------------------------
/lib/cjs/vector_base.d.ts:
--------------------------------------------------------------------------------
1 | export declare type TypedArrayLike = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
2 | /**
3 | * An interface for vectors.
4 | */
5 | export interface Vector {
6 | /**
7 | * Returns values of the vector.
8 | * @returns {T}
9 | */
10 | readonly values: T;
11 | /**
12 | * Returns magnitude of the vector.
13 | */
14 | readonly magnitude: number;
15 | /**
16 | * Returns `values` as a string.
17 | * @returns {string}
18 | */
19 | toString(): string;
20 | }
21 | /**
22 | * An abstract class for vectors.
23 | */
24 | export declare abstract class VectorBase implements Vector {
25 | /**
26 | * Values that the vector contains.
27 | */
28 | protected _values: T;
29 | get values(): T;
30 | get magnitude(): number;
31 | toString(): string;
32 | }
33 | /**
34 | * A base abstract class for 2-dimensional vectors.
35 | */
36 | export declare abstract class Vector2Base extends VectorBase {
37 | /**
38 | * Returns x value of the vector.
39 | * @returns {number}
40 | */
41 | get x(): number;
42 | /**
43 | * Returns y value of the vector.
44 | * @returns {number}
45 | */
46 | get y(): number;
47 | /**
48 | * Set the `value` as new x.
49 | * @param {number} value
50 | */
51 | set x(value: number);
52 | /**
53 | * Set the `value` as new y.
54 | * @param {number} value
55 | */
56 | set y(value: number);
57 | }
58 | /**
59 | * A base abstract class for 3-dimensional vectors.
60 | */
61 | export declare abstract class Vector3Base extends VectorBase {
62 | /**
63 | * Returns x value of the vector.
64 | * @returns {number}
65 | */
66 | get x(): number;
67 | /**
68 | * Returns y value of the vector.
69 | * @returns {number}
70 | */
71 | get y(): number;
72 | /**
73 | * Returns z value of the vector.
74 | * @returns {number}
75 | */
76 | get z(): number;
77 | /**
78 | * Set the `value` as new x.
79 | * @param {number} value
80 | */
81 | set x(value: number);
82 | /**
83 | * Set the `value` as new y.
84 | * @param {number} value
85 | */
86 | set y(value: number);
87 | /**
88 | * Set the `value` as new z.
89 | * @param {number} value
90 | */
91 | set z(value: number);
92 | }
93 | /**
94 | * A base abstract class for 4-dimensional vectors.
95 | */
96 | export declare abstract class Vector4Base extends VectorBase {
97 | /**
98 | * Returns x value of the vector.
99 | * @returns {number}
100 | */
101 | get x(): number;
102 | /**
103 | * Returns y value of the vector.
104 | * @returns {number}
105 | */
106 | get y(): number;
107 | /**
108 | * Returns z value of the vector.
109 | * @returns {number}
110 | */
111 | get z(): number;
112 | /**
113 | * Returns w value of the vector.
114 | * @returns {number}
115 | */
116 | get w(): number;
117 | /**
118 | * Set the `value` as new x.
119 | * @param {number} value
120 | */
121 | set x(value: number);
122 | /**
123 | * Set the `value` as new y.
124 | * @param {number} value
125 | */
126 | set y(value: number);
127 | /**
128 | * Set the `value` as new z.
129 | * @param {number} value
130 | */
131 | set z(value: number);
132 | /**
133 | * Set the `value` as new w.
134 | * @param {number} value
135 | */
136 | set w(value: number);
137 | }
138 |
--------------------------------------------------------------------------------
/lib/cjs/vector_base.js:
--------------------------------------------------------------------------------
1 | var __defProp = Object.defineProperty;
2 | var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
3 | var __export = (target, all) => {
4 | __markAsModule(target);
5 | for (var name in all)
6 | __defProp(target, name, { get: all[name], enumerable: true });
7 | };
8 |
9 | // src/vector_base.ts
10 | __export(exports, {
11 | Vector2Base: () => Vector2Base,
12 | Vector3Base: () => Vector3Base,
13 | Vector4Base: () => Vector4Base,
14 | VectorBase: () => VectorBase
15 | });
16 | var VectorBase = class {
17 | get values() {
18 | return this._values;
19 | }
20 | get magnitude() {
21 | let sumSq = 0;
22 | for (const val of this._values) {
23 | sumSq += val ** 2;
24 | }
25 | return Math.sqrt(sumSq);
26 | }
27 | toString() {
28 | const dimension = this._values.length;
29 | return `Vector${dimension}(${this._values.join(", ")})`;
30 | }
31 | };
32 | var Vector2Base = class extends VectorBase {
33 | get x() {
34 | return this._values[0];
35 | }
36 | get y() {
37 | return this._values[1];
38 | }
39 | set x(value) {
40 | this._values[0] = value;
41 | }
42 | set y(value) {
43 | this._values[1] = value;
44 | }
45 | };
46 | var Vector3Base = class extends VectorBase {
47 | get x() {
48 | return this._values[0];
49 | }
50 | get y() {
51 | return this._values[1];
52 | }
53 | get z() {
54 | return this._values[2];
55 | }
56 | set x(value) {
57 | this._values[0] = value;
58 | }
59 | set y(value) {
60 | this._values[1] = value;
61 | }
62 | set z(value) {
63 | this._values[2] = value;
64 | }
65 | };
66 | var Vector4Base = class extends VectorBase {
67 | get x() {
68 | return this._values[0];
69 | }
70 | get y() {
71 | return this._values[1];
72 | }
73 | get z() {
74 | return this._values[2];
75 | }
76 | get w() {
77 | return this._values[3];
78 | }
79 | set x(value) {
80 | this._values[0] = value;
81 | }
82 | set y(value) {
83 | this._values[1] = value;
84 | }
85 | set z(value) {
86 | this._values[2] = value;
87 | }
88 | set w(value) {
89 | this._values[3] = value;
90 | }
91 | };
92 | // Annotate the CommonJS export names for ESM import in node:
93 | 0 && (module.exports = {
94 | Vector2Base,
95 | Vector3Base,
96 | Vector4Base,
97 | VectorBase
98 | });
99 |
--------------------------------------------------------------------------------
/lib/esm/float32vector.d.ts:
--------------------------------------------------------------------------------
1 | import { Vector2Base, Vector3Base, Vector4Base } from './vector_base';
2 | /**
3 | * A 2-dimensional vector of single-precision float numbers.
4 | */
5 | export declare class Float32Vector2 extends Vector2Base {
6 | constructor(x: number, y: number);
7 | /**
8 | * Add `other` to the vector and returns new `Float32Vector2`.
9 | *
10 | * This method does not mutate the vector.
11 | * @param {Float32Vector2} other
12 | * @returns {Float32Vector2}
13 | */
14 | add(other: Float32Vector2): Float32Vector2;
15 | /**
16 | * Subtract `other` from the vector and returns new `Float32Vector2`.
17 | *
18 | * This method does not mutate the vector.
19 | * @param {Float32Vector2} other
20 | * @returns {Float32Vector2}
21 | */
22 | sub(other: Float32Vector2): Float32Vector2;
23 | /**
24 | * Multiply the vector by `scalar` and returns new `Float32Vector2`.
25 | *
26 | * This method does not mutate the vector.
27 | * @param {number} scalar
28 | * @returns {Float32Vector2}
29 | */
30 | mulByScalar(scalar: number): Float32Vector2;
31 | }
32 | /**
33 | * A 3-dimensional vector of single-precision float numbers.
34 | */
35 | export declare class Float32Vector3 extends Vector3Base {
36 | constructor(x: number, y: number, z: number);
37 | /**
38 | * Add `other` to the vector and returns new `Float32Vector3`.
39 | *
40 | * This method does not mutate the vector.
41 | * @param {Float32Vector3} other
42 | * @returns {Float32Vector3}
43 | */
44 | add(other: Float32Vector3): Float32Vector3;
45 | /**
46 | * Subtract `other` from the vector and returns new `Float32Vector3`.
47 | *
48 | * This method does not mutate the vector.
49 | * @param {Float32Vector3} other
50 | * @returns {Float32Vector3}
51 | */
52 | sub(other: Float32Vector3): Float32Vector3;
53 | /**
54 | * Multiply the vector by `scalar` and returns new `Float32Vector3`.
55 | *
56 | * This method does not mutate the vector.
57 | * @param {number} scalar
58 | * @returns {Float32Vector3}
59 | */
60 | mulByScalar(scalar: number): Float32Vector3;
61 | /**
62 | * Calculate dot product.
63 | * @param {Float32Vector3} other
64 | * @returns {number}
65 | */
66 | dot(other: Float32Vector3): number;
67 | /**
68 | * Calculate cross product.
69 | * @param {Float32Vector3} other
70 | * @returns {Float32Vector3}
71 | */
72 | cross(other: Float32Vector3): Float32Vector3;
73 | /**
74 | * Normalize the vector and returns new `Float32Vector3`.
75 | *
76 | * This method does not mutate the vector.
77 | * @returns {Float32Vector3}
78 | */
79 | normalize(): Float32Vector3;
80 | /**
81 | * Returns xy values of the vector as `Float32Vector2`.
82 | * @returns {Float32Vector2}
83 | */
84 | get xy(): Float32Vector2;
85 | }
86 | /**
87 | * A 4-dimensional vector of single-precision float numbers.
88 | */
89 | export declare class Float32Vector4 extends Vector4Base {
90 | constructor(x: number, y: number, z: number, w: number);
91 | /**
92 | * Add `other` to the vector and returns new `Float32Vector4`.
93 | *
94 | * This method does not mutate the vector.
95 | * @param {Float32Vector4} other
96 | * @returns {Float32Vector4}
97 | */
98 | add(other: Float32Vector4): Float32Vector4;
99 | /**
100 | * Subtract `other` from the vector and returns new `Float32Vector4`.
101 | *
102 | * This method does not mutate the vector.
103 | * @param {Float32Vector4} other
104 | * @returns {Float32Vector4}
105 | */
106 | sub(other: Float32Vector4): Float32Vector4;
107 | /**
108 | * Multiply the vector by `scalar` and returns new `Float32Vector4`.
109 | *
110 | * This method does not mutate the vector.
111 | * @param {number} scalar
112 | * @returns {Float32Vector4}
113 | */
114 | mulByScalar(scalar: number): Float32Vector4;
115 | /**
116 | * Returns xyz values of the vector as `Float32Vector3`.
117 | * @returns {Float32Vector3}
118 | */
119 | get xyz(): Float32Vector3;
120 | }
121 | /**
122 | * An alias for `Float32Vector2`.
123 | * @type {Float32Vector2}
124 | */
125 | export declare const Vector2: typeof Float32Vector2;
126 | /**
127 | * An alias for `Float32Vector3`.
128 | * @type {Float32Vector3}
129 | */
130 | export declare const Vector3: typeof Float32Vector3;
131 | /**
132 | * An alias for `Float32Vector4`.
133 | * @type {Float32Vector4}
134 | */
135 | export declare const Vector4: typeof Float32Vector4;
136 |
--------------------------------------------------------------------------------
/lib/esm/float32vector.js:
--------------------------------------------------------------------------------
1 | // src/vector_base.ts
2 | var VectorBase = class {
3 | get values() {
4 | return this._values;
5 | }
6 | get magnitude() {
7 | let sumSq = 0;
8 | for (const val of this._values) {
9 | sumSq += val ** 2;
10 | }
11 | return Math.sqrt(sumSq);
12 | }
13 | toString() {
14 | const dimension = this._values.length;
15 | return `Vector${dimension}(${this._values.join(", ")})`;
16 | }
17 | };
18 | var Vector2Base = class extends VectorBase {
19 | get x() {
20 | return this._values[0];
21 | }
22 | get y() {
23 | return this._values[1];
24 | }
25 | set x(value) {
26 | this._values[0] = value;
27 | }
28 | set y(value) {
29 | this._values[1] = value;
30 | }
31 | };
32 | var Vector3Base = class extends VectorBase {
33 | get x() {
34 | return this._values[0];
35 | }
36 | get y() {
37 | return this._values[1];
38 | }
39 | get z() {
40 | return this._values[2];
41 | }
42 | set x(value) {
43 | this._values[0] = value;
44 | }
45 | set y(value) {
46 | this._values[1] = value;
47 | }
48 | set z(value) {
49 | this._values[2] = value;
50 | }
51 | };
52 | var Vector4Base = class extends VectorBase {
53 | get x() {
54 | return this._values[0];
55 | }
56 | get y() {
57 | return this._values[1];
58 | }
59 | get z() {
60 | return this._values[2];
61 | }
62 | get w() {
63 | return this._values[3];
64 | }
65 | set x(value) {
66 | this._values[0] = value;
67 | }
68 | set y(value) {
69 | this._values[1] = value;
70 | }
71 | set z(value) {
72 | this._values[2] = value;
73 | }
74 | set w(value) {
75 | this._values[3] = value;
76 | }
77 | };
78 |
79 | // src/float32vector.ts
80 | var Float32Vector2 = class extends Vector2Base {
81 | constructor(x, y) {
82 | super();
83 | this._values = new Float32Array([x, y]);
84 | }
85 | add(other) {
86 | return new Float32Vector2(this.x + other.x, this.y + other.y);
87 | }
88 | sub(other) {
89 | return new Float32Vector2(this.x - other.x, this.y - other.y);
90 | }
91 | mulByScalar(scalar) {
92 | return new Float32Vector2(this.x * scalar, this.y * scalar);
93 | }
94 | };
95 | var Float32Vector3 = class extends Vector3Base {
96 | constructor(x, y, z) {
97 | super();
98 | this._values = new Float32Array([x, y, z]);
99 | }
100 | add(other) {
101 | return new Float32Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
102 | }
103 | sub(other) {
104 | return new Float32Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
105 | }
106 | mulByScalar(scalar) {
107 | return new Float32Vector3(this.x * scalar, this.y * scalar, this.z * scalar);
108 | }
109 | dot(other) {
110 | return this.x * other.x + this.y * other.y + this.z * other.z;
111 | }
112 | cross(other) {
113 | const cx = this.y * other.z - this.z * other.y;
114 | const cy = this.z * other.x - this.x * other.z;
115 | const cz = this.x * other.y - this.y * other.x;
116 | return new Float32Vector3(cx, cy, cz);
117 | }
118 | normalize() {
119 | const mag = this.magnitude;
120 | if (mag === 0) {
121 | return this;
122 | }
123 | return new Float32Vector3(this.x / mag, this.y / mag, this.z / mag);
124 | }
125 | get xy() {
126 | return new Float32Vector2(this.x, this.y);
127 | }
128 | };
129 | var Float32Vector4 = class extends Vector4Base {
130 | constructor(x, y, z, w) {
131 | super();
132 | this._values = new Float32Array([x, y, z, w]);
133 | }
134 | add(other) {
135 | return new Float32Vector4(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
136 | }
137 | sub(other) {
138 | return new Float32Vector4(this.x - other.x, this.y - other.y, this.z - other.z, this.w - other.w);
139 | }
140 | mulByScalar(scalar) {
141 | return new Float32Vector4(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
142 | }
143 | get xyz() {
144 | return new Float32Vector3(this.x, this.y, this.z);
145 | }
146 | };
147 | var Vector2 = Float32Vector2;
148 | var Vector3 = Float32Vector3;
149 | var Vector4 = Float32Vector4;
150 | export {
151 | Float32Vector2,
152 | Float32Vector3,
153 | Float32Vector4,
154 | Vector2,
155 | Vector3,
156 | Vector4
157 | };
158 |
--------------------------------------------------------------------------------
/lib/esm/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './float32vector';
2 | export * from './matrix';
3 | export * from './quaternion';
4 |
--------------------------------------------------------------------------------
/lib/esm/index.js:
--------------------------------------------------------------------------------
1 | // src/vector_base.ts
2 | var VectorBase = class {
3 | get values() {
4 | return this._values;
5 | }
6 | get magnitude() {
7 | let sumSq = 0;
8 | for (const val of this._values) {
9 | sumSq += val ** 2;
10 | }
11 | return Math.sqrt(sumSq);
12 | }
13 | toString() {
14 | const dimension = this._values.length;
15 | return `Vector${dimension}(${this._values.join(", ")})`;
16 | }
17 | };
18 | var Vector2Base = class extends VectorBase {
19 | get x() {
20 | return this._values[0];
21 | }
22 | get y() {
23 | return this._values[1];
24 | }
25 | set x(value) {
26 | this._values[0] = value;
27 | }
28 | set y(value) {
29 | this._values[1] = value;
30 | }
31 | };
32 | var Vector3Base = class extends VectorBase {
33 | get x() {
34 | return this._values[0];
35 | }
36 | get y() {
37 | return this._values[1];
38 | }
39 | get z() {
40 | return this._values[2];
41 | }
42 | set x(value) {
43 | this._values[0] = value;
44 | }
45 | set y(value) {
46 | this._values[1] = value;
47 | }
48 | set z(value) {
49 | this._values[2] = value;
50 | }
51 | };
52 | var Vector4Base = class extends VectorBase {
53 | get x() {
54 | return this._values[0];
55 | }
56 | get y() {
57 | return this._values[1];
58 | }
59 | get z() {
60 | return this._values[2];
61 | }
62 | get w() {
63 | return this._values[3];
64 | }
65 | set x(value) {
66 | this._values[0] = value;
67 | }
68 | set y(value) {
69 | this._values[1] = value;
70 | }
71 | set z(value) {
72 | this._values[2] = value;
73 | }
74 | set w(value) {
75 | this._values[3] = value;
76 | }
77 | };
78 |
79 | // src/float32vector.ts
80 | var Float32Vector2 = class extends Vector2Base {
81 | constructor(x, y) {
82 | super();
83 | this._values = new Float32Array([x, y]);
84 | }
85 | add(other) {
86 | return new Float32Vector2(this.x + other.x, this.y + other.y);
87 | }
88 | sub(other) {
89 | return new Float32Vector2(this.x - other.x, this.y - other.y);
90 | }
91 | mulByScalar(scalar) {
92 | return new Float32Vector2(this.x * scalar, this.y * scalar);
93 | }
94 | };
95 | var Float32Vector3 = class extends Vector3Base {
96 | constructor(x, y, z) {
97 | super();
98 | this._values = new Float32Array([x, y, z]);
99 | }
100 | add(other) {
101 | return new Float32Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
102 | }
103 | sub(other) {
104 | return new Float32Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
105 | }
106 | mulByScalar(scalar) {
107 | return new Float32Vector3(this.x * scalar, this.y * scalar, this.z * scalar);
108 | }
109 | dot(other) {
110 | return this.x * other.x + this.y * other.y + this.z * other.z;
111 | }
112 | cross(other) {
113 | const cx = this.y * other.z - this.z * other.y;
114 | const cy = this.z * other.x - this.x * other.z;
115 | const cz = this.x * other.y - this.y * other.x;
116 | return new Float32Vector3(cx, cy, cz);
117 | }
118 | normalize() {
119 | const mag = this.magnitude;
120 | if (mag === 0) {
121 | return this;
122 | }
123 | return new Float32Vector3(this.x / mag, this.y / mag, this.z / mag);
124 | }
125 | get xy() {
126 | return new Float32Vector2(this.x, this.y);
127 | }
128 | };
129 | var Float32Vector4 = class extends Vector4Base {
130 | constructor(x, y, z, w) {
131 | super();
132 | this._values = new Float32Array([x, y, z, w]);
133 | }
134 | add(other) {
135 | return new Float32Vector4(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
136 | }
137 | sub(other) {
138 | return new Float32Vector4(this.x - other.x, this.y - other.y, this.z - other.z, this.w - other.w);
139 | }
140 | mulByScalar(scalar) {
141 | return new Float32Vector4(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
142 | }
143 | get xyz() {
144 | return new Float32Vector3(this.x, this.y, this.z);
145 | }
146 | };
147 | var Vector2 = Float32Vector2;
148 | var Vector3 = Float32Vector3;
149 | var Vector4 = Float32Vector4;
150 |
151 | // src/quaternion.ts
152 | var Quaternion = class {
153 | constructor(x, y, z, w) {
154 | this._values = new Float32Array([x, y, z, w]);
155 | }
156 | static rotationAround(normalizedAxis, radian) {
157 | const sin = Math.sin(radian / 2);
158 | const cos = Math.cos(radian / 2);
159 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
160 | }
161 | normalize() {
162 | const mag = this.magnitude;
163 | if (mag === 0) {
164 | return this;
165 | }
166 | const r = 1 / mag;
167 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
168 | }
169 | add(other) {
170 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
171 | }
172 | mulByScalar(scalar) {
173 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
174 | }
175 | dot(other) {
176 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
177 | }
178 | slerp(other, t, options = { chooseShorterAngle: true }) {
179 | let dotProd = this.dot(other);
180 | let otherQuaternion = other;
181 | if (dotProd < 0) {
182 | dotProd = -dotProd;
183 | otherQuaternion = other.mulByScalar(-1);
184 | }
185 | const omega = Math.acos(dotProd);
186 | const sinOmega = Math.sin(omega);
187 | const q1 = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
188 | const q2 = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
189 | return q1.add(q2);
190 | }
191 | get magnitude() {
192 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
193 | }
194 | get norm() {
195 | return this.magnitude;
196 | }
197 | get x() {
198 | return this._values[0];
199 | }
200 | get y() {
201 | return this._values[1];
202 | }
203 | get z() {
204 | return this._values[2];
205 | }
206 | get w() {
207 | return this._values[3];
208 | }
209 | set x(value) {
210 | this._values[0] = value;
211 | }
212 | set y(value) {
213 | this._values[1] = value;
214 | }
215 | set z(value) {
216 | this._values[2] = value;
217 | }
218 | set w(value) {
219 | this._values[3] = value;
220 | }
221 | get values() {
222 | return this._values;
223 | }
224 | toRotationMatrix4() {
225 | const x = this.x;
226 | const y = this.y;
227 | const z = this.z;
228 | const w = this.w;
229 | const m11 = 1 - 2 * y * y - 2 * z * z;
230 | const m12 = 2 * x * y - 2 * w * z;
231 | const m13 = 2 * x * z + 2 * w * y;
232 | const m14 = 0;
233 | const m21 = 2 * x * y + 2 * w * z;
234 | const m22 = 1 - 2 * x * x - 2 * z * z;
235 | const m23 = 2 * y * z - 2 * w * x;
236 | const m24 = 0;
237 | const m31 = 2 * x * z - 2 * w * y;
238 | const m32 = 2 * y * z + 2 * w * x;
239 | const m33 = 1 - 2 * x * x - 2 * y * y;
240 | const m34 = 0;
241 | const m41 = 0;
242 | const m42 = 0;
243 | const m43 = 0;
244 | const m44 = 1;
245 | return new Matrix4x4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44);
246 | }
247 | toString() {
248 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
249 | }
250 | };
251 |
252 | // src/matrix.ts
253 | var Matrix2x2 = class {
254 | constructor(m11, m21, m12, m22) {
255 | this._values = new Float32Array([
256 | m11,
257 | m21,
258 | m12,
259 | m22
260 | ]);
261 | }
262 | static identity() {
263 | return new Matrix2x2(1, 0, 0, 1);
264 | }
265 | get values() {
266 | return this._values;
267 | }
268 | toString() {
269 | return this._values.toString();
270 | }
271 | };
272 | var Matrix3x3 = class {
273 | constructor(m11, m21, m31, m12, m22, m32, m13, m23, m33) {
274 | this._values = new Float32Array([
275 | m11,
276 | m21,
277 | m31,
278 | m12,
279 | m22,
280 | m32,
281 | m13,
282 | m23,
283 | m33
284 | ]);
285 | }
286 | static identity() {
287 | return new Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
288 | }
289 | get values() {
290 | return this._values;
291 | }
292 | toString() {
293 | return this._values.toString();
294 | }
295 | };
296 | var Matrix4x4 = class {
297 | constructor(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44) {
298 | this._values = new Float32Array([
299 | m11,
300 | m21,
301 | m31,
302 | m41,
303 | m12,
304 | m22,
305 | m32,
306 | m42,
307 | m13,
308 | m23,
309 | m33,
310 | m43,
311 | m14,
312 | m24,
313 | m34,
314 | m44
315 | ]);
316 | }
317 | static identity() {
318 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
319 | }
320 | static translation(tx, ty, tz) {
321 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
322 | }
323 | static scaling(sx, sy, sz) {
324 | return new Matrix4x4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
325 | }
326 | static rotationX(radian) {
327 | const sin = Math.sin(radian);
328 | const cos = Math.cos(radian);
329 | return new Matrix4x4(1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1);
330 | }
331 | static rotationY(radian) {
332 | const sin = Math.sin(radian);
333 | const cos = Math.cos(radian);
334 | return new Matrix4x4(cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1);
335 | }
336 | static rotationZ(radian) {
337 | const sin = Math.sin(radian);
338 | const cos = Math.cos(radian);
339 | return new Matrix4x4(cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
340 | }
341 | static rotationAround(normalizedAxis, radian) {
342 | const q = Quaternion.rotationAround(normalizedAxis, radian);
343 | return q.toRotationMatrix4();
344 | }
345 | static lookAt(cameraPosition, lookAtPosition, cameraUp) {
346 | const zAxis = cameraPosition.sub(lookAtPosition).normalize();
347 | const xAxis = cameraUp.cross(zAxis).normalize();
348 | const yAxis = zAxis.cross(xAxis).normalize();
349 | return new Matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1);
350 | }
351 | static orthographic(argsObject) {
352 | const top = argsObject.top;
353 | const bottom = argsObject.bottom;
354 | const left = argsObject.left;
355 | const right = argsObject.right;
356 | const near = argsObject.near;
357 | const far = argsObject.far;
358 | return new Matrix4x4(2 / (right - left), 0, 0, 0, 0, 2 / (top - bottom), 0, 0, 0, 0, -2 / (far - near), 0, -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1);
359 | }
360 | static frustum(argsObject) {
361 | const top = argsObject.top;
362 | const bottom = argsObject.bottom;
363 | const left = argsObject.left;
364 | const right = argsObject.right;
365 | const near = argsObject.near;
366 | const far = argsObject.far;
367 | return new Matrix4x4(2 * near / (right - left), 0, 0, 0, 0, 2 * near / (top - bottom), 0, 0, (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0);
368 | }
369 | static perspective(argsObject) {
370 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
371 | const height = top * 2;
372 | const width = argsObject.aspectRatio * height;
373 | const left = -0.5 * width;
374 | const right = left + width;
375 | const bottom = top - height;
376 | return Matrix4x4.frustum({
377 | top,
378 | bottom,
379 | left,
380 | right,
381 | near: argsObject.near,
382 | far: argsObject.far
383 | });
384 | }
385 | mulByMatrix4x4(other) {
386 | const m11 = this._values[0];
387 | const m12 = this._values[4];
388 | const m13 = this._values[8];
389 | const m14 = this._values[12];
390 | const m21 = this._values[1];
391 | const m22 = this._values[5];
392 | const m23 = this._values[9];
393 | const m24 = this._values[13];
394 | const m31 = this._values[2];
395 | const m32 = this._values[6];
396 | const m33 = this._values[10];
397 | const m34 = this._values[14];
398 | const m41 = this._values[3];
399 | const m42 = this._values[7];
400 | const m43 = this._values[11];
401 | const m44 = this._values[15];
402 | const o11 = other.values[0];
403 | const o12 = other.values[4];
404 | const o13 = other.values[8];
405 | const o14 = other.values[12];
406 | const o21 = other.values[1];
407 | const o22 = other.values[5];
408 | const o23 = other.values[9];
409 | const o24 = other.values[13];
410 | const o31 = other.values[2];
411 | const o32 = other.values[6];
412 | const o33 = other.values[10];
413 | const o34 = other.values[14];
414 | const o41 = other.values[3];
415 | const o42 = other.values[7];
416 | const o43 = other.values[11];
417 | const o44 = other.values[15];
418 | const p11 = m11 * o11 + m12 * o21 + m13 * o31 + m14 * o41;
419 | const p12 = m11 * o12 + m12 * o22 + m13 * o32 + m14 * o42;
420 | const p13 = m11 * o13 + m12 * o23 + m13 * o33 + m14 * o43;
421 | const p14 = m11 * o14 + m12 * o24 + m13 * o34 + m14 * o44;
422 | const p21 = m21 * o11 + m22 * o21 + m23 * o31 + m24 * o41;
423 | const p22 = m21 * o12 + m22 * o22 + m23 * o32 + m24 * o42;
424 | const p23 = m21 * o13 + m22 * o23 + m23 * o33 + m24 * o43;
425 | const p24 = m21 * o14 + m22 * o24 + m23 * o34 + m24 * o44;
426 | const p31 = m31 * o11 + m32 * o21 + m33 * o31 + m34 * o41;
427 | const p32 = m31 * o12 + m32 * o22 + m33 * o32 + m34 * o42;
428 | const p33 = m31 * o13 + m32 * o23 + m33 * o33 + m34 * o43;
429 | const p34 = m31 * o14 + m32 * o24 + m33 * o34 + m34 * o44;
430 | const p41 = m41 * o11 + m42 * o21 + m43 * o31 + m44 * o41;
431 | const p42 = m41 * o12 + m42 * o22 + m43 * o32 + m44 * o42;
432 | const p43 = m41 * o13 + m42 * o23 + m43 * o33 + m44 * o43;
433 | const p44 = m41 * o14 + m42 * o24 + m43 * o34 + m44 * o44;
434 | return new Matrix4x4(p11, p21, p31, p41, p12, p22, p32, p42, p13, p23, p33, p43, p14, p24, p34, p44);
435 | }
436 | mulByMatrix4(other) {
437 | return this.mulByMatrix4x4(other);
438 | }
439 | translate(tx, ty, tz) {
440 | const t = Matrix4x4.translation(tx, ty, tz);
441 | return this.mulByMatrix4x4(t);
442 | }
443 | scale(sx, sy, sz) {
444 | const s = Matrix4x4.scaling(sx, sy, sz);
445 | return this.mulByMatrix4x4(s);
446 | }
447 | rotateX(radian) {
448 | const rx = Matrix4x4.rotationX(radian);
449 | return this.mulByMatrix4x4(rx);
450 | }
451 | rotateY(radian) {
452 | const ry = Matrix4x4.rotationY(radian);
453 | return this.mulByMatrix4x4(ry);
454 | }
455 | rotateZ(radian) {
456 | const rz = Matrix4x4.rotationZ(radian);
457 | return this.mulByMatrix4x4(rz);
458 | }
459 | rotateAround(normalizedAxis, radian) {
460 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
461 | return this.mulByMatrix4x4(r);
462 | }
463 | get values() {
464 | return this._values;
465 | }
466 | toString() {
467 | return this._values.toString();
468 | }
469 | };
470 | var Matrix2 = Matrix2x2;
471 | var Matrix3 = Matrix3x3;
472 | var Matrix4 = Matrix4x4;
473 | export {
474 | Float32Vector2,
475 | Float32Vector3,
476 | Float32Vector4,
477 | Matrix2,
478 | Matrix2x2,
479 | Matrix3,
480 | Matrix3x3,
481 | Matrix4,
482 | Matrix4x4,
483 | Quaternion,
484 | Vector2,
485 | Vector3,
486 | Vector4
487 | };
488 |
--------------------------------------------------------------------------------
/lib/esm/matrix.d.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3 } from './float32vector';
2 | /**
3 | * An interface for matrices;
4 | */
5 | export interface Matrix {
6 | /**
7 | * Values of the matrix, that is stored in column major order.
8 | */
9 | readonly values: Float32Array;
10 | /**
11 | * Returns `values` as string.
12 | * @returns {string}
13 | */
14 | toString(): string;
15 | }
16 | /**
17 | * 2x2 Matrix of single-precision float numbers.
18 | *
19 | * Values are stored in column major order.
20 | */
21 | export declare class Matrix2x2 implements Matrix {
22 | protected _values: Float32Array;
23 | constructor(m11: number, m21: number, m12: number, m22: number);
24 | /**
25 | * Returns an identity matrix.
26 | * @returns {Matrix2x2}
27 | */
28 | static identity(): Matrix2x2;
29 | get values(): Float32Array;
30 | toString(): string;
31 | }
32 | /**
33 | * 3x3 Matrix of single-precision float numbers.
34 | *
35 | * Values are stored in column major order.
36 | */
37 | export declare class Matrix3x3 implements Matrix {
38 | protected _values: Float32Array;
39 | constructor(m11: number, m21: number, m31: number, m12: number, m22: number, m32: number, m13: number, m23: number, m33: number);
40 | /**
41 | * Returns an identity matrix.
42 | * @returns {Matrix3x3}
43 | */
44 | static identity(): Matrix3x3;
45 | get values(): Float32Array;
46 | toString(): string;
47 | }
48 | /**
49 | * 4x4 Matrix of single-precision float numbers.
50 | *
51 | * Values are stored in column major order.
52 | */
53 | export declare class Matrix4x4 implements Matrix {
54 | protected _values: Float32Array;
55 | constructor(m11: number, m21: number, m31: number, m41: number, m12: number, m22: number, m32: number, m42: number, m13: number, m23: number, m33: number, m43: number, m14: number, m24: number, m34: number, m44: number);
56 | /**
57 | * Returns an identity matrix.
58 | * @returns {Matrix4x4}
59 | */
60 | static identity(): Matrix4x4;
61 | /**
62 | * Returns translation matrix.
63 | * @param {number} tx
64 | * @param {number} ty
65 | * @param {number} tz
66 | * @returns {Matrix4x4}
67 | */
68 | static translation(tx: number, ty: number, tz: number): Matrix4x4;
69 | /**
70 | * Returns scaling matrix.
71 | * @param {number} sx
72 | * @param {number} sy
73 | * @param {number} sz
74 | * @returns {Matrix4x4}
75 | */
76 | static scaling(sx: number, sy: number, sz: number): Matrix4x4;
77 | /**
78 | * Returns rotation matrix around x-axis.
79 | * @param {number} radian
80 | * @returns {Matrix4x4}
81 | */
82 | static rotationX(radian: number): Matrix4x4;
83 | /**
84 | * Returns rotation matrix around y-axis.
85 | * @param {number} radian
86 | * @returns {Matrix4x4}
87 | */
88 | static rotationY(radian: number): Matrix4x4;
89 | /**
90 | * Returns rotation matrix around z-axis.
91 | * @param {number} radian
92 | * @returns {Matrix4x4}
93 | */
94 | static rotationZ(radian: number): Matrix4x4;
95 | /**
96 | * Returns rotation matrix around `normalizedAxis`. `normalizedAxis` must be normalized.
97 | * @param {Float32Vector3} normalizedAxis
98 | * @param {number} radian
99 | * @returns {Matrix4x4}
100 | */
101 | static rotationAround(normalizedAxis: Float32Vector3, radian: number): Matrix4x4;
102 | /**
103 | * Returns "look at" matrix.
104 | * @param {Float32Vector3} cameraPosition
105 | * @param {Float32Vector3} lookAtPosition
106 | * @param {Float32Vector3} cameraUp
107 | * @returns {Matrix4x4}
108 | */
109 | static lookAt(cameraPosition: Float32Vector3, lookAtPosition: Float32Vector3, cameraUp: Float32Vector3): Matrix4x4;
110 | /**
111 | * Returns an orthographic projection matrix.
112 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
113 | * @returns {Matrix4x4}
114 | */
115 | static orthographic(argsObject: {
116 | top: number;
117 | bottom: number;
118 | left: number;
119 | right: number;
120 | near: number;
121 | far: number;
122 | }): Matrix4x4;
123 | /**
124 | * Returns a frustrum projection matrix.
125 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
126 | * @returns {Matrix4x4}
127 | */
128 | static frustum(argsObject: {
129 | top: number;
130 | bottom: number;
131 | left: number;
132 | right: number;
133 | near: number;
134 | far: number;
135 | }): Matrix4x4;
136 | /**
137 | * Returns a perspective projection matrix.
138 | * @param {{fovY: number; aspect: number; near: number; far: number}} argsObject
139 | * @returns {Matrix4x4}
140 | */
141 | static perspective(argsObject: {
142 | fovYRadian: number;
143 | aspectRatio: number;
144 | near: number;
145 | far: number;
146 | }): Matrix4x4;
147 | /**
148 | * Multiply by `other` matrix and returns a product.
149 | *
150 | * This method does not mutate the matrix.
151 | * @param {Matrix4x4} other
152 | * @returns {Matrix4x4}
153 | */
154 | mulByMatrix4x4(other: Matrix4x4): Matrix4x4;
155 | /**
156 | * An alias for `mulByMatrix4x4`.
157 | * @param {Matrix4x4} other
158 | * @returns {Matrix4x4}
159 | */
160 | mulByMatrix4(other: Matrix4x4): Matrix4x4;
161 | /**
162 | * Translate the matrix and returns new `Matrix4x4`.
163 | *
164 | * This method does not mutate the matrix.
165 | * @param {number} tx
166 | * @param {number} ty
167 | * @param {number} tz
168 | * @returns {Matrix4x4}
169 | */
170 | translate(tx: number, ty: number, tz: number): Matrix4x4;
171 | /**
172 | * Scale the matrix and returns new `Matrix4x4`.
173 | * @param {number} sx
174 | * @param {number} sy
175 | * @param {number} sz
176 | * @returns {Matrix4x4}
177 | */
178 | scale(sx: number, sy: number, sz: number): Matrix4x4;
179 | /**
180 | * Rotate the matrix around x-axis and returns new `Matrix4x4`.
181 | *
182 | * This method does not mutate the matrix.
183 | * @param {number} radian
184 | * @returns {Matrix4x4}
185 | */
186 | rotateX(radian: number): Matrix4x4;
187 | /**
188 | * Rotate the matrix around y-axis and returns new `Matrix4x4`.
189 | *
190 | * This method does not mutate the matrix.
191 | * @param {number} radian
192 | * @returns {Matrix4x4}
193 | */
194 | rotateY(radian: number): Matrix4x4;
195 | /**
196 | * Rotate the matrix around z-axis and returns new `Matrix4x4`.
197 | *
198 | * This method does not mutate the matrix.
199 | * @param {number} radian
200 | * @returns {Matrix4x4}
201 | */
202 | rotateZ(radian: number): Matrix4x4;
203 | /**
204 | * Rotate the matrix around the `normalizedAxis` and return new Matrix4x4.
205 | *
206 | * This method does not mutate the matrix.
207 | * @param {Float32Vector3} normalizedAxis
208 | * @param {number} radian
209 | * @returns {Matrix4x4}
210 | */
211 | rotateAround(normalizedAxis: Float32Vector3, radian: number): Matrix4x4;
212 | get values(): Float32Array;
213 | toString(): string;
214 | }
215 | /**
216 | * An alias for `Matrix2x2`.
217 | * @type {Matrix2x2}
218 | */
219 | export declare const Matrix2: typeof Matrix2x2;
220 | /**
221 | * An alias for `Matrix3x3`.
222 | * @type {Matrix3x3}
223 | */
224 | export declare const Matrix3: typeof Matrix3x3;
225 | /**
226 | * An alias for `Matrix4x4`.
227 | * @type {Matrix4x4}
228 | */
229 | export declare const Matrix4: typeof Matrix4x4;
230 |
--------------------------------------------------------------------------------
/lib/esm/matrix.js:
--------------------------------------------------------------------------------
1 | // src/quaternion.ts
2 | var Quaternion = class {
3 | constructor(x, y, z, w) {
4 | this._values = new Float32Array([x, y, z, w]);
5 | }
6 | static rotationAround(normalizedAxis, radian) {
7 | const sin = Math.sin(radian / 2);
8 | const cos = Math.cos(radian / 2);
9 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
10 | }
11 | normalize() {
12 | const mag = this.magnitude;
13 | if (mag === 0) {
14 | return this;
15 | }
16 | const r = 1 / mag;
17 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
18 | }
19 | add(other) {
20 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
21 | }
22 | mulByScalar(scalar) {
23 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
24 | }
25 | dot(other) {
26 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
27 | }
28 | slerp(other, t, options = { chooseShorterAngle: true }) {
29 | let dotProd = this.dot(other);
30 | let otherQuaternion = other;
31 | if (dotProd < 0) {
32 | dotProd = -dotProd;
33 | otherQuaternion = other.mulByScalar(-1);
34 | }
35 | const omega = Math.acos(dotProd);
36 | const sinOmega = Math.sin(omega);
37 | const q1 = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
38 | const q2 = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
39 | return q1.add(q2);
40 | }
41 | get magnitude() {
42 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
43 | }
44 | get norm() {
45 | return this.magnitude;
46 | }
47 | get x() {
48 | return this._values[0];
49 | }
50 | get y() {
51 | return this._values[1];
52 | }
53 | get z() {
54 | return this._values[2];
55 | }
56 | get w() {
57 | return this._values[3];
58 | }
59 | set x(value) {
60 | this._values[0] = value;
61 | }
62 | set y(value) {
63 | this._values[1] = value;
64 | }
65 | set z(value) {
66 | this._values[2] = value;
67 | }
68 | set w(value) {
69 | this._values[3] = value;
70 | }
71 | get values() {
72 | return this._values;
73 | }
74 | toRotationMatrix4() {
75 | const x = this.x;
76 | const y = this.y;
77 | const z = this.z;
78 | const w = this.w;
79 | const m11 = 1 - 2 * y * y - 2 * z * z;
80 | const m12 = 2 * x * y - 2 * w * z;
81 | const m13 = 2 * x * z + 2 * w * y;
82 | const m14 = 0;
83 | const m21 = 2 * x * y + 2 * w * z;
84 | const m22 = 1 - 2 * x * x - 2 * z * z;
85 | const m23 = 2 * y * z - 2 * w * x;
86 | const m24 = 0;
87 | const m31 = 2 * x * z - 2 * w * y;
88 | const m32 = 2 * y * z + 2 * w * x;
89 | const m33 = 1 - 2 * x * x - 2 * y * y;
90 | const m34 = 0;
91 | const m41 = 0;
92 | const m42 = 0;
93 | const m43 = 0;
94 | const m44 = 1;
95 | return new Matrix4x4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44);
96 | }
97 | toString() {
98 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
99 | }
100 | };
101 |
102 | // src/matrix.ts
103 | var Matrix2x2 = class {
104 | constructor(m11, m21, m12, m22) {
105 | this._values = new Float32Array([
106 | m11,
107 | m21,
108 | m12,
109 | m22
110 | ]);
111 | }
112 | static identity() {
113 | return new Matrix2x2(1, 0, 0, 1);
114 | }
115 | get values() {
116 | return this._values;
117 | }
118 | toString() {
119 | return this._values.toString();
120 | }
121 | };
122 | var Matrix3x3 = class {
123 | constructor(m11, m21, m31, m12, m22, m32, m13, m23, m33) {
124 | this._values = new Float32Array([
125 | m11,
126 | m21,
127 | m31,
128 | m12,
129 | m22,
130 | m32,
131 | m13,
132 | m23,
133 | m33
134 | ]);
135 | }
136 | static identity() {
137 | return new Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
138 | }
139 | get values() {
140 | return this._values;
141 | }
142 | toString() {
143 | return this._values.toString();
144 | }
145 | };
146 | var Matrix4x4 = class {
147 | constructor(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44) {
148 | this._values = new Float32Array([
149 | m11,
150 | m21,
151 | m31,
152 | m41,
153 | m12,
154 | m22,
155 | m32,
156 | m42,
157 | m13,
158 | m23,
159 | m33,
160 | m43,
161 | m14,
162 | m24,
163 | m34,
164 | m44
165 | ]);
166 | }
167 | static identity() {
168 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
169 | }
170 | static translation(tx, ty, tz) {
171 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
172 | }
173 | static scaling(sx, sy, sz) {
174 | return new Matrix4x4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
175 | }
176 | static rotationX(radian) {
177 | const sin = Math.sin(radian);
178 | const cos = Math.cos(radian);
179 | return new Matrix4x4(1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1);
180 | }
181 | static rotationY(radian) {
182 | const sin = Math.sin(radian);
183 | const cos = Math.cos(radian);
184 | return new Matrix4x4(cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1);
185 | }
186 | static rotationZ(radian) {
187 | const sin = Math.sin(radian);
188 | const cos = Math.cos(radian);
189 | return new Matrix4x4(cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
190 | }
191 | static rotationAround(normalizedAxis, radian) {
192 | const q = Quaternion.rotationAround(normalizedAxis, radian);
193 | return q.toRotationMatrix4();
194 | }
195 | static lookAt(cameraPosition, lookAtPosition, cameraUp) {
196 | const zAxis = cameraPosition.sub(lookAtPosition).normalize();
197 | const xAxis = cameraUp.cross(zAxis).normalize();
198 | const yAxis = zAxis.cross(xAxis).normalize();
199 | return new Matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1);
200 | }
201 | static orthographic(argsObject) {
202 | const top = argsObject.top;
203 | const bottom = argsObject.bottom;
204 | const left = argsObject.left;
205 | const right = argsObject.right;
206 | const near = argsObject.near;
207 | const far = argsObject.far;
208 | return new Matrix4x4(2 / (right - left), 0, 0, 0, 0, 2 / (top - bottom), 0, 0, 0, 0, -2 / (far - near), 0, -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1);
209 | }
210 | static frustum(argsObject) {
211 | const top = argsObject.top;
212 | const bottom = argsObject.bottom;
213 | const left = argsObject.left;
214 | const right = argsObject.right;
215 | const near = argsObject.near;
216 | const far = argsObject.far;
217 | return new Matrix4x4(2 * near / (right - left), 0, 0, 0, 0, 2 * near / (top - bottom), 0, 0, (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0);
218 | }
219 | static perspective(argsObject) {
220 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
221 | const height = top * 2;
222 | const width = argsObject.aspectRatio * height;
223 | const left = -0.5 * width;
224 | const right = left + width;
225 | const bottom = top - height;
226 | return Matrix4x4.frustum({
227 | top,
228 | bottom,
229 | left,
230 | right,
231 | near: argsObject.near,
232 | far: argsObject.far
233 | });
234 | }
235 | mulByMatrix4x4(other) {
236 | const m11 = this._values[0];
237 | const m12 = this._values[4];
238 | const m13 = this._values[8];
239 | const m14 = this._values[12];
240 | const m21 = this._values[1];
241 | const m22 = this._values[5];
242 | const m23 = this._values[9];
243 | const m24 = this._values[13];
244 | const m31 = this._values[2];
245 | const m32 = this._values[6];
246 | const m33 = this._values[10];
247 | const m34 = this._values[14];
248 | const m41 = this._values[3];
249 | const m42 = this._values[7];
250 | const m43 = this._values[11];
251 | const m44 = this._values[15];
252 | const o11 = other.values[0];
253 | const o12 = other.values[4];
254 | const o13 = other.values[8];
255 | const o14 = other.values[12];
256 | const o21 = other.values[1];
257 | const o22 = other.values[5];
258 | const o23 = other.values[9];
259 | const o24 = other.values[13];
260 | const o31 = other.values[2];
261 | const o32 = other.values[6];
262 | const o33 = other.values[10];
263 | const o34 = other.values[14];
264 | const o41 = other.values[3];
265 | const o42 = other.values[7];
266 | const o43 = other.values[11];
267 | const o44 = other.values[15];
268 | const p11 = m11 * o11 + m12 * o21 + m13 * o31 + m14 * o41;
269 | const p12 = m11 * o12 + m12 * o22 + m13 * o32 + m14 * o42;
270 | const p13 = m11 * o13 + m12 * o23 + m13 * o33 + m14 * o43;
271 | const p14 = m11 * o14 + m12 * o24 + m13 * o34 + m14 * o44;
272 | const p21 = m21 * o11 + m22 * o21 + m23 * o31 + m24 * o41;
273 | const p22 = m21 * o12 + m22 * o22 + m23 * o32 + m24 * o42;
274 | const p23 = m21 * o13 + m22 * o23 + m23 * o33 + m24 * o43;
275 | const p24 = m21 * o14 + m22 * o24 + m23 * o34 + m24 * o44;
276 | const p31 = m31 * o11 + m32 * o21 + m33 * o31 + m34 * o41;
277 | const p32 = m31 * o12 + m32 * o22 + m33 * o32 + m34 * o42;
278 | const p33 = m31 * o13 + m32 * o23 + m33 * o33 + m34 * o43;
279 | const p34 = m31 * o14 + m32 * o24 + m33 * o34 + m34 * o44;
280 | const p41 = m41 * o11 + m42 * o21 + m43 * o31 + m44 * o41;
281 | const p42 = m41 * o12 + m42 * o22 + m43 * o32 + m44 * o42;
282 | const p43 = m41 * o13 + m42 * o23 + m43 * o33 + m44 * o43;
283 | const p44 = m41 * o14 + m42 * o24 + m43 * o34 + m44 * o44;
284 | return new Matrix4x4(p11, p21, p31, p41, p12, p22, p32, p42, p13, p23, p33, p43, p14, p24, p34, p44);
285 | }
286 | mulByMatrix4(other) {
287 | return this.mulByMatrix4x4(other);
288 | }
289 | translate(tx, ty, tz) {
290 | const t = Matrix4x4.translation(tx, ty, tz);
291 | return this.mulByMatrix4x4(t);
292 | }
293 | scale(sx, sy, sz) {
294 | const s = Matrix4x4.scaling(sx, sy, sz);
295 | return this.mulByMatrix4x4(s);
296 | }
297 | rotateX(radian) {
298 | const rx = Matrix4x4.rotationX(radian);
299 | return this.mulByMatrix4x4(rx);
300 | }
301 | rotateY(radian) {
302 | const ry = Matrix4x4.rotationY(radian);
303 | return this.mulByMatrix4x4(ry);
304 | }
305 | rotateZ(radian) {
306 | const rz = Matrix4x4.rotationZ(radian);
307 | return this.mulByMatrix4x4(rz);
308 | }
309 | rotateAround(normalizedAxis, radian) {
310 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
311 | return this.mulByMatrix4x4(r);
312 | }
313 | get values() {
314 | return this._values;
315 | }
316 | toString() {
317 | return this._values.toString();
318 | }
319 | };
320 | var Matrix2 = Matrix2x2;
321 | var Matrix3 = Matrix3x3;
322 | var Matrix4 = Matrix4x4;
323 | export {
324 | Matrix2,
325 | Matrix2x2,
326 | Matrix3,
327 | Matrix3x3,
328 | Matrix4,
329 | Matrix4x4
330 | };
331 |
--------------------------------------------------------------------------------
/lib/esm/quaternion.d.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3 } from './float32vector';
2 | import { Matrix4x4 } from './matrix';
3 | /**
4 | * Quaternion which is 4-dimensional complex number.
5 | * See [Wikipedia](https://en.wikipedia.org/wiki/Quaternion).
6 | */
7 | export declare class Quaternion {
8 | protected _values: Float32Array;
9 | constructor(x: number, y: number, z: number, w: number);
10 | /**
11 | * Create a rotation quaternion around `normalizedAxis`.
12 | * `normalizedAxis` must be normalized.
13 | * @param {Float32Vector3} normalizedAxis
14 | * @param {number} radian
15 | * @returns {Quaternion}
16 | */
17 | static rotationAround(normalizedAxis: Float32Vector3, radian: number): Quaternion;
18 | /**
19 | * Returns a normalized quaternion.
20 | * @returns {Quaternion}
21 | */
22 | normalize(): Quaternion;
23 | /**
24 | * Adds the `other` to the quaternion and returns the sum.
25 | *
26 | * This method does not mutate the quaternion.
27 | * @param {Quaternion} other
28 | * @returns {Quaternion}
29 | */
30 | add(other: Quaternion): Quaternion;
31 | /**
32 | * Multiplies the quaternion by `scalar` and returns the product.
33 | *
34 | * This method does not mutate the quaternion.
35 | * @param {number} scalar
36 | * @returns {Quaternion}
37 | */
38 | mulByScalar(scalar: number): Quaternion;
39 | /**
40 | * Calculates dot product.
41 | * @param {Quaternion} other
42 | * @returns {number}
43 | */
44 | dot(other: Quaternion): number;
45 | /**
46 | * Calculates spherical linear interpolation(also known as Slerp) and returns new `Quaternion` between the quaternion and the other.
47 | * @param {Quaternion} other
48 | * @param {number} t 0.0 <= t <= 1.0
49 | * @param {{chooseShorterAngle: boolean}} options Does not work currently. slerp chooses shorter angle regardless of this value.
50 | * @returns {Quaternion}
51 | */
52 | slerp(other: Quaternion, t: number, options?: {
53 | chooseShorterAngle: boolean;
54 | }): Quaternion;
55 | /**
56 | * Calc magnitude of the quaternion.
57 | * @returns {number}
58 | */
59 | get magnitude(): number;
60 | /**
61 | * Calc norm of the quaternion.
62 | * An alias for `magnitude`.
63 | * @returns {number}
64 | */
65 | get norm(): number;
66 | /**
67 | * Returns x value of the vector.
68 | * @returns {number}
69 | */
70 | get x(): number;
71 | /**
72 | * Returns y value of the vector.
73 | * @returns {number}
74 | */
75 | get y(): number;
76 | /**
77 | * Returns z value of the vector.
78 | * @returns {number}
79 | */
80 | get z(): number;
81 | /**
82 | * Returns w value of the vector.
83 | * @returns {number}
84 | */
85 | get w(): number;
86 | /**
87 | * Set the `value` as new x.
88 | * @param {number} value
89 | */
90 | set x(value: number);
91 | /**
92 | * Set the `value` as new y.
93 | * @param {number} value
94 | */
95 | set y(value: number);
96 | /**
97 | * Set the `value` as new z.
98 | * @param {number} value
99 | */
100 | set z(value: number);
101 | /**
102 | * Set the `value` as new w.
103 | * @param {number} value
104 | */
105 | set w(value: number);
106 | /**
107 | * Returns values of the quaternion.
108 | * @returns {Float32Array}
109 | */
110 | get values(): Float32Array;
111 | /**
112 | * Convert the quaternion to a rotation matrix.
113 | * @returns {Matrix4x4}
114 | */
115 | toRotationMatrix4(): Matrix4x4;
116 | /**
117 | * Returns values as `String`.
118 | * @returns {string}
119 | */
120 | toString(): string;
121 | }
122 |
--------------------------------------------------------------------------------
/lib/esm/quaternion.js:
--------------------------------------------------------------------------------
1 | // src/matrix.ts
2 | var Matrix4x4 = class {
3 | constructor(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44) {
4 | this._values = new Float32Array([
5 | m11,
6 | m21,
7 | m31,
8 | m41,
9 | m12,
10 | m22,
11 | m32,
12 | m42,
13 | m13,
14 | m23,
15 | m33,
16 | m43,
17 | m14,
18 | m24,
19 | m34,
20 | m44
21 | ]);
22 | }
23 | static identity() {
24 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
25 | }
26 | static translation(tx, ty, tz) {
27 | return new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
28 | }
29 | static scaling(sx, sy, sz) {
30 | return new Matrix4x4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
31 | }
32 | static rotationX(radian) {
33 | const sin = Math.sin(radian);
34 | const cos = Math.cos(radian);
35 | return new Matrix4x4(1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1);
36 | }
37 | static rotationY(radian) {
38 | const sin = Math.sin(radian);
39 | const cos = Math.cos(radian);
40 | return new Matrix4x4(cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1);
41 | }
42 | static rotationZ(radian) {
43 | const sin = Math.sin(radian);
44 | const cos = Math.cos(radian);
45 | return new Matrix4x4(cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
46 | }
47 | static rotationAround(normalizedAxis, radian) {
48 | const q = Quaternion.rotationAround(normalizedAxis, radian);
49 | return q.toRotationMatrix4();
50 | }
51 | static lookAt(cameraPosition, lookAtPosition, cameraUp) {
52 | const zAxis = cameraPosition.sub(lookAtPosition).normalize();
53 | const xAxis = cameraUp.cross(zAxis).normalize();
54 | const yAxis = zAxis.cross(xAxis).normalize();
55 | return new Matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1);
56 | }
57 | static orthographic(argsObject) {
58 | const top = argsObject.top;
59 | const bottom = argsObject.bottom;
60 | const left = argsObject.left;
61 | const right = argsObject.right;
62 | const near = argsObject.near;
63 | const far = argsObject.far;
64 | return new Matrix4x4(2 / (right - left), 0, 0, 0, 0, 2 / (top - bottom), 0, 0, 0, 0, -2 / (far - near), 0, -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1);
65 | }
66 | static frustum(argsObject) {
67 | const top = argsObject.top;
68 | const bottom = argsObject.bottom;
69 | const left = argsObject.left;
70 | const right = argsObject.right;
71 | const near = argsObject.near;
72 | const far = argsObject.far;
73 | return new Matrix4x4(2 * near / (right - left), 0, 0, 0, 0, 2 * near / (top - bottom), 0, 0, (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0);
74 | }
75 | static perspective(argsObject) {
76 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
77 | const height = top * 2;
78 | const width = argsObject.aspectRatio * height;
79 | const left = -0.5 * width;
80 | const right = left + width;
81 | const bottom = top - height;
82 | return Matrix4x4.frustum({
83 | top,
84 | bottom,
85 | left,
86 | right,
87 | near: argsObject.near,
88 | far: argsObject.far
89 | });
90 | }
91 | mulByMatrix4x4(other) {
92 | const m11 = this._values[0];
93 | const m12 = this._values[4];
94 | const m13 = this._values[8];
95 | const m14 = this._values[12];
96 | const m21 = this._values[1];
97 | const m22 = this._values[5];
98 | const m23 = this._values[9];
99 | const m24 = this._values[13];
100 | const m31 = this._values[2];
101 | const m32 = this._values[6];
102 | const m33 = this._values[10];
103 | const m34 = this._values[14];
104 | const m41 = this._values[3];
105 | const m42 = this._values[7];
106 | const m43 = this._values[11];
107 | const m44 = this._values[15];
108 | const o11 = other.values[0];
109 | const o12 = other.values[4];
110 | const o13 = other.values[8];
111 | const o14 = other.values[12];
112 | const o21 = other.values[1];
113 | const o22 = other.values[5];
114 | const o23 = other.values[9];
115 | const o24 = other.values[13];
116 | const o31 = other.values[2];
117 | const o32 = other.values[6];
118 | const o33 = other.values[10];
119 | const o34 = other.values[14];
120 | const o41 = other.values[3];
121 | const o42 = other.values[7];
122 | const o43 = other.values[11];
123 | const o44 = other.values[15];
124 | const p11 = m11 * o11 + m12 * o21 + m13 * o31 + m14 * o41;
125 | const p12 = m11 * o12 + m12 * o22 + m13 * o32 + m14 * o42;
126 | const p13 = m11 * o13 + m12 * o23 + m13 * o33 + m14 * o43;
127 | const p14 = m11 * o14 + m12 * o24 + m13 * o34 + m14 * o44;
128 | const p21 = m21 * o11 + m22 * o21 + m23 * o31 + m24 * o41;
129 | const p22 = m21 * o12 + m22 * o22 + m23 * o32 + m24 * o42;
130 | const p23 = m21 * o13 + m22 * o23 + m23 * o33 + m24 * o43;
131 | const p24 = m21 * o14 + m22 * o24 + m23 * o34 + m24 * o44;
132 | const p31 = m31 * o11 + m32 * o21 + m33 * o31 + m34 * o41;
133 | const p32 = m31 * o12 + m32 * o22 + m33 * o32 + m34 * o42;
134 | const p33 = m31 * o13 + m32 * o23 + m33 * o33 + m34 * o43;
135 | const p34 = m31 * o14 + m32 * o24 + m33 * o34 + m34 * o44;
136 | const p41 = m41 * o11 + m42 * o21 + m43 * o31 + m44 * o41;
137 | const p42 = m41 * o12 + m42 * o22 + m43 * o32 + m44 * o42;
138 | const p43 = m41 * o13 + m42 * o23 + m43 * o33 + m44 * o43;
139 | const p44 = m41 * o14 + m42 * o24 + m43 * o34 + m44 * o44;
140 | return new Matrix4x4(p11, p21, p31, p41, p12, p22, p32, p42, p13, p23, p33, p43, p14, p24, p34, p44);
141 | }
142 | mulByMatrix4(other) {
143 | return this.mulByMatrix4x4(other);
144 | }
145 | translate(tx, ty, tz) {
146 | const t = Matrix4x4.translation(tx, ty, tz);
147 | return this.mulByMatrix4x4(t);
148 | }
149 | scale(sx, sy, sz) {
150 | const s = Matrix4x4.scaling(sx, sy, sz);
151 | return this.mulByMatrix4x4(s);
152 | }
153 | rotateX(radian) {
154 | const rx = Matrix4x4.rotationX(radian);
155 | return this.mulByMatrix4x4(rx);
156 | }
157 | rotateY(radian) {
158 | const ry = Matrix4x4.rotationY(radian);
159 | return this.mulByMatrix4x4(ry);
160 | }
161 | rotateZ(radian) {
162 | const rz = Matrix4x4.rotationZ(radian);
163 | return this.mulByMatrix4x4(rz);
164 | }
165 | rotateAround(normalizedAxis, radian) {
166 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
167 | return this.mulByMatrix4x4(r);
168 | }
169 | get values() {
170 | return this._values;
171 | }
172 | toString() {
173 | return this._values.toString();
174 | }
175 | };
176 |
177 | // src/quaternion.ts
178 | var Quaternion = class {
179 | constructor(x, y, z, w) {
180 | this._values = new Float32Array([x, y, z, w]);
181 | }
182 | static rotationAround(normalizedAxis, radian) {
183 | const sin = Math.sin(radian / 2);
184 | const cos = Math.cos(radian / 2);
185 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
186 | }
187 | normalize() {
188 | const mag = this.magnitude;
189 | if (mag === 0) {
190 | return this;
191 | }
192 | const r = 1 / mag;
193 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
194 | }
195 | add(other) {
196 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
197 | }
198 | mulByScalar(scalar) {
199 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
200 | }
201 | dot(other) {
202 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
203 | }
204 | slerp(other, t, options = { chooseShorterAngle: true }) {
205 | let dotProd = this.dot(other);
206 | let otherQuaternion = other;
207 | if (dotProd < 0) {
208 | dotProd = -dotProd;
209 | otherQuaternion = other.mulByScalar(-1);
210 | }
211 | const omega = Math.acos(dotProd);
212 | const sinOmega = Math.sin(omega);
213 | const q1 = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
214 | const q2 = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
215 | return q1.add(q2);
216 | }
217 | get magnitude() {
218 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
219 | }
220 | get norm() {
221 | return this.magnitude;
222 | }
223 | get x() {
224 | return this._values[0];
225 | }
226 | get y() {
227 | return this._values[1];
228 | }
229 | get z() {
230 | return this._values[2];
231 | }
232 | get w() {
233 | return this._values[3];
234 | }
235 | set x(value) {
236 | this._values[0] = value;
237 | }
238 | set y(value) {
239 | this._values[1] = value;
240 | }
241 | set z(value) {
242 | this._values[2] = value;
243 | }
244 | set w(value) {
245 | this._values[3] = value;
246 | }
247 | get values() {
248 | return this._values;
249 | }
250 | toRotationMatrix4() {
251 | const x = this.x;
252 | const y = this.y;
253 | const z = this.z;
254 | const w = this.w;
255 | const m11 = 1 - 2 * y * y - 2 * z * z;
256 | const m12 = 2 * x * y - 2 * w * z;
257 | const m13 = 2 * x * z + 2 * w * y;
258 | const m14 = 0;
259 | const m21 = 2 * x * y + 2 * w * z;
260 | const m22 = 1 - 2 * x * x - 2 * z * z;
261 | const m23 = 2 * y * z - 2 * w * x;
262 | const m24 = 0;
263 | const m31 = 2 * x * z - 2 * w * y;
264 | const m32 = 2 * y * z + 2 * w * x;
265 | const m33 = 1 - 2 * x * x - 2 * y * y;
266 | const m34 = 0;
267 | const m41 = 0;
268 | const m42 = 0;
269 | const m43 = 0;
270 | const m44 = 1;
271 | return new Matrix4x4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44);
272 | }
273 | toString() {
274 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
275 | }
276 | };
277 | export {
278 | Quaternion
279 | };
280 |
--------------------------------------------------------------------------------
/lib/esm/vector_base.d.ts:
--------------------------------------------------------------------------------
1 | export declare type TypedArrayLike = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
2 | /**
3 | * An interface for vectors.
4 | */
5 | export interface Vector {
6 | /**
7 | * Returns values of the vector.
8 | * @returns {T}
9 | */
10 | readonly values: T;
11 | /**
12 | * Returns magnitude of the vector.
13 | */
14 | readonly magnitude: number;
15 | /**
16 | * Returns `values` as a string.
17 | * @returns {string}
18 | */
19 | toString(): string;
20 | }
21 | /**
22 | * An abstract class for vectors.
23 | */
24 | export declare abstract class VectorBase implements Vector {
25 | /**
26 | * Values that the vector contains.
27 | */
28 | protected _values: T;
29 | get values(): T;
30 | get magnitude(): number;
31 | toString(): string;
32 | }
33 | /**
34 | * A base abstract class for 2-dimensional vectors.
35 | */
36 | export declare abstract class Vector2Base extends VectorBase {
37 | /**
38 | * Returns x value of the vector.
39 | * @returns {number}
40 | */
41 | get x(): number;
42 | /**
43 | * Returns y value of the vector.
44 | * @returns {number}
45 | */
46 | get y(): number;
47 | /**
48 | * Set the `value` as new x.
49 | * @param {number} value
50 | */
51 | set x(value: number);
52 | /**
53 | * Set the `value` as new y.
54 | * @param {number} value
55 | */
56 | set y(value: number);
57 | }
58 | /**
59 | * A base abstract class for 3-dimensional vectors.
60 | */
61 | export declare abstract class Vector3Base extends VectorBase {
62 | /**
63 | * Returns x value of the vector.
64 | * @returns {number}
65 | */
66 | get x(): number;
67 | /**
68 | * Returns y value of the vector.
69 | * @returns {number}
70 | */
71 | get y(): number;
72 | /**
73 | * Returns z value of the vector.
74 | * @returns {number}
75 | */
76 | get z(): number;
77 | /**
78 | * Set the `value` as new x.
79 | * @param {number} value
80 | */
81 | set x(value: number);
82 | /**
83 | * Set the `value` as new y.
84 | * @param {number} value
85 | */
86 | set y(value: number);
87 | /**
88 | * Set the `value` as new z.
89 | * @param {number} value
90 | */
91 | set z(value: number);
92 | }
93 | /**
94 | * A base abstract class for 4-dimensional vectors.
95 | */
96 | export declare abstract class Vector4Base extends VectorBase {
97 | /**
98 | * Returns x value of the vector.
99 | * @returns {number}
100 | */
101 | get x(): number;
102 | /**
103 | * Returns y value of the vector.
104 | * @returns {number}
105 | */
106 | get y(): number;
107 | /**
108 | * Returns z value of the vector.
109 | * @returns {number}
110 | */
111 | get z(): number;
112 | /**
113 | * Returns w value of the vector.
114 | * @returns {number}
115 | */
116 | get w(): number;
117 | /**
118 | * Set the `value` as new x.
119 | * @param {number} value
120 | */
121 | set x(value: number);
122 | /**
123 | * Set the `value` as new y.
124 | * @param {number} value
125 | */
126 | set y(value: number);
127 | /**
128 | * Set the `value` as new z.
129 | * @param {number} value
130 | */
131 | set z(value: number);
132 | /**
133 | * Set the `value` as new w.
134 | * @param {number} value
135 | */
136 | set w(value: number);
137 | }
138 |
--------------------------------------------------------------------------------
/lib/esm/vector_base.js:
--------------------------------------------------------------------------------
1 | // src/vector_base.ts
2 | var VectorBase = class {
3 | get values() {
4 | return this._values;
5 | }
6 | get magnitude() {
7 | let sumSq = 0;
8 | for (const val of this._values) {
9 | sumSq += val ** 2;
10 | }
11 | return Math.sqrt(sumSq);
12 | }
13 | toString() {
14 | const dimension = this._values.length;
15 | return `Vector${dimension}(${this._values.join(", ")})`;
16 | }
17 | };
18 | var Vector2Base = class extends VectorBase {
19 | get x() {
20 | return this._values[0];
21 | }
22 | get y() {
23 | return this._values[1];
24 | }
25 | set x(value) {
26 | this._values[0] = value;
27 | }
28 | set y(value) {
29 | this._values[1] = value;
30 | }
31 | };
32 | var Vector3Base = class extends VectorBase {
33 | get x() {
34 | return this._values[0];
35 | }
36 | get y() {
37 | return this._values[1];
38 | }
39 | get z() {
40 | return this._values[2];
41 | }
42 | set x(value) {
43 | this._values[0] = value;
44 | }
45 | set y(value) {
46 | this._values[1] = value;
47 | }
48 | set z(value) {
49 | this._values[2] = value;
50 | }
51 | };
52 | var Vector4Base = class extends VectorBase {
53 | get x() {
54 | return this._values[0];
55 | }
56 | get y() {
57 | return this._values[1];
58 | }
59 | get z() {
60 | return this._values[2];
61 | }
62 | get w() {
63 | return this._values[3];
64 | }
65 | set x(value) {
66 | this._values[0] = value;
67 | }
68 | set y(value) {
69 | this._values[1] = value;
70 | }
71 | set z(value) {
72 | this._values[2] = value;
73 | }
74 | set w(value) {
75 | this._values[3] = value;
76 | }
77 | };
78 | export {
79 | Vector2Base,
80 | Vector3Base,
81 | Vector4Base,
82 | VectorBase
83 | };
84 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "matrixgl",
3 | "version": "2.0.0",
4 | "description": "Yet another matrix library for WebGL",
5 | "keywords": [
6 | "webgl",
7 | "math",
8 | "matrix",
9 | "vector"
10 | ],
11 | "type": "module",
12 | "main": "./lib/esm/index.js",
13 | "types": "./lib/esm/index.d.ts",
14 | "author": "Koto Furumiya ",
15 | "license": "Zlib",
16 | "files": [
17 | "lib/"
18 | ],
19 | "exports": {
20 | "import": "./lib/esm/index.js",
21 | "require": "./lib/csm/index.js",
22 | "default": "./lib/esm/index.js"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/kotofurumiya/matrixgl.git"
27 | },
28 | "bugs": {
29 | "url": "https://github.com/kotofurumiya/matrixgl/issues",
30 | "email": "kotofurumiya@gmail.com"
31 | },
32 | "homepage": "https://github.com/kotofurumiya/matrixgl",
33 | "scripts": {
34 | "typedoc": "typedoc ./src --out ./docs --readme README.md && nodetouch ./docs/.nojekyll",
35 | "test": "uvu -r tsm __tests__",
36 | "build:esm": "esbuild src/*.ts --bundle --platform=node --format=esm --target=es2020 --outdir=lib/esm && tsc --emitDeclarationOnly --outDir lib/esm",
37 | "build:cjs": "esbuild src/*.ts --bundle --platform=node --format=cjs --target=es2020 --outdir=lib/cjs && tsc --emitDeclarationOnly --outDir lib/cjs",
38 | "build:browser": "esbuild src/index.ts --bundle --minify --platform=browser --target=es2020 --outfile=build/matrixgl.min.js",
39 | "build": "npm run build:esm && npm run build:cjs && npm run build:browser && npm run typedoc"
40 | },
41 | "devDependencies": {
42 | "esbuild": "^0.13.15",
43 | "touch": "^3.1.0",
44 | "tsm": "^2.1.4",
45 | "typedoc": "^0.22.9",
46 | "typescript": "^4.4.4",
47 | "uvu": "^0.5.2"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/float32vector.ts:
--------------------------------------------------------------------------------
1 | import { Vector2Base, Vector3Base, Vector4Base } from './vector_base';
2 |
3 | /**
4 | * A 2-dimensional vector of single-precision float numbers.
5 | */
6 | export class Float32Vector2 extends Vector2Base {
7 | constructor(x: number, y: number) {
8 | super();
9 | this._values = new Float32Array([x, y]);
10 | }
11 |
12 | /**
13 | * Add `other` to the vector and returns new `Float32Vector2`.
14 | *
15 | * This method does not mutate the vector.
16 | * @param {Float32Vector2} other
17 | * @returns {Float32Vector2}
18 | */
19 | add(other: Float32Vector2): Float32Vector2 {
20 | return new Float32Vector2(this.x + other.x, this.y + other.y);
21 | }
22 |
23 | /**
24 | * Subtract `other` from the vector and returns new `Float32Vector2`.
25 | *
26 | * This method does not mutate the vector.
27 | * @param {Float32Vector2} other
28 | * @returns {Float32Vector2}
29 | */
30 | sub(other: Float32Vector2): Float32Vector2 {
31 | return new Float32Vector2(this.x - other.x, this.y - other.y);
32 | }
33 |
34 | /**
35 | * Multiply the vector by `scalar` and returns new `Float32Vector2`.
36 | *
37 | * This method does not mutate the vector.
38 | * @param {number} scalar
39 | * @returns {Float32Vector2}
40 | */
41 | mulByScalar(scalar: number): Float32Vector2 {
42 | return new Float32Vector2(this.x * scalar, this.y * scalar);
43 | }
44 | }
45 |
46 | /**
47 | * A 3-dimensional vector of single-precision float numbers.
48 | */
49 | export class Float32Vector3 extends Vector3Base {
50 | constructor(x: number, y: number, z: number) {
51 | super();
52 | this._values = new Float32Array([x, y, z]);
53 | }
54 |
55 | /**
56 | * Add `other` to the vector and returns new `Float32Vector3`.
57 | *
58 | * This method does not mutate the vector.
59 | * @param {Float32Vector3} other
60 | * @returns {Float32Vector3}
61 | */
62 | add(other: Float32Vector3): Float32Vector3 {
63 | return new Float32Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
64 | }
65 |
66 | /**
67 | * Subtract `other` from the vector and returns new `Float32Vector3`.
68 | *
69 | * This method does not mutate the vector.
70 | * @param {Float32Vector3} other
71 | * @returns {Float32Vector3}
72 | */
73 | sub(other: Float32Vector3): Float32Vector3 {
74 | return new Float32Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
75 | }
76 |
77 | /**
78 | * Multiply the vector by `scalar` and returns new `Float32Vector3`.
79 | *
80 | * This method does not mutate the vector.
81 | * @param {number} scalar
82 | * @returns {Float32Vector3}
83 | */
84 | mulByScalar(scalar: number): Float32Vector3 {
85 | return new Float32Vector3(this.x * scalar, this.y * scalar, this.z * scalar);
86 | }
87 |
88 | /**
89 | * Calculate dot product.
90 | * @param {Float32Vector3} other
91 | * @returns {number}
92 | */
93 | dot(other: Float32Vector3): number {
94 | return this.x * other.x + this.y * other.y + this.z * other.z;
95 | }
96 |
97 | /**
98 | * Calculate cross product.
99 | * @param {Float32Vector3} other
100 | * @returns {Float32Vector3}
101 | */
102 | cross(other: Float32Vector3): Float32Vector3 {
103 | const cx: number = this.y * other.z - this.z * other.y;
104 | const cy: number = this.z * other.x - this.x * other.z;
105 | const cz: number = this.x * other.y - this.y * other.x;
106 |
107 | return new Float32Vector3(cx, cy, cz);
108 | }
109 |
110 | /**
111 | * Normalize the vector and returns new `Float32Vector3`.
112 | *
113 | * This method does not mutate the vector.
114 | * @returns {Float32Vector3}
115 | */
116 | normalize(): Float32Vector3 {
117 | const mag: number = this.magnitude;
118 | if(mag === 0) { return this; }
119 | return new Float32Vector3(this.x / mag, this.y / mag, this.z / mag);
120 | }
121 |
122 | /**
123 | * Returns xy values of the vector as `Float32Vector2`.
124 | * @returns {Float32Vector2}
125 | */
126 | get xy(): Float32Vector2 {
127 | return new Float32Vector2(this.x, this.y);
128 | }
129 | }
130 |
131 | /**
132 | * A 4-dimensional vector of single-precision float numbers.
133 | */
134 | export class Float32Vector4 extends Vector4Base {
135 | constructor(x: number, y: number, z: number, w: number) {
136 | super();
137 | this._values = new Float32Array([x, y, z, w]);
138 | }
139 |
140 | /**
141 | * Add `other` to the vector and returns new `Float32Vector4`.
142 | *
143 | * This method does not mutate the vector.
144 | * @param {Float32Vector4} other
145 | * @returns {Float32Vector4}
146 | */
147 | add(other: Float32Vector4): Float32Vector4 {
148 | return new Float32Vector4(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
149 | }
150 |
151 | /**
152 | * Subtract `other` from the vector and returns new `Float32Vector4`.
153 | *
154 | * This method does not mutate the vector.
155 | * @param {Float32Vector4} other
156 | * @returns {Float32Vector4}
157 | */
158 | sub(other: Float32Vector4): Float32Vector4 {
159 | return new Float32Vector4(this.x - other.x, this.y - other.y, this.z - other.z, this.w - other.w);
160 | }
161 |
162 | /**
163 | * Multiply the vector by `scalar` and returns new `Float32Vector4`.
164 | *
165 | * This method does not mutate the vector.
166 | * @param {number} scalar
167 | * @returns {Float32Vector4}
168 | */
169 | mulByScalar(scalar: number): Float32Vector4 {
170 | return new Float32Vector4(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
171 | }
172 |
173 | /**
174 | * Returns xyz values of the vector as `Float32Vector3`.
175 | * @returns {Float32Vector3}
176 | */
177 | get xyz(): Float32Vector3 {
178 | return new Float32Vector3(this.x, this.y, this.z);
179 | }
180 | }
181 |
182 | /**
183 | * An alias for `Float32Vector2`.
184 | * @type {Float32Vector2}
185 | */
186 | export const Vector2 = Float32Vector2;
187 |
188 | /**
189 | * An alias for `Float32Vector3`.
190 | * @type {Float32Vector3}
191 | */
192 | export const Vector3 = Float32Vector3;
193 |
194 | /**
195 | * An alias for `Float32Vector4`.
196 | * @type {Float32Vector4}
197 | */
198 | export const Vector4 = Float32Vector4;
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './float32vector';
2 | export * from './matrix';
3 | export * from './quaternion';
--------------------------------------------------------------------------------
/src/matrix.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3, Float32Vector4 } from './float32vector';
2 | import { Quaternion } from './quaternion';
3 |
4 | /**
5 | * An interface for matrices;
6 | */
7 | export interface Matrix {
8 | /**
9 | * Values of the matrix, that is stored in column major order.
10 | */
11 | readonly values: Float32Array;
12 |
13 | /**
14 | * Returns `values` as string.
15 | * @returns {string}
16 | */
17 | toString(): string;
18 | }
19 |
20 | /**
21 | * 2x2 Matrix of single-precision float numbers.
22 | *
23 | * Values are stored in column major order.
24 | */
25 | export class Matrix2x2 implements Matrix {
26 | protected _values: Float32Array;
27 |
28 | constructor(m11: number, m21: number, m12: number, m22: number) {
29 | this._values = new Float32Array([
30 | m11, m21,
31 | m12, m22
32 | ]);
33 | }
34 |
35 | /**
36 | * Returns an identity matrix.
37 | * @returns {Matrix2x2}
38 | */
39 | static identity(): Matrix2x2 {
40 | return new Matrix2x2(1.0, 0.0, 0.0, 1.0);
41 | }
42 |
43 | get values(): Float32Array {
44 | return this._values;
45 | }
46 |
47 | toString(): string {
48 | return this._values.toString();
49 | }
50 | }
51 |
52 | /**
53 | * 3x3 Matrix of single-precision float numbers.
54 | *
55 | * Values are stored in column major order.
56 | */
57 | export class Matrix3x3 implements Matrix {
58 | protected _values: Float32Array;
59 |
60 | constructor(
61 | m11: number, m21: number, m31: number,
62 | m12: number, m22: number, m32: number,
63 | m13: number, m23: number, m33: number
64 | ) {
65 | this._values = new Float32Array([
66 | m11, m21, m31,
67 | m12, m22, m32,
68 | m13, m23, m33
69 | ]);
70 | }
71 |
72 | /**
73 | * Returns an identity matrix.
74 | * @returns {Matrix3x3}
75 | */
76 | static identity(): Matrix3x3 {
77 | return new Matrix3x3(
78 | 1.0, 0.0, 0.0,
79 | 0.0, 1.0, 0.0,
80 | 0.0, 0.0, 1.0
81 | );
82 | }
83 |
84 | get values(): Float32Array {
85 | return this._values;
86 | }
87 |
88 | toString(): string {
89 | return this._values.toString();
90 | }
91 | }
92 |
93 | /**
94 | * 4x4 Matrix of single-precision float numbers.
95 | *
96 | * Values are stored in column major order.
97 | */
98 | export class Matrix4x4 implements Matrix {
99 | protected _values: Float32Array;
100 |
101 | constructor(
102 | m11: number, m21: number, m31: number, m41: number,
103 | m12: number, m22: number, m32: number, m42: number,
104 | m13: number, m23: number, m33: number, m43: number,
105 | m14: number, m24: number, m34: number, m44: number
106 | ) {
107 | this._values = new Float32Array([
108 | m11, m21, m31, m41,
109 | m12, m22, m32, m42,
110 | m13, m23, m33, m43,
111 | m14, m24, m34, m44
112 | ]);
113 | }
114 |
115 | /**
116 | * Returns an identity matrix.
117 | * @returns {Matrix4x4}
118 | */
119 | static identity(): Matrix4x4 {
120 | return new Matrix4x4(
121 | 1.0, 0.0, 0.0, 0.0,
122 | 0.0, 1.0, 0.0, 0.0,
123 | 0.0, 0.0, 1.0, 0.0,
124 | 0.0, 0.0, 0.0, 1.0
125 | );
126 | }
127 |
128 | /**
129 | * Returns translation matrix.
130 | * @param {number} tx
131 | * @param {number} ty
132 | * @param {number} tz
133 | * @returns {Matrix4x4}
134 | */
135 | static translation(tx: number, ty: number, tz: number): Matrix4x4 {
136 | return new Matrix4x4(
137 | 1.0, 0.0, 0.0, 0.0,
138 | 0.0, 1.0, 0.0, 0.0,
139 | 0.0, 0.0, 1.0, 0.0,
140 | tx, ty, tz, 1.0
141 | );
142 | }
143 |
144 | /**
145 | * Returns scaling matrix.
146 | * @param {number} sx
147 | * @param {number} sy
148 | * @param {number} sz
149 | * @returns {Matrix4x4}
150 | */
151 | static scaling(sx: number, sy: number, sz: number): Matrix4x4 {
152 | return new Matrix4x4(
153 | sx, 0.0, 0.0, 0.0,
154 | 0.0, sy, 0.0, 0.0,
155 | 0.0, 0.0, sz, 0.0,
156 | 0.0, 0.0, 0.0, 1.0
157 | );
158 | }
159 |
160 | /**
161 | * Returns rotation matrix around x-axis.
162 | * @param {number} radian
163 | * @returns {Matrix4x4}
164 | */
165 | static rotationX(radian: number): Matrix4x4 {
166 | const sin: number = Math.sin(radian);
167 | const cos: number = Math.cos(radian);
168 |
169 | return new Matrix4x4(
170 | 1.0, 0.0, 0.0, 0.0,
171 | 0.0, cos, sin, 0.0,
172 | 0.0, -sin, cos, 0.0,
173 | 0.0, 0.0, 0.0, 1.0
174 | );
175 | }
176 |
177 | /**
178 | * Returns rotation matrix around y-axis.
179 | * @param {number} radian
180 | * @returns {Matrix4x4}
181 | */
182 | static rotationY(radian: number): Matrix4x4 {
183 | const sin: number = Math.sin(radian);
184 | const cos: number = Math.cos(radian);
185 |
186 | return new Matrix4x4(
187 | cos, 0.0, -sin, 0.0,
188 | 0.0, 1.0, 0.0, 0.0,
189 | sin, 0.0, cos, 0.0,
190 | 0.0, 0.0, 0.0, 1.0
191 | );
192 | }
193 |
194 | /**
195 | * Returns rotation matrix around z-axis.
196 | * @param {number} radian
197 | * @returns {Matrix4x4}
198 | */
199 | static rotationZ(radian: number): Matrix4x4 {
200 | const sin: number = Math.sin(radian);
201 | const cos: number = Math.cos(radian);
202 |
203 | return new Matrix4x4(
204 | cos, sin, 0.0, 0.0,
205 | -sin, cos, 0.0, 0.0,
206 | 0.0, 0.0, 1.0, 0.0,
207 | 0.0, 0.0, 0.0, 1.0
208 | );
209 | }
210 |
211 | /**
212 | * Returns rotation matrix around `normalizedAxis`. `normalizedAxis` must be normalized.
213 | * @param {Float32Vector3} normalizedAxis
214 | * @param {number} radian
215 | * @returns {Matrix4x4}
216 | */
217 | static rotationAround(normalizedAxis: Float32Vector3, radian: number) : Matrix4x4 {
218 | const q = Quaternion.rotationAround(normalizedAxis, radian);
219 | return q.toRotationMatrix4();
220 | }
221 |
222 | /**
223 | * Returns "look at" matrix.
224 | * @param {Float32Vector3} cameraPosition
225 | * @param {Float32Vector3} lookAtPosition
226 | * @param {Float32Vector3} cameraUp
227 | * @returns {Matrix4x4}
228 | */
229 | static lookAt(cameraPosition: Float32Vector3, lookAtPosition: Float32Vector3, cameraUp: Float32Vector3): Matrix4x4 {
230 | const zAxis: Float32Vector3 = cameraPosition.sub(lookAtPosition).normalize();
231 | const xAxis: Float32Vector3 = cameraUp.cross(zAxis).normalize();
232 | const yAxis: Float32Vector3 = zAxis.cross(xAxis).normalize();
233 |
234 | return new Matrix4x4(
235 | xAxis.x, yAxis.x, zAxis.x, 0.0,
236 | xAxis.y, yAxis.y, zAxis.y, 0.0,
237 | xAxis.z, yAxis.z, zAxis.z, 0.0,
238 | -cameraPosition.dot(xAxis), -cameraPosition.dot(yAxis), -cameraPosition.dot(zAxis), 1.0
239 | );
240 | }
241 |
242 | /**
243 | * Returns an orthographic projection matrix.
244 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
245 | * @returns {Matrix4x4}
246 | */
247 | static orthographic(argsObject: {top: number, bottom: number, left: number, right: number, near: number, far: number}): Matrix4x4 {
248 | const top: number = argsObject.top;
249 | const bottom: number = argsObject.bottom;
250 | const left: number = argsObject.left;
251 | const right: number = argsObject.right;
252 | const near: number = argsObject.near;
253 | const far: number = argsObject.far;
254 |
255 | return new Matrix4x4(
256 | 2/(right-left), 0.0, 0.0, 0.0,
257 | 0.0, 2/(top-bottom), 0.0, 0.0,
258 | 0.0, 0.0, -2/(far-near), 0.0,
259 | -(right+left)/(right-left), -(top+bottom)/(top-bottom), -(far+near)/(far-near), 1.0
260 | );
261 | }
262 |
263 | /**
264 | * Returns a frustrum projection matrix.
265 | * @param {{top: number; bottom: number; left: number; right: number; near: number; far: number}} argsObject
266 | * @returns {Matrix4x4}
267 | */
268 | static frustum(argsObject: {top: number, bottom: number, left: number, right: number, near: number, far: number}): Matrix4x4 {
269 | const top: number = argsObject.top;
270 | const bottom: number = argsObject.bottom;
271 | const left: number = argsObject.left;
272 | const right: number = argsObject.right;
273 | const near: number = argsObject.near;
274 | const far: number = argsObject.far;
275 |
276 | return new Matrix4x4(
277 | 2*near/(right-left), 0.0, 0.0, 0.0,
278 | 0.0, 2*near/(top-bottom), 0.0, 0.0,
279 | (right+left)/(right-left), (top+bottom)/(top-bottom), -(far+near)/(far-near), -1.0,
280 | 0.0, 0.0, -2*far*near/(far-near), 0.0
281 | );
282 | }
283 |
284 | /**
285 | * Returns a perspective projection matrix.
286 | * @param {{fovY: number; aspect: number; near: number; far: number}} argsObject
287 | * @returns {Matrix4x4}
288 | */
289 | static perspective(argsObject: {fovYRadian: number, aspectRatio: number, near: number, far: number}): Matrix4x4 {
290 | const top = argsObject.near * Math.tan(argsObject.fovYRadian * 0.5);
291 | const height = top * 2;
292 | const width = argsObject.aspectRatio * height;
293 | const left = -0.5 * width;
294 | const right = left + width;
295 | const bottom = top - height;
296 |
297 | return Matrix4x4.frustum({
298 | top,
299 | bottom,
300 | left,
301 | right,
302 | near: argsObject.near,
303 | far: argsObject.far
304 | })
305 | }
306 |
307 | /**
308 | * Multiply by `other` matrix and returns a product.
309 | *
310 | * This method does not mutate the matrix.
311 | * @param {Matrix4x4} other
312 | * @returns {Matrix4x4}
313 | */
314 | mulByMatrix4x4(other: Matrix4x4): Matrix4x4 {
315 | const m11: number = this._values[0];
316 | const m12: number = this._values[4];
317 | const m13: number = this._values[8];
318 | const m14: number = this._values[12];
319 | const m21: number = this._values[1];
320 | const m22: number = this._values[5];
321 | const m23: number = this._values[9];
322 | const m24: number = this._values[13];
323 | const m31: number = this._values[2];
324 | const m32: number = this._values[6];
325 | const m33: number = this._values[10];
326 | const m34: number = this._values[14];
327 | const m41: number = this._values[3];
328 | const m42: number = this._values[7];
329 | const m43: number = this._values[11];
330 | const m44: number = this._values[15];
331 |
332 | const o11: number = other.values[0];
333 | const o12: number = other.values[4];
334 | const o13: number = other.values[8];
335 | const o14: number = other.values[12];
336 | const o21: number = other.values[1];
337 | const o22: number = other.values[5];
338 | const o23: number = other.values[9];
339 | const o24: number = other.values[13];
340 | const o31: number = other.values[2];
341 | const o32: number = other.values[6];
342 | const o33: number = other.values[10];
343 | const o34: number = other.values[14];
344 | const o41: number = other.values[3];
345 | const o42: number = other.values[7];
346 | const o43: number = other.values[11];
347 | const o44: number = other.values[15];
348 |
349 | const p11: number = (m11 * o11) + (m12 * o21) + (m13 * o31) + (m14 * o41);
350 | const p12: number = (m11 * o12) + (m12 * o22) + (m13 * o32) + (m14 * o42);
351 | const p13: number = (m11 * o13) + (m12 * o23) + (m13 * o33) + (m14 * o43);
352 | const p14: number = (m11 * o14) + (m12 * o24) + (m13 * o34) + (m14 * o44);
353 |
354 | const p21: number = (m21 * o11) + (m22 * o21) + (m23 * o31) + (m24 * o41);
355 | const p22: number = (m21 * o12) + (m22 * o22) + (m23 * o32) + (m24 * o42);
356 | const p23: number = (m21 * o13) + (m22 * o23) + (m23 * o33) + (m24 * o43);
357 | const p24: number = (m21 * o14) + (m22 * o24) + (m23 * o34) + (m24 * o44);
358 |
359 | const p31: number = (m31 * o11) + (m32 * o21) + (m33 * o31) + (m34 * o41);
360 | const p32: number = (m31 * o12) + (m32 * o22) + (m33 * o32) + (m34 * o42);
361 | const p33: number = (m31 * o13) + (m32 * o23) + (m33 * o33) + (m34 * o43);
362 | const p34: number = (m31 * o14) + (m32 * o24) + (m33 * o34) + (m34 * o44);
363 |
364 | const p41: number = (m41 * o11) + (m42 * o21) + (m43 * o31) + (m44 * o41);
365 | const p42: number = (m41 * o12) + (m42 * o22) + (m43 * o32) + (m44 * o42);
366 | const p43: number = (m41 * o13) + (m42 * o23) + (m43 * o33) + (m44 * o43);
367 | const p44: number = (m41 * o14) + (m42 * o24) + (m43 * o34) + (m44 * o44);
368 |
369 | return new Matrix4x4(
370 | p11, p21, p31, p41,
371 | p12, p22, p32, p42,
372 | p13, p23, p33, p43,
373 | p14, p24, p34, p44
374 | );
375 | }
376 |
377 | /**
378 | * An alias for `mulByMatrix4x4`.
379 | * @param {Matrix4x4} other
380 | * @returns {Matrix4x4}
381 | */
382 | mulByMatrix4(other: Matrix4x4): Matrix4x4 {
383 | return this.mulByMatrix4x4(other);
384 | }
385 |
386 | /**
387 | * Translate the matrix and returns new `Matrix4x4`.
388 | *
389 | * This method does not mutate the matrix.
390 | * @param {number} tx
391 | * @param {number} ty
392 | * @param {number} tz
393 | * @returns {Matrix4x4}
394 | */
395 | translate(tx: number, ty: number, tz: number): Matrix4x4 {
396 | const t: Matrix4x4 = Matrix4x4.translation(tx, ty, tz);
397 | return this.mulByMatrix4x4(t);
398 | }
399 |
400 | /**
401 | * Scale the matrix and returns new `Matrix4x4`.
402 | * @param {number} sx
403 | * @param {number} sy
404 | * @param {number} sz
405 | * @returns {Matrix4x4}
406 | */
407 | scale(sx: number, sy: number, sz: number): Matrix4x4 {
408 | const s: Matrix4x4 = Matrix4x4.scaling(sx, sy, sz);
409 | return this.mulByMatrix4x4(s);
410 | }
411 |
412 | /**
413 | * Rotate the matrix around x-axis and returns new `Matrix4x4`.
414 | *
415 | * This method does not mutate the matrix.
416 | * @param {number} radian
417 | * @returns {Matrix4x4}
418 | */
419 | rotateX(radian: number): Matrix4x4 {
420 | const rx: Matrix4x4 = Matrix4x4.rotationX(radian);
421 | return this.mulByMatrix4x4(rx);
422 | }
423 |
424 | /**
425 | * Rotate the matrix around y-axis and returns new `Matrix4x4`.
426 | *
427 | * This method does not mutate the matrix.
428 | * @param {number} radian
429 | * @returns {Matrix4x4}
430 | */
431 | rotateY(radian: number): Matrix4x4 {
432 | const ry: Matrix4x4 = Matrix4x4.rotationY(radian);
433 | return this.mulByMatrix4x4(ry);
434 | }
435 |
436 | /**
437 | * Rotate the matrix around z-axis and returns new `Matrix4x4`.
438 | *
439 | * This method does not mutate the matrix.
440 | * @param {number} radian
441 | * @returns {Matrix4x4}
442 | */
443 | rotateZ(radian: number): Matrix4x4 {
444 | const rz: Matrix4x4 = Matrix4x4.rotationZ(radian);
445 | return this.mulByMatrix4x4(rz);
446 | }
447 |
448 | /**
449 | * Rotate the matrix around the `normalizedAxis` and return new Matrix4x4.
450 | *
451 | * This method does not mutate the matrix.
452 | * @param {Float32Vector3} normalizedAxis
453 | * @param {number} radian
454 | * @returns {Matrix4x4}
455 | */
456 | rotateAround(normalizedAxis: Float32Vector3, radian: number): Matrix4x4 {
457 | const r = Matrix4x4.rotationAround(normalizedAxis, radian);
458 | return this.mulByMatrix4x4(r);
459 | }
460 |
461 | get values(): Float32Array {
462 | return this._values;
463 | }
464 |
465 | toString(): string {
466 | return this._values.toString();
467 | }
468 | }
469 |
470 | /**
471 | * An alias for `Matrix2x2`.
472 | * @type {Matrix2x2}
473 | */
474 | export const Matrix2 = Matrix2x2;
475 |
476 | /**
477 | * An alias for `Matrix3x3`.
478 | * @type {Matrix3x3}
479 | */
480 | export const Matrix3 = Matrix3x3;
481 |
482 | /**
483 | * An alias for `Matrix4x4`.
484 | * @type {Matrix4x4}
485 | */
486 | export const Matrix4 = Matrix4x4;
--------------------------------------------------------------------------------
/src/quaternion.ts:
--------------------------------------------------------------------------------
1 | import { Float32Vector3 } from './float32vector';
2 | import { Matrix4x4 } from './matrix';
3 |
4 | /**
5 | * Quaternion which is 4-dimensional complex number.
6 | * See [Wikipedia](https://en.wikipedia.org/wiki/Quaternion).
7 | */
8 | export class Quaternion {
9 | protected _values: Float32Array;
10 |
11 | constructor(x: number, y: number, z: number, w: number) {
12 | this._values = new Float32Array([x, y, z, w]);
13 | }
14 |
15 | /**
16 | * Create a rotation quaternion around `normalizedAxis`.
17 | * `normalizedAxis` must be normalized.
18 | * @param {Float32Vector3} normalizedAxis
19 | * @param {number} radian
20 | * @returns {Quaternion}
21 | */
22 | static rotationAround(normalizedAxis: Float32Vector3, radian: number): Quaternion {
23 | const sin = Math.sin(radian / 2.0);
24 | const cos = Math.cos(radian / 2.0);
25 | return new Quaternion(normalizedAxis.x * sin, normalizedAxis.y * sin, normalizedAxis.z * sin, cos);
26 | }
27 |
28 | /**
29 | * Returns a normalized quaternion.
30 | * @returns {Quaternion}
31 | */
32 | normalize() : Quaternion {
33 | const mag = this.magnitude;
34 | if(mag === 0) { return this; }
35 | const r = 1 / mag;
36 | return new Quaternion(this.x * r, this.y * r, this.z * r, this.w * r);
37 | }
38 |
39 | /**
40 | * Adds the `other` to the quaternion and returns the sum.
41 | *
42 | * This method does not mutate the quaternion.
43 | * @param {Quaternion} other
44 | * @returns {Quaternion}
45 | */
46 | add(other: Quaternion): Quaternion {
47 | return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
48 | }
49 |
50 | /**
51 | * Multiplies the quaternion by `scalar` and returns the product.
52 | *
53 | * This method does not mutate the quaternion.
54 | * @param {number} scalar
55 | * @returns {Quaternion}
56 | */
57 | mulByScalar(scalar: number): Quaternion {
58 | return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
59 | }
60 |
61 | /**
62 | * Calculates dot product.
63 | * @param {Quaternion} other
64 | * @returns {number}
65 | */
66 | dot(other: Quaternion): number {
67 | return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;
68 | }
69 |
70 | /**
71 | * Calculates spherical linear interpolation(also known as Slerp) and returns new `Quaternion` between the quaternion and the other.
72 | * @param {Quaternion} other
73 | * @param {number} t 0.0 <= t <= 1.0
74 | * @param {{chooseShorterAngle: boolean}} options Does not work currently. slerp chooses shorter angle regardless of this value.
75 | * @returns {Quaternion}
76 | */
77 | slerp(other: Quaternion , t: number, options: { chooseShorterAngle: boolean } = { chooseShorterAngle: true }): Quaternion {
78 | let dotProd: number = this.dot(other);
79 | let otherQuaternion: Quaternion = other;
80 |
81 | // When the dot product is negative, slerp chooses the longer way.
82 | // So we should negate the `other` quaternion.
83 | if(dotProd < 0) {
84 | dotProd = -dotProd;
85 | otherQuaternion = other.mulByScalar(-1);
86 | }
87 |
88 | const omega: number = Math.acos(dotProd);
89 | const sinOmega: number = Math.sin(omega);
90 |
91 | const q1: Quaternion = this.mulByScalar(Math.sin((1 - t) * omega) / sinOmega);
92 | const q2: Quaternion = otherQuaternion.mulByScalar(Math.sin(t * omega) / sinOmega);
93 |
94 | return q1.add(q2);
95 | }
96 |
97 | /**
98 | * Calc magnitude of the quaternion.
99 | * @returns {number}
100 | */
101 | get magnitude(): number {
102 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
103 | }
104 |
105 | /**
106 | * Calc norm of the quaternion.
107 | * An alias for `magnitude`.
108 | * @returns {number}
109 | */
110 | get norm(): number {
111 | return this.magnitude;
112 | }
113 |
114 | /**
115 | * Returns x value of the vector.
116 | * @returns {number}
117 | */
118 | get x(): number {
119 | return this._values[0];
120 | }
121 |
122 | /**
123 | * Returns y value of the vector.
124 | * @returns {number}
125 | */
126 | get y(): number {
127 | return this._values[1];
128 | }
129 |
130 | /**
131 | * Returns z value of the vector.
132 | * @returns {number}
133 | */
134 | get z(): number {
135 | return this._values[2];
136 | }
137 |
138 | /**
139 | * Returns w value of the vector.
140 | * @returns {number}
141 | */
142 | get w(): number {
143 | return this._values[3];
144 | }
145 |
146 | /**
147 | * Set the `value` as new x.
148 | * @param {number} value
149 | */
150 | set x(value: number) {
151 | this._values[0] = value;
152 | }
153 |
154 | /**
155 | * Set the `value` as new y.
156 | * @param {number} value
157 | */
158 | set y(value: number) {
159 | this._values[1] = value;
160 | }
161 |
162 | /**
163 | * Set the `value` as new z.
164 | * @param {number} value
165 | */
166 | set z(value: number) {
167 | this._values[2] = value;
168 | }
169 |
170 | /**
171 | * Set the `value` as new w.
172 | * @param {number} value
173 | */
174 | set w(value: number) {
175 | this._values[3] = value;
176 | }
177 |
178 | /**
179 | * Returns values of the quaternion.
180 | * @returns {Float32Array}
181 | */
182 | get values(): Float32Array {
183 | return this._values;
184 | }
185 |
186 | /**
187 | * Convert the quaternion to a rotation matrix.
188 | * @returns {Matrix4x4}
189 | */
190 | toRotationMatrix4(): Matrix4x4 {
191 | const x = this.x;
192 | const y = this.y;
193 | const z = this.z;
194 | const w = this.w;
195 |
196 | const m11 = 1 - 2 * y * y - 2 * z * z;
197 | const m12 = 2 * x * y - 2 * w * z;
198 | const m13 = 2 * x * z + 2 * w * y;
199 | const m14 = 0;
200 | const m21 = 2 * x * y + 2 * w * z;
201 | const m22 = 1 - 2 * x * x - 2 * z * z;
202 | const m23 = 2 * y * z - 2 * w * x;
203 | const m24 = 0;
204 | const m31 = 2 * x * z - 2 * w * y;
205 | const m32 = 2 * y * z + 2 * w * x;
206 | const m33 = 1 - 2 * x * x - 2 * y * y;
207 | const m34 = 0;
208 | const m41 = 0;
209 | const m42 = 0;
210 | const m43 = 0;
211 | const m44 = 1;
212 |
213 | return new Matrix4x4(
214 | m11, m21, m31, m41,
215 | m12, m22, m32, m42,
216 | m13, m23, m33, m43,
217 | m14, m24, m34, m44
218 | );
219 | }
220 |
221 | /**
222 | * Returns values as `String`.
223 | * @returns {string}
224 | */
225 | toString(): string {
226 | return `Quaternion(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
227 | }
228 | }
--------------------------------------------------------------------------------
/src/vector_base.ts:
--------------------------------------------------------------------------------
1 | export type TypedArrayLike = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
2 |
3 | /**
4 | * An interface for vectors.
5 | */
6 | export interface Vector {
7 | /**
8 | * Returns values of the vector.
9 | * @returns {T}
10 | */
11 | readonly values: T;
12 |
13 | /**
14 | * Returns magnitude of the vector.
15 | */
16 | readonly magnitude: number;
17 |
18 | /**
19 | * Returns `values` as a string.
20 | * @returns {string}
21 | */
22 | toString(): string;
23 | }
24 |
25 | /**
26 | * An abstract class for vectors.
27 | */
28 | export abstract class VectorBase implements Vector {
29 | /**
30 | * Values that the vector contains.
31 | */
32 | protected _values: T;
33 |
34 | get values(): T {
35 | return this._values;
36 | }
37 |
38 | get magnitude(): number {
39 | let sumSq = 0;
40 | for(const val of this._values) {
41 | sumSq += val ** 2;
42 | }
43 | return Math.sqrt(sumSq);
44 | }
45 |
46 | toString(): string {
47 | const dimension = this._values.length;
48 | return `Vector${dimension}(${this._values.join(', ')})`;
49 | }
50 | }
51 |
52 | /**
53 | * A base abstract class for 2-dimensional vectors.
54 | */
55 | export abstract class Vector2Base extends VectorBase {
56 | /**
57 | * Returns x value of the vector.
58 | * @returns {number}
59 | */
60 | get x(): number {
61 | return this._values[0];
62 | }
63 |
64 | /**
65 | * Returns y value of the vector.
66 | * @returns {number}
67 | */
68 | get y(): number {
69 | return this._values[1];
70 | }
71 |
72 | /**
73 | * Set the `value` as new x.
74 | * @param {number} value
75 | */
76 | set x(value: number) {
77 | this._values[0] = value;
78 | }
79 |
80 | /**
81 | * Set the `value` as new y.
82 | * @param {number} value
83 | */
84 | set y(value: number) {
85 | this._values[1] = value;
86 | }
87 |
88 | }
89 |
90 | /**
91 | * A base abstract class for 3-dimensional vectors.
92 | */
93 | export abstract class Vector3Base extends VectorBase {
94 | /**
95 | * Returns x value of the vector.
96 | * @returns {number}
97 | */
98 | get x(): number {
99 | return this._values[0];
100 | }
101 |
102 | /**
103 | * Returns y value of the vector.
104 | * @returns {number}
105 | */
106 | get y(): number {
107 | return this._values[1];
108 | }
109 |
110 | /**
111 | * Returns z value of the vector.
112 | * @returns {number}
113 | */
114 | get z(): number {
115 | return this._values[2];
116 | }
117 |
118 | /**
119 | * Set the `value` as new x.
120 | * @param {number} value
121 | */
122 | set x(value: number) {
123 | this._values[0] = value;
124 | }
125 |
126 | /**
127 | * Set the `value` as new y.
128 | * @param {number} value
129 | */
130 | set y(value: number) {
131 | this._values[1] = value;
132 | }
133 |
134 | /**
135 | * Set the `value` as new z.
136 | * @param {number} value
137 | */
138 | set z(value: number) {
139 | this._values[2] = value;
140 | }
141 | }
142 |
143 | /**
144 | * A base abstract class for 4-dimensional vectors.
145 | */
146 | export abstract class Vector4Base extends VectorBase {
147 | /**
148 | * Returns x value of the vector.
149 | * @returns {number}
150 | */
151 | get x(): number {
152 | return this._values[0];
153 | }
154 |
155 | /**
156 | * Returns y value of the vector.
157 | * @returns {number}
158 | */
159 | get y(): number {
160 | return this._values[1];
161 | }
162 |
163 | /**
164 | * Returns z value of the vector.
165 | * @returns {number}
166 | */
167 | get z(): number {
168 | return this._values[2];
169 | }
170 |
171 | /**
172 | * Returns w value of the vector.
173 | * @returns {number}
174 | */
175 | get w(): number {
176 | return this._values[3];
177 | }
178 |
179 | /**
180 | * Set the `value` as new x.
181 | * @param {number} value
182 | */
183 | set x(value: number) {
184 | this._values[0] = value;
185 | }
186 |
187 | /**
188 | * Set the `value` as new y.
189 | * @param {number} value
190 | */
191 | set y(value: number) {
192 | this._values[1] = value;
193 | }
194 |
195 | /**
196 | * Set the `value` as new z.
197 | * @param {number} value
198 | */
199 | set z(value: number) {
200 | this._values[2] = value;
201 | }
202 |
203 | /**
204 | * Set the `value` as new w.
205 | * @param {number} value
206 | */
207 | set w(value: number) {
208 | this._values[3] = value;
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2020",
4 | "module": "commonjs",
5 | "outDir": "lib",
6 | "newLine": "LF",
7 | "sourceMap": false,
8 | "declaration": true,
9 | "strict": true,
10 | "strictPropertyInitialization": false
11 | },
12 |
13 | "include": [ "src/**/*" ],
14 |
15 | "exclude": [ "node_modules" ]
16 | }
--------------------------------------------------------------------------------
2x2 Matrix of single-precision float numbers.
3 |Values are stored in column major order.
4 |