Skip to content

Commit

Permalink
Finalize EXT_primitive_voxels README
Browse files Browse the repository at this point in the history
  • Loading branch information
j9liu committed Jan 31, 2025
1 parent 92688a3 commit 351ef49
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Angles are given in radians within the range `[-pi, pi]` and open clockwise arou
"minRadius": 0.5,
"maxRadius": 1,
"height": 2,
"minAngle": 0
"minAngle": 0,
"maxAngle": 3.1415
}
}
Expand Down
100 changes: 68 additions & 32 deletions extensions/2.0/Vendor/EXT_primitive_voxels/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Typical mesh primitives make use of the `POSITION` attribute to store positional
"attributes": {
"_TEMPERATURE": 0
},
"mode": 2147483648,
"mode": 2147483647,
"extensions": {
"EXT_primitive_voxels": {
"shape": 0,
Expand All @@ -61,48 +61,66 @@ Typical mesh primitives make use of the `POSITION` attribute to store positional
}
```

Though voxels are commonly associated with cubic geometry on a box-based grid, this extension allows voxels to be based on other types of grid geometry. This currently includes cylinder-based regions specified by [`EXT_implicit_cylinder_region`](../EXT_implicit_cylinder_region/) as well as ellipsoid-based regions specified by [`EXT_implicit_ellipsoid_region`](../EXT_implicit_ellipsoid_region/). The supported shapes are visualized below.
Though voxels are commonly associated with cubic geometry on a box-based grid, this extension also allows voxels to be based on other shapes, including cylinder-based regions specified by [`EXT_implicit_cylinder_region`](../EXT_implicit_cylinder_region/) and ellipsoid-based regions specified by [`EXT_implicit_ellipsoid_region`](../EXT_implicit_ellipsoid_region/). The supported shapes are visualized below.

|Box|Cylinder|Region|
| ------------- | ------------- | ------------- |
|![Box Voxel Grid](figures/box.png)|![Cylindrical Voxel Grid](figures/cylinder.png)|![Ellipsoid Voxel Grid](figures/sphere.png)|

Voxels exist inside a bounding volume that conforms to the shape of the grid. The `dimensions` property refers to the number of subdivisions _within_ this bounding volume. Each value of `dimensions` must be a positive integer.

The relationship between `dimensions` and the grid geometry is explained in detail below.
The relationship between `dimensions` and the grid geometry is explained below.

### Box Grid

A **box** grid is a Cartesian grid defined by `x`, `y`, and `z` axes with equally-sized boxes. The `dimensions` correspond to the subdivisions of the box along the `x`, `y`, and `z` axes respectively.
A **box** grid is a Cartesian grid defined by `x`, `y`, and `z` axes with equally-sized boxes. The `dimensions` correspond to the subdivisions of the box along the `x`, `y`, and `z` axes respectively. Elements are laid out in memory where the `x` data is contiguous up to stride.

![Uniform box grid](figures/uniform-box.png)
<p align="center"><i>A box grid spanning from -1 to 1 in all three axes, subdivided into two cells along each axis. The origin is in the center of the box.</i></p>

These properties may be used to define the scale of the box grid, independent of the `scale` applied by a node. Additionally, the `dimensions` may be non-uniform.
<p align="center"><i>A uniform box grid that is subdivided into two cells along each axis.</i></p>

![Non-uniform box grid](figures/non-uniform-box.png)
<p align="center"><i>A box grid that is non-uniformly scaled due to its min and max properties. It is also non-uniformly subdivided.</i></p>

Elements are laid out in memory where the `x` data is contiguous (up to stride).
<p align="center"><i>A box grid that is non-uniformly scaled and also non-uniformly subdivided.</i></p>

### Cylinder Region Grid

A **cylinder** region grid is subdivided along the radius, height, and angle ranges of the region, visualized below.

![Cylinder subdivisions](figures/cylinder-subdivisions.png)

The cylinder is aligned with the `y`-axis in the primitive's local space. As such, the `height` is subdivided along that local `y`-axis. Subdivisions along the radius are concentric, centered around the `y`-axis and extending outwards. The angle is subdivided around the circumference of the cylinder.
The cylinder is aligned with the `y`-axis in the primitive's local space. Its height is subdivided along that local `y`-axis from bottom to top. Subdivisions along the radius are concentric, centered around the `y`-axis and extending outwards. Finally, the angular bounds subdivided clockwise around the circumference of the cylinder.

Elements are laid out in memory where data along the radius is contiguous up to stride.

Elements are laid out in memory where the radius data is contiguous (up to stride).
![Whole cylinder grid](figures/whole-cylinder.png)
<p align="center"><i>A cylinder that is subdivided into two cells along each axis.</i></p>

![Non-uniform cylinder grid](figures/non-uniform-cylinder.png)
<p align="center"><i>A smaller cylinder region with radial and angular bounds that is non-uniformly subdivided.</i></p>

### Ellipsoid Region Grid

An **ellipsoid** region grid is subdivided along the longitude, latitude, and height ranges of the region, visualized below.
An **ellipsoid** region grid is subdivided along the longitude, latitude, and height ranges of the region. The `dimensions` correspond to the subdivisions of those ranges, respectively.

Elements are laid out in memory where the `longitude` data is contiguous (up to stride).

![Region grid](figures/part-ellipsoid.png)
<p align="center"><i>An ellipsoid region that is subdivided into two cells along each axis.</i></p>

![Non-uniform region grid](figures/non-uniform-part-ellipsoid.png)

<p align="center"><i>An ellipsoid region that is non-uniformly subdivided.</i></p>

![Whole ellipsoid grid](figures/whole-ellipsoid.png)
<p align="center"><i>A hollow ellipsoid region that covers the entire ellipsoid, subdivided into two cells along each axis.</i></p>

### Padding

The `padding` property specifies how many rows of attribute data in each dimension come from neighboring grids. This is useful in situations where the primitive represents a single tile in a larger grid, and data from neighboring tiles is needed for non-local effects e.g. trilinear interpolation, blurring, or antialiasing.

`padding.before` and `padding.after` specify the number of rows before and after the grid in each dimension, e.g. a `padding.before` of 1 and a `padding.after` of 2 in the `y` dimension mean that each series of values in a given `y`-slice is preceded by one value and followed by two.

Padding data must be included with the rest of the voxel data. In other words, given `dimensions` of `[d1, d2, d3]`, `padding.before` of `[b1, b2, b3]`, and `padding.after` of `[a1, a2, a3]`, the voxel primitive's attributes must contain `(d1 + a1 + b1)*(d2 + a2 + b2)*(d3 + a3 + b3)` elements. In the following example, the attributes on this voxel primitive must supply `(8 + 1 + 1)*(8 + 1 + 1)*(8 + 1 + 1) = 100` elements.

```json
"extensions": {
"EXT_primitive_voxels": {
Expand All @@ -116,11 +134,30 @@ Elements are laid out in memory where the `longitude` data is contiguous (up to
}
```

The `padding` property specifies how many rows of attribute data in each dimension come from neighboring grids. This is useful in situations where the primitive represents a single tile in a larger grid, and data from neighboring tiles is needed for non-local effects e.g. trilinear interpolation, blurring, antialiasing. `padding.before` and `padding.after` specify the number of rows before and after the grid in each dimension, e.g. a `padding.before` of 1 and a `padding.after` of 2 in the `y` dimension mean that each series of values in a given `y`-slice is preceded by one value and followed by two.
### No Data Values

The padding data must be supplied with the rest of the voxel data - this means if `dimensions` is `[d1, d2, d3]`, `padding.before` is `[b1, b2, b3]`, and `padding.after` is `[a1, a2, a3]`, the attribute must supply `(d1 + a1 + b1)*(d2 + a2 + b2)*(d3 + a3 + b3)` elements.
Voxel primitives may optionally specify a "No Data" value (or "sentinel value") for its attributes to indicate where property values do not exist. This "No Data" value may be provided for any type of attribute, but must be defined according to the type of its `accessor`. For `normalized` accessors, the `noData` value should be specified as the raw data value *before* normalization.

### No Data Values
The "No Data" values for attributes must be defined in the `noData` object. Any key in `noData` must match an existing key in the primitive's `attributes` object. However, not all `attributes` are required to provide a `noData` value.

For instance, if a voxel primitive references the following accessors...

```json
"accessors": [
{
"type": "SCALAR",
"componentType": 5122, // SHORT
"normalized": true
},
{
"type": "VEC3",
"componentType": 5126, // FLOAT
},
// ....
]
```

...then it may define `noData` values for its corresponding attributes like so:

```json
"meshes": [
Expand All @@ -129,17 +166,17 @@ The padding data must be supplied with the rest of the voxel data - this means i
{
"attributes": {
"_TEMPERATURE": 0,
"_SALINITY": 1,
"_DATA_LOSS": 2
"_DIRECTION": 1,
"_DATA_CONFIDENCE": 2
},
"mode": 2147483648,
"mode": 2147483647,
"extensions": {
"EXT_primitive_voxels": {
"shape": 0,
"dimensions": [8, 8, 8],
"noData": {
"_TEMPERATURE": -999.99,
"_SALINITY": -999
"_TEMPERATURE": -32768,
"_DIRECTION": [-999.99, -999.99, -999.99]
}
}
}
Expand All @@ -149,34 +186,31 @@ The padding data must be supplied with the rest of the voxel data - this means i
]
```

Note that `_DATA_CONFIDENCE` intentionally does not specify a `noData` value. The attribute is expected to contain a valid value for every voxel cell.

### Metadata

This extension may be paired with the `EXT_structural_metadata` extension to convey more semantic information about the voxel attributes.

```json
{
"extensions": {
"KHR_implicit_shapes": {
"shapes": [
{
"box": {
"size": [2, 2, 2]
}
}
]
},
"EXT_structural_metadata": {
"schema": {
"classes": {
"voxels": {
"properties": {
"temperature": {
// ...
"type": "SCALAR",
"componentType": "UINT32",
"normalized": true,
"offset": 32.0,
"scale": 1.8
}
}
}
}
}
},
"propertyAttributes": [
{
"class": "voxels",
Expand Down Expand Up @@ -215,5 +249,7 @@ This extension may be paired with the `EXT_structural_metadata` extension to con
}
```

`EXT_structural_metadata` may also specify a `noData` value for a property attribute property. Runtimes have the liberty to decide what will happen if `EXT_primitive_voxels` also provides a different `noData` value for the same attribute.

## Optional vs. Required
This extension is required, meaning it should be placed in both the `extensionsUsed` list and `extensionsRequired` list.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"minItems": 1
}
],
"description": "For `SCALAR` attributes this is a number. For `VECN` attributes this is an array of `N` numbers. For `MATN` attributes this is `N` arrays of `N` numbers."
"description": "A `noData` value represents missing data — also known as a sentinel value — wherever it appears. For `SCALAR` attributes this is a number. For `VECN` attributes this is an array of `N` numbers. For `MATN` attributes this is `N` arrays of `N` numbers."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"$ref": "padding.schema.json"
},
"noData": {
"description": "A plain JSON object, where each key corresponds to a mesh attribute semantic and each value is the attribute's `noData` value. A `noData` value represents missing data — also known as a sentinel value — wherever it appears.",
"description": "A plain JSON object, where each key corresponds to an existing semantic in the primitive's `attributes`, and each value is the attribute's `noData` value. A `noData` value represents missing data — also known as a sentinel value — wherever it appears.",
"type": "object",
"minProperties": 1,
"additionalProperties": {
Expand Down

0 comments on commit 351ef49

Please sign in to comment.