@multiplekex/shallot 0.1.1 → 0.1.3

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 +5 -14
  2. package/src/core/math.ts +135 -55
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplekex/shallot",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -12,32 +12,23 @@
12
12
  "src",
13
13
  "rust/transforms/pkg"
14
14
  ],
15
- "workspaces": [
16
- "examples/*"
17
- ],
18
15
  "scripts": {
19
16
  "build:wasm": "./rust/transforms/build.sh",
20
- "check": "tsc",
21
- "test": "bun test",
22
- "format": "prettier --write .",
23
- "format:check": "prettier --check ."
17
+ "test": "bun test"
24
18
  },
25
19
  "dependencies": {
26
20
  "@mapbox/tiny-sdf": "^2.0.7",
27
21
  "bitecs": "^0.4.0",
28
- "fast-xml-parser": "^5.3.3",
29
- "wgpu-matrix": "^3.4.0"
22
+ "fast-xml-parser": "^5.3.3"
30
23
  },
31
24
  "devDependencies": {
32
25
  "@napi-rs/canvas": "^0.1.88",
33
- "@tauri-apps/plugin-fs": "^2.4.4",
34
26
  "@types/bun": "latest",
35
27
  "@types/three": "^0.182.0",
36
- "mitata": "^1.0.34",
37
- "prettier": "^3.7.4",
38
28
  "three": "^0.182.0",
39
29
  "troika-three-text": "^0.52.4",
40
- "webgpu": "^0.3.8"
30
+ "webgpu": "^0.3.8",
31
+ "wgpu-matrix": "^3.4.0"
41
32
  },
42
33
  "peerDependencies": {
43
34
  "typescript": "^5"
package/src/core/math.ts CHANGED
@@ -1,15 +1,11 @@
1
- import { quat, utils, mat4 } from "wgpu-matrix";
1
+ const DEG_TO_RAD = Math.PI / 180;
2
+ const RAD_TO_DEG = 180 / Math.PI;
2
3
 
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);
4
+ const _quat = { x: 0, y: 0, z: 0, w: 1 };
5
+ const _euler = { x: 0, y: 0, z: 0 };
10
6
 
11
7
  export function clamp(value: number, min: number, max: number): number {
12
- return Math.max(min, Math.min(max, value));
8
+ return value < min ? min : value > max ? max : value;
13
9
  }
14
10
 
15
11
  export function lerp(a: number, b: number, t: number): number {
@@ -27,25 +23,65 @@ export function slerp(
27
23
  toW: number,
28
24
  t: number
29
25
  ): { 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] };
26
+ let dot = fromX * toX + fromY * toY + fromZ * toZ + fromW * toW;
27
+
28
+ if (dot < 0) {
29
+ dot = -dot;
30
+ toX = -toX;
31
+ toY = -toY;
32
+ toZ = -toZ;
33
+ toW = -toW;
34
+ }
35
+
36
+ let s0: number, s1: number;
37
+ if (dot > 0.9995) {
38
+ s0 = 1 - t;
39
+ s1 = t;
40
+ } else {
41
+ const theta0 = Math.acos(dot);
42
+ const sinTheta0 = Math.sqrt(1 - dot * dot);
43
+ const theta = theta0 * t;
44
+ const sinTheta = Math.sin(theta);
45
+ s0 = Math.cos(theta) - (dot * sinTheta) / sinTheta0;
46
+ s1 = sinTheta / sinTheta0;
47
+ }
48
+
49
+ _quat.x = s0 * fromX + s1 * toX;
50
+ _quat.y = s0 * fromY + s1 * toY;
51
+ _quat.z = s0 * fromZ + s1 * toZ;
52
+ _quat.w = s0 * fromW + s1 * toW;
53
+ return _quat;
34
54
  }
35
55
 
36
56
  export function rotateQuaternion(
37
- quatX: number,
38
- quatY: number,
39
- quatZ: number,
40
- quatW: number,
57
+ qx: number,
58
+ qy: number,
59
+ qz: number,
60
+ qw: number,
41
61
  dx: number,
42
62
  dy: number,
43
63
  dz: number
44
64
  ): { 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] };
65
+ const hx = dx * DEG_TO_RAD * 0.5;
66
+ const hy = dy * DEG_TO_RAD * 0.5;
67
+ const hz = dz * DEG_TO_RAD * 0.5;
68
+ const cx = Math.cos(hx),
69
+ sx = Math.sin(hx);
70
+ const cy = Math.cos(hy),
71
+ sy = Math.sin(hy);
72
+ const cz = Math.cos(hz),
73
+ sz = Math.sin(hz);
74
+
75
+ const bx = sx * cy * cz + cx * sy * sz;
76
+ const by = cx * sy * cz - sx * cy * sz;
77
+ const bz = cx * cy * sz + sx * sy * cz;
78
+ const bw = cx * cy * cz - sx * sy * sz;
79
+
80
+ _quat.x = qw * bx + qx * bw + qy * bz - qz * by;
81
+ _quat.y = qw * by - qx * bz + qy * bw + qz * bx;
82
+ _quat.z = qw * bz + qx * by - qy * bx + qz * bw;
83
+ _quat.w = qw * bw - qx * bx - qy * by - qz * bz;
84
+ return _quat;
49
85
  }
50
86
 
51
87
  export function eulerToQuaternion(
@@ -53,8 +89,21 @@ export function eulerToQuaternion(
53
89
  y: number,
54
90
  z: number
55
91
  ): { 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] };
92
+ const hx = x * DEG_TO_RAD * 0.5;
93
+ const hy = y * DEG_TO_RAD * 0.5;
94
+ const hz = z * DEG_TO_RAD * 0.5;
95
+ const cx = Math.cos(hx),
96
+ sx = Math.sin(hx);
97
+ const cy = Math.cos(hy),
98
+ sy = Math.sin(hy);
99
+ const cz = Math.cos(hz),
100
+ sz = Math.sin(hz);
101
+
102
+ _quat.x = sx * cy * cz + cx * sy * sz;
103
+ _quat.y = cx * sy * cz - sx * cy * sz;
104
+ _quat.z = cx * cy * sz + sx * sy * cz;
105
+ _quat.w = cx * cy * cz - sx * sy * sz;
106
+ return _quat;
58
107
  }
59
108
 
60
109
  export function quaternionToEuler(
@@ -76,30 +125,18 @@ 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
+ _euler.x = Math.atan2(wx - yz, 1 - (xx + yy)) * RAD_TO_DEG;
133
+ _euler.z = Math.atan2(wz - xy, 1 - (yy + zz)) * RAD_TO_DEG;
93
134
  } else {
94
- ex = Math.atan2(m32, m22);
95
- ez = 0;
135
+ _euler.x = Math.atan2(yz + wx, 1 - (xx + zz)) * RAD_TO_DEG;
136
+ _euler.z = 0;
96
137
  }
97
-
98
- return {
99
- x: utils.radToDeg(ex),
100
- y: utils.radToDeg(ey),
101
- z: utils.radToDeg(ez),
102
- };
138
+ _euler.y = ey * RAD_TO_DEG;
139
+ return _euler;
103
140
  }
104
141
 
105
142
  export function lookAt(
@@ -113,16 +150,59 @@ export function lookAt(
113
150
  upY = 1,
114
151
  upZ = 0
115
152
  ): { 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] };
153
+ let fwdX = targetX - eyeX;
154
+ let fwdY = targetY - eyeY;
155
+ let fwdZ = targetZ - eyeZ;
156
+ const fwdLenSq = fwdX * fwdX + fwdY * fwdY + fwdZ * fwdZ;
157
+ if (fwdLenSq > 0) {
158
+ const invLen = 1 / Math.sqrt(fwdLenSq);
159
+ fwdX *= invLen;
160
+ fwdY *= invLen;
161
+ fwdZ *= invLen;
162
+ }
163
+
164
+ let rightX = upY * fwdZ - upZ * fwdY;
165
+ let rightY = upZ * fwdX - upX * fwdZ;
166
+ let rightZ = upX * fwdY - upY * fwdX;
167
+ const rightLenSq = rightX * rightX + rightY * rightY + rightZ * rightZ;
168
+ if (rightLenSq > 0) {
169
+ const invLen = 1 / Math.sqrt(rightLenSq);
170
+ rightX *= invLen;
171
+ rightY *= invLen;
172
+ rightZ *= invLen;
173
+ }
174
+
175
+ const newUpX = fwdY * rightZ - fwdZ * rightY;
176
+ const newUpY = fwdZ * rightX - fwdX * rightZ;
177
+ const newUpZ = fwdX * rightY - fwdY * rightX;
178
+
179
+ const trace = rightX + newUpY + fwdZ;
180
+
181
+ if (trace > 0) {
182
+ const s = 0.5 / Math.sqrt(trace + 1);
183
+ _quat.w = 0.25 / s;
184
+ _quat.x = (newUpZ - fwdY) * s;
185
+ _quat.y = (fwdX - rightZ) * s;
186
+ _quat.z = (rightY - newUpX) * s;
187
+ } else if (rightX > newUpY && rightX > fwdZ) {
188
+ const s = 2 * Math.sqrt(1 + rightX - newUpY - fwdZ);
189
+ _quat.w = (newUpZ - fwdY) / s;
190
+ _quat.x = 0.25 * s;
191
+ _quat.y = (newUpX + rightY) / s;
192
+ _quat.z = (fwdX + rightZ) / s;
193
+ } else if (newUpY > fwdZ) {
194
+ const s = 2 * Math.sqrt(1 + newUpY - rightX - fwdZ);
195
+ _quat.w = (fwdX - rightZ) / s;
196
+ _quat.x = (newUpX + rightY) / s;
197
+ _quat.y = 0.25 * s;
198
+ _quat.z = (fwdY + newUpZ) / s;
199
+ } else {
200
+ const s = 2 * Math.sqrt(1 + fwdZ - rightX - newUpY);
201
+ _quat.w = (rightY - newUpX) / s;
202
+ _quat.x = (fwdX + rightZ) / s;
203
+ _quat.y = (fwdY + newUpZ) / s;
204
+ _quat.z = 0.25 * s;
205
+ }
206
+
207
+ return _quat;
128
208
  }