Skip to content
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

Add preliminary GPU instance metadata example #53

Merged
merged 2 commits into from Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
178 changes: 178 additions & 0 deletions glTF/GpuInstancesMetadata/GpuInstancesMetadata.gltf
@@ -0,0 +1,178 @@
{
"extensions" : {
"EXT_structural_metadata" : {
"schema" : {
"classes" : {
"exampleMetadataClass" : {
"name" : "Example metadata class",
"description" : "An example metadata class",
"properties" : {
"example_STRING" : {
"name" : "Example STRING property",
"description" : "An example property, with component type STRING",
"type" : "STRING"
}
}
}
}
},
"propertyTables" : [ {
"name" : "Example property table",
"class" : "exampleMetadataClass",
"count" : 10,
"properties" : {
"example_STRING" : {
"values" : 7,
"stringOffsets" : 8
}
}
} ]
}
},
"extensionsUsed" : [ "EXT_structural_metadata", "EXT_mesh_gpu_instancing", "EXT_instance_features" ],
"accessors" : [ {
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5125,
"count" : 36,
"type" : "SCALAR",
"max" : [ 23 ],
"min" : [ 0 ]
}, {
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 24,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 1.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}, {
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 24,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 1.0 ],
"min" : [ -1.0, -1.0, -1.0 ]
}, {
"bufferView" : 3,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 10,
"type" : "VEC3",
"max" : [ 10.0, 10.0, 10.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}, {
"bufferView" : 4,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 10,
"type" : "VEC4",
"max" : [ 0.733, 0.462, 0.191, 1.0 ],
"min" : [ 0.0, 0.0, 0.0, 0.462 ]
}, {
"bufferView" : 5,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 10,
"type" : "VEC3",
"max" : [ 2.0, 2.0, 2.0 ],
"min" : [ 1.0, 1.0, 1.0 ]
}, {
"bufferView" : 6,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 10,
"type" : "SCALAR",
"max" : [ 9 ],
"min" : [ 0 ]
} ],
"asset" : {
"generator" : "JglTF from https://github.com/javagl/JglTF",
"version" : "2.0"
},
"buffers" : [ {
"uri" : "data:application/gltf-buffer;base64,AAAAAAIAAAABAAAAAAAAAAMAAAACAAAABAAAAAYAAAAFAAAABAAAAAcAAAAGAAAACAAAAAoAAAAJAAAACAAAAAsAAAAKAAAADAAAAA4AAAANAAAADAAAAA8AAAAOAAAAEAAAABIAAAARAAAAEAAAABMAAAASAAAAFAAAABYAAAAVAAAAFAAAABcAAAAWAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA",
"byteLength" : 720
}, {
"uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAA5DiOP+Q4jj/kOI4/5DgOQOQ4DkDkOA5AVlVVQFZVVUBWVVVA5DiOQOQ4jkDkOI5AHcexQB3HsUAdx7FAVlXVQFZV1UBWVdVAjuP4QI7j+ECO4/hA5DgOQeQ4DkHkOA5BAAAgQQAAIEEAACBBAAAAAAAAAAAAAAAAAACAP92ZzD0Q9YA9B0HVPHcffj/QGUs+AAMAPrywUz3rhHg/HXaWPuWqPT4f05w9Y0VvP3UqxT6+ing+IIHNPZiDYj+d+vA+w+KXPqEr+z1ub1I/DaEMP/RFsT6bkxI+REU/P9m0Hj+hD8g+H2slPgpNKT/WdC4/P+rbPqHVNT462RA/46U7P0SL7D6BlUM+RIvsPgAAgD8AAIA/AACAP+Q4jj/kOI4/5DiOP8dxnD/HcZw/x3GcP6uqqj+rqqo/q6qqP47juD+O47g/juO4P3Icxz9yHMc/chzHP1ZV1T9WVdU/VlXVPzmO4z85juM/OY7jPxzH8T8cx/E/HMfxPwAAAEAAAABAAAAAQAkACAAHAAYABQAEAAMAAgABAAAA",
"byteLength" : 420
}, {
"uri" : "data:application/gltf-buffer;base64,emVyb29uZXR3b3RocmVlZm91cmZpdmVzaXhzZXZlbmVpZ2h0bmluZQAAAAAEAAAABwAAAAoAAAAPAAAAEwAAABcAAAAaAAAAHwAAACQAAAAoAAAA",
"byteLength" : 84
} ],
"bufferViews" : [ {
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 144,
"target" : 34963
}, {
"buffer" : 0,
"byteOffset" : 144,
"byteLength" : 288,
"target" : 34962
}, {
"buffer" : 0,
"byteOffset" : 432,
"byteLength" : 288,
"target" : 34962
}, {
"buffer" : 1,
"byteOffset" : 0,
"byteLength" : 120
}, {
"buffer" : 1,
"byteOffset" : 120,
"byteLength" : 160
}, {
"buffer" : 1,
"byteOffset" : 280,
"byteLength" : 120
}, {
"buffer" : 1,
"byteOffset" : 400,
"byteLength" : 20
}, {
"buffer" : 2,
"byteOffset" : 0,
"byteLength" : 40
}, {
"buffer" : 2,
"byteOffset" : 40,
"byteLength" : 44
} ],
"meshes" : [ {
"primitives" : [ {
"attributes" : {
"POSITION" : 1,
"NORMAL" : 2
},
"indices" : 0,
"mode" : 4
} ]
} ],
"nodes" : [ {
"extensions" : {
"EXT_mesh_gpu_instancing" : {
"attributes" : {
"TRANSLATION" : 3,
"ROTATION" : 4,
"SCALE" : 5,
"_FEATURE_ID_0" : 6
}
},
"EXT_instance_features" : {
"featureIds" : [ {
"featureCount" : 10,
"attribute" : 0,
"propertyTable" : 0
} ]
}
},
"mesh" : 0
} ],
"scene" : 0,
"scenes" : [ {
"nodes" : [ 0 ]
} ]
}
112 changes: 112 additions & 0 deletions glTF/GpuInstancesMetadata/README.md
@@ -0,0 +1,112 @@
# Metadata for GPU instances

An example showing how to assign metadata to GPU instances.

The example combines three different extensions:

- It uses `EXT_mesh_gpu_instancing` to create 10 GPU-based instances
- It uses `EXT_instance_features` to assign feature IDs to these instances
- It uses `EXT_structural_metadata` to define a property table with 10 rows, which can be looked up based on the feature IDs.

## Screenshot

![Image](screenshot/GpuInstancesMetadata.gif)

## Example Sandcastle

```JavaScript
const viewer = new Cesium.Viewer("cesiumContainer");

// Create the tileset, and move it to a certain position on the globe
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: `http://localhost:8003/glTF/GpuInstanceMetadata/tileset.json`,
debugShowBoundingVolume: true,
})
);
tileset.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.152325, 39.94704, 0)
);
const offset = new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(22.5),
Cesium.Math.toRadians(-22.5),
40.0
);
viewer.zoomTo(tileset, offset);

// Create an HTML element that will serve as the
// tooltip that displays the feature information
function createTooltip() {
const tooltip = document.createElement("div");
viewer.container.appendChild(tooltip);
tooltip.style.backgroundColor = "black";
tooltip.style.position = "absolute";
tooltip.style.left = "0";
tooltip.style.top = "0";
tooltip.style.padding = "14px";
tooltip.style["pointer-events"] = "none";
tooltip.style["block-size"] = "fit-content";
return tooltip;
}
const tooltip = createTooltip();

// Show the given HTML content in the tooltip
// at the given screen position
function showTooltip(screenX, screenY, htmlContent) {
tooltip.style.display = "block";
tooltip.style.left = `${screenX}px`;
tooltip.style.top = `${screenY}px`;
tooltip.innerHTML = htmlContent;
}

// Create an HTML string that contains information
// about the given feature, under the given title
function createFeatureHtml(title, feature) {
if (!Cesium.defined(feature)) {
return `(No ${title})<br>`;
}
const propertyKeys = feature.getPropertyIds();
if (!Cesium.defined(propertyKeys)) {
return `(No properties for ${title})<br>`;
}
let html = `<b>${title}:</b><br>`;
for (let i = 0; i < propertyKeys.length; i++) {
const propertyKey = propertyKeys[i];
const propertyValue = feature.getProperty(propertyKey);
html += `&nbsp;&nbsp;${propertyKey} : ${propertyValue}<br>`;
}
return html;
}

// Given an object that was obtained via Scene#pick: If it is
// a Cesium3DTileFeature, then it is returned.
// Otherwise, 'undefined' is returned.
function obtainFeature(picked) {
if (!Cesium.defined(picked)) {
return undefined;
}
const isFeature = picked instanceof Cesium.Cesium3DTileFeature;
if (!isFeature) {
return undefined;
}
return picked;
}

// Install the handler that will perform picking when the
// mouse is moved, and update the label entity when the
// mouse is over a Cesium3DTileFeature
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
let tooltipText = "";
const picked = viewer.scene.pick(movement.endPosition);
const feature = obtainFeature(picked);
tooltipText += createFeatureHtml("Feature", feature);
const screenX = movement.endPosition.x;
const screenY = movement.endPosition.y;
showTooltip(screenX, screenY, tooltipText);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
```

## License

[CC0](https://creativecommons.org/share-your-work/public-domain/cc0/)
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions glTF/GpuInstancesMetadata/tileset.json
@@ -0,0 +1,20 @@
{
"asset" : {
"version" : "1.1"
},
"geometricError" : 100.0,
"root" : {
"content" : {
"uri" : "GpuInstancesMetadata.gltf"
},
"boundingVolume" : {
"box" : [
6.707386, -5.8532143, 5.8532143,
6.707386, 0.0, 0.0,
0.0, -5.8532143, 0.0,
0.0, 0.0, 5.8532143
]
},
"geometricError" : 0.0
}
}
22 changes: 16 additions & 6 deletions glTF/README.md
@@ -1,15 +1,27 @@

# Samples for glTF extensions

The following is a list of samples for different glTF extensions that are supported by Cesium. Each directory contains a dedicated `.gltf` file that contains the actual glTF asset. Additionally, each directory also contains a simple `tileset.json` file that is a [3D Tiles](https://github.com/CesiumGS/3d-tiles) tileset which just contains the respective glTF asset as its only content. These tilesets can be viewed in CesiumJS, by hosting the base directory of this repository on a local server.

### `EXT_mesh_features`

The [`EXT_mesh_features`](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features) extension is a glTF 2.0 extension that allows identifying geometry or subcomponents of geometry in glTF 2.0 assets as individual 'features', by associating them with a feature ID.

The sandcastle code for viewing the `EXT_mesh_features` samples is shown in [glTF-Mesh-Features-Samples-Sandcastle.js](glTF-Mesh-Features-Samples-Sandcastle.js)

| Sample | Screenshot |
|:---|:--:|
| [`FeatureIdAttribute`](EXT_mesh_features/FeatureIdAttribute/)<br/> Uses an attribute of a mesh primitive to assign feature IDs to vertices | <img src="EXT_mesh_features/FeatureIdAttribute/screenshot/FeatureIdAttribute.gif" width="300">
| [`FeatureIdTexture`](EXT_mesh_features/FeatureIdTexture/)<br/> Uses a feature ID texture to assign feature IDs to texels on the surface of the geometry | <img src="EXT_mesh_features/FeatureIdTexture/screenshot/FeatureIdTexture.gif" width="300">


### `EXT_structural_metadata`

The [`EXT_structural_metadata`](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata) extension is a glTF 2.0 extension that allows storing structured metadata in glTF 2.0 assets in the form of _property tables_. Together with the [`EXT_mesh_features`](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features) extension, the metadata can be looked up in these tables, using the feature IDs.

The sandcastle code for viewing the `EXT_structural_metadata` samples is shown in [glTF-Structural-Metadata-Samples-Sandcastle.js](glTF-Structural-Metadata-Samples-Sandcastle.js)


| Sample | Screenshot |
|:---|:--:|
| [`FeatureIdAttributeAndPropertyTable`](EXT_structural_metadata/FeatureIdAttributeAndPropertyTable/)<br/> Vertices that are associated with properties that are stored in a property table | <img src="EXT_structural_metadata/FeatureIdAttributeAndPropertyTable/screenshot/FeatureIdAttributeAndPropertyTable.png" width="300">
Expand All @@ -20,12 +32,10 @@ The [`EXT_structural_metadata`](https://github.com/CesiumGS/glTF/tree/3d-tiles-n
| [`ComplexTypes`](EXT_structural_metadata/ComplexTypes/)<br/> Features that contain properties with more complex types | <img src="EXT_structural_metadata/ComplexTypes/screenshot/ComplexTypes.png" width="300">
| [`SimplePropertyTexture`](EXT_structural_metadata/SimplePropertyTexture/)<br/> Properties that are stored in a texture | <img src="EXT_structural_metadata/SimplePropertyTexture/screenshot/SimplePropertyTexture.gif" width="300">

Each directory contains a dedicated `.gltf` file that contains the actual glTF asset. Additionally, each directory also contains a simple `tileset.json` file that is a [3D Tiles](https://github.com/CesiumGS/3d-tiles) tileset which just contains the respective glTF asset as its only content. These tilesets can be viewed in CesiumJS, by hosting the base directory of this repository on a local server, and using the following Cesium Sandcastle code:

## Common Sandcastle Code

The sandcastle code for viewing the `EXT_mesh_features` samples is shown in [glTF-Mesh-Features-Samples-Sandcastle.js](glTF-Mesh-Features-Samples-Sandcastle.js)

The sandcastle code for viewing the `EXT_structural_metadata` samples is shown in [glTF-Structural-Metadata-Samples-Sandcastle.js](glTF-Structural-Metadata-Samples-Sandcastle.js)
### Other glTF extensions

| Sample | Screenshot |
|:---|:--:|
| [`GpuInstancesMetadata`](GpuInstancesMetadata/)<br/> An example that uses `EXT_mesh_gpu_instancing` to create GPU instances that are associated with feature IDs, which are used for looking up metadata in a property table | <img src="GpuInstancesMetadata/screenshot/GpuInstancesMetadata.gif" width="300">