Skip to content

add EXT_primitive_voxels #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1cbfb0a
add EXT_primitive_voxels
krupkad Dec 20, 2021
aea0fd2
add per-dimension and asymmetric neighboringEdges
krupkad Dec 21, 2021
2ed6724
explain memory layout and rework neighboringEdges
krupkad Dec 22, 2021
237186f
explain memory layout and rework neighboringEdges
krupkad Dec 22, 2021
d503e84
add image header and image formatting
krupkad Dec 22, 2021
e51dd28
use solid sample voxels for examples
krupkad Dec 23, 2021
4c5f021
add voxel bounds property
krupkad Dec 23, 2021
31fea78
add reserved primitive modes
krupkad Dec 23, 2021
458cc69
fix voxel grid shape sample axes
krupkad Jan 3, 2022
682e8ff
clarify explanation of voxel grid bounds
krupkad Jan 3, 2022
0d3670e
Update README.md
IanLilleyT Mar 30, 2022
58c66f4
Update README.md
IanLilleyT Mar 30, 2022
ed35109
Update README.md
IanLilleyT Mar 30, 2022
e03c114
Update README.md
IanLilleyT Mar 30, 2022
60a28d1
Update README.md
IanLilleyT Mar 30, 2022
5220357
Merge remote-tracking branch 'origin/main' into ext-primitive-voxels
IanLilleyT Mar 30, 2022
678c5ed
Merge branch '3d-tiles-next' into ext-primitive-voxels
IanLilleyT Mar 30, 2022
1387ba3
Update README.md
IanLilleyT Mar 30, 2022
4484f25
Merge branch '3d-tiles-next' into ext-primitive-voxels
lilleyse Jul 10, 2022
0eefbe8
Update schema
lilleyse Jul 16, 2022
91fc2f8
Merge branch '3d-tiles-next' into ext-primitive-voxels
lilleyse Aug 31, 2022
dcc826e
Update README.md
j9liu May 21, 2024
0107640
Add box grid visuals
j9liu May 22, 2024
b3a961d
Add cylinder grid visuals
j9liu May 22, 2024
40ebbdb
Begin rewriting bounds property
j9liu May 22, 2024
c805aaf
Add voxel grid geometry schemas
j9liu May 30, 2024
dc1029a
Add EXT_implicit_geometry
j9liu Jun 4, 2024
22e2c71
Bounds -> Slice
j9liu Jun 4, 2024
98f2868
Begin to tie EXT_implicit_geometry into EXT_primitive_voxels
j9liu Jun 4, 2024
be26d0f
Move EXT_implicit_geometry to glTF root
j9liu Jun 12, 2024
74113f2
Fix broken uris
j9liu Jun 12, 2024
c9c6abf
Fix typos in region slice
j9liu Jun 12, 2024
60a4b4f
Add 'shape' to voxel extension
j9liu Jun 12, 2024
cd6749e
Make shape integer + required
j9liu Jun 17, 2024
981c69b
Use glTFid instead
j9liu Jun 17, 2024
9e8df19
Delete extraneous characters
j9liu Jun 27, 2024
1244f79
Remove EXT_implicit_geometry, add EXT_implicit_ellipsoid_region
j9liu Oct 25, 2024
2b387c0
Add cylinder region extension
j9liu Oct 25, 2024
6dec236
Minor cleanup
j9liu Oct 29, 2024
fe44738
Fix some typos and outdated info
j9liu Dec 3, 2024
ea998cf
Tweak `EXT_implicit_cylinder_region` README
j9liu Jan 28, 2025
5048335
Update README.md for EXT_implicit_ellipsoid_region
j9liu Jan 28, 2025
cfe3cc7
Try updating CI to v4
j9liu Jan 29, 2025
af8ea2d
Change v2 -> v4
j9liu Jan 29, 2025
92688a3
Add to EXT_primitive_voxels, update figures
j9liu Jan 30, 2025
351ef49
Finalize EXT_primitive_voxels README
j9liu Jan 31, 2025
519ff87
Review feedback
j9liu Jan 31, 2025
a877414
Merge pull request #69 from CesiumGS/ext-primitive-voxels-revisions
lilleyse Jan 31, 2025
574bda2
Region -> Ellipsoid
j9liu Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions extensions/2.0/Vendor/EXT_primitive_voxels/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# EXT_primitive_voxels

<p align="center">
<img src="figures/voxel_cube.png">
</p>

## Contributors
- Daniel Krupka, Cesium
- Ian Lilley, Cesium
- Sean Lilley, Cesium

## Status
Draft

## Dependencies
Written against the glTF 2.0 specification.

## Overview

This extension allows primitives to use their attribute data to represent volumetric (voxel) data.

```
{
"meshes": [
{
"primitives": [
{
"attributes": {
"_TEMPERATURE": 1
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't say much about the attributes used here. Some questions:

  • Do any of the built-in attributes (POSITION, NORMAL, TEXCOORD_n, etc.) have well-defined behavior in a voxel context? or are they treated the same as custom attributes like _TEMPERATURE here?
  • Just to check, are there any restrictions on types? e.g. if I made a matrix attribute, that would work fine? if so, how does it interact with the matrix padding requirements

},
"mode": 2147483648,
"extensions": {
"EXT_primitive_voxels": {
"dimensions": [8, 8, 8],
"bounds": {
"min": [0.25, 0.5, 0.5],
"max": [0.375, 0.625, 0.625]
},
"padding": {
"before": [1, 1, 1],
"after": [1, 1, 1]
}
}
}
}
]
}
]
}
```

The extension adds three new primitive modes, corresponding to voxel grid geometries:
- `0x80000000` (`2147483648`) - A Cartesian box. The grid is a Cartesian grid of equally-sized boxes.
- `0x80000001` (`2147483649`) - A cylinder. The grid is a stack of concentric rings, evenly divided around the circumference.
- `0x80000002` (`2147483650`) - An ellipsoid. The grid is a set of concentric ellipsoids, divided evenly in latitude and longitude.

The lowest byte is reserved for future voxel modes: `0x80000000`-`0x800000FF`.

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

These grids all define "unit" objects centered at the origin, contained in the bounding box between `(-1, -1, -1)` and `(1, 1, 1)`. Node transforms should be used to position, orient, and scale the voxel grid as needed. The `POSITION` attribute is _not_ required or used by this extension - all positioning is through node transforms.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sentence about POSITION, which of these two cases is true:

  • A voxel primitive with a POSITION attribute is valid, but the attribute will be ignored
  • the POSITION attribute is forbidden.

The current wording sounds like the former (which I think makes sense), just wanted to check.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's the former


The `dimensions` property of the extension specifies the voxel grid dimensions:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a short explanation of how these coordinates map to the memory layout

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree, you've described this to me as a "reinterpret cast", but it would be good to describe this in more detail in the spec.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diagrams and pictures could be helpful here, like showing how the same voxel grid maps to these different shapes.

- x/y/z for boxes
- r/z/theta for cylinders
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In glTF, y is up -- is the cylinder z coordinate pointing in the y direction or the z direction? this should be made clear (perhaps with a diagram)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the cylinder coordinate names from r/z/theta to radius/height/angle so I hope it's more clear now. The flat top of the cylinder (bounds.max.y) corresponds to height and is positive Y axis.

👍 to a diagram.

- lon/lat/height for ellipsoids
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- lon/lat/height for ellipsoids
- longitude/latitude/height for ellipsoids

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


Dimensions must be nonzero. Elements are laid out in memory first-axis-contiguous, e.g. for boxes, `x` data is contiguous (up to stride).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"first-axis-contiguous" is a term I've never heard before. I find this confusing.

I think you mean column major? (albeit that is a confusing term in 3D. here's an example of row major in 3D) basically "x-major" means it's the first index if you access it array[a][b][c] and therefore the index that changes the slowest. At least I think?

Also see how NumPy describes its arrays as either row- or column- major (the order parameter) for an example with n-dimensional arrays.

Copy link

@IanLilleyT IanLilleyT Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps that sentence can be reworded. It's row-major access where x changes the fastest. If this were a C array (row major) it would be accessed like array[z][y][x]. I wonder if array[x][y][z] is more typical...


The `bounds` property describes which section of the primitive is mapped to the voxel grid. `bounds.min` and `bounds.max` specify a "rectangular" region of the voxel grid in the appropriate coordinate systems:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is bounds used to crop the data or is it used to compress the grid into a smaller region?

e.g. if you were to use a sector of a cylinder (let's say a quarter, pi/2 radians), is it using only 1/4th of the grid or is it a sector that's 4 times as detailed?

Copy link

@IanLilleyT IanLilleyT Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's compress, not crop. That's a good word, might get the point across better. In you example it would be 1/4th the grid. If you changed the bounds to pi/4 it would be 1/8th the grid, but the same total number of voxels (and thus more detailed).

- Boxes: a rectangular region of the box, between `(-1, -1, -1)` and `(1, 1, 1)`. **This is essentially a no-op - prefer using node transforms for boxes**.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not going to be used, should it be forbidden for boxes?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- Cylinders: a slice of the cylinder, between `(0, -1, 0)` and `(1, 1, 2*pi)`
- Ellipsoids: a surface patch with height, between `(-pi, -pi/2, 0)` and `(pi, pi/2, 1)`

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.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To a glTF user (and not a 3D Tiles user), this is going to sound confusing. what is a "tile"? do you have a concrete example to illustrate this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll need a diagram for this. You're right that calling it a tile is confusing since the padding can be used for other purposes. I'll have to rework this paragraph a bit.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait is it padding or neighboringEdges? the spec and schema seem inconsistent.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to padding


The padding data must be supplied with the rest of the voxel data - this means if `dimensions` is `[d1, d2, d3]`, `beforeCount` is `[b1, b2, b3]`, and `afterCount` is `[a1, a2, a3]`,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I see what you're getting at, but a more concrete example, perhaps with a diagram would be helpful

the attribute must supply `(d1 + a1 + b1)*(d2 + a2 + b2)*(d3 + a3 + b3)` elements.

## 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "mesh.primitive.EXT_primitive_voxels.schema.json",
"title": "EXT_primitive_voxels glTF Mesh Primitive extension",
"type": "object",
"description": "`EXT_primitive_voxels` extension for a primitive in a glTF model, to specify voxel grid geomtetry for volumetric data",
"allOf": [
{
"$ref": "glTFProperty.schema.json"
}
],
"properties": {
"dimensions": {
"type": "array",
"description": "Dimensions of the voxel grid. x/y/z for a box, r/theta/z for a cylinder, lat/lon/height for an ellipsoid.",
"items": {
"type": "integer",
"minimum": 1
},
"minItems": 3,
"maxItems": 3
},
"bounds": {
"type": {
"properties": {
"minimum": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 3,
"maxItems": 3
},
"maximum": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 3,
"maxItems": 3
}
}
}
},
"neighboringEdges": {
"type": {
"properties": {
"beforeCount": {
"type": "array",
"description": "Number of neighboring data values before each dimension of the grid.",
"items": {
"type": "integer",
"minimum": 0,
"default": 0
},
"minItems": 3,
"maxItems": 3
},
"afterCount": {
"type": "array",
"description": "Number of neighboring data values after each dimension of the grid.",
"items": {
"type": "integer",
"minimum": 0,
"default": 0
},
"minItems": 3,
"maxItems": 3
}
}
},
"description": "The number of rows of neighboring tiles' voxel data."
}
},
"required": ["dimensions"]
}
1 change: 1 addition & 0 deletions extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SPDX-License-Identifier: CC-BY-4.0
* [EXT_lights_image_based](2.0/Vendor/EXT_lights_image_based/README.md)
* [EXT_mesh_gpu_instancing](2.0/Vendor/EXT_mesh_gpu_instancing/README.md)
* [EXT_meshopt_compression](2.0/Vendor/EXT_meshopt_compression/README.md)
* [EXT_primitive_voxels](2.0/Vendor/EXT_primitive_voxels/README.md)
* [EXT_texture_webp](2.0/Vendor/EXT_texture_webp/README.md)

#### Vendor Extensions
Expand Down