@es3d/es3d 1.0.0 → 1.0.2
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.
- package/LICENSE +201 -201
- package/README.md +95 -86
- package/docs/SPEC.md +426 -417
- package/package.json +1 -1
- package/scripts/es3d-cli.mjs +390 -377
- package/src/cache/geometry-store.js +392 -392
- package/src/cache/mesh-bundle.js +123 -123
- package/src/cache/sha256.js +73 -73
- package/src/format/ast.js +238 -238
- package/src/format/colors.js +93 -93
- package/src/format/compact-parser.js +171 -171
- package/src/format/compact-tokenizer.js +165 -165
- package/src/format/errors.js +247 -247
- package/src/format/json.js +55 -55
- package/src/format/limits.js +14 -14
- package/src/format/parse.js +132 -92
- package/src/format/schema.js +617 -617
- package/src/format/serializer.js +333 -333
- package/src/format/validator.js +330 -330
- package/src/format/value-error.js +12 -12
- package/src/format/value-format.js +314 -314
- package/src/format/values.js +459 -459
- package/src/format/xml-parser.js +136 -136
- package/src/format/xml-tokenizer.js +237 -237
- package/src/geometry/contour.js +86 -86
- package/src/geometry/extrude.js +175 -175
- package/src/geometry/gear.js +85 -85
- package/src/geometry/geometry-cache.js +159 -159
- package/src/geometry/lod-error.js +178 -178
- package/src/geometry/mesh.js +458 -458
- package/src/geometry/primitives.js +299 -299
- package/src/geometry/registry.js +645 -645
- package/src/geometry/revolve.js +136 -136
- package/src/geometry/sweep.js +441 -441
- package/src/index.js +47 -47
- package/src/io/compression.js +67 -67
- package/src/io/convert.js +236 -236
- package/src/io/download.js +13 -13
- package/src/io/external-scene.js +127 -127
- package/src/io/file-loader.js +28 -28
- package/src/io/gltf-pack.js +1461 -0
- package/src/io/gltf.js +630 -630
- package/src/io/mesh-import.js +104 -104
- package/src/io/obj.js +352 -352
- package/src/io/step-brep.js +439 -439
- package/src/io/step-exact.js +1149 -1149
- package/src/io/step.js +1418 -1418
- package/src/io/stl.js +193 -193
- package/src/io/svg-import.js +787 -787
- package/src/material/materials.js +154 -154
- package/src/math/mat4.js +475 -475
- package/src/math/random.js +30 -30
- package/src/math/trig.js +65 -65
- package/src/math/vec3.js +81 -81
- package/src/optimize/optimizer.js +604 -579
- package/src/path/path-flatten.js +322 -322
- package/src/path/path-parser.js +332 -332
- package/src/path/shapes.js +129 -129
- package/src/path/triangulate.js +517 -517
- package/src/pipeline.js +74 -74
- package/src/render/camera.js +168 -168
- package/src/render/frame-builder.js +362 -362
- package/src/render/geometry-pool.js +149 -149
- package/src/render/lighting.js +149 -149
- package/src/render/orbit-controls.js +237 -237
- package/src/render/renderer.js +258 -249
- package/src/render/scroll-timeline.js +104 -104
- package/src/render/shaders/glsl.js +285 -285
- package/src/render/shaders/wgsl.js +252 -252
- package/src/render/stage.js +365 -352
- package/src/render/texture-cache.js +40 -40
- package/src/render/textures.js +223 -223
- package/src/render/webgl2/webgl2-backend.js +586 -532
- package/src/render/webgpu/webgpu-backend.js +482 -480
- package/src/scene/flatten.js +754 -754
- package/src/scene/picking.js +161 -161
- package/src/scene/scene-graph.js +320 -320
- package/src/transform/transform.js +211 -211
- package/src/wasm/kernels-binary.js +3 -3
- package/src/wasm/kernels.js +385 -385
package/src/index.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
// Public API of the ES3D reference implementation.
|
|
2
|
-
//
|
|
3
|
-
// import { compile, createRenderer, Camera } from '@es3d/es3d';
|
|
4
|
-
//
|
|
5
|
-
// const result = compile(text); // parse + validate + build + flatten
|
|
6
|
-
// if (!result.ok) console.error(result
|
|
7
|
-
// const renderer = await createRenderer(canvas); // WebGPU, else WebGL2
|
|
8
|
-
// renderer.setScene(result.scene, (entry, lod) => result.cache.mesh(entry, lod));
|
|
9
|
-
// const camera = new Camera().frame(result.scene.bounds);
|
|
10
|
-
// renderer.render(camera, { width: canvas.clientWidth, height: canvas.clientHeight });
|
|
11
|
-
//
|
|
12
|
-
// const svg = await importFiles([{ name: 'logo.svg', bytes }]); // SVG, OBJ, STL, STEP, glTF → ES3D
|
|
13
|
-
// const { files } = exportFormat(svg.text, 'glb'); // ES3D → glTF, OBJ, STL, STEP
|
|
14
|
-
//
|
|
15
|
-
// The format, scene, geometry and I/O modules run in Node as well; only the
|
|
16
|
-
// renderer and controls need a browser.
|
|
17
|
-
|
|
18
|
-
// documents
|
|
19
|
-
export { parse, parseStrict, detectSyntax, formatDiagnostics } from './format/parse.js';
|
|
20
|
-
export { serialize, SERIALIZE_PRESETS } from './format/serializer.js';
|
|
21
|
-
export { Document, Element, Attr, Comment, walk, h } from './format/ast.js';
|
|
22
|
-
export { Diagnostic, ES3DError } from './format/errors.js';
|
|
23
|
-
export { ELEMENTS, elementSpec, attrSpec } from './format/schema.js';
|
|
24
|
-
|
|
25
|
-
// scene pipeline
|
|
26
|
-
export { compile, generateGeometry, GeometryCache } from './pipeline.js';
|
|
27
|
-
export { openGeometryStore, indexedDBStore, memoryStore, restoreGeometry, saveGeometry, persistGeometry, geometryKey, GEOMETRY_REVISION } from './cache/geometry-store.js';
|
|
28
|
-
export { RenderScene, updateDynamic, FLAG_MIRRORED, FLAG_NO_COLLIDE } from './scene/flatten.js';
|
|
29
|
-
export { pick, raycast } from './scene/picking.js';
|
|
30
|
-
export { applyLimits, sweepCamera, constrainCamera } from './scene/camera-constraints.js';
|
|
31
|
-
|
|
32
|
-
// rendering (browser)
|
|
33
|
-
export { createRenderer, Renderer } from './render/renderer.js';
|
|
34
|
-
export { Camera } from './render/camera.js';
|
|
35
|
-
export { OrbitControls } from './render/orbit-controls.js';
|
|
36
|
-
export { ScrollTimeline } from './render/scroll-timeline.js';
|
|
37
|
-
export { createStage, ancestorNames } from './render/stage.js';
|
|
38
|
-
|
|
39
|
-
// conversion and optimization
|
|
40
|
-
export { importFiles, exportFormat, detectKind, INPUT_KINDS, OUTPUT_FORMATS } from './io/convert.js';
|
|
41
|
-
export { svgToES3D } from './io/svg-import.js';
|
|
42
|
-
export { exportOBJ, parseOBJ, objToScene } from './io/obj.js';
|
|
43
|
-
export { exportGLB, parseGLB, glbToScene, isGLB, parseGLTF, gltfToScene } from './io/gltf.js';
|
|
44
|
-
export { exportSTL, parseSTL, stlToScene } from './io/stl.js';
|
|
45
|
-
export { exportSTEP, parseSTEP, stepToScene, isSTEP } from './io/step.js';
|
|
46
|
-
export { sceneToMeshDocument } from './io/mesh-import.js';
|
|
47
|
-
export { optimize, expandProcedural } from './optimize/optimizer.js';
|
|
1
|
+
// Public API of the ES3D reference implementation.
|
|
2
|
+
//
|
|
3
|
+
// import { compile, createRenderer, Camera, formatDiagnostics } from '@es3d/es3d';
|
|
4
|
+
//
|
|
5
|
+
// const result = compile(text); // parse + validate + build + flatten
|
|
6
|
+
// if (!result.ok) console.error(formatDiagnostics(result));
|
|
7
|
+
// const renderer = await createRenderer(canvas); // WebGPU, else WebGL2
|
|
8
|
+
// renderer.setScene(result.scene, (entry, lod) => result.cache.mesh(entry, lod));
|
|
9
|
+
// const camera = new Camera().frame(result.scene.bounds);
|
|
10
|
+
// renderer.render(camera, { width: canvas.clientWidth, height: canvas.clientHeight });
|
|
11
|
+
//
|
|
12
|
+
// const svg = await importFiles([{ name: 'logo.svg', bytes }]); // SVG, OBJ, STL, STEP, glTF → ES3D
|
|
13
|
+
// const { files } = exportFormat(svg.text, 'glb'); // ES3D → glTF, OBJ, STL, STEP
|
|
14
|
+
//
|
|
15
|
+
// The format, scene, geometry and I/O modules run in Node as well; only the
|
|
16
|
+
// renderer and controls need a browser.
|
|
17
|
+
|
|
18
|
+
// documents
|
|
19
|
+
export { parse, parseStrict, detectSyntax, formatDiagnostics } from './format/parse.js';
|
|
20
|
+
export { serialize, SERIALIZE_PRESETS } from './format/serializer.js';
|
|
21
|
+
export { Document, Element, Attr, Comment, walk, h } from './format/ast.js';
|
|
22
|
+
export { Diagnostic, ES3DError } from './format/errors.js';
|
|
23
|
+
export { ELEMENTS, elementSpec, attrSpec } from './format/schema.js';
|
|
24
|
+
|
|
25
|
+
// scene pipeline
|
|
26
|
+
export { compile, generateGeometry, GeometryCache } from './pipeline.js';
|
|
27
|
+
export { openGeometryStore, indexedDBStore, memoryStore, restoreGeometry, saveGeometry, persistGeometry, geometryKey, GEOMETRY_REVISION } from './cache/geometry-store.js';
|
|
28
|
+
export { RenderScene, updateDynamic, FLAG_MIRRORED, FLAG_NO_COLLIDE } from './scene/flatten.js';
|
|
29
|
+
export { pick, raycast } from './scene/picking.js';
|
|
30
|
+
export { applyLimits, sweepCamera, constrainCamera } from './scene/camera-constraints.js';
|
|
31
|
+
|
|
32
|
+
// rendering (browser)
|
|
33
|
+
export { createRenderer, Renderer } from './render/renderer.js';
|
|
34
|
+
export { Camera } from './render/camera.js';
|
|
35
|
+
export { OrbitControls } from './render/orbit-controls.js';
|
|
36
|
+
export { ScrollTimeline } from './render/scroll-timeline.js';
|
|
37
|
+
export { createStage, ancestorNames } from './render/stage.js';
|
|
38
|
+
|
|
39
|
+
// conversion and optimization
|
|
40
|
+
export { importFiles, exportFormat, detectKind, INPUT_KINDS, OUTPUT_FORMATS } from './io/convert.js';
|
|
41
|
+
export { svgToES3D } from './io/svg-import.js';
|
|
42
|
+
export { exportOBJ, parseOBJ, objToScene } from './io/obj.js';
|
|
43
|
+
export { exportGLB, parseGLB, glbToScene, isGLB, parseGLTF, gltfToScene } from './io/gltf.js';
|
|
44
|
+
export { exportSTL, parseSTL, stlToScene } from './io/stl.js';
|
|
45
|
+
export { exportSTEP, parseSTEP, stepToScene, isSTEP } from './io/step.js';
|
|
46
|
+
export { sceneToMeshDocument } from './io/mesh-import.js';
|
|
47
|
+
export { optimize, expandProcedural } from './optimize/optimizer.js';
|
package/src/io/compression.js
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
// Compression helpers that work in browsers (CompressionStream) and in Node
|
|
2
|
-
// (zlib, which also provides brotli). Used for file-size statistics and the
|
|
3
|
-
// benchmark, and for loading .gz files.
|
|
4
|
-
|
|
5
|
-
const isNode = typeof process !== 'undefined' && !!(process.versions && process.versions.node) && typeof window === 'undefined';
|
|
6
|
-
|
|
7
|
-
let zlibPromise = null;
|
|
8
|
-
function zlib() {
|
|
9
|
-
// Node only; the variable keeps bundlers from trying to resolve it for browsers
|
|
10
|
-
const specifier = 'node:zlib';
|
|
11
|
-
if (!zlibPromise) zlibPromise = import(/* @vite-ignore */ specifier);
|
|
12
|
-
return zlibPromise;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function toBytes(data) {
|
|
16
|
-
if (typeof data === 'string') return new TextEncoder().encode(data);
|
|
17
|
-
if (data instanceof Uint8Array) return data;
|
|
18
|
-
return new Uint8Array(data);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function streamBytes(bytes, transform) {
|
|
22
|
-
const stream = new Blob([bytes]).stream().pipeThrough(transform);
|
|
23
|
-
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** gzip (level 9 in Node, browser default otherwise). */
|
|
27
|
-
export async function gzip(data) {
|
|
28
|
-
const bytes = toBytes(data);
|
|
29
|
-
if (isNode) {
|
|
30
|
-
const z = await zlib();
|
|
31
|
-
return new Uint8Array(z.gzipSync(bytes, { level: 9 }));
|
|
32
|
-
}
|
|
33
|
-
return streamBytes(bytes, new CompressionStream('gzip'));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function gunzip(data) {
|
|
37
|
-
const bytes = toBytes(data);
|
|
38
|
-
if (isNode) {
|
|
39
|
-
const z = await zlib();
|
|
40
|
-
return new Uint8Array(z.gunzipSync(bytes));
|
|
41
|
-
}
|
|
42
|
-
return streamBytes(bytes, new DecompressionStream('gzip'));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Brotli (quality 11). Returns null where unavailable (browsers lack a brotli compressor API). */
|
|
46
|
-
export async function brotli(data) {
|
|
47
|
-
const bytes = toBytes(data);
|
|
48
|
-
if (isNode) {
|
|
49
|
-
const z = await zlib();
|
|
50
|
-
return new Uint8Array(z.brotliCompressSync(bytes, { params: { [z.constants.BROTLI_PARAM_QUALITY]: 11, [z.constants.BROTLI_PARAM_SIZE_HINT]: bytes.length } }));
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
return await streamBytes(bytes, new CompressionStream('br'));
|
|
54
|
-
} catch {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function compressedSizes(data) {
|
|
60
|
-
const bytes = toBytes(data);
|
|
61
|
-
const [g, b] = await Promise.all([gzip(bytes), brotli(bytes)]);
|
|
62
|
-
return { raw: bytes.length, gzip: g.length, brotli: b ? b.length : null };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function isGzip(bytes) {
|
|
66
|
-
return bytes.length > 2 && bytes[0] === 0x1f && bytes[1] === 0x8b;
|
|
67
|
-
}
|
|
1
|
+
// Compression helpers that work in browsers (CompressionStream) and in Node
|
|
2
|
+
// (zlib, which also provides brotli). Used for file-size statistics and the
|
|
3
|
+
// benchmark, and for loading .gz files.
|
|
4
|
+
|
|
5
|
+
const isNode = typeof process !== 'undefined' && !!(process.versions && process.versions.node) && typeof window === 'undefined';
|
|
6
|
+
|
|
7
|
+
let zlibPromise = null;
|
|
8
|
+
function zlib() {
|
|
9
|
+
// Node only; the variable keeps bundlers from trying to resolve it for browsers
|
|
10
|
+
const specifier = 'node:zlib';
|
|
11
|
+
if (!zlibPromise) zlibPromise = import(/* @vite-ignore */ specifier);
|
|
12
|
+
return zlibPromise;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function toBytes(data) {
|
|
16
|
+
if (typeof data === 'string') return new TextEncoder().encode(data);
|
|
17
|
+
if (data instanceof Uint8Array) return data;
|
|
18
|
+
return new Uint8Array(data);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function streamBytes(bytes, transform) {
|
|
22
|
+
const stream = new Blob([bytes]).stream().pipeThrough(transform);
|
|
23
|
+
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** gzip (level 9 in Node, browser default otherwise). */
|
|
27
|
+
export async function gzip(data) {
|
|
28
|
+
const bytes = toBytes(data);
|
|
29
|
+
if (isNode) {
|
|
30
|
+
const z = await zlib();
|
|
31
|
+
return new Uint8Array(z.gzipSync(bytes, { level: 9 }));
|
|
32
|
+
}
|
|
33
|
+
return streamBytes(bytes, new CompressionStream('gzip'));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function gunzip(data) {
|
|
37
|
+
const bytes = toBytes(data);
|
|
38
|
+
if (isNode) {
|
|
39
|
+
const z = await zlib();
|
|
40
|
+
return new Uint8Array(z.gunzipSync(bytes));
|
|
41
|
+
}
|
|
42
|
+
return streamBytes(bytes, new DecompressionStream('gzip'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Brotli (quality 11). Returns null where unavailable (browsers lack a brotli compressor API). */
|
|
46
|
+
export async function brotli(data) {
|
|
47
|
+
const bytes = toBytes(data);
|
|
48
|
+
if (isNode) {
|
|
49
|
+
const z = await zlib();
|
|
50
|
+
return new Uint8Array(z.brotliCompressSync(bytes, { params: { [z.constants.BROTLI_PARAM_QUALITY]: 11, [z.constants.BROTLI_PARAM_SIZE_HINT]: bytes.length } }));
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return await streamBytes(bytes, new CompressionStream('br'));
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function compressedSizes(data) {
|
|
60
|
+
const bytes = toBytes(data);
|
|
61
|
+
const [g, b] = await Promise.all([gzip(bytes), brotli(bytes)]);
|
|
62
|
+
return { raw: bytes.length, gzip: g.length, brotli: b ? b.length : null };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function isGzip(bytes) {
|
|
66
|
+
return bytes.length > 2 && bytes[0] === 0x1f && bytes[1] === 0x8b;
|
|
67
|
+
}
|