webvdb 0.5.1 → 0.6.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/cli.mjs +95 -11
- package/package.json +6 -1
package/cli.mjs
CHANGED
|
@@ -8709,6 +8709,9 @@ class GridSharedContext {
|
|
|
8709
8709
|
// NOTE Read only grid headers, metadata and transforms. Trees are not read.
|
|
8710
8710
|
metadataOnly = false;
|
|
8711
8711
|
|
|
8712
|
+
// NOTE Read the tree topology (active voxels), but not the leaf values
|
|
8713
|
+
topologyOnly = false;
|
|
8714
|
+
|
|
8712
8715
|
// NOTE Grid value settings
|
|
8713
8716
|
valueType = null;
|
|
8714
8717
|
useHalf = null;
|
|
@@ -9410,6 +9413,38 @@ class ChildNode {
|
|
|
9410
9413
|
return values;
|
|
9411
9414
|
}
|
|
9412
9415
|
|
|
9416
|
+
// NOTE Extends min and max with the active voxels and tiles. Origin is the index position of this node.
|
|
9417
|
+
// Child origins are relative to the parent.
|
|
9418
|
+
evalActiveBbox(origin, min, max) {
|
|
9419
|
+
const log2dim = this.log2dim;
|
|
9420
|
+
const childTotal = this.total - log2dim;
|
|
9421
|
+
const tileSize = (1 << childTotal) - 1;
|
|
9422
|
+
const position = new Vector3();
|
|
9423
|
+
|
|
9424
|
+
this.valueMask.forEachOn(({ offset }) => {
|
|
9425
|
+
if (this.isInternalNode() && this.childMask.isOn(offset)) {
|
|
9426
|
+
return;
|
|
9427
|
+
}
|
|
9428
|
+
|
|
9429
|
+
position.set(
|
|
9430
|
+
origin.x + ((offset >> (2 * log2dim)) << childTotal),
|
|
9431
|
+
origin.y + (((offset >> log2dim) & ((1 << log2dim) - 1)) << childTotal),
|
|
9432
|
+
origin.z + ((offset & ((1 << log2dim) - 1)) << childTotal)
|
|
9433
|
+
);
|
|
9434
|
+
|
|
9435
|
+
min.min(position);
|
|
9436
|
+
max.max(position.addScalar(tileSize));
|
|
9437
|
+
});
|
|
9438
|
+
|
|
9439
|
+
if (this.isInternalNode()) {
|
|
9440
|
+
this.childMask.forEachOn(({ offset }) => {
|
|
9441
|
+
const child = this.table[offset];
|
|
9442
|
+
|
|
9443
|
+
child.evalActiveBbox(origin.clone().add(child.origin), min, max);
|
|
9444
|
+
});
|
|
9445
|
+
}
|
|
9446
|
+
}
|
|
9447
|
+
|
|
9413
9448
|
getLocalBbox() {
|
|
9414
9449
|
if (this.localBboxCache) {
|
|
9415
9450
|
return this.localBboxCache;
|
|
@@ -9592,6 +9627,16 @@ class RootTile {
|
|
|
9592
9627
|
return this.localBboxCache;
|
|
9593
9628
|
}
|
|
9594
9629
|
|
|
9630
|
+
// NOTE Extends min and max with the tile extent when the tile is active
|
|
9631
|
+
evalActiveBbox(origin, min, max) {
|
|
9632
|
+
if (!this.active) {
|
|
9633
|
+
return;
|
|
9634
|
+
}
|
|
9635
|
+
|
|
9636
|
+
min.min(origin);
|
|
9637
|
+
max.max(origin.clone().addScalar(this.dim - 1));
|
|
9638
|
+
}
|
|
9639
|
+
|
|
9595
9640
|
contains(position) {
|
|
9596
9641
|
const [min, max] = this.getLocalBbox();
|
|
9597
9642
|
|
|
@@ -9764,6 +9809,11 @@ class RootNode {
|
|
|
9764
9809
|
});
|
|
9765
9810
|
}
|
|
9766
9811
|
|
|
9812
|
+
// NOTE Root children and root tiles save their index origin in the file
|
|
9813
|
+
evalActiveBbox(min, max) {
|
|
9814
|
+
this.table.forEach((node) => node.evalActiveBbox(node.origin, min, max));
|
|
9815
|
+
}
|
|
9816
|
+
|
|
9767
9817
|
getLocalBbox() {
|
|
9768
9818
|
// NOTE Ignore bbox for root nodes
|
|
9769
9819
|
return [new Vector3(0.0, 0.0, 0.0), new Vector3(0.0, 0.0, 0.0)];
|
|
@@ -10101,7 +10151,7 @@ class GridDescriptor {
|
|
|
10101
10151
|
gridType;
|
|
10102
10152
|
|
|
10103
10153
|
readGrid() {
|
|
10104
|
-
const { bufferIterator, version, hasGridOffsets, metadataOnly } =
|
|
10154
|
+
const { bufferIterator, version, hasGridOffsets, metadataOnly, topologyOnly } =
|
|
10105
10155
|
GridSharedContext.getContext(this);
|
|
10106
10156
|
|
|
10107
10157
|
this.readGridHeader();
|
|
@@ -10124,10 +10174,20 @@ class GridDescriptor {
|
|
|
10124
10174
|
return;
|
|
10125
10175
|
}
|
|
10126
10176
|
|
|
10177
|
+
// NOTE With topologyOnly, leaf values are skipped. Without grid offsets, the reader cannot skip them.
|
|
10178
|
+
const readOrSkipBuffers = () => {
|
|
10179
|
+
if (topologyOnly && hasGridOffsets) {
|
|
10180
|
+
bufferIterator.offset = this.endBufferPosition;
|
|
10181
|
+
return;
|
|
10182
|
+
}
|
|
10183
|
+
|
|
10184
|
+
this.readBuffers();
|
|
10185
|
+
};
|
|
10186
|
+
|
|
10127
10187
|
if (Version.less(version, 216)) {
|
|
10128
10188
|
this.readTopology();
|
|
10129
10189
|
this.readGridTransform();
|
|
10130
|
-
|
|
10190
|
+
readOrSkipBuffers();
|
|
10131
10191
|
} else {
|
|
10132
10192
|
this.readGridTransform();
|
|
10133
10193
|
|
|
@@ -10142,7 +10202,7 @@ class GridDescriptor {
|
|
|
10142
10202
|
}
|
|
10143
10203
|
|
|
10144
10204
|
this.readTopology();
|
|
10145
|
-
|
|
10205
|
+
readOrSkipBuffers();
|
|
10146
10206
|
}
|
|
10147
10207
|
}
|
|
10148
10208
|
|
|
@@ -10302,11 +10362,29 @@ class GridDescriptor {
|
|
|
10302
10362
|
];
|
|
10303
10363
|
}
|
|
10304
10364
|
|
|
10365
|
+
// NOTE Index box of active voxels and tiles from the tree, same as Tree::evalActiveVoxelBoundingBox. Null when none is active.
|
|
10366
|
+
// Some writers (EmberGen) save wrong file_bbox metadata.
|
|
10367
|
+
evalActiveVoxelBoundingBox() {
|
|
10368
|
+
if (this.activeVoxelBboxCache === undefined) {
|
|
10369
|
+
const min = new Vector3(Infinity, Infinity, Infinity);
|
|
10370
|
+
const max = new Vector3(-Infinity, -Infinity, -Infinity);
|
|
10371
|
+
|
|
10372
|
+
this.root.evalActiveBbox(min, max);
|
|
10373
|
+
|
|
10374
|
+
this.activeVoxelBboxCache = min.x <= max.x ? [min, max] : null;
|
|
10375
|
+
}
|
|
10376
|
+
|
|
10377
|
+
return this.activeVoxelBboxCache;
|
|
10378
|
+
}
|
|
10379
|
+
|
|
10380
|
+
// NOTE Without a tree (metadataOnly) or without active voxels, the box comes from the file metadata
|
|
10305
10381
|
getPreciseWorldBbox() {
|
|
10306
|
-
return this.transform.applyTransformMapToBbox(
|
|
10307
|
-
this.
|
|
10308
|
-
|
|
10309
|
-
|
|
10382
|
+
return this.transform.applyTransformMapToBbox(
|
|
10383
|
+
(this.root && this.evalActiveVoxelBoundingBox()) || [
|
|
10384
|
+
this.metadata.file_bbox_min.value,
|
|
10385
|
+
this.metadata.file_bbox_max.value,
|
|
10386
|
+
]
|
|
10387
|
+
);
|
|
10310
10388
|
}
|
|
10311
10389
|
|
|
10312
10390
|
valueCache = {};
|
|
@@ -10351,11 +10429,13 @@ class OpenVDBReader {
|
|
|
10351
10429
|
}
|
|
10352
10430
|
|
|
10353
10431
|
// NOTE With metadataOnly, grids have metadata and transforms (for example the world box), but no tree.
|
|
10432
|
+
// With topologyOnly, grids also have the tree topology (active voxels, evalActiveVoxelBoundingBox), but no leaf values.
|
|
10354
10433
|
// Grids of files without grid offsets (before version 2.16) are read in full.
|
|
10355
|
-
async read(source, { metadataOnly = false } = {}) {
|
|
10434
|
+
async read(source, { metadataOnly = false, topologyOnly = false } = {}) {
|
|
10356
10435
|
await Compression.prepareModules();
|
|
10357
10436
|
GridSharedContext.getContext(this).bufferIterator = new BufferIterator(source);
|
|
10358
10437
|
GridSharedContext.getContext(this).metadataOnly = metadataOnly;
|
|
10438
|
+
GridSharedContext.getContext(this).topologyOnly = topologyOnly;
|
|
10359
10439
|
|
|
10360
10440
|
if (this.validateVDBFile()) {
|
|
10361
10441
|
this.readFileVersion();
|
|
@@ -11258,8 +11338,12 @@ const getBackground = (grid) => {
|
|
|
11258
11338
|
: [Math.fround(background.x), Math.fround(background.y), Math.fround(background.z)];
|
|
11259
11339
|
};
|
|
11260
11340
|
|
|
11261
|
-
// NOTE
|
|
11341
|
+
// NOTE With a tree, empty grids have no active voxels. Without a tree, empty grids store an inverted box.
|
|
11262
11342
|
const isEmptyGrid = (grid) => {
|
|
11343
|
+
if (grid.root) {
|
|
11344
|
+
return !grid.evalActiveVoxelBoundingBox();
|
|
11345
|
+
}
|
|
11346
|
+
|
|
11263
11347
|
const { file_voxel_count: voxelCount, file_bbox_min: min, file_bbox_max: max } =
|
|
11264
11348
|
grid.metadata || {};
|
|
11265
11349
|
|
|
@@ -12026,9 +12110,9 @@ const readVDB = async (source, readOptions) => {
|
|
|
12026
12110
|
return vdb;
|
|
12027
12111
|
};
|
|
12028
12112
|
|
|
12029
|
-
// NOTE The box needs
|
|
12113
|
+
// NOTE The box needs the tree topology (active voxels). Leaf values are not read.
|
|
12030
12114
|
const getSourceBox = async ({ source, options }) =>
|
|
12031
|
-
getWVDBBox(await readVDB(readSource(source), {
|
|
12115
|
+
getWVDBBox(await readVDB(readSource(source), { topologyOnly: true }), options.grids);
|
|
12032
12116
|
|
|
12033
12117
|
const convert = async ({ source, options }) => {
|
|
12034
12118
|
const sourceBytes = readSource(source);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webvdb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CLI that converts .vdb files, folders and ZIP files into streamed .wvdb files.",
|
|
5
5
|
"scripts": {},
|
|
6
6
|
"dependencies": {},
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
}
|
|
29
29
|
],
|
|
30
30
|
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/mjurczyk/openvdb.git",
|
|
34
|
+
"directory": "src/wvdb"
|
|
35
|
+
},
|
|
31
36
|
"bin": {
|
|
32
37
|
"wvdb": "./cli.mjs"
|
|
33
38
|
}
|