bg2e-js 2.1.2 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/bg2e-js.js +7031 -6989
  2. package/dist/bg2e-js.js.map +1 -1
  3. package/package.json +20 -2
  4. package/src/app/AppController.ts +39 -0
  5. package/src/app/Bg2KeyboardEvent.ts +54 -0
  6. package/src/app/Bg2MouseEvent.ts +82 -0
  7. package/src/app/Bg2TouchEvent.ts +18 -0
  8. package/src/app/Canvas.ts +108 -0
  9. package/src/app/EventBase.ts +10 -0
  10. package/src/app/MainLoop.ts +273 -0
  11. package/src/app/index.ts +25 -0
  12. package/src/base/Color.ts +134 -0
  13. package/src/base/Environment.ts +183 -0
  14. package/src/base/Light.ts +192 -0
  15. package/src/base/Material.ts +619 -0
  16. package/src/base/PolyList.ts +365 -0
  17. package/src/base/Texture.ts +620 -0
  18. package/src/base/index.ts +81 -0
  19. package/src/db/Bg2LoaderPlugin.ts +129 -0
  20. package/src/db/DBPluginApi.ts +48 -0
  21. package/src/db/Loader.ts +116 -0
  22. package/src/db/LoaderPlugin.ts +34 -0
  23. package/src/db/MtlParser.ts +7 -0
  24. package/src/db/ObjLoaderPlugin.ts +55 -0
  25. package/src/db/ObjParser.ts +252 -0
  26. package/src/db/ObjWriterPlugin.ts +19 -0
  27. package/src/db/VitscnjLoaderPlugin.ts +100 -0
  28. package/src/db/Writer.ts +52 -0
  29. package/src/db/WriterPlugin.ts +22 -0
  30. package/src/db/index.ts +44 -0
  31. package/src/debug/DebugRenderer.ts +173 -0
  32. package/src/debug/WebGLTextureViewer.ts +75 -0
  33. package/src/debug/index.ts +7 -0
  34. package/src/index.html +11 -0
  35. package/src/index.ts +33 -0
  36. package/src/manipulation/SelectionBuffer.ts +82 -0
  37. package/src/manipulation/SelectionHighlight.ts +85 -0
  38. package/src/manipulation/SelectionIdAssignVisitor.ts +97 -0
  39. package/src/manipulation/SelectionManager.ts +166 -0
  40. package/src/manipulation/SelectionMode.ts +6 -0
  41. package/src/math/Mat3.ts +259 -0
  42. package/src/math/Mat4.ts +706 -0
  43. package/src/math/MatrixStrategy.ts +25 -0
  44. package/src/math/Quat.ts +65 -0
  45. package/src/math/Vec.ts +753 -0
  46. package/src/math/constants.ts +47 -0
  47. package/src/math/functions.ts +103 -0
  48. package/src/math/index.ts +74 -0
  49. package/src/phsics/joint.ts +137 -0
  50. package/src/primitives/arrow.ts +58 -0
  51. package/src/primitives/cone.ts +138 -0
  52. package/src/primitives/cube.ts +60 -0
  53. package/src/primitives/cylinder.ts +216 -0
  54. package/src/primitives/index.ts +13 -0
  55. package/src/primitives/plane.ts +31 -0
  56. package/src/primitives/sphere.ts +809 -0
  57. package/src/render/BRDFIntegrationMap.ts +4 -0
  58. package/src/render/Environment.ts +136 -0
  59. package/src/render/FrameBuffer.ts +35 -0
  60. package/src/render/MaterialRenderer.ts +34 -0
  61. package/src/render/Pipeline.ts +109 -0
  62. package/src/render/PolyListRenderer.ts +47 -0
  63. package/src/render/RenderBuffer.ts +197 -0
  64. package/src/render/RenderQueue.ts +199 -0
  65. package/src/render/RenderState.ts +116 -0
  66. package/src/render/Renderer.ts +248 -0
  67. package/src/render/SceneAppController.ts +238 -0
  68. package/src/render/SceneRenderer.ts +373 -0
  69. package/src/render/Shader.ts +32 -0
  70. package/src/render/ShadowRenderer.ts +176 -0
  71. package/src/render/SkyCube.ts +106 -0
  72. package/src/render/SkySphere.ts +118 -0
  73. package/src/render/TextureMergerRenderer.ts +70 -0
  74. package/src/render/TextureRenderer.ts +34 -0
  75. package/src/render/index.ts +67 -0
  76. package/src/render/webgl/FrameBuffer.ts +10 -0
  77. package/src/render/webgl/MaterialRenderer.ts +113 -0
  78. package/src/render/webgl/Pipeline.ts +89 -0
  79. package/src/render/webgl/PolyListRenderer.ts +260 -0
  80. package/src/render/webgl/RenderBuffer.ts +227 -0
  81. package/src/render/webgl/Renderer.ts +262 -0
  82. package/src/render/webgl/SceneRenderer.ts +68 -0
  83. package/src/render/webgl/ShaderProgram.ts +424 -0
  84. package/src/render/webgl/ShadowRenderer.ts +6 -0
  85. package/src/render/webgl/SkyCube.ts +16 -0
  86. package/src/render/webgl/SkySphere.ts +16 -0
  87. package/src/render/webgl/State.ts +152 -0
  88. package/src/render/webgl/TextureRenderer.ts +167 -0
  89. package/src/render/webgl/VertexBuffer.ts +137 -0
  90. package/src/render/webgl/index.ts +35 -0
  91. package/src/scene/Camera.ts +458 -0
  92. package/src/scene/Chain.ts +44 -0
  93. package/src/scene/ChainJoint.ts +58 -0
  94. package/src/scene/Component.ts +173 -0
  95. package/src/scene/ComponentMap.ts +107 -0
  96. package/src/scene/Drawable.ts +154 -0
  97. package/src/scene/EnvironmentComponent.ts +142 -0
  98. package/src/scene/FindNodeVisitor.ts +60 -0
  99. package/src/scene/LightComponent.ts +155 -0
  100. package/src/scene/MatrixState.ts +46 -0
  101. package/src/scene/Node.ts +314 -0
  102. package/src/scene/NodeVisitor.ts +15 -0
  103. package/src/scene/OrbitCameraController.ts +450 -0
  104. package/src/scene/SmoothOrbitCameraController.ts +99 -0
  105. package/src/scene/Transform.ts +73 -0
  106. package/src/scene/index.ts +57 -0
  107. package/src/shaders/BasicDiffuseColorShader.ts +111 -0
  108. package/src/shaders/BasicPBRLightShader.ts +277 -0
  109. package/src/shaders/DebugRenderShader.ts +98 -0
  110. package/src/shaders/DepthRenderShader.ts +91 -0
  111. package/src/shaders/IrradianceMapCubeShader.ts +116 -0
  112. package/src/shaders/PBRLightIBLShader.ts +487 -0
  113. package/src/shaders/PickSelectionShader.ts +101 -0
  114. package/src/shaders/PresentDebugFramebufferShader.ts +118 -0
  115. package/src/shaders/PresentTextureShader.ts +99 -0
  116. package/src/shaders/SelectionHighlightShader.ts +127 -0
  117. package/src/shaders/ShaderFunction.ts +318 -0
  118. package/src/shaders/SkyCubeShader.ts +94 -0
  119. package/src/shaders/SkySphereShader.ts +102 -0
  120. package/src/shaders/SpecularMapCubeShader.ts +165 -0
  121. package/src/shaders/TextureMergerShader.ts +171 -0
  122. package/src/shaders/index.ts +37 -0
  123. package/src/shaders/webgl/color_correction.glsl +47 -0
  124. package/src/shaders/webgl/constants.glsl +6 -0
  125. package/src/shaders/webgl/index.ts +70 -0
  126. package/src/shaders/webgl/normal_map.glsl +9 -0
  127. package/src/shaders/webgl/pbr.glsl +173 -0
  128. package/src/shaders/webgl/uniforms.glsl +91 -0
  129. package/src/shaders/webgl_shader_lib.ts +213 -0
  130. package/src/tools/BinaryResourceProvider.ts +14 -0
  131. package/src/tools/ImageResourceProvider.ts +66 -0
  132. package/src/tools/MaterialModifier.ts +276 -0
  133. package/src/tools/Resource.ts +203 -0
  134. package/src/tools/ResourceProvider.ts +69 -0
  135. package/src/tools/TextResourceProvider.ts +24 -0
  136. package/src/tools/TextureCache.ts +52 -0
  137. package/src/tools/TextureResourceDatabase.ts +100 -0
  138. package/src/tools/UserAgent.ts +362 -0
  139. package/src/tools/VideoResourceProvider.ts +50 -0
  140. package/src/tools/WriteStrategy.ts +22 -0
  141. package/src/tools/base64.ts +11 -0
  142. package/src/tools/crypto.ts +19 -0
  143. package/src/tools/endiantess.ts +13 -0
  144. package/src/tools/image.ts +18 -0
  145. package/src/tools/index.ts +41 -0
  146. package/src/tools/processType.ts +38 -0
  147. package/src/vite-env.d.ts +12 -0
@@ -0,0 +1,97 @@
1
+ import NodeVisitor from "../scene/NodeVisitor";
2
+ import SelectionMode from "./SelectionMode";
3
+ import Color from "../base/Color";
4
+ import Node from "../scene/Node";
5
+
6
+ const getColor = (comps: number[]) => "" + comps[0] + comps[1] + comps[2];
7
+
8
+ export default class SelectionAssignVisitor extends NodeVisitor {
9
+ protected _selectionMode: SelectionMode;
10
+ protected _elements: Record<string, any>;
11
+ protected _r: number = 0;
12
+ protected _g: number = 0;
13
+ protected _b: number = 0;
14
+
15
+ constructor() {
16
+ super();
17
+
18
+ this._selectionMode = SelectionMode.POLY_LIST;
19
+ this._elements = {};
20
+ }
21
+
22
+ set selectionMode(mode) {
23
+ this._selectionMode = mode;
24
+ this.clear();
25
+ }
26
+
27
+ get selectionMode() {
28
+ return this._selectionMode;
29
+ }
30
+
31
+ clear() {
32
+ this._r = 0;
33
+ this._g = 0;
34
+ this._b = 0;
35
+ this._elements = {};
36
+ }
37
+
38
+ getNextColor() {
39
+ const getId = () => {
40
+ return [ Math.round(Math.random()*255),
41
+ Math.round(Math.random()*255),
42
+ Math.round(Math.random()*255)];
43
+ }
44
+
45
+ let components = getId();
46
+ let color = getColor(components);
47
+ while (this._elements[color]) {
48
+ components = getId();
49
+ color = getColor(components);
50
+ }
51
+
52
+ this._r = components[0];
53
+ this._g = components[1];
54
+ this._b = components[2];
55
+
56
+ return new Color([components[0]/255, components[1]/255, components[2]/255, 1]);
57
+ }
58
+
59
+ findElement(pickedColor: Uint8Array | undefined | null) {
60
+ if (!pickedColor) {
61
+ return null;
62
+ }
63
+
64
+ const color = [
65
+ pickedColor[0],
66
+ pickedColor[1],
67
+ pickedColor[2]
68
+ ];
69
+ return this._elements[getColor(color)];
70
+ }
71
+
72
+ visit(node: Node) {
73
+ const { drawable } = node;
74
+ if (drawable) {
75
+ let color = this.getNextColor();
76
+ drawable.items.forEach(({polyList}, i, array) => {
77
+ if (polyList.isSelectable) {
78
+ polyList.colorCode = color;
79
+ polyList.selected = false;
80
+ const colorCode = getColor([
81
+ Math.round(color[0] * 255),
82
+ Math.round(color[1] * 255),
83
+ Math.round(color[2] * 255)
84
+ ]);
85
+ this._elements[colorCode] = { polyList, drawable };
86
+ }
87
+
88
+ // Get new color code for the next polyList, only if this is not the
89
+ // last item, and the selection mode is POLY_LIST, otherwise we'll
90
+ // use the same color code for all polyList in the drawable
91
+ if (i<array.length-1 && this._selectionMode == SelectionMode.POLY_LIST) {
92
+ color = this.getNextColor();
93
+ }
94
+ });
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,166 @@
1
+ import Vec from "../math/Vec";
2
+ import SelectionBuffer from "./SelectionBuffer";
3
+ import Camera from "../scene/Camera";
4
+ import SelectionIdAssignVisitor from "./SelectionIdAssignVisitor";
5
+ import SelectionMode from "./SelectionMode";
6
+ import Renderer from "../render/Renderer";
7
+ import Node from "../scene/Node";
8
+ import Bg2MouseEvent from "../app/Bg2MouseEvent";
9
+ import Bg2TouchEvent from "../app/Bg2TouchEvent";
10
+
11
+ export type SelectionChangedData = {
12
+ polyList: any;
13
+ drawable: any;
14
+ }
15
+ export type SelectionChangedCallback = (selection: SelectionChangedData[]) => void;
16
+
17
+ export default class SelectionManager {
18
+ protected _renderer: Renderer;
19
+ protected _sceneRoot: Node | null;
20
+ protected _camera: Camera | null;
21
+ protected _selectionMode: SelectionMode;
22
+ protected _multiSelect: boolean;
23
+ protected _selection: Array<{ polyList: any; drawable: any }>;
24
+ protected _selectionChangedCallbacks: Record<string, SelectionChangedCallback>;
25
+ protected _selectionBuffer: SelectionBuffer | null = null;
26
+ protected _selectionIdVisitor: SelectionIdAssignVisitor | null = null;
27
+ protected _downPosition: Vec = new Vec();
28
+ protected _viewportSize: [number, number] = [1, 1];
29
+
30
+ constructor(renderer: Renderer) {
31
+ this._renderer = renderer;
32
+ this._sceneRoot = null;
33
+ this._camera = null;
34
+ this._selectionMode = SelectionMode.POLY_LIST;
35
+ this._multiSelect = false;
36
+
37
+ this._selection = [];
38
+
39
+ this._selectionChangedCallbacks = {}
40
+ }
41
+
42
+ async init() {
43
+ this._selectionBuffer = new SelectionBuffer(this._renderer);
44
+ await this._selectionBuffer.init();
45
+
46
+ this._selectionIdVisitor = new SelectionIdAssignVisitor();
47
+ }
48
+
49
+ setViewportSize(w: number, h: number) {
50
+ this._viewportSize = [w, h];
51
+ }
52
+
53
+ get selection() {
54
+ return this._selection;
55
+ }
56
+
57
+ clearSelection() {
58
+ this._selection = [];
59
+ }
60
+
61
+ set sceneRoot(root) {
62
+ this._sceneRoot = root;
63
+ this.clearSelection();
64
+ }
65
+
66
+ get sceneRoot() {
67
+ return this._sceneRoot;
68
+ }
69
+
70
+ set camera(cam) {
71
+ this._camera = cam;
72
+ this.clearSelection();
73
+ }
74
+
75
+ get camera() {
76
+ if (this._camera) {
77
+ return this._camera;
78
+ }
79
+
80
+ if (!this.sceneRoot) {
81
+ return null;
82
+ }
83
+
84
+ this._camera = Camera.GetMain(this.sceneRoot);
85
+ return this._camera;
86
+ }
87
+
88
+ set selectionMode(mode: SelectionMode) {
89
+ this._selectionMode = mode;
90
+ this.clearSelection();
91
+ }
92
+
93
+ get selectionMode() {
94
+ return this._selectionMode;
95
+ }
96
+
97
+ set multiSelectMode(mode) {
98
+ this._multiSelect = mode;
99
+ this.clearSelection();
100
+ }
101
+
102
+ get multiSelectMode() {
103
+ return this._multiSelect;
104
+ }
105
+
106
+ onSelectionChanged(id: string, cb: SelectionChangedCallback) {
107
+ this._selectionChangedCallbacks[id] = cb;
108
+ }
109
+
110
+ triggerSelectionChanged() {
111
+ for (const key in this._selectionChangedCallbacks) {
112
+ this._selectionChangedCallbacks[key](this._selection);
113
+ }
114
+ }
115
+
116
+ mouseUp(evt: { x: number; y: number }) {
117
+ if (!this._selectionBuffer || !this._selectionIdVisitor || !this.camera || !this.sceneRoot) {
118
+ return;
119
+ }
120
+
121
+ const upPosition = new Vec([evt.x, evt.y]);
122
+ if (Vec.Distance(this._downPosition, upPosition) < 2) {
123
+ if (this._selectionIdVisitor && this.sceneRoot) {
124
+ this._selectionIdVisitor.selectionMode = this.selectionMode;
125
+ this.sceneRoot.accept(this._selectionIdVisitor);
126
+ }
127
+ const pixelRatio = window.devicePixelRatio || 1;
128
+ this._selectionBuffer?.reshape(this._viewportSize[0], this._viewportSize[1]);
129
+ const pickedColor = this._selectionBuffer!.draw(this.sceneRoot, this.camera, evt.x * pixelRatio, evt.y * pixelRatio);
130
+ const item = this._selectionIdVisitor.findElement(pickedColor);
131
+ const isSelected = () => this._selection.find(s => {
132
+ return s.polyList === item.polyList && s.drawable === item.drawable
133
+ });
134
+ if (item && this._multiSelect && !isSelected()) {
135
+ this._selection.push(item);
136
+ this.triggerSelectionChanged();
137
+ }
138
+ else if (item && !isSelected()) {
139
+ this._selection = [item];
140
+ this.triggerSelectionChanged();
141
+ }
142
+ else if (!item && !this._multiSelect && this._selection.length > 0) {
143
+ this._selection = [];
144
+ this.triggerSelectionChanged();
145
+ }
146
+
147
+ this._selection.forEach(item => item.polyList.selected = true);
148
+ }
149
+ }
150
+
151
+ mouseDown(evt: Bg2MouseEvent) {
152
+ this._downPosition = new Vec([evt.x, evt.y]);
153
+ }
154
+
155
+ touchStart(evt: Bg2TouchEvent) {
156
+
157
+ }
158
+
159
+ touchEnd(evt: Bg2TouchEvent) {
160
+
161
+ }
162
+
163
+ destroy() {
164
+ this._selectionBuffer?.destroy();
165
+ }
166
+ }
@@ -0,0 +1,6 @@
1
+ enum SelectionMode {
2
+ OBJECT = 0,
3
+ POLY_LIST = 1
4
+ }
5
+
6
+ export default SelectionMode;
@@ -0,0 +1,259 @@
1
+ import { NumericArray } from "./constants";
2
+ import Vec from "./Vec";
3
+ import { isZero, equals } from "./functions";
4
+
5
+ export default class Mat3 extends NumericArray {
6
+ constructor();
7
+ constructor(m: ArrayLike<number>);
8
+ constructor(m0: number, m1: number, m2: number, m3: number, m4: number, m5: number, m6: number, m7: number, m8: number);
9
+ constructor(...args: any[]) {
10
+ if (args.length === 9) {
11
+ super(args);
12
+ }
13
+ else if (args.length === 1 && args[0].length === 9) {
14
+ super(args[0]);
15
+ }
16
+ else if (args.length === 0) {
17
+ super([0,0,0,0,0,0,0,0,0]);
18
+ }
19
+ else {
20
+ throw new Error(`Invalid parameter size in Mat3 constructor`);
21
+ }
22
+ }
23
+
24
+ identity(): this {
25
+ this[0] = 1; this[1] = 0; this[2] = 0;
26
+ this[3] = 0; this[4] = 1; this[5] = 0;
27
+ this[6] = 0; this[7] = 0; this[8] = 1;
28
+ return this;
29
+ }
30
+
31
+ zero(): this {
32
+ this[0] = 0; this[1] = 0; this[2] = 0;
33
+ this[3] = 0; this[4] = 0; this[5] = 0;
34
+ this[6] = 0; this[7] = 0; this[8] = 0;
35
+ return this;
36
+ }
37
+
38
+ row(i: number): Vec {
39
+ return new Vec(
40
+ this[i * 3],
41
+ this[i * 3 + 1],
42
+ this[i * 3 + 2]);
43
+ }
44
+
45
+ setRow(i: number, a: ArrayLike<number>): this;
46
+ setRow(i: number, x: number, y: number, z: number): this;
47
+ setRow(i: number, a: number | ArrayLike<number>, y?: number, z?: number): this {
48
+ if (typeof a === 'object' && a.length >= 3) {
49
+ this[i * 3] = a[0];
50
+ this[i * 3 + 1] = a[1];
51
+ this[i * 3 + 2] = a[2];
52
+ }
53
+ else if (typeof(a) === "number" &&
54
+ typeof(y) === "number" &&
55
+ typeof(z) === "number"
56
+ ) {
57
+ this[i * 3] = a;
58
+ this[i * 3 + 1] = y;
59
+ this[i * 3 + 2] = z;
60
+ }
61
+ else {
62
+ throw new Error(`Invalid parameter setting matrix row`);
63
+ }
64
+ return this;
65
+ }
66
+
67
+ col(i: number): Vec {
68
+ return new Vec(
69
+ this[i],
70
+ this[i + 3],
71
+ this[i + 3 * 2]
72
+ )
73
+ }
74
+
75
+ setCol(i: number, a: ArrayLike<number>): this;
76
+ setCol(i: number, x: number, y: number, z: number): this;
77
+ setCol(i: number, a: number | ArrayLike<number>, y: number | null = null, z: number | null = null): this {
78
+ if (typeof a === 'object' && a.length >= 3) {
79
+ this[i] = a[0];
80
+ this[i + 3] = a[1];
81
+ this[i + 3 * 2] = a[2];
82
+ }
83
+ else if (typeof(a) === "number" &&
84
+ typeof(y) === "number" &&
85
+ typeof(z) === "number"
86
+ ) {
87
+ this[i] = a;
88
+ this[i + 3] = y;
89
+ this[i + 3 * 2] = z;
90
+ }
91
+ else {
92
+ throw new Error(`Invalid parameter setting matrix row`);
93
+ }
94
+ return this;
95
+ }
96
+
97
+ assign(m: ArrayLike<number>): this {
98
+ if (m.length === 9) {
99
+ this[0] = m[0]; this[1] = m[1]; this[2] = m[2];
100
+ this[3] = m[3]; this[4] = m[4]; this[5] = m[5];
101
+ this[6] = m[6]; this[7] = m[7]; this[8] = m[8];
102
+ }
103
+ else if (m.length === 16) {
104
+ this[0] = m[0]; this[1] = m[1]; this[2] = m[2];
105
+ this[3] = m[4]; this[4] = m[5]; this[5] = m[6];
106
+ this[6] = m[8]; this[7] = m[9]; this[8] = m[10];
107
+ }
108
+ else {
109
+ throw new Error(`Invalid plarameter setting matrix data`);
110
+ }
111
+ return this;
112
+ }
113
+
114
+ setScale(x: number, y: number, z: number): this {
115
+ const rx = (new Vec(this[0], this[3], this[6])).normalize().scale(x);
116
+ const ry = (new Vec(this[1], this[4], this[7])).normalize().scale(y);
117
+ const rz = (new Vec(this[2], this[5], this[8])).normalize().scale(z);
118
+ this[0] = rx.x; this[3] = rx.y; this[6] = rx.z;
119
+ this[1] = ry.x; this[4] = ry.y; this[7] = ry.z;
120
+ this[2] = rz.x; this[5] = rz.y; this[8] = rz.z;
121
+ return this;
122
+ }
123
+
124
+ traspose(): this {
125
+ const m3 = this[3]; // 0, 1, 2
126
+ const m7 = this[7]; // 3, 4, 5
127
+ const m6 = this[6]; // 6, 7, 8
128
+ this[3] = this[1];
129
+ this[6] = this[2];
130
+ this[7] = this[5];
131
+ this[1] = m3;
132
+ this[2] = m6;
133
+ this[5] = m7;
134
+ return this;
135
+ }
136
+
137
+ mult(a: number): this;
138
+ mult(a: Mat3): this;
139
+ mult(a: number | Mat3): this {
140
+ if (typeof(a) === "number") {
141
+ this[0] *= a; this[1] *= a; this[2] *= a;
142
+ this[3] *= a; this[4] *= a; this[5] *= a;
143
+ this[6] *= a; this[7] *= a; this[8] *= a;
144
+ }
145
+ else if (a instanceof NumericArray && a.length === 9) {
146
+ const r0 = this.row(0);
147
+ const r1 = this.row(1);
148
+ const r2 = this.row(2);
149
+ const c0 = (a as Mat3).col(0);
150
+ const c1 = (a as Mat3).col(1);
151
+ const c2 = (a as Mat3).col(2);
152
+
153
+ this[0] = Vec.Dot(r0,c0); this[1] = Vec.Dot(r0,c1); this[2] = Vec.Dot(r0,c2);
154
+ this[3] = Vec.Dot(r1,c0); this[4] = Vec.Dot(r1,c1); this[5] = Vec.Dot(r1,c2);
155
+ this[6] = Vec.Dot(r2,c0); this[7] = Vec.Dot(r2,c1); this[8] = Vec.Dot(r2,c2);
156
+ }
157
+ else {
158
+ throw new Error(`Invalid parameter in Mat3.mult()`);
159
+ }
160
+ return this;
161
+ }
162
+
163
+ multVector(v: ArrayLike<number>): Vec {
164
+ if (v.length === 2 || v.length === 3) {
165
+ const x = v[0];
166
+ const y = v[1];
167
+ const z = v.length === 2 ? 1 : v[2];
168
+
169
+ return new Vec( this[0] * x + this[3] * y + this[6] * z,
170
+ this[1] * x + this[4] * y + this[7] * z,
171
+ this[2] * x + this[5] * y + this[8] * z);
172
+ }
173
+ else {
174
+ throw new Error(`Invalid parameter in Mat3.multVector()`);
175
+ }
176
+ }
177
+
178
+ toString(): string {
179
+ return `[ ${this[0]}, ${this[1]}, ${this[2]}\n` +
180
+ ` ${this[3]}, ${this[4]}, ${this[5]}\n` +
181
+ ` ${this[6]}, ${this[7]}, ${this[8]} ]`;
182
+ }
183
+
184
+ static MakeIdentity(): Mat3 {
185
+ const m = new Mat3();
186
+ return m.identity();
187
+ }
188
+
189
+ static MakeZero(): Mat3 {
190
+ const m = new Mat3();
191
+ return m.zero();
192
+ }
193
+
194
+ static MakeWithQuaternion(q: ArrayLike<number>): Mat3 {
195
+ const m = Mat3.MakeIdentity();
196
+
197
+ m.setRow(0, new Vec( 1 - 2 * q[1] * q[1] - 2 * q[2] * q[2], 2 * q[0] * q[1] - 2 * q[2] * q[3], 2 * q[0] * q[2] + 2 * q[1] * q[3]));
198
+ m.setRow(1, new Vec( 2 * q[0] * q[1] + 2 * q[2] * q[3], 1 - 2.0 * q[0] * q[0] - 2 * q[2] * q[2], 2 * q[1] * q[2] - 2 * q[0] * q[3]));
199
+ m.setRow(2, new Vec( 2 * q[0] * q[2] - 2 * q[1] * q[3], 2 * q[1] * q[2] + 2 * q[0] * q[3] , 1 - 2 * q[0] * q[0] - 2 * q[1] * q[1]));
200
+
201
+ return m;
202
+ }
203
+
204
+ // https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
205
+ // Make a rotation matrix from an axis and an angle
206
+ static MakeRotationWithDirection(direction: Vec, up?: Vec): Mat3 {
207
+ const m = Mat3.MakeIdentity();
208
+ const upVec = up || new Vec(0,1,0);
209
+ const z = direction.normalize();
210
+ // Since vectors are 3-dimensional, the cross product will always return a Vecz.
211
+ const x = (Vec.Cross(upVec, z) as Vec).normalize() as Vec;
212
+ const y = (Vec.Cross(z, x) as Vec).normalize() as Vec;
213
+
214
+ m.setRow(0, x);
215
+ m.setRow(1, y);
216
+ m.setRow(2, z);
217
+
218
+ return m;
219
+ }
220
+
221
+ static IsZero(m: ArrayLike<number>): boolean {
222
+ return isZero(m[0]) && isZero(m[1]) && isZero(m[2]) &&
223
+ isZero(m[3]) && isZero(m[4]) && isZero(m[5]) &&
224
+ isZero(m[6]) && isZero(m[7]) && isZero(m[8]);
225
+ }
226
+
227
+ static IsIdentity(m: ArrayLike<number>): boolean {
228
+ return equals(m[0], 1) && isZero(m[1]) && isZero(m[2]) &&
229
+ isZero(m[3]) && equals(m[4], 1) && isZero(m[5]) &&
230
+ isZero(m[6]) && isZero(m[7]) && equals(m[8], 1);
231
+ }
232
+
233
+ static GetScale(m: ArrayLike<number>): Vec {
234
+ return new Vec(
235
+ Vec.Magnitude(new Vec(m[0], m[3], m[6])),
236
+ Vec.Magnitude(new Vec(m[1], m[4], m[7])),
237
+ Vec.Magnitude(new Vec(m[2], m[5], m[8]))
238
+ );
239
+ }
240
+
241
+ static Equals(a: ArrayLike<number>, b: ArrayLike<number>): boolean {
242
+ return equals(a[0], b[0]) && equals(a[1], b[1]) && equals(a[2], b[2]) &&
243
+ equals(a[3], b[3]) && equals(a[4], b[4]) && equals(a[5], b[5]) &&
244
+ equals(a[6], b[6]) && equals(a[7], b[7]) && equals(a[8], b[8]);
245
+ }
246
+
247
+ static IsNaN(m: ArrayLike<number>): boolean {
248
+ return isNaN(m[0]) || isNaN(m[1]) || isNaN(m[2]) &&
249
+ isNaN(m[3]) || isNaN(m[4]) || isNaN(m[5]) &&
250
+ isNaN(m[6]) || isNaN(m[7]) || isNaN(m[8]);
251
+ }
252
+
253
+ // This function multyplies two B x A matrices. It works opposite than the non-static mult() function:
254
+ // A.mult(B) is the same as Mat4.Mult(B,A)
255
+ static Mult(A: Mat3, B: Mat3): Mat3 {
256
+ const result = new Mat3(B);
257
+ return result.mult(A);
258
+ }
259
+ };