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.
Files changed (2) hide show
  1. package/cli.mjs +95 -11
  2. 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
- this.readBuffers();
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
- this.readBuffers();
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.metadata.file_bbox_min.value,
10308
- this.metadata.file_bbox_max.value,
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 Empty grids store an inverted box
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 only grid metadata and transforms. The trees are not read.
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), { metadataOnly: true }), options.grids);
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.5.1",
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
  }