cesium
cesium copied to clipboard
Allow users to define clipping regions with polygons
Description
The PR implements a new API for clipping that allows user to define a collection of polygonal areas rather than defining individual clipping planes.
This allows:
- An easier-to-use API for clipping regions more inline with how clipping is implemented in Cesium for Unreal
- Users now specify polygon positions rather than planes with transforms
- In particular clipping for global tilesets such as Google's Photogrammetric 3D Tiles becomes much simpler
- Users can now define multiple regions instead of just one
- Users can now define concave regions
- Users can toggle an
inverse
property to isolate regions instead of clipping them
Out of scope for this PR:
-
Holes: It'd be possible to integrate holes into the existing implementation. In particular the inside/outside and distance algorithm would support holes as-is. The sticking point is mainly scope – Our existing
PolygonHierarchy
(what would really should use to keep the API cohesive) definition supports an unlimited recursive list of holes, and how we pack that into the texture used for the compute command would need some work to support holes. It's also totally feasible to add ahierarchy
option at a later date. Given all that, I would suggest keeping it out of the scope of this PR and see if the feature is requested. - Shadows: Currently, clipping polygons are not taken into account for shadows. They are not implemented for clipping planes either, so it may make sense to tackle this together outside of this PR.
With building inset | Without building inset |
---|---|
Concave clipping region | Inverted clipping regions |
---|---|
This is implemented very similar to clipping planes, where we:
- Add a new
ClippingPolygon
, defined by a list of three or more positions, andClippingPolygonCollection
for managing the list and state - This collection can be applied one or more tilesets, or a model
- Use intersections with 3D tiles bounding volumes to determine if a tile is being clipped or not
- Pack the details of the clipping area into a texture
- Add a new model pipeline stage and modifications to
GlobeFS
which add lines the fragment shader todiscard
the area within the polygon
To avoid doing inside/outside checks for each fragment, we instead use a ComputeCommand
to generate a texture containing the signed distance from the polygons' edges, and the fragment shader instead samples the results from this pre-computed texture. Additionally, the spherical approximation method is borrowed from our implementation of texture mapping for groundPrimitives, and should be enough precision for most cases.
Issue number and link
Fixes https://github.com/CesiumGS/cesium/issues/8751
Testing plan
For both 3D Tiles and the globe (this sandcastle allows you to toggle between the two):
- Verify multiple polygons can be clipped at once.
- Verify polygons far away clip.
- Verify polygons intersecting one another clip.
- Verify inverse clipping for multiple polygons.
- Verify concave polygons clip correctly.
- Verify concave polygons inverse clip correctly.
- Verify removing polygons from a collection.
- Verify performance (FPS) is comparable for a polygon with many positions, using:
viewer.scene.debugShowFramesPerSecond = true;
- Verify clipping resolution when zoomed in
Author checklist
- [x] I have submitted a Contributor License Agreement
- [x] I have added my name to
CONTRIBUTORS.md
- [x] I have updated
CHANGES.md
with a short summary of my change - [x] I have added or updated unit tests to ensure consistent code coverage
- [x] I have update the inline documentation, and included code examples where relevant
- [x] I have performed a self-review of my code
- [x] Performance testing
- [ ] ~Exclude clipped areas from shadows~
- [x] Testing plan
- [x] Polished Sandcastle
- [x] Jagged edges on large polygons
- [x] Move AEC tileset into the CesiumJS ion account
- [ ] Squash commits
Hi @ggetz Massive thank you for this PR. Your work represents a significant step forward in improving asset integration capabilities, and we are incredibly excited about the potential it unlocks for us and community.
Your implementation could greatly enhance the way users interact with external 3D integration into 3Dtileset. This is why your contribution is viewed as a key feature for us and the community.
We found a glitch with shadows where the hidden part always casts shadows, which is quite annoying when we want to do a shadow analysis of an integrated CAD or BIM model.
Looking forward to your thoughts and any further actions you deem necessary to bring this PR to completion. Let's make this amazing feature available to everyone in the CesiumJS community!
Very interesting tool! @cesiumgs-admin do you know when will be avalaible?
Thanks @tbenazzi and @Masty88 for the interest!
We are reviewing some performance impact of this feature currently, and I'm aiming to get it into the March 1 release.
We found a glitch with shadows where the hidden part always casts shadows, which is quite annoying when we want to do a shadow analysis of an integrated CAD or BIM model.
This is a good point. We will evaluate whether its possible to include in this iteration. If not, we will certainly open a feature request for it. Thanks for the idea!
Hi, Any idea when this feature will get released?
@saadatali48 Sorry for the delay. This PR is next on my list, and ideally will go out with the next release. Thanks for the interest!
@jjhembd This should be ready for a first pass. ~Please note the remaining TODO's include finishing up the unit tests~ ~and jagged edges on large polygons which corresponds with the one TODO
comment in the code~.
I'm getting some strange results with large polygons on terrain.
The polygon has just 4 points.
The same polygon on 3D Tiles doesn't seem to clip anything.
I'm getting some strange results with large polygons on terrain.
@jjhembd Thanks for pointing this out. Was this the only polygon in the scene or were there multiple?
Was this the only polygon in the scene or were there multiple?
Good question. I can only trigger the problem if there are multiple polygons. Here is the result with only one large polygon (looks fine):
And here is the result if I first draw a smaller polygon in the NW corner, then a large one in the center:
I'm getting some strange results with large polygons on terrain.
Thanks for pointing this out @jjhembd. I think this should be resolved now.
The same polygon on 3D Tiles doesn't seem to clip anything.
Something seems to be very different about the behavior of root tiles on Google P3DT. I'm looking into that now.
Thanks for the thorough review @jjhembd! I believe I've addressed all of you feedback and this is ready for another look.
Thanks @ggetz, the code is looking good, and the issue with large polygons is fixed.
I have two more smaller comments on the Sandcastles.
AEC Clipping Sandcastle
This one works well, and it's a very interesting demo!
A minor nitpick: the initial camera position is awkward for me. The region of interest is mostly out of view, below the camera.
Clipping Regions Sandcastle
The clipping polygon seems to lose resolution when zooming out to a lower LOD in the underlying data. For example, here I clipped out part of Michigan:
But when I zoom out, one point in the polygon appears to be lost:
Zooming out further leaves only 4 points in the polygon, and the original shape is gone:
This aggressive polygon simplification is similar in both Terrain and 3D Tiles.
Thanks @jjhembd! I believe I've addressed your feedback. You can now see 1) a better view of the AEC clipping region, and 2) Michigan at scale.
@jjhembd I've made some additional adjustments based on your feedback.
- There was a bug with removing then adding polygons with the same number of positions, which was a simple fix in the update function.
- To remove artifacts, I increased the amount of padding defining the polygon extents. My concern was this would affect performance, but when measuring I could not detect any effect on the framerate.
Super thank you!
Is clippingPolygon supported for VoxelPrimitive?
@catnuko Not presently, but we can open a feature request for this. Would you mind giving us a few details about your use case?