streamkit-pointcloud 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +345 -0
- package/dist/core/validators.d.ts +44 -0
- package/dist/core/validators.d.ts.map +1 -0
- package/dist/core/validators.js +115 -0
- package/dist/core/validators.js.map +1 -0
- package/dist/draco/decoder.d.ts +31 -0
- package/dist/draco/decoder.d.ts.map +1 -0
- package/dist/draco/decoder.js +204 -0
- package/dist/draco/decoder.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/three/pointCloudLayer.d.ts +43 -0
- package/dist/three/pointCloudLayer.d.ts.map +1 -0
- package/dist/three/pointCloudLayer.js +494 -0
- package/dist/three/pointCloudLayer.js.map +1 -0
- package/dist/three/three-types.d.ts +39 -0
- package/dist/three/three-types.d.ts.map +1 -0
- package/dist/three/three-types.js +6 -0
- package/dist/three/three-types.js.map +1 -0
- package/dist/types.d.ts +97 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 StreamKit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# @streamkit/pointcloud
|
|
2
|
+
|
|
3
|
+
Production-ready PointCloud rendering kit for Three.js.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@streamkit/pointcloud)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
## What This Package Is
|
|
9
|
+
|
|
10
|
+
- A **foundation library** for point cloud visualization on the web
|
|
11
|
+
- A **Three.js rendering layer** with proper lifecycle management
|
|
12
|
+
- A **Draco decoder** for compressed point cloud files
|
|
13
|
+
- A **stable data schema** designed for extensibility
|
|
14
|
+
|
|
15
|
+
**Use cases:** Robotics, GIS, LiDAR visualization, 3D scanning, real-time point cloud rendering.
|
|
16
|
+
|
|
17
|
+
## What This Package Is NOT
|
|
18
|
+
|
|
19
|
+
- ❌ **Not a streaming solution** — No WebRTC, no signaling
|
|
20
|
+
- ❌ **Not a UI framework** — No React, Vue, or Angular dependencies
|
|
21
|
+
- ❌ **Not a complete viewer** — You provide the Three.js scene and camera
|
|
22
|
+
|
|
23
|
+
This is v0.1 foundation code. Streaming capabilities will be added in future versions.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @streamkit/pointcloud three
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- Node.js 18+
|
|
34
|
+
- Three.js 0.150+
|
|
35
|
+
- Modern browser with WebGL support
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import * as THREE from "three";
|
|
41
|
+
import { createPointCloudLayer } from "@streamkit/pointcloud";
|
|
42
|
+
|
|
43
|
+
// Set up Three.js scene
|
|
44
|
+
const scene = new THREE.Scene();
|
|
45
|
+
const camera = new THREE.PerspectiveCamera(
|
|
46
|
+
75,
|
|
47
|
+
window.innerWidth / window.innerHeight,
|
|
48
|
+
0.1,
|
|
49
|
+
1000
|
|
50
|
+
);
|
|
51
|
+
const renderer = new THREE.WebGLRenderer();
|
|
52
|
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
53
|
+
document.body.appendChild(renderer.domElement);
|
|
54
|
+
|
|
55
|
+
// Create point cloud layer
|
|
56
|
+
const layer = createPointCloudLayer({
|
|
57
|
+
scene,
|
|
58
|
+
defaultSize: 0.02,
|
|
59
|
+
defaultColor: 0x00ff00,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Build point cloud from data
|
|
63
|
+
layer.build({
|
|
64
|
+
points: [
|
|
65
|
+
{ x: 0, y: 0, z: 0 },
|
|
66
|
+
{ x: 1, y: 0, z: 0 },
|
|
67
|
+
{ x: 0, y: 1, z: 0 },
|
|
68
|
+
{ x: 0, y: 0, z: 1 },
|
|
69
|
+
],
|
|
70
|
+
colors: [
|
|
71
|
+
{ r: 255, g: 0, b: 0 },
|
|
72
|
+
{ r: 0, g: 255, b: 0 },
|
|
73
|
+
{ r: 0, g: 0, b: 255 },
|
|
74
|
+
{ r: 255, g: 255, b: 0 },
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Animation loop
|
|
79
|
+
function animate() {
|
|
80
|
+
requestAnimationFrame(animate);
|
|
81
|
+
renderer.render(scene, camera);
|
|
82
|
+
}
|
|
83
|
+
animate();
|
|
84
|
+
|
|
85
|
+
// Clean up when done
|
|
86
|
+
// layer.dispose()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## API Reference
|
|
90
|
+
|
|
91
|
+
### Data Types
|
|
92
|
+
|
|
93
|
+
#### `PointCloudPoint`
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
interface PointCloudPoint {
|
|
97
|
+
x: number;
|
|
98
|
+
y: number;
|
|
99
|
+
z: number;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### `PointCloudColor`
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
interface PointCloudColor {
|
|
107
|
+
r: number; // 0-255
|
|
108
|
+
g: number; // 0-255
|
|
109
|
+
b: number; // 0-255
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `PointCloudData`
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface PointCloudData {
|
|
117
|
+
points: PointCloudPoint[];
|
|
118
|
+
colors?: PointCloudColor[]; // Per-vertex colors
|
|
119
|
+
size?: number; // Point size override
|
|
120
|
+
color?: number; // Uniform color (hex)
|
|
121
|
+
opacity?: number; // 0-1
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `createPointCloudLayer(options)`
|
|
126
|
+
|
|
127
|
+
Creates a managed point cloud rendering layer.
|
|
128
|
+
|
|
129
|
+
**Options:**
|
|
130
|
+
|
|
131
|
+
- `scene` — Three.js Scene (required)
|
|
132
|
+
- `defaultSize` — Default point size (default: `0.01`)
|
|
133
|
+
- `defaultColor` — Default color as hex (default: `0xffffff`)
|
|
134
|
+
|
|
135
|
+
**Returns:** `PointCloudLayer`
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface PointCloudLayer {
|
|
139
|
+
build(data: PointCloudData): void;
|
|
140
|
+
update(data: PointCloudData, options?: PointCloudUpdateOptions): void;
|
|
141
|
+
clear(): void;
|
|
142
|
+
dispose(): void;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `PointCloudUpdateOptions`
|
|
147
|
+
|
|
148
|
+
Options for incremental updates:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
type PointCloudUpdateMode = "replace" | "append" | "partial";
|
|
152
|
+
|
|
153
|
+
interface PointCloudUpdateOptions {
|
|
154
|
+
mode: PointCloudUpdateMode;
|
|
155
|
+
offset?: number; // For 'partial' mode
|
|
156
|
+
maxPoints?: number; // For 'append' mode (ring buffer)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `PointCloudFrame`
|
|
161
|
+
|
|
162
|
+
Streaming-ready frame type for temporal data:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
interface PointCloudFrame {
|
|
166
|
+
frameId: number;
|
|
167
|
+
timestamp: number; // milliseconds
|
|
168
|
+
data: PointCloudData;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `decodeDraco(buffer, options?)`
|
|
173
|
+
|
|
174
|
+
Decodes Draco-compressed point cloud data.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { decodeDraco } from "@streamkit/pointcloud";
|
|
178
|
+
|
|
179
|
+
const response = await fetch("pointcloud.drc");
|
|
180
|
+
const buffer = await response.arrayBuffer();
|
|
181
|
+
const data = await decodeDraco(buffer);
|
|
182
|
+
|
|
183
|
+
layer.build(data);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Options:**
|
|
187
|
+
|
|
188
|
+
- `decoderPath` — Path to Draco decoder files (default: Google CDN)
|
|
189
|
+
|
|
190
|
+
If colors are not present in the Draco file, fallback colors are generated based on Z-height.
|
|
191
|
+
|
|
192
|
+
### `preloadDracoDecoder(options?)`
|
|
193
|
+
|
|
194
|
+
Pre-loads the Draco WASM module for faster first decode.
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { preloadDracoDecoder } from "@streamkit/pointcloud";
|
|
198
|
+
|
|
199
|
+
// Call early in your app
|
|
200
|
+
await preloadDracoDecoder();
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Validators
|
|
204
|
+
|
|
205
|
+
Utility functions for validating point cloud data:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import {
|
|
209
|
+
isValidPoint,
|
|
210
|
+
isValidColor,
|
|
211
|
+
isValidPointCloudData,
|
|
212
|
+
hasMatchingColorCount,
|
|
213
|
+
normalizeColorValue,
|
|
214
|
+
clampColorValue,
|
|
215
|
+
} from "@streamkit/pointcloud";
|
|
216
|
+
|
|
217
|
+
// Validate incoming data
|
|
218
|
+
if (isValidPointCloudData(data)) {
|
|
219
|
+
layer.build(data);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Memory Management
|
|
224
|
+
|
|
225
|
+
The layer properly disposes Three.js resources:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// Always call dispose when done
|
|
229
|
+
layer.dispose();
|
|
230
|
+
|
|
231
|
+
// Or clear without disposing (can still reuse)
|
|
232
|
+
layer.clear();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Best practices:**
|
|
236
|
+
|
|
237
|
+
- Call `dispose()` when removing the layer permanently
|
|
238
|
+
- Call `clear()` if you plan to reuse the layer
|
|
239
|
+
- Use `update()` instead of `build()` for real-time data to reuse buffers
|
|
240
|
+
|
|
241
|
+
## Incremental Updates
|
|
242
|
+
|
|
243
|
+
The layer supports three update modes for efficient real-time rendering.
|
|
244
|
+
|
|
245
|
+
### Replace Mode (default)
|
|
246
|
+
|
|
247
|
+
Replaces entire point cloud. Use for complete scene changes.
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
layer.update(data); // Implicit replace
|
|
251
|
+
layer.update(data, { mode: "replace" });
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Append Mode
|
|
255
|
+
|
|
256
|
+
Adds points to existing buffer. Optimal for streaming point clouds.
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// Append new points
|
|
260
|
+
layer.update(newPoints, { mode: "append" });
|
|
261
|
+
|
|
262
|
+
// With ring buffer (keeps last N points)
|
|
263
|
+
layer.update(newPoints, { mode: "append", maxPoints: 100000 });
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Buffer management:
|
|
267
|
+
|
|
268
|
+
- Pre-allocates capacity to minimize reallocations
|
|
269
|
+
- Grows automatically when needed (2x factor)
|
|
270
|
+
- `maxPoints` enables ring buffer behavior (oldest points discarded)
|
|
271
|
+
|
|
272
|
+
### Partial Mode
|
|
273
|
+
|
|
274
|
+
Updates subset of points at specified offset. Use for localized changes.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// Update 100 points starting at index 500
|
|
278
|
+
layer.update(partialData, { mode: "partial", offset: 500 });
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Constraints:
|
|
282
|
+
|
|
283
|
+
- Requires existing geometry (call `build()` first)
|
|
284
|
+
- Cannot extend beyond current point count
|
|
285
|
+
- Invalid offsets are rejected with warning
|
|
286
|
+
|
|
287
|
+
### Performance Considerations
|
|
288
|
+
|
|
289
|
+
| Mode | Buffer Reuse | Allocation | Use Case |
|
|
290
|
+
| --------- | ------------ | -------------------- | ----------------- |
|
|
291
|
+
| `replace` | No | Full rebuild | Scene changes |
|
|
292
|
+
| `append` | Yes | On capacity overflow | Streaming data |
|
|
293
|
+
| `partial` | Yes | None | Localized updates |
|
|
294
|
+
|
|
295
|
+
## Color Handling
|
|
296
|
+
|
|
297
|
+
Colors in `PointCloudData` use 0-255 range for network efficiency. They are automatically normalized to 0-1 for Three.js rendering.
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Per-vertex colors (0-255 range)
|
|
301
|
+
layer.build({
|
|
302
|
+
points: [...],
|
|
303
|
+
colors: [
|
|
304
|
+
{ r: 255, g: 0, b: 0 }, // Red
|
|
305
|
+
{ r: 0, g: 255, b: 0 } // Green
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
// Uniform color (hex)
|
|
310
|
+
layer.build({
|
|
311
|
+
points: [...],
|
|
312
|
+
color: 0xff0000 // All points red
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## TypeScript Support
|
|
317
|
+
|
|
318
|
+
Full TypeScript support with exported types:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
import type {
|
|
322
|
+
PointCloudPoint,
|
|
323
|
+
PointCloudColor,
|
|
324
|
+
PointCloudData,
|
|
325
|
+
PointCloudFrame,
|
|
326
|
+
PointCloudLayer,
|
|
327
|
+
PointCloudLayerOptions,
|
|
328
|
+
PointCloudUpdateMode,
|
|
329
|
+
PointCloudUpdateOptions,
|
|
330
|
+
DracoDecoderOptions,
|
|
331
|
+
} from "@streamkit/pointcloud";
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Browser Support
|
|
335
|
+
|
|
336
|
+
- Chrome 90+
|
|
337
|
+
- Firefox 90+
|
|
338
|
+
- Safari 15+
|
|
339
|
+
- Edge 90+
|
|
340
|
+
|
|
341
|
+
Requires WebGL 2.0 support.
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streamkit/pointcloud - Data Validators
|
|
3
|
+
*
|
|
4
|
+
* Validation utilities for PointCloud data structures.
|
|
5
|
+
* These ensure data integrity before processing.
|
|
6
|
+
*/
|
|
7
|
+
import type { PointCloudColor, PointCloudData, PointCloudPoint } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Validates a single point object.
|
|
10
|
+
* @param point - The point to validate
|
|
11
|
+
* @returns True if the point is valid
|
|
12
|
+
*/
|
|
13
|
+
export declare function isValidPoint(point: unknown): point is PointCloudPoint;
|
|
14
|
+
/**
|
|
15
|
+
* Validates a single color object.
|
|
16
|
+
* @param color - The color to validate
|
|
17
|
+
* @returns True if the color is valid
|
|
18
|
+
*/
|
|
19
|
+
export declare function isValidColor(color: unknown): color is PointCloudColor;
|
|
20
|
+
/**
|
|
21
|
+
* Validates PointCloudData structure.
|
|
22
|
+
* @param data - The data to validate
|
|
23
|
+
* @returns True if the data structure is valid
|
|
24
|
+
*/
|
|
25
|
+
export declare function isValidPointCloudData(data: unknown): data is PointCloudData;
|
|
26
|
+
/**
|
|
27
|
+
* Validates that colors array length matches points array length.
|
|
28
|
+
* @param data - The PointCloudData to check
|
|
29
|
+
* @returns True if colors and points arrays have matching lengths (or colors is undefined)
|
|
30
|
+
*/
|
|
31
|
+
export declare function hasMatchingColorCount(data: PointCloudData): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Clamps a color value to the valid 0-255 range.
|
|
34
|
+
* @param value - The color value to clamp
|
|
35
|
+
* @returns Clamped value
|
|
36
|
+
*/
|
|
37
|
+
export declare function clampColorValue(value: number): number;
|
|
38
|
+
/**
|
|
39
|
+
* Normalizes a color value from 0-255 to 0-1 range.
|
|
40
|
+
* @param value - Color value in 0-255 range
|
|
41
|
+
* @returns Normalized value in 0-1 range
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeColorValue(value: number): number;
|
|
44
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/core/validators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAarE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAgBrE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAgD3E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAKnE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streamkit/pointcloud - Data Validators
|
|
3
|
+
*
|
|
4
|
+
* Validation utilities for PointCloud data structures.
|
|
5
|
+
* These ensure data integrity before processing.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates a single point object.
|
|
9
|
+
* @param point - The point to validate
|
|
10
|
+
* @returns True if the point is valid
|
|
11
|
+
*/
|
|
12
|
+
export function isValidPoint(point) {
|
|
13
|
+
if (typeof point !== "object" || point === null) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const p = point;
|
|
17
|
+
return (typeof p.x === "number" &&
|
|
18
|
+
typeof p.y === "number" &&
|
|
19
|
+
typeof p.z === "number" &&
|
|
20
|
+
isFinite(p.x) &&
|
|
21
|
+
isFinite(p.y) &&
|
|
22
|
+
isFinite(p.z));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates a single color object.
|
|
26
|
+
* @param color - The color to validate
|
|
27
|
+
* @returns True if the color is valid
|
|
28
|
+
*/
|
|
29
|
+
export function isValidColor(color) {
|
|
30
|
+
if (typeof color !== "object" || color === null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const c = color;
|
|
34
|
+
return (typeof c.r === "number" &&
|
|
35
|
+
typeof c.g === "number" &&
|
|
36
|
+
typeof c.b === "number" &&
|
|
37
|
+
c.r >= 0 &&
|
|
38
|
+
c.r <= 255 &&
|
|
39
|
+
c.g >= 0 &&
|
|
40
|
+
c.g <= 255 &&
|
|
41
|
+
c.b >= 0 &&
|
|
42
|
+
c.b <= 255);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validates PointCloudData structure.
|
|
46
|
+
* @param data - The data to validate
|
|
47
|
+
* @returns True if the data structure is valid
|
|
48
|
+
*/
|
|
49
|
+
export function isValidPointCloudData(data) {
|
|
50
|
+
if (typeof data !== "object" || data === null) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const d = data;
|
|
54
|
+
// Points array is required
|
|
55
|
+
if (!Array.isArray(d.points)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
// Validate all points
|
|
59
|
+
for (const point of d.points) {
|
|
60
|
+
if (!isValidPoint(point)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Validate colors if present
|
|
65
|
+
if (d.colors !== undefined) {
|
|
66
|
+
if (!Array.isArray(d.colors)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
for (const color of d.colors) {
|
|
70
|
+
if (!isValidColor(color)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Validate optional numeric fields
|
|
76
|
+
if (d.size !== undefined && (typeof d.size !== "number" || d.size <= 0)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (d.color !== undefined && (typeof d.color !== "number" || d.color < 0)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (d.opacity !== undefined &&
|
|
83
|
+
(typeof d.opacity !== "number" || d.opacity < 0 || d.opacity > 1)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validates that colors array length matches points array length.
|
|
90
|
+
* @param data - The PointCloudData to check
|
|
91
|
+
* @returns True if colors and points arrays have matching lengths (or colors is undefined)
|
|
92
|
+
*/
|
|
93
|
+
export function hasMatchingColorCount(data) {
|
|
94
|
+
if (!data.colors) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return data.colors.length === data.points.length;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Clamps a color value to the valid 0-255 range.
|
|
101
|
+
* @param value - The color value to clamp
|
|
102
|
+
* @returns Clamped value
|
|
103
|
+
*/
|
|
104
|
+
export function clampColorValue(value) {
|
|
105
|
+
return Math.max(0, Math.min(255, Math.round(value)));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Normalizes a color value from 0-255 to 0-1 range.
|
|
109
|
+
* @param value - Color value in 0-255 range
|
|
110
|
+
* @returns Normalized value in 0-1 range
|
|
111
|
+
*/
|
|
112
|
+
export function normalizeColorValue(value) {
|
|
113
|
+
return clampColorValue(value) / 255;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/core/validators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streamkit/pointcloud - Draco Decoder
|
|
3
|
+
*
|
|
4
|
+
* Utility for decoding Draco-compressed point cloud data.
|
|
5
|
+
* Uses Three.js DRACOLoader internally.
|
|
6
|
+
*/
|
|
7
|
+
import type { DracoDecoderOptions, PointCloudData } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Decodes a Draco-compressed buffer into PointCloudData.
|
|
10
|
+
*
|
|
11
|
+
* @param buffer - Raw ArrayBuffer containing Draco-compressed data
|
|
12
|
+
* @param options - Optional decoder configuration
|
|
13
|
+
* @returns Promise resolving to PointCloudData
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const response = await fetch('model.drc')
|
|
18
|
+
* const buffer = await response.arrayBuffer()
|
|
19
|
+
* const data = await decodeDraco(buffer)
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function decodeDraco(buffer: ArrayBuffer, options?: DracoDecoderOptions): Promise<PointCloudData>;
|
|
23
|
+
/**
|
|
24
|
+
* Pre-warms the Draco decoder by loading the WASM module.
|
|
25
|
+
* Call this early in your application to reduce first-decode latency.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Optional decoder configuration
|
|
28
|
+
* @returns Promise that resolves when decoder is ready
|
|
29
|
+
*/
|
|
30
|
+
export declare function preloadDracoDecoder(options?: DracoDecoderOptions): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/draco/decoder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,mBAAmB,EAEnB,cAAc,EAEf,MAAM,aAAa,CAAC;AA4LrB;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAYf"}
|