@playcanvas/splat-transform 0.11.0 → 0.12.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 +26 -26
- package/dist/index.mjs +53 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,12 +28,12 @@ npm install -g @playcanvas/splat-transform
|
|
|
28
28
|
## Usage
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
splat-transform [GLOBAL]
|
|
31
|
+
splat-transform [GLOBAL] input [ACTIONS] ... output [ACTIONS]
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
**Key points:**
|
|
35
|
-
-
|
|
36
|
-
- The last file
|
|
35
|
+
- Input files become the working set; ACTIONS are applied in order
|
|
36
|
+
- The last file is the output; actions after it modify the final result
|
|
37
37
|
|
|
38
38
|
## Supported Formats
|
|
39
39
|
|
|
@@ -54,28 +54,28 @@ splat-transform [GLOBAL] <input.{ply|compressed.ply|splat|ksplat|spz|sog|meta.j
|
|
|
54
54
|
Actions can be repeated and applied in any order:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
-t, --translate
|
|
58
|
-
-r, --rotate
|
|
59
|
-
-s, --scale
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
57
|
+
-t, --translate <x,y,z> Translate splats by (x, y, z).
|
|
58
|
+
-r, --rotate <x,y,z> Rotate splats by Euler angles (x, y, z), in degrees.
|
|
59
|
+
-s, --scale <factor> Uniformly scale splats by factor.
|
|
60
|
+
-N, --filter-nan Remove Gaussians with NaN or Inf values.
|
|
61
|
+
-V, --filter-value <name,cmp,value> Keep splats where <name> <cmp> <value>
|
|
62
|
+
cmp ∈ {lt,lte,gt,gte,eq,neq}
|
|
63
|
+
-H, --filter-harmonics <0|1|2|3> Remove spherical harmonic bands > n.
|
|
64
|
+
-B, --filter-box <mx,my,mz,Mx,My,Mz> Remove Gaussians outside box (min, max corners).
|
|
65
|
+
-S, --filter-sphere <x,y,z,radius> Remove Gaussians outside sphere (center, radius).
|
|
66
|
+
-p, --params <key=val,...> Pass parameters to .mjs generator script.
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
## Global Options
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
-h, --help
|
|
73
|
-
-v, --version
|
|
74
|
-
-w, --overwrite
|
|
75
|
-
-
|
|
76
|
-
-i, --iterations
|
|
77
|
-
-
|
|
78
|
-
-
|
|
72
|
+
-h, --help Show this help and exit.
|
|
73
|
+
-v, --version Show version and exit.
|
|
74
|
+
-w, --overwrite Overwrite output file if it exists.
|
|
75
|
+
-c, --cpu Use CPU for spherical harmonic compression.
|
|
76
|
+
-i, --iterations <n> Iterations for SOG SH compression (more = better). Default: 10.
|
|
77
|
+
-C, --camera-pos <x,y,z> HTML viewer camera position. Default: (2, 2, -2).
|
|
78
|
+
-T, --camera-target <x,y,z> HTML viewer target position. Default: (0, 0, 0).
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
## Examples
|
|
@@ -112,7 +112,7 @@ splat-transform scene.sog restored.ply
|
|
|
112
112
|
splat-transform output/meta.json restored.ply
|
|
113
113
|
|
|
114
114
|
# Convert to HTML viewer with target and camera location
|
|
115
|
-
splat-transform -
|
|
115
|
+
splat-transform -C 0,0,0 -T 0,0,10 input.ply output.html
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
### Transformations
|
|
@@ -132,13 +132,13 @@ splat-transform input.ply -s 2 -t 1,0,0 -r 0,0,45 output.ply
|
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
134
|
# Remove entries containing NaN and Inf
|
|
135
|
-
splat-transform input.ply --
|
|
135
|
+
splat-transform input.ply --filter-nan output.ply
|
|
136
136
|
|
|
137
137
|
# Filter by opacity values (keep only splats with opacity > 0.5)
|
|
138
|
-
splat-transform input.ply -
|
|
138
|
+
splat-transform input.ply -V opacity,gt,0.5 output.ply
|
|
139
139
|
|
|
140
140
|
# Strip spherical harmonic bands higher than 2
|
|
141
|
-
splat-transform input.ply --
|
|
141
|
+
splat-transform input.ply --filter-harmonics 2 output.ply
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
### Advanced Usage
|
|
@@ -148,7 +148,7 @@ splat-transform input.ply --filterBands 2 output.ply
|
|
|
148
148
|
splat-transform -w cloudA.ply -r 0,90,0 cloudB.ply -s 2 merged.compressed.ply
|
|
149
149
|
|
|
150
150
|
# Apply final transformations to combined result
|
|
151
|
-
splat-transform input1.ply input2.ply output.ply -
|
|
151
|
+
splat-transform input1.ply input2.ply output.ply -t 0,0,10 -s 0.5
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
### Generators (Beta)
|
|
@@ -156,7 +156,7 @@ splat-transform input1.ply input2.ply output.ply -p 0,0,10 -e 0.5
|
|
|
156
156
|
Generator scripts can be used to synthesize gaussian splat data. See [gen-grid.mjs](generators/gen-grid.mjs) for an example.
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
|
-
splat-transform gen-grid.mjs -
|
|
159
|
+
splat-transform gen-grid.mjs -p width=10,height=10,scale=10,color=0.1 scenes/grid.ply -w
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
## Getting Help
|
package/dist/index.mjs
CHANGED
|
@@ -1890,7 +1890,7 @@ let Quat$1 = class Quat {
|
|
|
1890
1890
|
}
|
|
1891
1891
|
};
|
|
1892
1892
|
|
|
1893
|
-
var version$1 = "0.
|
|
1893
|
+
var version$1 = "0.12.0";
|
|
1894
1894
|
|
|
1895
1895
|
class Column {
|
|
1896
1896
|
name;
|
|
@@ -94334,7 +94334,7 @@ const writeFile = async (filename, dataTable, options) => {
|
|
|
94334
94334
|
await writeCsv(outputFile, dataTable);
|
|
94335
94335
|
break;
|
|
94336
94336
|
case 'sog':
|
|
94337
|
-
await writeSog(outputFile, dataTable, filename, options.iterations, options.
|
|
94337
|
+
await writeSog(outputFile, dataTable, filename, options.iterations, options.cpu ? 'cpu' : 'gpu');
|
|
94338
94338
|
break;
|
|
94339
94339
|
case 'compressed-ply':
|
|
94340
94340
|
await writeCompressedPly(outputFile, dataTable);
|
|
@@ -94437,20 +94437,20 @@ const parseArguments = () => {
|
|
|
94437
94437
|
overwrite: { type: 'boolean', short: 'w' },
|
|
94438
94438
|
help: { type: 'boolean', short: 'h' },
|
|
94439
94439
|
version: { type: 'boolean', short: 'v' },
|
|
94440
|
-
|
|
94440
|
+
cpu: { type: 'boolean', short: 'c' },
|
|
94441
94441
|
iterations: { type: 'string', short: 'i' },
|
|
94442
|
-
|
|
94443
|
-
|
|
94442
|
+
'camera-pos': { type: 'string', short: 'C' },
|
|
94443
|
+
'camera-target': { type: 'string', short: 'T' },
|
|
94444
94444
|
// file options
|
|
94445
94445
|
translate: { type: 'string', short: 't', multiple: true },
|
|
94446
94446
|
rotate: { type: 'string', short: 'r', multiple: true },
|
|
94447
94447
|
scale: { type: 'string', short: 's', multiple: true },
|
|
94448
|
-
|
|
94449
|
-
|
|
94450
|
-
|
|
94451
|
-
|
|
94452
|
-
|
|
94453
|
-
params: { type: 'string', short: '
|
|
94448
|
+
'filter-nan': { type: 'boolean', short: 'N', multiple: true },
|
|
94449
|
+
'filter-value': { type: 'string', short: 'V', multiple: true },
|
|
94450
|
+
'filter-harmonics': { type: 'string', short: 'H', multiple: true },
|
|
94451
|
+
'filter-box': { type: 'string', short: 'B', multiple: true },
|
|
94452
|
+
'filter-sphere': { type: 'string', short: 'S', multiple: true },
|
|
94453
|
+
params: { type: 'string', short: 'p', multiple: true }
|
|
94454
94454
|
}
|
|
94455
94455
|
});
|
|
94456
94456
|
const parseNumber = (value) => {
|
|
@@ -94491,10 +94491,10 @@ const parseArguments = () => {
|
|
|
94491
94491
|
overwrite: v.overwrite ?? false,
|
|
94492
94492
|
help: v.help ?? false,
|
|
94493
94493
|
version: v.version ?? false,
|
|
94494
|
-
|
|
94494
|
+
cpu: v.cpu ?? false,
|
|
94495
94495
|
iterations: parseInteger(v.iterations ?? '10'),
|
|
94496
|
-
cameraPos: parseVec3(v
|
|
94497
|
-
cameraTarget: parseVec3(v
|
|
94496
|
+
cameraPos: parseVec3(v['camera-pos'] ?? '2,2,-2'),
|
|
94497
|
+
cameraTarget: parseVec3(v['camera-target'] ?? '0,0,0')
|
|
94498
94498
|
};
|
|
94499
94499
|
for (const t of tokens) {
|
|
94500
94500
|
if (t.kind === 'positional') {
|
|
@@ -94524,15 +94524,15 @@ const parseArguments = () => {
|
|
|
94524
94524
|
value: parseNumber(t.value)
|
|
94525
94525
|
});
|
|
94526
94526
|
break;
|
|
94527
|
-
case '
|
|
94527
|
+
case 'filter-nan':
|
|
94528
94528
|
current.processActions.push({
|
|
94529
94529
|
kind: 'filterNaN'
|
|
94530
94530
|
});
|
|
94531
94531
|
break;
|
|
94532
|
-
case '
|
|
94532
|
+
case 'filter-value': {
|
|
94533
94533
|
const parts = t.value.split(',').map((p) => p.trim());
|
|
94534
94534
|
if (parts.length !== 3) {
|
|
94535
|
-
throw new Error(`Invalid
|
|
94535
|
+
throw new Error(`Invalid filter-value value: ${t.value}`);
|
|
94536
94536
|
}
|
|
94537
94537
|
current.processActions.push({
|
|
94538
94538
|
kind: 'filterByValue',
|
|
@@ -94542,10 +94542,10 @@ const parseArguments = () => {
|
|
|
94542
94542
|
});
|
|
94543
94543
|
break;
|
|
94544
94544
|
}
|
|
94545
|
-
case '
|
|
94545
|
+
case 'filter-harmonics': {
|
|
94546
94546
|
const shBands = parseInteger(t.value);
|
|
94547
94547
|
if (![0, 1, 2, 3].includes(shBands)) {
|
|
94548
|
-
throw new Error(`Invalid
|
|
94548
|
+
throw new Error(`Invalid filter-harmonics value: ${t.value}. Must be 0, 1, 2, or 3.`);
|
|
94549
94549
|
}
|
|
94550
94550
|
current.processActions.push({
|
|
94551
94551
|
kind: 'filterBands',
|
|
@@ -94553,10 +94553,10 @@ const parseArguments = () => {
|
|
|
94553
94553
|
});
|
|
94554
94554
|
break;
|
|
94555
94555
|
}
|
|
94556
|
-
case '
|
|
94556
|
+
case 'filter-box': {
|
|
94557
94557
|
const parts = t.value.split(',').map((p) => p.trim());
|
|
94558
94558
|
if (parts.length !== 6) {
|
|
94559
|
-
throw new Error(`Invalid
|
|
94559
|
+
throw new Error(`Invalid filter-box value: ${t.value}`);
|
|
94560
94560
|
}
|
|
94561
94561
|
const defaults = [-Infinity, -Infinity, -Infinity, Infinity, Infinity, Infinity];
|
|
94562
94562
|
const values = [];
|
|
@@ -94575,16 +94575,16 @@ const parseArguments = () => {
|
|
|
94575
94575
|
});
|
|
94576
94576
|
break;
|
|
94577
94577
|
}
|
|
94578
|
-
case '
|
|
94578
|
+
case 'filter-sphere': {
|
|
94579
94579
|
const parts = t.value.split(',').map((p) => p.trim());
|
|
94580
94580
|
if (parts.length !== 4) {
|
|
94581
|
-
throw new Error(`Invalid
|
|
94581
|
+
throw new Error(`Invalid filter-sphere value: ${t.value}`);
|
|
94582
94582
|
}
|
|
94583
94583
|
const values = parts.map(parseNumber);
|
|
94584
94584
|
current.processActions.push({
|
|
94585
94585
|
kind: 'filterSphere',
|
|
94586
94586
|
center: new Vec3$1(values[0], values[1], values[2]),
|
|
94587
|
-
radius: values[
|
|
94587
|
+
radius: values[3]
|
|
94588
94588
|
});
|
|
94589
94589
|
break;
|
|
94590
94590
|
}
|
|
@@ -94606,57 +94606,55 @@ const parseArguments = () => {
|
|
|
94606
94606
|
return { files, options };
|
|
94607
94607
|
};
|
|
94608
94608
|
const usage = `
|
|
94609
|
-
|
|
94610
|
-
|
|
94609
|
+
Transform & filter Gaussian splats
|
|
94610
|
+
===================================
|
|
94611
94611
|
|
|
94612
94612
|
USAGE
|
|
94613
|
-
splat-transform [GLOBAL]
|
|
94613
|
+
splat-transform [GLOBAL] input [ACTIONS] ... output [ACTIONS]
|
|
94614
94614
|
|
|
94615
|
-
•
|
|
94616
|
-
|
|
94617
|
-
• The last file on the command line is treated as the output; anything after it is
|
|
94618
|
-
interpreted as actions that modify the final result.
|
|
94615
|
+
• Input files become the working set; ACTIONS are applied in order.
|
|
94616
|
+
• The last file is the output; actions after it modify the final result.
|
|
94619
94617
|
|
|
94620
94618
|
SUPPORTED INPUTS
|
|
94621
|
-
.ply .compressed.ply .
|
|
94619
|
+
.ply .compressed.ply .sog meta.json .ksplat .splat .spz .mjs
|
|
94622
94620
|
|
|
94623
94621
|
SUPPORTED OUTPUTS
|
|
94624
94622
|
.ply .compressed.ply .sog meta.json .csv .html
|
|
94625
94623
|
|
|
94626
94624
|
ACTIONS (can be repeated, in any order)
|
|
94627
|
-
-t, --translate
|
|
94628
|
-
-r, --rotate
|
|
94629
|
-
-s, --scale
|
|
94630
|
-
-
|
|
94631
|
-
-
|
|
94632
|
-
|
|
94633
|
-
-
|
|
94634
|
-
-
|
|
94635
|
-
-
|
|
94636
|
-
-
|
|
94625
|
+
-t, --translate <x,y,z> Translate splats by (x, y, z).
|
|
94626
|
+
-r, --rotate <x,y,z> Rotate splats by Euler angles (x, y, z), in degrees.
|
|
94627
|
+
-s, --scale <factor> Uniformly scale splats by factor.
|
|
94628
|
+
-N, --filter-nan Remove Gaussians with NaN or Inf values.
|
|
94629
|
+
-V, --filter-value <name,cmp,value> Keep splats where <name> <cmp> <value>
|
|
94630
|
+
cmp ∈ {lt,lte,gt,gte,eq,neq}
|
|
94631
|
+
-H, --filter-harmonics <0|1|2|3> Remove spherical harmonic bands > n.
|
|
94632
|
+
-B, --filter-box <mx,my,mz,Mx,My,Mz> Remove Gaussians outside box (min, max corners).
|
|
94633
|
+
-S, --filter-sphere <x,y,z,radius> Remove Gaussians outside sphere (center, radius).
|
|
94634
|
+
-p, --params <key=val,...> Pass parameters to .mjs generator script.
|
|
94637
94635
|
|
|
94638
94636
|
GLOBAL OPTIONS
|
|
94639
|
-
-h, --help
|
|
94640
|
-
-v, --version
|
|
94641
|
-
-w, --overwrite
|
|
94642
|
-
-
|
|
94643
|
-
-i, --iterations
|
|
94644
|
-
-
|
|
94645
|
-
-
|
|
94637
|
+
-h, --help Show this help and exit.
|
|
94638
|
+
-v, --version Show version and exit.
|
|
94639
|
+
-w, --overwrite Overwrite output file if it exists.
|
|
94640
|
+
-c, --cpu Use CPU for spherical harmonic compression.
|
|
94641
|
+
-i, --iterations <n> Iterations for SOG SH compression (more = better). Default: 10.
|
|
94642
|
+
-C, --camera-pos <x,y,z> HTML viewer camera position. Default: (2, 2, -2).
|
|
94643
|
+
-T, --camera-target <x,y,z> HTML viewer target position. Default: (0, 0, 0).
|
|
94646
94644
|
|
|
94647
94645
|
EXAMPLES
|
|
94648
|
-
#
|
|
94646
|
+
# Scale then translate
|
|
94649
94647
|
splat-transform bunny.ply -s 0.5 -t 0,0,10 bunny_scaled.ply
|
|
94650
94648
|
|
|
94651
|
-
#
|
|
94649
|
+
# Merge two files with transforms
|
|
94652
94650
|
splat-transform -w cloudA.ply -r 0,90,0 cloudB.ply -s 2 merged.compressed.ply
|
|
94653
94651
|
|
|
94654
|
-
#
|
|
94655
|
-
splat-transform -
|
|
94652
|
+
# HTML viewer with custom camera
|
|
94653
|
+
splat-transform -C 0,0,0 -T 0,0,10 bunny.ply bunny_app.html
|
|
94656
94654
|
|
|
94657
94655
|
GENERATORS (beta)
|
|
94658
|
-
# Generate
|
|
94659
|
-
splat-transform gen-grid.mjs -
|
|
94656
|
+
# Generate synthetic splats
|
|
94657
|
+
splat-transform gen-grid.mjs -p width=500,height=500,scale=0.1 grid.ply
|
|
94660
94658
|
`;
|
|
94661
94659
|
const main = async () => {
|
|
94662
94660
|
console.log(`splat-transform v${version$1}`);
|