@carbonenginejs/runtime-utils 0.1.0

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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +23 -0
  3. package/README.md +56 -0
  4. package/THIRD-PARTY-NOTICES.md +38 -0
  5. package/docs/README.md +81 -0
  6. package/docs/architecture.md +101 -0
  7. package/docs/concepts/foundation-consolidation.md +86 -0
  8. package/docs/const-kb.md +92 -0
  9. package/docs/core-types/DECORATOR-TODOS.md +25 -0
  10. package/docs/core-types/README.md +203 -0
  11. package/docs/reference/api.md +70 -0
  12. package/docs/reference/classes/README.md +115 -0
  13. package/package.json +132 -0
  14. package/src/arrays.js +5 -0
  15. package/src/audio/audioFormats.js +34 -0
  16. package/src/audio/index.js +1 -0
  17. package/src/box3.js +1385 -0
  18. package/src/bytes.js +56 -0
  19. package/src/compression.js +56 -0
  20. package/src/constants/index.js +6 -0
  21. package/src/constants.js +15 -0
  22. package/src/curve.js +419 -0
  23. package/src/d3d/dxgiFormats.js +46 -0
  24. package/src/d3d/index.js +2 -0
  25. package/src/d3d/primitiveTopology.js +11 -0
  26. package/src/document/CjsCarbonDocument.js +212 -0
  27. package/src/document/CjsClassRegistry.js +373 -0
  28. package/src/document/CjsDocumentDehydrator.js +142 -0
  29. package/src/document/CjsDocumentHydrator.js +156 -0
  30. package/src/document/CjsStructRegistry.js +348 -0
  31. package/src/document/hydrationAdapter.js +129 -0
  32. package/src/document/index.js +6 -0
  33. package/src/geometry/box.js +137 -0
  34. package/src/geometry/cylinder.js +244 -0
  35. package/src/geometry/helpers/LICENSE +15 -0
  36. package/src/geometry/helpers/earcut.js +766 -0
  37. package/src/geometry/helpers/misc.js +103 -0
  38. package/src/geometry/index.js +8 -0
  39. package/src/geometry/json.js +165 -0
  40. package/src/geometry/lathe.js +172 -0
  41. package/src/geometry/octahedron.js +0 -0
  42. package/src/geometry/plane.js +81 -0
  43. package/src/geometry/shape.js +95 -0
  44. package/src/geometry/sphere.js +123 -0
  45. package/src/geometry/torus.js +96 -0
  46. package/src/graphics/colorSpaces.js +22 -0
  47. package/src/graphics/index.js +4 -0
  48. package/src/graphics/pixelFormats.js +158 -0
  49. package/src/graphics/textureDimensions.js +22 -0
  50. package/src/graphics/trinityEnums.js +87 -0
  51. package/src/index.js +58 -0
  52. package/src/is.js +524 -0
  53. package/src/json.js +23 -0
  54. package/src/lifecycle/CjsLifecycleState.js +77 -0
  55. package/src/lifecycle/index.js +1 -0
  56. package/src/lne3.js +497 -0
  57. package/src/lookup.js +48 -0
  58. package/src/mat3.js +131 -0
  59. package/src/mat4.js +699 -0
  60. package/src/math/index.js +25 -0
  61. package/src/math/scalar.js +63 -0
  62. package/src/media/index.js +1 -0
  63. package/src/media/mediaTypes.js +50 -0
  64. package/src/mesh.js +394 -0
  65. package/src/model/CjsEventEmitter.js +333 -0
  66. package/src/model/CjsModel.js +1544 -0
  67. package/src/model/CjsModelState.js +72 -0
  68. package/src/model/index.js +4 -0
  69. package/src/model/sourceRecordUtils.js +54 -0
  70. package/src/noise.js +310 -0
  71. package/src/num.js +827 -0
  72. package/src/path.js +21 -0
  73. package/src/pln.js +762 -0
  74. package/src/pool.js +160 -0
  75. package/src/quat.js +144 -0
  76. package/src/ray3.js +1085 -0
  77. package/src/renderContext/formats.js +145 -0
  78. package/src/renderContext/index.js +5 -0
  79. package/src/renderContext/presentation.js +125 -0
  80. package/src/renderContext/resources.js +27 -0
  81. package/src/renderContext/upscaling.js +22 -0
  82. package/src/renderContext/window.js +20 -0
  83. package/src/runtime/CjsRuntimeState.js +50 -0
  84. package/src/schema/CjsSchema.js +1009 -0
  85. package/src/schema/index.js +17 -0
  86. package/src/shader/index.js +1 -0
  87. package/src/shader/shaderStages.js +37 -0
  88. package/src/sph3.js +754 -0
  89. package/src/tangent.js +288 -0
  90. package/src/text.js +40 -0
  91. package/src/tri3.js +650 -0
  92. package/src/types/carbonTypes.js +635 -0
  93. package/src/types/index.js +2 -0
  94. package/src/utils.js +58 -0
  95. package/src/validation.js +46 -0
  96. package/src/vec2.js +229 -0
  97. package/src/vec3.js +1172 -0
  98. package/src/vec4.js +347 -0
  99. package/src/vertex.js +108 -0
  100. package/src/webgpu/index.js +1 -0
  101. package/src/webgpu/textureFormats.js +121 -0
package/src/tangent.js ADDED
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Packed tangent-frame helpers for CarbonEngineJS/GR2-style mesh data.
3
+ *
4
+ * The packed-frame constants and decode/encode behavior are based on observed
5
+ * Fenris Creations (CCP Games) shader behavior for EVE/Carbon packed tangent
6
+ * frames. No shader source is included here.
7
+ */
8
+
9
+ import {
10
+ generateBiNormals,
11
+ generateNormals,
12
+ generateTangentFrames,
13
+ generateTangents
14
+ } from "./mesh.js";
15
+ import {
16
+ EPSILON,
17
+ clamp
18
+ } from "./num.js";
19
+ import {
20
+ cross,
21
+ dot,
22
+ length as vec3Length,
23
+ normalize
24
+ } from "gl-matrix/esm/vec3.js";
25
+
26
+ /** Full-turn float32 constant used by the CCP tangent-frame shader. */
27
+ export const TANGENT_TAU = 6.28318548;
28
+
29
+ /** Half-turn float32 constant used by the CCP tangent-frame shader. */
30
+ export const TANGENT_PI = 3.14159274;
31
+
32
+ const
33
+ TAU = TANGENT_TAU,
34
+ PI = TANGENT_PI,
35
+ POLAR_EPSILON = 1e-6;
36
+
37
+ /**
38
+ * Packed UNorm sentinel used for vertices with no authored tangent frame.
39
+ *
40
+ * @type {number[]}
41
+ */
42
+ export const NULL_TANGENT_UNORM = Object.freeze([ 0, 1, 0, 1 ]);
43
+
44
+ /**
45
+ * Test whether a packed tangent payload is the null-frame sentinel.
46
+ *
47
+ * @param {ArrayLike<number>} u Four UNorm values.
48
+ * @returns {boolean} Whether the payload marks a missing authored frame.
49
+ */
50
+ export function isNullTangent(u)
51
+ {
52
+ const
53
+ e1 = u[1],
54
+ e3 = u[3];
55
+
56
+ return (e1 <= 1e-3 || e1 >= 1 - 1e-3) && (e3 <= 1e-3 || e3 >= 1 - 1e-3);
57
+ }
58
+
59
+ const
60
+ scratchT = new Float64Array(3),
61
+ scratchB = new Float64Array(3),
62
+ scratchN = new Float64Array(3);
63
+
64
+ function decodeTangentFrameInto(u0, u1, u2, u3, outT, outB, outN)
65
+ {
66
+ const
67
+ a0 = u0 * TAU - PI,
68
+ a1 = u1 * TAU - PI,
69
+ a2 = u2 * TAU - PI,
70
+ a3 = u3 * TAU - PI,
71
+ s1 = Math.abs(Math.sin(a1)),
72
+ s3 = Math.abs(Math.sin(a3));
73
+
74
+ outT[0] = s1 * Math.cos(a0);
75
+ outT[1] = s1 * Math.sin(a0);
76
+ outT[2] = Math.cos(a1);
77
+
78
+ outB[0] = s3 * Math.cos(a2);
79
+ outB[1] = s3 * Math.sin(a2);
80
+ outB[2] = Math.cos(a3);
81
+
82
+ const sign = (a1 > 0 && a3 > 0) ? 1 : -1;
83
+ outN[0] = (outT[1] * outB[2] - outT[2] * outB[1]) * sign;
84
+ outN[1] = (outT[2] * outB[0] - outT[0] * outB[2]) * sign;
85
+ outN[2] = (outT[0] * outB[1] - outT[1] * outB[0]) * sign;
86
+
87
+ return s1 < 1e-6 && s3 < 1e-6;
88
+ }
89
+
90
+ /**
91
+ * Decode a packed tangent frame.
92
+ *
93
+ * @param {ArrayLike<number>} u Four UNorm values in `[0, 1]`.
94
+ * @returns {{T: number[], B: number[], N: number[], null: boolean}} Decoded basis.
95
+ */
96
+ export function decodeTangentFrame(u)
97
+ {
98
+ const isNull = decodeTangentFrameInto(u[0], u[1], u[2], u[3], scratchT, scratchB, scratchN);
99
+ return { T: Array.from(scratchT), B: Array.from(scratchB), N: Array.from(scratchN), null: isNull };
100
+ }
101
+
102
+ /**
103
+ * Encode a tangent frame back to four UNorm angles.
104
+ *
105
+ * @param {ArrayLike<number>} T Unit tangent.
106
+ * @param {ArrayLike<number>} B Unit binormal.
107
+ * @param {ArrayLike<number>} [N] Unit normal; only handedness is used.
108
+ * @returns {number[]} Four UNorm values in `[0, 1]`.
109
+ */
110
+ export function encodeTangentFrame(T, B, N)
111
+ {
112
+ let a0 = Math.atan2(T[1], T[0]),
113
+ a1 = Math.acos(clamp(T[2], -1, 1));
114
+
115
+ const a2 = Math.atan2(B[1], B[0]);
116
+ let a3 = Math.acos(clamp(B[2], -1, 1));
117
+
118
+ const negativeHandedness = N && dot(N, cross([ 0, 0, 0 ], T, B)) < 0;
119
+ if (negativeHandedness)
120
+ {
121
+ a1 = a1 === 0 ? -POLAR_EPSILON : -a1;
122
+ }
123
+ else
124
+ {
125
+ if (a1 === 0) a1 = POLAR_EPSILON;
126
+ if (a3 === 0) a3 = POLAR_EPSILON;
127
+ }
128
+
129
+ const enc = angle => clamp((angle + PI) / TAU, 0, 1);
130
+ return [ enc(a0), enc(a1), enc(a2), enc(a3) ];
131
+ }
132
+
133
+ function vertexCount(mesh)
134
+ {
135
+ const p = mesh.vertex && mesh.vertex.position;
136
+ return p ? (p.length / 3) | 0 : 0;
137
+ }
138
+
139
+ /**
140
+ * Is this shared JSON mesh's tangent frame packed?
141
+ *
142
+ * @param {object} mesh Shared JSON mesh.
143
+ * @returns {boolean} Whether the mesh has packed tangent frames.
144
+ */
145
+ export function isPacked(mesh)
146
+ {
147
+ const v = mesh.vertex;
148
+ if (!v || !v.tangent || !v.tangent.length) return false;
149
+
150
+ const n = vertexCount(mesh);
151
+ if (!n) return false;
152
+
153
+ const
154
+ comps = v.tangent.length / n,
155
+ empty = value => !value || value.length === 0;
156
+
157
+ return comps === 4 && empty(v.normal) && empty(v.binormal);
158
+ }
159
+
160
+ /**
161
+ * Unpack a packed shared JSON mesh in place.
162
+ *
163
+ * @param {object} mesh Shared JSON mesh to mutate.
164
+ * @returns {boolean} Whether unpacking happened.
165
+ */
166
+ export function unpackMeshTangents(mesh)
167
+ {
168
+ if (!isPacked(mesh)) return false;
169
+
170
+ const
171
+ v = mesh.vertex,
172
+ n = vertexCount(mesh),
173
+ src = v.tangent,
174
+ normal = new Array(n * 3),
175
+ tangent = new Array(n * 3),
176
+ binormal = new Array(n * 3);
177
+
178
+ for (let i = 0; i < n; i++)
179
+ {
180
+ const
181
+ s = i * 4,
182
+ o = i * 3,
183
+ isNull = decodeTangentFrameInto(src[s], src[s + 1], src[s + 2], src[s + 3], scratchT, scratchB, scratchN);
184
+
185
+ if (isNull)
186
+ {
187
+ normal[o] = normal[o + 1] = normal[o + 2] = 0;
188
+ tangent[o] = tangent[o + 1] = tangent[o + 2] = 0;
189
+ binormal[o] = binormal[o + 1] = binormal[o + 2] = 0;
190
+ }
191
+ else
192
+ {
193
+ normal[o] = scratchN[0];
194
+ normal[o + 1] = scratchN[1];
195
+ normal[o + 2] = scratchN[2];
196
+ tangent[o] = scratchT[0];
197
+ tangent[o + 1] = scratchT[1];
198
+ tangent[o + 2] = scratchT[2];
199
+ binormal[o] = scratchB[0];
200
+ binormal[o + 1] = scratchB[1];
201
+ binormal[o + 2] = scratchB[2];
202
+ }
203
+ }
204
+
205
+ v.normal = normal;
206
+ v.tangent = tangent;
207
+ v.binormal = binormal;
208
+ return true;
209
+ }
210
+
211
+ /**
212
+ * Pack explicit tangent frames into GR2-style four-component tangent data.
213
+ *
214
+ * @param {ArrayLike<number>} normals Flat xyz normals.
215
+ * @param {ArrayLike<number>} tangents Flat xyz tangents.
216
+ * @param {ArrayLike<number>} binormals Flat xyz binormals.
217
+ * @returns {number[]} Flat xyzw packed tangent-frame values.
218
+ */
219
+ export function packTangentFrames(normals, tangents, binormals)
220
+ {
221
+ if (normals.length !== tangents.length ||
222
+ normals.length !== binormals.length ||
223
+ normals.length % 3 !== 0)
224
+ {
225
+ throw new Error("packTangentFrames requires matching complete xyz channels");
226
+ }
227
+
228
+ const packed = new Array((normals.length / 3) * 4);
229
+ for (let i = 0, o = 0; i < normals.length; i += 3, o += 4)
230
+ {
231
+ const components = [
232
+ normals[i], normals[i + 1], normals[i + 2],
233
+ tangents[i], tangents[i + 1], tangents[i + 2],
234
+ binormals[i], binormals[i + 1], binormals[i + 2]
235
+ ];
236
+ if (!components.every(Number.isFinite))
237
+ {
238
+ throw new Error(`packTangentFrames received non-finite data at vertex ${i / 3}`);
239
+ }
240
+
241
+ const
242
+ normal = normalize([ 0, 0, 0 ], components.slice(0, 3)),
243
+ tangent = normalize([ 0, 0, 0 ], components.slice(3, 6)),
244
+ binormal = normalize([ 0, 0, 0 ], components.slice(6, 9)),
245
+ frameNormalLength = vec3Length(cross([ 0, 0, 0 ], tangent, binormal));
246
+
247
+ if (vec3Length(normal) <= EPSILON ||
248
+ vec3Length(tangent) <= EPSILON ||
249
+ vec3Length(binormal) <= EPSILON ||
250
+ frameNormalLength <= EPSILON)
251
+ {
252
+ packed[o] = NULL_TANGENT_UNORM[0];
253
+ packed[o + 1] = NULL_TANGENT_UNORM[1];
254
+ packed[o + 2] = NULL_TANGENT_UNORM[2];
255
+ packed[o + 3] = NULL_TANGENT_UNORM[3];
256
+ continue;
257
+ }
258
+
259
+ const encoded = encodeTangentFrame(tangent, binormal, normal);
260
+ packed[o] = encoded[0];
261
+ packed[o + 1] = encoded[1];
262
+ packed[o + 2] = encoded[2];
263
+ packed[o + 3] = encoded[3];
264
+ }
265
+
266
+ return packed;
267
+ }
268
+
269
+ export const tangent = Object.freeze({
270
+ TAU: TANGENT_TAU,
271
+ PI: TANGENT_PI,
272
+ NULL_TANGENT_UNORM,
273
+ isNull: isNullTangent,
274
+ isNullTangent,
275
+ decode: decodeTangentFrame,
276
+ decodeTangentFrame,
277
+ pack: encodeTangentFrame,
278
+ encode: encodeTangentFrame,
279
+ encodeTangentFrame,
280
+ packTangentFrames,
281
+ unpack: unpackMeshTangents,
282
+ unpackMeshTangents,
283
+ isPacked,
284
+ generateNormals,
285
+ generateTangents,
286
+ generateTangentFrames,
287
+ generateBiNormals
288
+ });
package/src/text.js ADDED
@@ -0,0 +1,40 @@
1
+ import { asUint8Array } from "./bytes.js";
2
+
3
+ /** Encodes a value as UTF-8 without importing a platform-specific module. */
4
+ export function encodeUtf8(value)
5
+ {
6
+ const TextEncoderClass = globalThis.TextEncoder;
7
+
8
+ if (typeof TextEncoderClass !== "function")
9
+ {
10
+ throw unsupportedTextCodec("TextEncoder");
11
+ }
12
+
13
+ return new TextEncoderClass().encode(String(value));
14
+ }
15
+
16
+ /** Decodes supported byte input as UTF-8. */
17
+ export function decodeUtf8(value, options = {})
18
+ {
19
+ const TextDecoderClass = globalThis.TextDecoder;
20
+
21
+ if (typeof TextDecoderClass !== "function")
22
+ {
23
+ throw unsupportedTextCodec("TextDecoder");
24
+ }
25
+
26
+ const decoder = new TextDecoderClass("utf-8", {
27
+ fatal: Boolean(options.fatal),
28
+ ignoreBOM: Boolean(options.ignoreBOM)
29
+ });
30
+
31
+ return decoder.decode(asUint8Array(value, "UTF-8 input"));
32
+ }
33
+
34
+ function unsupportedTextCodec(name)
35
+ {
36
+ const error = new Error(`${name} is unavailable in this environment.`);
37
+
38
+ error.code = "CJS_TEXT_CODEC_UNSUPPORTED";
39
+ return error;
40
+ }