From 6c71ebc0c2b19977b7e9fc20e3ab369f4af37465 Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:00:48 -0500 Subject: [PATCH 1/8] support BENTLEY_materials_point_style --- .../StyledPoints/points-r5-g8-b14-y10.gltf | 222 ++++++++++++++++++ packages/engine/Source/Scene/GltfLoader.js | 10 + .../Scene/Model/MaterialPipelineStage.js | 17 ++ .../engine/Source/Scene/ModelComponents.js | 10 + .../engine/Source/Shaders/Model/ModelFS.glsl | 8 + .../engine/Source/Shaders/Model/ModelVS.glsl | 2 + .../gallery/styled-gltf-points/index.html | 36 +++ .../gallery/styled-gltf-points/main.js | 42 ++++ .../styled-gltf-points/sandcastle.yaml | 6 + .../gallery/styled-gltf-points/thumbnail.jpg | Bin 0 -> 5949 bytes 10 files changed, 353 insertions(+) create mode 100755 Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf create mode 100644 packages/sandcastle/gallery/styled-gltf-points/index.html create mode 100644 packages/sandcastle/gallery/styled-gltf-points/main.js create mode 100644 packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml create mode 100644 packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg diff --git a/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf b/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf new file mode 100755 index 000000000000..fae9d455bb8b --- /dev/null +++ b/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf @@ -0,0 +1,222 @@ +{ + "asset": { + "version": "2.0" + }, + "extensionsUsed": [ + "BENTLEY_materials_point_style" + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5126, + "count": 4, + "type": "VEC3", + "max": [ + 5.0, + 5.0, + 5.0 + ], + "min": [ + -5.0, + -5.0, + -5.0 + ] + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 0 + ], + "min": [ + 0 + ] + }, + { + "bufferView": 1, + "byteOffset": 4, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 1 + ], + "min": [ + 1 + ] + }, + { + "bufferView": 1, + "byteOffset": 8, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 2 + ], + "min": [ + 2 + ] + }, + { + "bufferView": 1, + "byteOffset": 12, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 3 + ], + "min": [ + 3 + ] + } + ], + "buffers": [ + { + "byteLength": 64, + "uri": "data:application/octet-stream;base64,AACgwAAAoMAAAKDAAACgQAAAoMAAAKDAAAAAAAAAoEAAAKDAAAAAAAAAAAAAAKBAAAAAAAEAAAACAAAAAwAAAA==" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 48, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 48, + "byteLength": 16, + "target": 34963 + } + ], + "materials": [ + { + "name": "Red", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1.0, + 0.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 5.0 + } + } + }, + { + "name": "Green", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 1.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 8.0 + } + } + }, + { + "name": "Blue", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 0.0, + 1.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 14.0 + } + } + }, + { + "name": "Yellow", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1.0, + 1.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 10.0 + } + } + } + ], + "meshes": [ + { + "name": "PointCloud", + "primitives": [ + { + "mode": 0, + "material": 0, + "indices": 1, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 1, + "indices": 2, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 2, + "indices": 3, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 3, + "indices": 4, + "attributes": { + "POSITION": 0 + } + } + ] + } + ], + "nodes": [ + { + "name": "PointCloudNode", + "mesh": 0 + } + ], + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "scene": 0 +} diff --git a/packages/engine/Source/Scene/GltfLoader.js b/packages/engine/Source/Scene/GltfLoader.js index 800d4a7c2428..c96ca9b82178 100644 --- a/packages/engine/Source/Scene/GltfLoader.js +++ b/packages/engine/Source/Scene/GltfLoader.js @@ -1811,6 +1811,16 @@ function loadMaterial(loader, gltfMaterial, frameState) { material.alphaCutoff = gltfMaterial.alphaCutoff; material.doubleSided = gltfMaterial.doubleSided; + // BENTLEY_materials_point_style extension + const pointStyleExtension = extensions.BENTLEY_materials_point_style; + if (defined(pointStyleExtension) && defined(pointStyleExtension.diameter)) { + const diameter = pointStyleExtension.diameter; + // Validate that diameter is a positive integer as the extension specification requires. + if (diameter > 0 && Math.floor(diameter) === diameter) { + material.pointDiameter = diameter; + } + } + return material; } diff --git a/packages/engine/Source/Scene/Model/MaterialPipelineStage.js b/packages/engine/Source/Scene/Model/MaterialPipelineStage.js index ed2f9e2f1f94..58136200d6aa 100644 --- a/packages/engine/Source/Scene/Model/MaterialPipelineStage.js +++ b/packages/engine/Source/Scene/Model/MaterialPipelineStage.js @@ -167,6 +167,23 @@ MaterialPipelineStage.process = function ( alphaOptions.alphaCutoff = material.alphaCutoff; } + // Configure and handle point diameter for POINTS primitives (BENTLEY_materials_point_style extension). + if (defined(material.pointDiameter)) { + shaderBuilder.addDefine( + "HAS_POINT_DIAMETER", + undefined, + ShaderDestination.VERTEX, + ); + shaderBuilder.addUniform( + "float", + "u_pointDiameter", + ShaderDestination.VERTEX, + ); + uniformMap.u_pointDiameter = function () { + return material.pointDiameter * frameState.pixelRatio; + }; + } + shaderBuilder.addFragmentLines(MaterialStageFS); if (material.doubleSided) { diff --git a/packages/engine/Source/Scene/ModelComponents.js b/packages/engine/Source/Scene/ModelComponents.js index 71d7fb088076..b63d5f20741b 100644 --- a/packages/engine/Source/Scene/ModelComponents.js +++ b/packages/engine/Source/Scene/ModelComponents.js @@ -1623,6 +1623,16 @@ function Material() { * @private */ this.unlit = false; + + /** + * The point diameter in pixels for POINTS primitives. This is set by the + * BENTLEY_materials_point_style extension. + * + * @type {number} + * @default undefined + * @private + */ + this.pointDiameter = undefined; } /** diff --git a/packages/engine/Source/Shaders/Model/ModelFS.glsl b/packages/engine/Source/Shaders/Model/ModelFS.glsl index 76d3469ef094..4be74fa86844 100644 --- a/packages/engine/Source/Shaders/Model/ModelFS.glsl +++ b/packages/engine/Source/Shaders/Model/ModelFS.glsl @@ -29,6 +29,14 @@ SelectedFeature selectedFeature; void main() { + #ifdef PRIMITIVE_TYPE_POINTS + // Render points as circles + float distanceToCenter = length(gl_PointCoord - vec2(0.5)); + if (distanceToCenter > 0.5) { + discard; + } + #endif + #ifdef HAS_POINT_CLOUD_SHOW_STYLE if (v_pointCloudShow == 0.0) { diff --git a/packages/engine/Source/Shaders/Model/ModelVS.glsl b/packages/engine/Source/Shaders/Model/ModelVS.glsl index 96cee64b06e1..8b11b84d05bf 100644 --- a/packages/engine/Source/Shaders/Model/ModelVS.glsl +++ b/packages/engine/Source/Shaders/Model/ModelVS.glsl @@ -142,6 +142,8 @@ void main() gl_PointSize = vsOutput.pointSize; #elif defined(HAS_POINT_CLOUD_POINT_SIZE_STYLE) || defined(HAS_POINT_CLOUD_ATTENUATION) gl_PointSize = pointCloudPointSizeStylingStage(attributes, metadata); + #elif defined(HAS_POINT_DIAMETER) + gl_PointSize = u_pointDiameter; #else gl_PointSize = 1.0; #endif diff --git a/packages/sandcastle/gallery/styled-gltf-points/index.html b/packages/sandcastle/gallery/styled-gltf-points/index.html new file mode 100644 index 000000000000..abd8f4b3276d --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points/index.html @@ -0,0 +1,36 @@ + + + + + + + + + Styled glTF Points + + + + + + +
+

Loading...

+
+ + + diff --git a/packages/sandcastle/gallery/styled-gltf-points/main.js b/packages/sandcastle/gallery/styled-gltf-points/main.js new file mode 100644 index 000000000000..f316829c513d --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points/main.js @@ -0,0 +1,42 @@ +import * as Cesium from "cesium"; + +const viewer = new Cesium.Viewer("cesiumContainer"); + +// The following .gltf file contains styled point data using the BENTLEY_materials_point_style extension. +// The styled point data allows the points to have a variety of diameters. +const modelURL = + "../../SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf"; + +const height = 0.0; +const hpr = new Cesium.HeadingPitchRoll(0.0, 0.0, 0.0); +const origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height); +const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, hpr); + +try { + const model = viewer.scene.primitives.add( + await Cesium.Model.fromGltfAsync({ + url: modelURL, + modelMatrix: modelMatrix, + }), + ); + + model.readyEvent.addEventListener(() => { + const camera = viewer.camera; + + // Zoom to model + const controller = viewer.scene.screenSpaceCameraController; + const r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near); + controller.minimumZoomDistance = r * 0.5; + + const center = model.boundingSphere.center; + const heading = Cesium.Math.toRadians(230.0); + const pitch = Cesium.Math.toRadians(-20.0); + camera.lookAt( + center, + new Cesium.HeadingPitchRange(heading, pitch, r * 2.0), + ); + camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + }); +} catch (error) { + window.alert(`Error loading model: ${error}`); +} diff --git a/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml b/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml new file mode 100644 index 000000000000..8ea6d4aa2b7d --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml @@ -0,0 +1,6 @@ +legacyId: Styled glTF Points.html +title: Styled glTF Points +description: Use BENTLEY_materials_point_style to apply width to glTF points. +labels: + - Showcases +thumbnail: thumbnail.jpg diff --git a/packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg b/packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f3cdb739642dcadb004362da52b745fecdabbe17 GIT binary patch literal 5949 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 literal 0 HcmV?d00001 From 7b2920c7a9f8f6bb909428e0e293ff0d15402fcb Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:02:50 -0500 Subject: [PATCH 2/8] CHANGES.md --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9e7c825dac05..5dbd898f3a0a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,10 @@ - Fixes label positioning in workflows that delete and recreate clamped labels [#12949](https://github.com/CesiumGS/cesium/issues/12949) +#### Additions :tada: + +- Added support for the proposed [BENTLEY_materials_point_style](https://github.com/CesiumGS/glTF/pull/91) glTF extension. This allows point primitives to have a diameter property specified and respected when loaded via glTF. + ## 1.136 - 2025-12-01 ### @cesium/engine From ada58133eba617458ebdd58a987220b444da7884 Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:43:22 -0500 Subject: [PATCH 3/8] unit test --- .../StyledPoints/points-r5-g8-b14-y10.gltf | 222 ++++++++++++++++++ packages/engine/Specs/Scene/GltfLoaderSpec.js | 53 +++++ 2 files changed, 275 insertions(+) create mode 100755 Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf diff --git a/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf b/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf new file mode 100755 index 000000000000..fae9d455bb8b --- /dev/null +++ b/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf @@ -0,0 +1,222 @@ +{ + "asset": { + "version": "2.0" + }, + "extensionsUsed": [ + "BENTLEY_materials_point_style" + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5126, + "count": 4, + "type": "VEC3", + "max": [ + 5.0, + 5.0, + 5.0 + ], + "min": [ + -5.0, + -5.0, + -5.0 + ] + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 0 + ], + "min": [ + 0 + ] + }, + { + "bufferView": 1, + "byteOffset": 4, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 1 + ], + "min": [ + 1 + ] + }, + { + "bufferView": 1, + "byteOffset": 8, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 2 + ], + "min": [ + 2 + ] + }, + { + "bufferView": 1, + "byteOffset": 12, + "componentType": 5125, + "count": 1, + "type": "SCALAR", + "max": [ + 3 + ], + "min": [ + 3 + ] + } + ], + "buffers": [ + { + "byteLength": 64, + "uri": "data:application/octet-stream;base64,AACgwAAAoMAAAKDAAACgQAAAoMAAAKDAAAAAAAAAoEAAAKDAAAAAAAAAAAAAAKBAAAAAAAEAAAACAAAAAwAAAA==" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 48, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 48, + "byteLength": 16, + "target": 34963 + } + ], + "materials": [ + { + "name": "Red", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1.0, + 0.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 5.0 + } + } + }, + { + "name": "Green", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 1.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 8.0 + } + } + }, + { + "name": "Blue", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 0.0, + 1.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 14.0 + } + } + }, + { + "name": "Yellow", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1.0, + 1.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0 + }, + "extensions": { + "BENTLEY_materials_point_style": { + "diameter": 10.0 + } + } + } + ], + "meshes": [ + { + "name": "PointCloud", + "primitives": [ + { + "mode": 0, + "material": 0, + "indices": 1, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 1, + "indices": 2, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 2, + "indices": 3, + "attributes": { + "POSITION": 0 + } + }, + { + "mode": 0, + "material": 3, + "indices": 4, + "attributes": { + "POSITION": 0 + } + } + ] + } + ], + "nodes": [ + { + "name": "PointCloudNode", + "mesh": 0 + } + ], + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "scene": 0 +} diff --git a/packages/engine/Specs/Scene/GltfLoaderSpec.js b/packages/engine/Specs/Scene/GltfLoaderSpec.js index 41ac57e6330d..dea68f41770f 100644 --- a/packages/engine/Specs/Scene/GltfLoaderSpec.js +++ b/packages/engine/Specs/Scene/GltfLoaderSpec.js @@ -128,6 +128,8 @@ describe( "./Data/Models/glTF-2.0/BoxAnisotropy/glTF/BoxAnisotropy.gltf"; const clearcoatTestData = "./Data/Models/glTF-2.0/BoxClearcoat/glTF/BoxClearcoat.gltf"; + const pointStyleTestData = + "./Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf"; const meshPrimitiveRestartTestData = "./Data/Models/glTF-2.0/MeshPrimitiveRestart/glTF/MeshPrimitiveRestart.gltf"; const edgeVisibilityTestData = @@ -4176,6 +4178,57 @@ describe( expect(clearcoatNormalTexture.texture.width).toBe(256); }); + it("loads model with BENTLEY_materials_point_style extension", async function () { + const gltfLoader = await loadGltf(pointStyleTestData); + + // The test model has 4 primitives with different materials. Let's verify they all exist. + const primitives = gltfLoader.components.nodes[0].primitives; + expect(primitives.length).toBe(4); + + // Check that pointDiameter was loaded correctly for each material. Each primitive has a different diameter. + expect(primitives[0].material.pointDiameter).toBe(5); + expect(primitives[1].material.pointDiameter).toBe(8); + expect(primitives[2].material.pointDiameter).toBe(14); + expect(primitives[3].material.pointDiameter).toBe(10); + }); + + it("ignores BENTLEY_materials_point_style with invalid negative diameter", async function () { + function modifyGltf(gltf) { + // Set an invalid negative diameter (diameters must be >0). + gltf.materials[0].extensions.BENTLEY_materials_point_style.diameter = + -5; + return gltf; + } + + const gltfLoader = await loadModifiedGltfAndTest( + pointStyleTestData, + undefined, + modifyGltf, + ); + + // The invalid negative diameter should be ignored; property should be undefined once the glTF is loaded. + const material = gltfLoader.components.nodes[0].primitives[0].material; + expect(material.pointDiameter).toBeUndefined(); + }); + + it("ignores BENTLEY_materials_point_style with non-integer diameter", async function () { + function modifyGltf(gltf) { + // Set an invalid non-integer diameter (diameters must be integers). + gltf.materials[0].extensions.BENTLEY_materials_point_style.diameter = 5.5; + return gltf; + } + + const gltfLoader = await loadModifiedGltfAndTest( + pointStyleTestData, + undefined, + modifyGltf, + ); + + // Invalid non-integer diameter should be ignored; property should be undefined once the glTF is loaded. + const material = gltfLoader.components.nodes[0].primitives[0].material; + expect(material.pointDiameter).toBeUndefined(); + }); + it("loads model with EXT_mesh_primitive_restart extension", async function () { const gltf = await Resource.fetchJson({ url: meshPrimitiveRestartTestData, From 200d0863fa8957819775b89e422a9eed90ed0163 Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Thu, 11 Dec 2025 07:43:26 -0500 Subject: [PATCH 4/8] use unsigned short indices so CI can work if OES_element_index_uint is not available --- .../models/StyledPoints/points-r5-g8-b14-y10.gltf | 8 ++++---- .../glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf b/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf index fae9d455bb8b..3de571c1a3b3 100755 --- a/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf +++ b/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf @@ -26,7 +26,7 @@ { "bufferView": 1, "byteOffset": 0, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -39,7 +39,7 @@ { "bufferView": 1, "byteOffset": 4, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -52,7 +52,7 @@ { "bufferView": 1, "byteOffset": 8, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -65,7 +65,7 @@ { "bufferView": 1, "byteOffset": 12, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ diff --git a/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf b/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf index fae9d455bb8b..3de571c1a3b3 100755 --- a/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf +++ b/Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf @@ -26,7 +26,7 @@ { "bufferView": 1, "byteOffset": 0, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -39,7 +39,7 @@ { "bufferView": 1, "byteOffset": 4, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -52,7 +52,7 @@ { "bufferView": 1, "byteOffset": 8, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ @@ -65,7 +65,7 @@ { "bufferView": 1, "byteOffset": 12, - "componentType": 5125, + "componentType": 5123, "count": 1, "type": "SCALAR", "max": [ From 24025b550de1dfcfed884f9b38808a889ec714a3 Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:32:45 -0500 Subject: [PATCH 5/8] make the sandcastle example be dev --- .../gallery/styled-gltf-points/index.html | 36 --------------- .../gallery/styled-gltf-points/main.js | 42 ------------------ .../styled-gltf-points/sandcastle.yaml | 6 --- .../gallery/styled-gltf-points/thumbnail.jpg | Bin 5949 -> 0 bytes 4 files changed, 84 deletions(-) delete mode 100644 packages/sandcastle/gallery/styled-gltf-points/index.html delete mode 100644 packages/sandcastle/gallery/styled-gltf-points/main.js delete mode 100644 packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml delete mode 100644 packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg diff --git a/packages/sandcastle/gallery/styled-gltf-points/index.html b/packages/sandcastle/gallery/styled-gltf-points/index.html deleted file mode 100644 index abd8f4b3276d..000000000000 --- a/packages/sandcastle/gallery/styled-gltf-points/index.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - Styled glTF Points - - - - - - -
-

Loading...

-
- - - diff --git a/packages/sandcastle/gallery/styled-gltf-points/main.js b/packages/sandcastle/gallery/styled-gltf-points/main.js deleted file mode 100644 index f316829c513d..000000000000 --- a/packages/sandcastle/gallery/styled-gltf-points/main.js +++ /dev/null @@ -1,42 +0,0 @@ -import * as Cesium from "cesium"; - -const viewer = new Cesium.Viewer("cesiumContainer"); - -// The following .gltf file contains styled point data using the BENTLEY_materials_point_style extension. -// The styled point data allows the points to have a variety of diameters. -const modelURL = - "../../SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf"; - -const height = 0.0; -const hpr = new Cesium.HeadingPitchRoll(0.0, 0.0, 0.0); -const origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height); -const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, hpr); - -try { - const model = viewer.scene.primitives.add( - await Cesium.Model.fromGltfAsync({ - url: modelURL, - modelMatrix: modelMatrix, - }), - ); - - model.readyEvent.addEventListener(() => { - const camera = viewer.camera; - - // Zoom to model - const controller = viewer.scene.screenSpaceCameraController; - const r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near); - controller.minimumZoomDistance = r * 0.5; - - const center = model.boundingSphere.center; - const heading = Cesium.Math.toRadians(230.0); - const pitch = Cesium.Math.toRadians(-20.0); - camera.lookAt( - center, - new Cesium.HeadingPitchRange(heading, pitch, r * 2.0), - ); - camera.lookAtTransform(Cesium.Matrix4.IDENTITY); - }); -} catch (error) { - window.alert(`Error loading model: ${error}`); -} diff --git a/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml b/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml deleted file mode 100644 index 8ea6d4aa2b7d..000000000000 --- a/packages/sandcastle/gallery/styled-gltf-points/sandcastle.yaml +++ /dev/null @@ -1,6 +0,0 @@ -legacyId: Styled glTF Points.html -title: Styled glTF Points -description: Use BENTLEY_materials_point_style to apply width to glTF points. -labels: - - Showcases -thumbnail: thumbnail.jpg diff --git a/packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg b/packages/sandcastle/gallery/styled-gltf-points/thumbnail.jpg deleted file mode 100644 index f3cdb739642dcadb004362da52b745fecdabbe17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5949 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 From 9ebb71b675fc225fbdc57466dc7ff0713d3511bc Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:33:01 -0500 Subject: [PATCH 6/8] make the sandcastle example be dev --- .../gallery/styled-gltf-points-dev/index.html | 36 +++++++++++++++ .../gallery/styled-gltf-points-dev/main.js | 42 ++++++++++++++++++ .../styled-gltf-points-dev/sandcastle.yaml | 7 +++ .../styled-gltf-points-dev/thumbnail.jpg | Bin 0 -> 5949 bytes 4 files changed, 85 insertions(+) create mode 100644 packages/sandcastle/gallery/styled-gltf-points-dev/index.html create mode 100644 packages/sandcastle/gallery/styled-gltf-points-dev/main.js create mode 100644 packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml create mode 100644 packages/sandcastle/gallery/styled-gltf-points-dev/thumbnail.jpg diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/index.html b/packages/sandcastle/gallery/styled-gltf-points-dev/index.html new file mode 100644 index 000000000000..abd8f4b3276d --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points-dev/index.html @@ -0,0 +1,36 @@ + + + + + + + + + Styled glTF Points + + + + + + +
+

Loading...

+
+ + + diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/main.js b/packages/sandcastle/gallery/styled-gltf-points-dev/main.js new file mode 100644 index 000000000000..f316829c513d --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points-dev/main.js @@ -0,0 +1,42 @@ +import * as Cesium from "cesium"; + +const viewer = new Cesium.Viewer("cesiumContainer"); + +// The following .gltf file contains styled point data using the BENTLEY_materials_point_style extension. +// The styled point data allows the points to have a variety of diameters. +const modelURL = + "../../SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf"; + +const height = 0.0; +const hpr = new Cesium.HeadingPitchRoll(0.0, 0.0, 0.0); +const origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height); +const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, hpr); + +try { + const model = viewer.scene.primitives.add( + await Cesium.Model.fromGltfAsync({ + url: modelURL, + modelMatrix: modelMatrix, + }), + ); + + model.readyEvent.addEventListener(() => { + const camera = viewer.camera; + + // Zoom to model + const controller = viewer.scene.screenSpaceCameraController; + const r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near); + controller.minimumZoomDistance = r * 0.5; + + const center = model.boundingSphere.center; + const heading = Cesium.Math.toRadians(230.0); + const pitch = Cesium.Math.toRadians(-20.0); + camera.lookAt( + center, + new Cesium.HeadingPitchRange(heading, pitch, r * 2.0), + ); + camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + }); +} catch (error) { + window.alert(`Error loading model: ${error}`); +} diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml b/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml new file mode 100644 index 000000000000..9ab94a96dd3c --- /dev/null +++ b/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml @@ -0,0 +1,7 @@ +legacyId: Styled glTF Points.html +title: Styled glTF Points - Dev +description: Use BENTLEY_materials_point_style to apply width to glTF points. +labels: + - Showcases +thumbnail: thumbnail.jpg +development: true diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/thumbnail.jpg b/packages/sandcastle/gallery/styled-gltf-points-dev/thumbnail.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f3cdb739642dcadb004362da52b745fecdabbe17 GIT binary patch literal 5949 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 literal 0 HcmV?d00001 From e3e4ab07f8bc9ac00ed5fbe536feb59e0687a310 Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:46:40 -0500 Subject: [PATCH 7/8] Remove Showcases label --- .../sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml b/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml index 9ab94a96dd3c..568be84b77e7 100644 --- a/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml +++ b/packages/sandcastle/gallery/styled-gltf-points-dev/sandcastle.yaml @@ -2,6 +2,6 @@ legacyId: Styled glTF Points.html title: Styled glTF Points - Dev description: Use BENTLEY_materials_point_style to apply width to glTF points. labels: - - Showcases + - Development thumbnail: thumbnail.jpg development: true From f93f62294bd2fc37604735674000af5d8697adfe Mon Sep 17 00:00:00 2001 From: Mark Schlosser <47000437+markschlosseratbentley@users.noreply.github.com> Date: Fri, 9 Jan 2026 14:57:54 -0500 Subject: [PATCH 8/8] only use one copy of the .gltf sample file --- .../StyledPoints/points-r5-g8-b14-y10.gltf | 222 ------------------ .../gallery/styled-gltf-points-dev/main.js | 2 +- 2 files changed, 1 insertion(+), 223 deletions(-) delete mode 100755 Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf diff --git a/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf b/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf deleted file mode 100755 index 3de571c1a3b3..000000000000 --- a/Apps/SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf +++ /dev/null @@ -1,222 +0,0 @@ -{ - "asset": { - "version": "2.0" - }, - "extensionsUsed": [ - "BENTLEY_materials_point_style" - ], - "accessors": [ - { - "bufferView": 0, - "byteOffset": 0, - "componentType": 5126, - "count": 4, - "type": "VEC3", - "max": [ - 5.0, - 5.0, - 5.0 - ], - "min": [ - -5.0, - -5.0, - -5.0 - ] - }, - { - "bufferView": 1, - "byteOffset": 0, - "componentType": 5123, - "count": 1, - "type": "SCALAR", - "max": [ - 0 - ], - "min": [ - 0 - ] - }, - { - "bufferView": 1, - "byteOffset": 4, - "componentType": 5123, - "count": 1, - "type": "SCALAR", - "max": [ - 1 - ], - "min": [ - 1 - ] - }, - { - "bufferView": 1, - "byteOffset": 8, - "componentType": 5123, - "count": 1, - "type": "SCALAR", - "max": [ - 2 - ], - "min": [ - 2 - ] - }, - { - "bufferView": 1, - "byteOffset": 12, - "componentType": 5123, - "count": 1, - "type": "SCALAR", - "max": [ - 3 - ], - "min": [ - 3 - ] - } - ], - "buffers": [ - { - "byteLength": 64, - "uri": "data:application/octet-stream;base64,AACgwAAAoMAAAKDAAACgQAAAoMAAAKDAAAAAAAAAoEAAAKDAAAAAAAAAAAAAAKBAAAAAAAEAAAACAAAAAwAAAA==" - } - ], - "bufferViews": [ - { - "buffer": 0, - "byteOffset": 0, - "byteLength": 48, - "target": 34962 - }, - { - "buffer": 0, - "byteOffset": 48, - "byteLength": 16, - "target": 34963 - } - ], - "materials": [ - { - "name": "Red", - "pbrMetallicRoughness": { - "baseColorFactor": [ - 1.0, - 0.0, - 0.0, - 1.0 - ], - "metallicFactor": 0.0 - }, - "extensions": { - "BENTLEY_materials_point_style": { - "diameter": 5.0 - } - } - }, - { - "name": "Green", - "pbrMetallicRoughness": { - "baseColorFactor": [ - 0.0, - 1.0, - 0.0, - 1.0 - ], - "metallicFactor": 0.0 - }, - "extensions": { - "BENTLEY_materials_point_style": { - "diameter": 8.0 - } - } - }, - { - "name": "Blue", - "pbrMetallicRoughness": { - "baseColorFactor": [ - 0.0, - 0.0, - 1.0, - 1.0 - ], - "metallicFactor": 0.0 - }, - "extensions": { - "BENTLEY_materials_point_style": { - "diameter": 14.0 - } - } - }, - { - "name": "Yellow", - "pbrMetallicRoughness": { - "baseColorFactor": [ - 1.0, - 1.0, - 0.0, - 1.0 - ], - "metallicFactor": 0.0 - }, - "extensions": { - "BENTLEY_materials_point_style": { - "diameter": 10.0 - } - } - } - ], - "meshes": [ - { - "name": "PointCloud", - "primitives": [ - { - "mode": 0, - "material": 0, - "indices": 1, - "attributes": { - "POSITION": 0 - } - }, - { - "mode": 0, - "material": 1, - "indices": 2, - "attributes": { - "POSITION": 0 - } - }, - { - "mode": 0, - "material": 2, - "indices": 3, - "attributes": { - "POSITION": 0 - } - }, - { - "mode": 0, - "material": 3, - "indices": 4, - "attributes": { - "POSITION": 0 - } - } - ] - } - ], - "nodes": [ - { - "name": "PointCloudNode", - "mesh": 0 - } - ], - "scenes": [ - { - "nodes": [ - 0 - ] - } - ], - "scene": 0 -} diff --git a/packages/sandcastle/gallery/styled-gltf-points-dev/main.js b/packages/sandcastle/gallery/styled-gltf-points-dev/main.js index f316829c513d..efc6a27da0aa 100644 --- a/packages/sandcastle/gallery/styled-gltf-points-dev/main.js +++ b/packages/sandcastle/gallery/styled-gltf-points-dev/main.js @@ -5,7 +5,7 @@ const viewer = new Cesium.Viewer("cesiumContainer"); // The following .gltf file contains styled point data using the BENTLEY_materials_point_style extension. // The styled point data allows the points to have a variety of diameters. const modelURL = - "../../SampleData/models/StyledPoints/points-r5-g8-b14-y10.gltf"; + "../../../Specs/Data/Models/glTF-2.0/StyledPoints/points-r5-g8-b14-y10.gltf"; const height = 0.0; const hpr = new Cesium.HeadingPitchRoll(0.0, 0.0, 0.0);