Hello Cesium Community,
I’m working on an interactive visualization feature for a point cloud Cesium3DTileset and need some guidance on achieving a specific effect.
Goal: I want to increase the pointSize of a single, specific point within a Cesium3DTileset only when the mouse cursor hovers directly over that point for a sustained duration (e.g., 3-5 seconds). When the cursor moves away, the point should revert to its default size.
What I’ve tried and the challenges encountered:
- Mouse Picking:
- I can get the screen position of the mouse cursor using
movement.endPositionfrom aScreenSpaceEventHandler. - Using
viewer.scene.pick(movement.endPosition): This often returns aPickedObjectwhoseprimitiveis theCesium3DTilesetitself, but I’m struggling to reliably get aCesium3DTileFeaturefor the individual point under the cursor. For point clouds, I expectpick()to return aCesium3DTileFeatureif an individual point is hit. - Using
viewer.scene.pickPosition(movement.endPosition): This gives me aCartesian3world position on the surface (which could be terrain or the tileset), but it doesn’t provide a direct link to the specificCesium3DTileFeatureor its properties, which I believe is crucial for targeting.
- Custom Shaders for Point Size:
- I’ve implemented a
CustomShaderto modifypointSizein thevertexShaderusingvsOutput.pointSize. - I pass the
currentMousePosition(obtained frompickPosition) as au_positionMCuniform. - Issue: My current shader logic applies the size change to all points, rather than just the single, precisely hovered point. Here’s the relevant shader code I’m using:
const customShader = new Cesium.CustomShader({
uniforms: {
u_pointSize: {
type: Cesium.UniformType.FLOAT,
value: 10.0, // Example highlight size
},
u_defaultPointSize: { // Added default point size uniform
type: Cesium.UniformType.FLOAT,
value: 2.0, // Example default size
},
u_positionMC: {
type: Cesium.UniformType.VEC3,
value: currentMousePosition, // This is updated from JS
},
u_highlightRadius: { // Added highlight radius uniform
type: Cesium.UniformType.FLOAT,
value: 0.1, // Small radius to simulate 'equality'
}
},
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
// Transform the point's model coordinates to world coordinates
vec3 pointWorldPosition = (czm_modelView * vec4(vsInput.attributes.positionMC, 1.0)).xyz;
float dist = distance(pointWorldPosition, u_positionMC);
if (dist < u_highlightRadius) {
vsOutput.pointSize = u_pointSize; // Apply highlight size
} else {
vsOutput.pointSize = u_defaultPointSize; // Revert to default size
}
}
`,
});
The Core Challenge:
My primary difficulty is how to effectively target only the specific point that the mouse has hovered over for a prolonged period.
- Precise Point Targeting in Shader: How can I pass information to the
CustomShaderthat allows it to uniquely identify and modify just the hovered point’s size (and potentially color), rather than all points within a general radius? Is there a way to leveragefeatureIdor other per-feature properties within the shader for this purpose?
Any insights, alternative approaches, or examples demonstrating precise point targeting and sustained hover detection for Cesium3DTileset point clouds would be immensely helpful!
Thank you in advance for your time and expertise.
Best regards,
Sarah O.