@multiplekex/shallot 0.1.2 → 0.1.4

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 (2) hide show
  1. package/package.json +4 -4
  2. package/src/core/math.ts +163 -56
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplekex/shallot",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -19,8 +19,7 @@
19
19
  "dependencies": {
20
20
  "@mapbox/tiny-sdf": "^2.0.7",
21
21
  "bitecs": "^0.4.0",
22
- "fast-xml-parser": "^5.3.3",
23
- "wgpu-matrix": "^3.4.0"
22
+ "fast-xml-parser": "^5.3.3"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@napi-rs/canvas": "^0.1.88",
@@ -28,7 +27,8 @@
28
27
  "@types/three": "^0.182.0",
29
28
  "three": "^0.182.0",
30
29
  "troika-three-text": "^0.52.4",
31
- "webgpu": "^0.3.8"
30
+ "webgpu": "^0.3.8",
31
+ "wgpu-matrix": "^3.4.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "typescript": "^5"
package/src/core/math.ts CHANGED
@@ -1,15 +1,8 @@
1
- import { quat, utils, mat4 } from "wgpu-matrix";
2
-
3
- const tempQuatA = quat.create();
4
- const tempQuatB = quat.create();
5
- const tempQuatOut = quat.create();
6
- const tempMat4 = mat4.create();
7
- const tempVec3A = new Float32Array(3);
8
- const tempVec3B = new Float32Array(3);
9
- const tempVec3C = new Float32Array(3);
1
+ const DEG_TO_RAD = Math.PI / 180;
2
+ const RAD_TO_DEG = 180 / Math.PI;
10
3
 
11
4
  export function clamp(value: number, min: number, max: number): number {
12
- return Math.max(min, Math.min(max, value));
5
+ return value < min ? min : value > max ? max : value;
13
6
  }
14
7
 
15
8
  export function lerp(a: number, b: number, t: number): number {
@@ -27,25 +20,67 @@ export function slerp(
27
20
  toW: number,
28
21
  t: number
29
22
  ): { x: number; y: number; z: number; w: number } {
30
- quat.set(fromX, fromY, fromZ, fromW, tempQuatA);
31
- quat.set(toX, toY, toZ, toW, tempQuatB);
32
- quat.slerp(tempQuatA, tempQuatB, t, tempQuatOut);
33
- return { x: tempQuatOut[0], y: tempQuatOut[1], z: tempQuatOut[2], w: tempQuatOut[3] };
23
+ let dot = fromX * toX + fromY * toY + fromZ * toZ + fromW * toW;
24
+
25
+ if (dot < 0) {
26
+ dot = -dot;
27
+ toX = -toX;
28
+ toY = -toY;
29
+ toZ = -toZ;
30
+ toW = -toW;
31
+ }
32
+
33
+ let s0: number, s1: number;
34
+ if (dot > 0.9995) {
35
+ s0 = 1 - t;
36
+ s1 = t;
37
+ } else {
38
+ const theta0 = Math.acos(dot);
39
+ const sinTheta0 = Math.sqrt(1 - dot * dot);
40
+ const theta = theta0 * t;
41
+ const sinTheta = Math.sin(theta);
42
+ s0 = Math.cos(theta) - (dot * sinTheta) / sinTheta0;
43
+ s1 = sinTheta / sinTheta0;
44
+ }
45
+
46
+ return {
47
+ x: s0 * fromX + s1 * toX,
48
+ y: s0 * fromY + s1 * toY,
49
+ z: s0 * fromZ + s1 * toZ,
50
+ w: s0 * fromW + s1 * toW,
51
+ };
34
52
  }
35
53
 
36
54
  export function rotateQuaternion(
37
- quatX: number,
38
- quatY: number,
39
- quatZ: number,
40
- quatW: number,
55
+ qx: number,
56
+ qy: number,
57
+ qz: number,
58
+ qw: number,
41
59
  dx: number,
42
60
  dy: number,
43
61
  dz: number
44
62
  ): { x: number; y: number; z: number; w: number } {
45
- quat.fromEuler(utils.degToRad(dx), utils.degToRad(dy), utils.degToRad(dz), "xyz", tempQuatA);
46
- quat.set(quatX, quatY, quatZ, quatW, tempQuatB);
47
- quat.multiply(tempQuatB, tempQuatA, tempQuatOut);
48
- return { x: tempQuatOut[0], y: tempQuatOut[1], z: tempQuatOut[2], w: tempQuatOut[3] };
63
+ const hx = dx * DEG_TO_RAD * 0.5;
64
+ const hy = dy * DEG_TO_RAD * 0.5;
65
+ const hz = dz * DEG_TO_RAD * 0.5;
66
+ const cx = Math.cos(hx),
67
+ sx = Math.sin(hx);
68
+ const cy = Math.cos(hy),
69
+ sy = Math.sin(hy);
70
+ const cz = Math.cos(hz),
71
+ sz = Math.sin(hz);
72
+
73
+ const bx = sx * cy * cz + cx * sy * sz;
74
+ const by = cx * sy * cz - sx * cy * sz;
75
+ const bz = cx * cy * sz + sx * sy * cz;
76
+ const bw = cx * cy * cz - sx * sy * sz;
77
+
78
+ return {
79
+ x: qw * bx + qx * bw + qy * bz - qz * by,
80
+ y: qw * by - qx * bz + qy * bw + qz * bx,
81
+ z: qw * bz + qx * by - qy * bx + qz * bw,
82
+ w: qw * bw - qx * bx - qy * by - qz * bz,
83
+ };
49
84
  }
50
85
 
51
86
  export function eulerToQuaternion(
@@ -53,8 +88,22 @@ export function eulerToQuaternion(
53
88
  y: number,
54
89
  z: number
55
90
  ): { x: number; y: number; z: number; w: number } {
56
- quat.fromEuler(utils.degToRad(x), utils.degToRad(y), utils.degToRad(z), "xyz", tempQuatOut);
57
- return { x: tempQuatOut[0], y: tempQuatOut[1], z: tempQuatOut[2], w: tempQuatOut[3] };
91
+ const hx = x * DEG_TO_RAD * 0.5;
92
+ const hy = y * DEG_TO_RAD * 0.5;
93
+ const hz = z * DEG_TO_RAD * 0.5;
94
+ const cx = Math.cos(hx),
95
+ sx = Math.sin(hx);
96
+ const cy = Math.cos(hy),
97
+ sy = Math.sin(hy);
98
+ const cz = Math.cos(hz),
99
+ sz = Math.sin(hz);
100
+
101
+ return {
102
+ x: sx * cy * cz + cx * sy * sz,
103
+ y: cx * sy * cz - sx * cy * sz,
104
+ z: cx * cy * sz + sx * sy * cz,
105
+ w: cx * cy * cz - sx * sy * sz,
106
+ };
58
107
  }
59
108
 
60
109
  export function quaternionToEuler(
@@ -76,30 +125,22 @@ export function quaternionToEuler(
76
125
  wy = w * y2,
77
126
  wz = w * z2;
78
127
 
79
- const m11 = 1 - (yy + zz);
80
- const m12 = xy - wz;
81
128
  const m13 = xz + wy;
82
- const m22 = 1 - (xx + zz);
83
- const m23 = yz - wx;
84
- const m32 = yz + wx;
85
- const m33 = 1 - (xx + yy);
86
-
87
- const ey = Math.asin(Math.max(-1, Math.min(1, m13)));
88
- let ex: number, ez: number;
129
+ const ey = Math.asin(m13 < -1 ? -1 : m13 > 1 ? 1 : m13);
89
130
 
90
- if (Math.abs(m13) < 0.9999999) {
91
- ex = Math.atan2(-m23, m33);
92
- ez = Math.atan2(-m12, m11);
131
+ if (m13 > -0.9999999 && m13 < 0.9999999) {
132
+ return {
133
+ x: Math.atan2(wx - yz, 1 - (xx + yy)) * RAD_TO_DEG,
134
+ y: ey * RAD_TO_DEG,
135
+ z: Math.atan2(wz - xy, 1 - (yy + zz)) * RAD_TO_DEG,
136
+ };
93
137
  } else {
94
- ex = Math.atan2(m32, m22);
95
- ez = 0;
138
+ return {
139
+ x: Math.atan2(yz + wx, 1 - (xx + zz)) * RAD_TO_DEG,
140
+ y: ey * RAD_TO_DEG,
141
+ z: 0,
142
+ };
96
143
  }
97
-
98
- return {
99
- x: utils.radToDeg(ex),
100
- y: utils.radToDeg(ey),
101
- z: utils.radToDeg(ez),
102
- };
103
144
  }
104
145
 
105
146
  export function lookAt(
@@ -113,16 +154,82 @@ export function lookAt(
113
154
  upY = 1,
114
155
  upZ = 0
115
156
  ): { x: number; y: number; z: number; w: number } {
116
- tempVec3A[0] = eyeX;
117
- tempVec3A[1] = eyeY;
118
- tempVec3A[2] = eyeZ;
119
- tempVec3B[0] = targetX;
120
- tempVec3B[1] = targetY;
121
- tempVec3B[2] = targetZ;
122
- tempVec3C[0] = upX;
123
- tempVec3C[1] = upY;
124
- tempVec3C[2] = upZ;
125
- mat4.cameraAim(tempVec3A, tempVec3B, tempVec3C, tempMat4);
126
- quat.fromMat(tempMat4, tempQuatOut);
127
- return { x: tempQuatOut[0], y: tempQuatOut[1], z: tempQuatOut[2], w: tempQuatOut[3] };
157
+ let zx = eyeX - targetX;
158
+ let zy = eyeY - targetY;
159
+ let zz = eyeZ - targetZ;
160
+ let zLen = Math.sqrt(zx * zx + zy * zy + zz * zz);
161
+
162
+ if (zLen === 0) {
163
+ zz = 1;
164
+ } else {
165
+ zLen = 1 / zLen;
166
+ zx *= zLen;
167
+ zy *= zLen;
168
+ zz *= zLen;
169
+ }
170
+
171
+ let xx = upY * zz - upZ * zy;
172
+ let xy = upZ * zx - upX * zz;
173
+ let xz = upX * zy - upY * zx;
174
+ let xLen = Math.sqrt(xx * xx + xy * xy + xz * xz);
175
+
176
+ if (xLen === 0) {
177
+ if (upZ !== 0) {
178
+ upX += 1e-4 * upX;
179
+ upY += 1e-4 * upY;
180
+ upZ += 1e-4 * upZ;
181
+ } else if (upY !== 0) {
182
+ upX += 1e-4 * upX;
183
+ upY += 1e-4 * upY;
184
+ upZ += 1e-4 * upZ;
185
+ } else {
186
+ upX += 1e-4 * upX;
187
+ upY += 1e-4 * upY;
188
+ upZ += 1e-4 * upZ;
189
+ }
190
+ xx = upY * zz - upZ * zy;
191
+ xy = upZ * zx - upX * zz;
192
+ xz = upX * zy - upY * zx;
193
+ xLen = Math.sqrt(xx * xx + xy * xy + xz * xz);
194
+ }
195
+
196
+ xLen = 1 / xLen;
197
+ xx *= xLen;
198
+ xy *= xLen;
199
+ xz *= xLen;
200
+
201
+ const yx = zy * xz - zz * xy;
202
+ const yy = zz * xx - zx * xz;
203
+ const yz = zx * xy - zy * xx;
204
+
205
+ const trace = xx + yy + zz;
206
+ let qw: number, qx: number, qy: number, qz: number;
207
+
208
+ if (trace > 0) {
209
+ const s = 0.5 / Math.sqrt(trace + 1);
210
+ qw = 0.25 / s;
211
+ qx = (yz - zy) * s;
212
+ qy = (zx - xz) * s;
213
+ qz = (xy - yx) * s;
214
+ } else if (xx > yy && xx > zz) {
215
+ const s = 2 * Math.sqrt(1 + xx - yy - zz);
216
+ qw = (yz - zy) / s;
217
+ qx = 0.25 * s;
218
+ qy = (yx + xy) / s;
219
+ qz = (zx + xz) / s;
220
+ } else if (yy > zz) {
221
+ const s = 2 * Math.sqrt(1 + yy - xx - zz);
222
+ qw = (zx - xz) / s;
223
+ qx = (yx + xy) / s;
224
+ qy = 0.25 * s;
225
+ qz = (yz + zy) / s;
226
+ } else {
227
+ const s = 2 * Math.sqrt(1 + zz - xx - yy);
228
+ qw = (xy - yx) / s;
229
+ qx = (zx + xz) / s;
230
+ qy = (yz + zy) / s;
231
+ qz = 0.25 * s;
232
+ }
233
+
234
+ return { x: qx, y: qy, z: qz, w: qw };
128
235
  }