Skip to content

Commit

Permalink
Merge pull request #53 from javagl/add-gpu-instance-metadata-example
Browse files Browse the repository at this point in the history
Add preliminary GPU instance metadata example
  • Loading branch information
lilleyse authored Aug 2, 2022
2 parents d87268f + 879cb78 commit 380bbd4
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 6 deletions.
178 changes: 178 additions & 0 deletions glTF/GpuInstancesMetadata/GpuInstancesMetadata.gltf
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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/)
Loading
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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">

0 comments on commit 380bbd4

Please sign in to comment.