@ifc-lite/wasm 1.19.2 → 2.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.
- package/README.md +36 -71
- package/package.json +1 -1
- package/pkg/ifc-lite.d.ts +22 -769
- package/pkg/ifc-lite.js +110 -1877
- package/pkg/ifc-lite_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ifc-lite/wasm
|
|
2
2
|
|
|
3
|
-
Pre-built WebAssembly bindings for the IFClite Rust core
|
|
3
|
+
Pre-built WebAssembly bindings for the IFClite Rust core, covering STEP parsing and geometry tessellation (including the Manifold CSG kernel).
|
|
4
4
|
|
|
5
5
|
> **You probably don't need to use this package directly.** It's the WASM binary plus generated JS/TypeScript bindings that `@ifc-lite/parser`, `@ifc-lite/geometry`, and `@ifc-lite/renderer` consume internally. Reach for it when you want raw access to the Rust core without the higher-level wrappers.
|
|
6
6
|
|
|
@@ -12,7 +12,9 @@ npm install @ifc-lite/wasm
|
|
|
12
12
|
|
|
13
13
|
## Direct WASM use
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
The text-based parse methods (`parse`, `parseStreaming`) take the raw IFC text
|
|
16
|
+
(a `string`) — decode the buffer first. The geometry methods (`buildPrePassOnce`,
|
|
17
|
+
`processGeometryBatch`, see below) instead take the raw `Uint8Array` bytes.
|
|
16
18
|
|
|
17
19
|
```typescript
|
|
18
20
|
import init, { IfcAPI } from '@ifc-lite/wasm';
|
|
@@ -27,94 +29,57 @@ const content = new TextDecoder().decode(buffer);
|
|
|
27
29
|
const result = await api.parse(content);
|
|
28
30
|
console.log(`Entities: ${result.entityCount}`);
|
|
29
31
|
|
|
30
|
-
// Tessellated meshes — each entry has expressId, positions, indices, normals, color
|
|
31
|
-
const meshes = api.parseMeshes(content);
|
|
32
|
-
console.log(`${meshes.length} meshes`);
|
|
33
|
-
for (let i = 0; i < meshes.length; i++) {
|
|
34
|
-
const mesh = meshes.get(i);
|
|
35
|
-
console.log(mesh.ifcType, mesh.expressId, mesh.vertexCount, 'vertices');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
meshes.free(); // free the Rust-side mesh buffer
|
|
39
32
|
api.free(); // free the API instance
|
|
40
33
|
```
|
|
41
34
|
|
|
42
|
-
##
|
|
35
|
+
## Meshes (pre-pass + job batches)
|
|
43
36
|
|
|
44
|
-
|
|
37
|
+
Geometry runs as a single pre-pass (one scan that produces a flat job list
|
|
38
|
+
plus unit scale, RTC offset, void/style indices) followed by
|
|
39
|
+
`processGeometryBatch` calls over slices of that job list. Pass the IFC
|
|
40
|
+
**bytes** (`Uint8Array`) to these methods:
|
|
45
41
|
|
|
46
42
|
```typescript
|
|
47
43
|
import init, { IfcAPI } from '@ifc-lite/wasm';
|
|
48
44
|
|
|
49
45
|
await init();
|
|
50
46
|
const api = new IfcAPI();
|
|
47
|
+
const bytes = new Uint8Array(await fetch('model.ifc').then(r => r.arrayBuffer()));
|
|
48
|
+
|
|
49
|
+
const pre = api.buildPrePassOnce(bytes);
|
|
50
|
+
// Large-coordinate models: pre.needsShift / pre.rtcOffset give the RTC origin.
|
|
51
|
+
for (let start = 0; start < pre.totalJobs; start += 100) {
|
|
52
|
+
const end = Math.min(start + 100, pre.totalJobs);
|
|
53
|
+
const jobs = pre.jobs.slice(start * 3, end * 3);
|
|
54
|
+
const collection = api.processGeometryBatch(
|
|
55
|
+
bytes, jobs, pre.unitScale,
|
|
56
|
+
pre.rtcOffset?.[0] ?? 0, pre.rtcOffset?.[1] ?? 0, pre.rtcOffset?.[2] ?? 0,
|
|
57
|
+
pre.needsShift,
|
|
58
|
+
pre.voidKeys, pre.voidCounts, pre.voidValues,
|
|
59
|
+
pre.styleIds, pre.styleColors,
|
|
60
|
+
);
|
|
61
|
+
for (let i = 0; i < collection.length; i++) {
|
|
62
|
+
const mesh = collection.get(i);
|
|
63
|
+
scene.add(toThreeMesh(mesh)); // mesh.expressId, .ifcType, .positions, .normals, .indices, .color
|
|
64
|
+
mesh.free();
|
|
65
|
+
}
|
|
66
|
+
collection.free();
|
|
67
|
+
}
|
|
51
68
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
onRtcOffset: ({ x, y, z, hasRtc }) => {
|
|
55
|
-
if (hasRtc) viewer.setWorldOffset(x, y, z);
|
|
56
|
-
},
|
|
57
|
-
onBatch: (meshes, progress) => {
|
|
58
|
-
for (const mesh of meshes) scene.add(toThreeMesh(mesh));
|
|
59
|
-
console.log(`${progress.percent}%`);
|
|
60
|
-
},
|
|
61
|
-
onComplete: ({ totalMeshes }) => console.log(`Done — ${totalMeshes} meshes`),
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Zero-copy GPU upload
|
|
66
|
-
|
|
67
|
-
`parseToGpuGeometry` returns interleaved (position + normal) vertex data with pointers into WASM linear memory, ready for direct `GPUBuffer` upload:
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import init, { IfcAPI } from '@ifc-lite/wasm';
|
|
71
|
-
|
|
72
|
-
await init();
|
|
73
|
-
const api = new IfcAPI();
|
|
74
|
-
const gpuGeom = api.parseToGpuGeometry(content);
|
|
75
|
-
const memory = api.getMemory();
|
|
76
|
-
|
|
77
|
-
// Direct views into WASM memory — no intermediate copy
|
|
78
|
-
const vertexView = new Float32Array(memory.buffer, gpuGeom.vertexDataPtr, gpuGeom.vertexDataLen);
|
|
79
|
-
const indexView = new Uint32Array(memory.buffer, gpuGeom.indicesPtr, gpuGeom.indicesLen);
|
|
80
|
-
|
|
81
|
-
device.queue.writeBuffer(gpuVertexBuffer, 0, vertexView);
|
|
82
|
-
device.queue.writeBuffer(gpuIndexBuffer, 0, indexView);
|
|
83
|
-
|
|
84
|
-
// IMPORTANT: views are only valid until the next WASM allocation. Free immediately after upload.
|
|
85
|
-
gpuGeom.free();
|
|
69
|
+
api.clearPrePassCache();
|
|
70
|
+
api.free(); // release the API instance when done
|
|
86
71
|
```
|
|
87
72
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
import init, { IfcAPI } from '@ifc-lite/wasm';
|
|
94
|
-
|
|
95
|
-
await init();
|
|
96
|
-
const api = new IfcAPI();
|
|
97
|
-
const georef = api.getGeoReference(content);
|
|
98
|
-
|
|
99
|
-
if (georef) {
|
|
100
|
-
console.log(`CRS: ${georef.crsName}`);
|
|
101
|
-
const [e, n, h] = georef.localToMap(10, 20, 5);
|
|
102
|
-
console.log(`Local (10,20,5) → Map (${e}, ${n}, ${h})`);
|
|
103
|
-
georef.free();
|
|
104
|
-
}
|
|
105
|
-
```
|
|
73
|
+
> Most consumers should use [`@ifc-lite/geometry`](../geometry/README.md)'s
|
|
74
|
+
> `GeometryProcessor` instead — it wraps this pre-pass/job-batch flow with a
|
|
75
|
+
> Web-Worker pool, RTC coordinate handling, and progressive streaming.
|
|
106
76
|
|
|
107
77
|
## Exports
|
|
108
78
|
|
|
109
79
|
| Class | Purpose |
|
|
110
80
|
|---|---|
|
|
111
|
-
| `IfcAPI` | Top-level
|
|
81
|
+
| `IfcAPI` | Top-level entry point — `parse`, `parseStreaming`, `buildPrePassOnce` / `buildPrePassFast` / `buildPrePassStreaming`, `processGeometryBatch`, `scanEntitiesFast` / `scanEntitiesFastBytes` / `scanGeometryEntitiesFast`, `extractProfiles`, `parseSymbolicRepresentations` |
|
|
112
82
|
| `MeshCollection`, `MeshDataJs` | Tessellated geometry output |
|
|
113
|
-
| `MeshCollectionWithRtc`, `RtcOffsetJs` | Mesh collection with relative-to-centre offset for large-coordinate models |
|
|
114
|
-
| `InstancedMeshCollection`, `InstancedGeometry`, `InstanceData` | Instanced geometry path (deduplicated meshes + per-instance transforms) |
|
|
115
|
-
| `ZeroCopyMesh`, `GpuGeometry`, `GpuMeshMetadata` | Zero-copy GPU upload handles |
|
|
116
|
-
| `GpuInstancedGeometry`, `GpuInstancedGeometryCollection`, `GpuInstancedGeometryRef` | Zero-copy instanced path |
|
|
117
|
-
| `GeoReferenceJs` | Georeferencing transform |
|
|
118
83
|
| `ProfileCollection`, `ProfileEntryJs` | Cross-section profile data (extruded-area solids) |
|
|
119
84
|
| `SymbolicRepresentationCollection`, `SymbolicCircle`, `SymbolicPolyline` | 2D symbolic representations (for plan / annotation views) |
|
|
120
85
|
|