It was great meeting many of you at the Cesium Conference last week!
While I was there, I took the opportunity to discuss some specific feature requirements I currently have with @janine.
Thank you again for nudging me in the right direction .
Since returning, I have started exploring the changes needed to introduce the functionality Iām looking for.
Here is my problem:
GeoJSON files can currently be used to clip parts of 3D Tiles using CesiumGeoJsonDocumentRasterOverlay.
However, this only hides the mesh by discarding the texture during rendering. The mesh itself and its textures are still loaded and cached, and if collisions are enabled, it also contributes to physics calculations.
In my specific use case, I use GeoJSON files to cut out the GoogleMaps 3D Tiles to replace with our own mesh for a city. As you can imagine this has tremendous performance implications.
Furthermore, CesiumGeoJsonDocumentRasterOverlay is currently broken on WebGL, as I reported here:
(I also hope my new class would function as a workaround to this GitHub-Issue~)
Cesium already has a very clever workaround for this, which is used by CesiumPolygonRasterOverlay. In this approach, the polygon becomes a RasterizedPolygonsTileExcluder, causing tiles entirely inside the polygon to not be loaded at all.
To address this, I started implementing a new class that acts as an abstraction of CesiumCartographicPolygon and uses the existing CesiumGeoJsonDocument to enable efficient GeoJSON-based cutouts.
I already have a working prototype up and running and am now looking into a proper implementation for a pull-request.
For this, I have two questions:
Architecture
CesiumCartographicPolygon was clearly not designed to be inherited for such a use case. Furthermore, CesiumPolygonRasterOverlay currently requires objects of this type to function:
The two options I see are:
1) Inherit from CesiumCartographicPolygon
This would work, but it would also inherit the following requirements:
These components are entirely unnecessary for the new class using GeoJson as they neither require Splines or a CesiumGlobeAnchor as the GeoJson already contains the required cartographicPoints in the correct format.
2) Create an abstract base class
Both CesiumCartographicPolygon and the new GeoJSON-based class would inherit from this base class.
While this would introduce architectural changes, it should retain backward compatibility as CesiumCartographicPolygon may continue to be used as is.
Support for Holes
Currently, CesiumCartographicPolygon does not support additional rings for holes.
Likewise, the new GeoJSON cutout class would not support holes, since the current cesium-native implementation does not allow for them.
The triangulation library being used, mapbox::earcut:
does however support holes according to their documentation:
CartographicPolygon.cpp currently only accepts a single std::vector<glm::dvec2>, which prevents support for additional rings.
Extending this to support an arbitrary number of rings would allow polygons to contain any number of holes.
From what I can tell, this would only require overloading the function here:
to accept a std::vector<std::vector<glm::dvec2>>.
I do wonder whether there are any reasons Iām overlooking as to why this hasnāt been implemented already. I figured it would be worth asking before I attempt the impossible .
It was great to meet you at DevCon! Thanks for posting on the community forum
For reference, Iām sharing the approach we did in Unreal. We added a function that takes an array of points and constructs the spline from it; in this way, you can take the points of a GeoJSON polygon and plug them into the polygon at runtime:
Now, it would be nice to just set a GeoJSON asset on the polygon so it would automatically assume its shape. My first instinct would be to make the normal CesiumCartographicPolygon consume the GeoJSON and automatically move its spline points based on the input polygon. This would allow for both Editor and Runtime visualization of the polygon, and potentially allows for fine-tune editing if you āsaveā the shape of the polygon in the Editor. But weād be open to other ideas, since we havenāt fully tried this out from a UI/UX perspective.
RE: support for holes ā thatās a limitation we just havenāt tackled yet, so itād be great to get a community contribution for a solution! I believe we handle polygon rings when we rasterize GeoJSONs in cesium-native, so we just have to add similar capability in CartographicPolygon.
Excited to see where this goes ā keep us updated!
While I think the ability to convert to Spline Points is great for further fine-tuning, it also introduces some unnecessary overhead to the application. Also, in my opinion, modifying the loaded GeoJSON somewhat defeats its purpose in a geospatial workflow. At that point, one might as well use Splines directly from the start.
My current implementation focuses heavily on reusing existing logic and providing the same flexibility as similar overlays, allowing them to be used via code, URL, and Ion.
That said, I think it would make a lot of sense to support converting a GeoJSON polygon into a spline-based polygon as an additional workflow.
In my implementation, this should be fairly straightforward, since both the spline-based and GeoJSON-based cutouts now inherit from the same base class .
My plan would be to add a function like:
List<double2> GetPolygonRing()
to expose the polygon ring from the new GeoJSON-based class, and a corresponding
FromRing(List<double2>)
factory/helper on CesiumCartographicPolygon.
With those pieces in place, converting a GeoJSON polygon into a spline-based polygon at runtime becomes as trivial as in Unreal.
On top of that, I could add a button to CesiumPolygonRasterOverlayEditor that creates a new CesiumCartographicPolygon with splines generated from the GeoJSON geometry In-Editor.
Lastly - Editor visualization should not be a problem.
My idea would be to submit an initial PR with this functionality (+any changes to them) first, and then follow up with support for holes in the future ^^.
How does that sound?
Also: Feel free to try the changes I added to get a feel for the UI/UX ^^ I have added a package to my fork here.
I appreciate your thoughts on this! Let me take a step back, because Iām worried weāll go too narrow with implementation details.
Currently, Cesium for Unity provides two existing overlays that can handle polygons:
CesiumPolygonRasterOverlay, which consumes the CesiumCartographicPolygon splines
CesiumGeoJsonRasterOverlay, which rasterizes the GeoJSON and also allows for styling.
The concern with adding a CesiumGeoJsonPolygonRasterOverlay is it would be an ad-hoc in-between of our two existing solutions. And what CesiumGeoJsonPolygonRasterOverlay does is technically already possible with CesiumGeoJsonDocumentRasterOverlay. One could import a GeoJSON doc, style the polygons with a masking color, and modify the tileset material to consume it as a clipping overlay. (Perhaps it would even work if you set the material key to Clipping, though I canāt remember if we allow that in the Unity UI.)
With this in mind, it seems like the major friction would be:
Fine-grained control over which polygons in the GeoJSON document are used for clipping
Requiring less user changes to the material/overlay to enable this workflow
Rather than creating a third, unique overlay, we should be able to expand on CesiumPolygonRasterOverlay/CesiumCartographicPolygon or CesiumGeoJsonRasterOverlay to enable the two points above. Or both! Thatās why I proposed making a way to turn a GeoJSON polygon into a CesiumCartographicPolygon, since that connection to the clipping code in the material already exists.
However, when using a CesiumGeoJsonDocumentRasterOverlay with āClippingā, this comes with the huge downside that this is purely styling.
From my original post:
However, this only hides the mesh by discarding the texture during rendering. The mesh itself and its textures are still loaded and cached, and if collisions are enabled, it also contributes to physics calculations.
Since CesiumGeoJsonDocumentRasterOverlayās use case seem to be purely styling, I donāt know if it would be the correct choice to add RasterizedPolygonsTileExclude to it.
It would be entirely possible to forgo a new class and instead extend CesiumCartographicPolygon.
This, however, carries the drawback that every CesiumCartographicPolygon comes with the overhead of two additional components: SplineContainer and CesiumGlobeAnchor, which are technically unnecessary in this context.
I personally think that the proposed class represents a distinctly different use case, which in my view justifies introducing a new class. Especially since all existing functionality remains as is, and my last proposal would cover ALL of the methodologies we talked about so far.
(Besides choosing, which polygons of the the GeoJSON are used - but since Multipolygons are not currently supported I did not so far concern with that).
In the project I am working on, I operate under extremely tight performance constraints, and squeezing out every last bit of performance is of the highest importance. I may therefore be over-optimizing compared to a more general use case.
If that is the case, I could simply extend CesiumCartographicPolygon and devise another class in my own repository to address the issue I am encountering with this approach locally.