cesium
cesium copied to clipboard
Add support for concave /convex clipping planes + holes in CesiumJS
The user should be able to define a 2D clipping polygon with zero or more holes.
We should support:
- Multiple clipping planes
- Multiple holes in each clipping plane
- Overlapping holes
We should disallow:
- Self-intersecting polygons / holes
- Holes that extend beyond the region of their parent clipping plane.
Requested on the forum here: https://community.cesium.com/t/how-to-clipping-multiple-polygon-on-the-cesium3dtileset/9182/2
I also need support for concave polygon
@NotEmptyWKL can you describe your use case?
@NotEmptyWKL您可以描述您的用例吗? After supporting concave polygon clipping, I can cut the earth into the scope of a country without showing the whole earth
Another request for multiple disjoint clipping polygons came from https://community.cesium.com/t/multiple-clippingplanes/11809
I urgently need multiple clipping on the globe!. Here is a simple effect I achieved.
These files are modified: GlobeSurfaceShaderSet.js, GlobeSurfaceTileProvieder.js, Globe.js, GlobeVS.glsl. New files are created: MultiClippingPlaneCollection.js, getMultiClippingFunction.js.
You can now clip multiple polygons on the globe by passing an instance of MultiClippingPlaneCollection which manages a list of ClippingPlaneCollection to the multiClippingPlanes property new added to the globe.
For example:
var clippingPlanecollection1 = new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 0.0),
new Cesium.ClippingPlane(
new Cesium.Cartesian3(-1.0, 0.0, 0.0),
-500.0
),
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0),
new Cesium.ClippingPlane(
new Cesium.Cartesian3(0.0, -1.0, 0.0),
-15.0
),
],
});
var clippingPlanecollection2 = new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 1000),
new Cesium.ClippingPlane(
new Cesium.Cartesian3(-1.0, 0.0, 0.0),
-2000.0
),
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0),
new Cesium.ClippingPlane(
new Cesium.Cartesian3(0.0, -1.0, 0.0),
-15.0
),
],
});
globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({
collections: [clippingPlanecollection1, clippingPlanecollection2],
modelMatrix: entity.computeModelMatrix(Cesium.JulianDate.now()),
edgeWidth: 1,
edgeColor: Cesium.Color.WHITE,
});
The key point is to rewrite the orginal getClippingFunction.js to getMultiClippingFunction.js to make the fragment shader able to handle multiple clipping plane collections. The shader also needs to know the length of every collection so it can get the correct clipping plane.
This is only a temporary solution on multi-clipping on terrain, more problems to be solved:
- Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
-
It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons.
The star below is actually two triangles.
- It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
- Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
- Having too many clipping collections or too many clipping planes in one collection will cause performance issues.
- There might be bugs. : P
Hope this feautre will come out soon!
There are some mistakes in the MultiClippingPlaneCollection.js file. Please replace it with the new file below. Thanks to @andrevall.
I reuploaded files after I updated Cesium to 1.92. files.zip
I put the exmaple in the sandcaslte https://zhwy.github.io/cesium/Apps/Sandcastle/index.html?src=Terrain%20Multiple%20Clipping%20Planes.html.
Hello @zhwy,
thank you for your reply! I applied the changes you mentioned to the MultiClippingPlaneCollection.js
file and it worked perfectly 😀.
I really hope that @cesiumgs-admin will merge this feature in a future release: clipping multiple holes in the terrain is a feature that a lot of people would benefit from.
Thank you again!
Andrea
You are welcome, Andrea. @andrevall
I urgently need multiple clipping on the globe!. Here is a simple effect I achieved.
These files are modified: GlobeSurfaceShaderSet.js, GlobeSurfaceTileProvieder.js, Globe.js, GlobeVS.glsl. New files are created: MultiClippingPlaneCollection.js, getMultiClippingFunction.js. files.zip
You can now clip multiple polygons on the globe by passing an instance of MultiClippingPlaneCollection which manages a list of ClippingPlaneCollection to the multiClippingPlanes property new added to the globe.
For example:
var clippingPlanecollection1 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 0.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -500.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); var clippingPlanecollection2 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 1000), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -2000.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({ collections: [clippingPlanecollection1, clippingPlanecollection2], modelMatrix: entity.computeModelMatrix(Cesium.JulianDate.now()), edgeWidth: 1, edgeColor: Cesium.Color.WHITE, });
The key point is to rewrite the orginal getClippingFunction.js to getMultiClippingFunction.js to make the fragment shader able to handle multiple clipping plane collections. The shader also needs to know the length of every collection so it can get the correct clipping plane.
This is only a temporary solution on multi-clipping on terrain, more problems to be solved:
- Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
- It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons. The star below is actually two triangles.
![]()
- It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
- Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
- There might be bugs. : P
Hope this feautre will come out soon!
There are some mistakes in the MultiClippingPlaneCollection.js file. Please replace it with the new file below. Thanks to @andrevall. MultiClippingPlaneCollection.zip
excuse me, how to works on the 3dtiles?
@abcdweiok Sorry, I'm not working on it now, might take some time to figure this out.
@Samulus Hi, When will this capability be supported?
Hi @zhwy,
again thank you so much for this amazing extension to CesiumJS! I would like to notify two bugs that I experience with the multiClippingPlaneCollection:
- The first bug happens on iOS devices such as iPhones, iPads etc... I have attached below a video of the bug. Basically, when zooming out, the imagery and terrain disappears completely, but reappears when zooming in. On Android and Windows PC this bug doesn't happen. This is the link I used for demonstration, which is based on Cesium 1.83
- The second problem is that starting from Cesium 1.84 and after (including the latest 1.85 release), the multiClippingPlanes feature crashes Cesium. The latest working version of Cesium that I was able to use with multiClippingPlanes was release version 1.83. For example, on this demo you can see what happens when I compile with Cesium 1.85
I tried fixing these problems, but my webGL and JS knowledge is too limited for this complex stuff 😌
Hi @andrevall,
Thank you for notifying!
The first problem seems to be a bug of Cesium. I found the same problem of the original terrain clipping example on iphone. https://sandcastle.cesium.com/?src=Terrain%20Clipping%20Planes.html I have no idea about how to fix it 😮, maybe we can open a new issue.
About the second problem, the copyFrom interface of Texture class has been modified from 1.84, a 'source' parameter is now required. Two places in MultiClippingPlaneCollection.js need correcting:
this._dataTexture.copyFrom({
source: {
width: widthTotal,
height: height,
arrayBufferView: arrayBuffer,
},
});
this._lengthTexture.copyFrom({
source: {
width: collections.length,
height: 1,
arrayBufferView: lengthArrayBuffer,
},
});
Here's the new file: MultiClippingPlaneCollection.zip
Hi @zhwy,
Following these lines, I reaffirm the importance of this extension. In my case, I am looking for a way to fit the holes in the tunnels of an underground infrastructure and without a doubt it would be great to have this active capacity.
Thanks.
At the moment I can only apply a transparency when I approach the mouth of the tunnel.
Hi @raulvigueras,
Sorry for my replying late. You may try to use the MultiClippingPlaneCollection to clip the holes of tunnels.
Yet the effect is not very good, it's hard to fit the tunnel holes very well.
Thanks @zhwy. I've replaced the GlobeSurfaceTileProvider.js, GlobeSurfaceShaderSet.js, GlobeFS.glsl y Globe.js files, and copied the new MultiClippingPlaneCollection.js and getMultiClippingFunction.js files to their location in ./Source/Scene but I can't create the holes. In the brownser console I get the message 'Uncaught TypeError: Cesium.MultiClippingPlaneCollection is not a constructor'. I have tried with version 1.86 and 1.89. Am I doing something wrong? or am I missing something?
Thanks @zhwy. I've replaced the GlobeSurfaceTileProvider.js, GlobeSurfaceShaderSet.js, GlobeFS.glsl y Globe.js files, and copied the new MultiClippingPlaneCollection.js and getMultiClippingFunction.js files to their location in ./Source/Scene but I can't create the holes. In the brownser console I get the message 'Uncaught TypeError: Cesium.MultiClippingPlaneCollection is not a constructor'. I have tried with version 1.86 and 1.89. Am I doing something wrong? or am I missing something?
Hi @raulvigueras , did you run the compile command like 'npm run build' in the cesium root directory?
After doing this a new Cesium.js will be created in the 'Source' directory and you can import it as a module to use Cesium.MultiClippingPlaneCollection in your test page with 'import * as Cesium from "path/to/Source/Cesium.js"'. You may need to add 'window.CESIUM_BASE_URL = "path/to/Source"' to avoid the Unable to determine Cesium base URL automatically error.
If you want to make a release version, run the command 'npm run minifyRelease' in the root directory and this will create a 'Build/Cesium' directory which contains the Cesium.js. Put the entire 'Build/Cesium' directory on a server, now you can use it with .
I added six clipping surfaces to the project, which caused my page to get stuck
Another problem is that if I add clipping surfaces at the beginning and then I clear them, I need to add them twice if I want to add them again
Hi, @chenwwsdo Can you show some code snippets?
Please show me some code snippets or upload data for me to run tests.
Initial work was started in https://github.com/CesiumGS/cesium/pull/8915
I urgently need multiple clipping on the globe!. Here is a simple effect I achieved.
These files are modified: GlobeSurfaceShaderSet.js, GlobeSurfaceTileProvieder.js, Globe.js, GlobeVS.glsl. New files are created: MultiClippingPlaneCollection.js, getMultiClippingFunction.js.
You can now clip multiple polygons on the globe by passing an instance of MultiClippingPlaneCollection which manages a list of ClippingPlaneCollection to the multiClippingPlanes property new added to the globe.
For example:
var clippingPlanecollection1 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 0.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -500.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); var clippingPlanecollection2 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 1000), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -2000.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({ collections: [clippingPlanecollection1, clippingPlanecollection2], modelMatrix: entity.computeModelMatrix(Cesium.JulianDate.now()), edgeWidth: 1, edgeColor: Cesium.Color.WHITE, });
The key point is to rewrite the orginal getClippingFunction.js to getMultiClippingFunction.js to make the fragment shader able to handle multiple clipping plane collections. The shader also needs to know the length of every collection so it can get the correct clipping plane.
This is only a temporary solution on multi-clipping on terrain, more problems to be solved:
- Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
- It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons. The star below is actually two triangles.
![]()
- It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
- Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
- Having too many clipping collections or too many clipping planes in one collection will cause performance issues.
- There might be bugs. : P
Hope this feautre will come out soon!
There are some mistakes in the MultiClippingPlaneCollection.js file. Please replace it with the new file below. Thanks to @andrevall.
I reuploaded files after I updated Cesium to 1.92. files.zip
Hello,Can I ask how to modify this to apply it in 3DTiles? I apply it in terrain and it success, but it doesn't work in 3DTiles.
我迫切需要在地球上进行多次剪辑!这是我取得的一个简单的效果。
这些文件被修改:GlobeSurfaceShaderSet.js,GlobeSurfaceTileProvieder.js,Globe.js,GlobeVS.glsl。将创建新文件:MultiClippingPlaneCollection.js,getMultiClippingFunction.js。
现在,您可以通过将 MultiClippingPlaneCollection 的实例传递到新添加到 globe 的 multiClippingPlanes 属性来裁剪地球上的多个多边形,该实例管理 ClippingPlaneCollection 的列表。
例如:
var clippingPlanecollection1 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 0.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -500.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); var clippingPlanecollection2 = new Cesium.ClippingPlaneCollection({ planes: [ new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), 1000), new Cesium.ClippingPlane( new Cesium.Cartesian3(-1.0, 0.0, 0.0), -2000.0 ), new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -15.0), new Cesium.ClippingPlane( new Cesium.Cartesian3(0.0, -1.0, 0.0), -15.0 ), ], }); globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({ collections: [clippingPlanecollection1, clippingPlanecollection2], modelMatrix: entity.computeModelMatrix(Cesium.JulianDate.now()), edgeWidth: 1, edgeColor: Cesium.Color.WHITE, });
关键点是重写原始的 getClippingFunction.js **getMultiClippingFunction.js**使片段着色器能够处理多个剪切平面集合。着色器还需要知道每个集合的长度,以便获得正确的剪切平面。
This is only a temporary solution on multi-clipping on terrain, more problems to be solved:
- Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
- It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons. The star below is actually two triangles.
![]()
- It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
- Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
- Having too many clipping collections or too many clipping planes in one collection will cause performance issues.
- There might be bugs. : P
Hope this feautre will come out soon!
There are some mistakes in the MultiClippingPlaneCollection.js file. Please replace it with the new file below. Thanks to @andrevall.
I reuploaded files after I updated Cesium to 1.92. files.zip
Hello, for this fifth shortcoming, I need to load a long curved underground pipeline, and then after using your multiClippingPlanes, it can be loaded, but the page is really stuck. Later, I considered loading the pipeline dynamically, that is, when the camera is at a certain position, only the screen space coordinates of all pipeline points are loaded in the current screen, and these points are composed of pipeline loading. When the camera changes, re-acquire the pipeline points in the screen and reload the pipeline. Now I am indeed able to reacquire the pipe points, regenerate the pipe and load, but one problem I am having now: the clipping plane of the pipe disappears, pulling the camera to height 0, being able to see through the ground that the pipe is indeed loaded However, there is a layer of ground above, and I can't see the pipeline below from above the ground. What should I do? thank you very much.
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Sorry, I want to upload a gif, but it doesn't seem to work.
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
The red line at the beginning is the pipeline loaded through multiClippingPlanes, to make it obvious I used the red image. When the camera is away from the earth, you can see a very long red line, and indeed the page will be very stuck. When I brought the camera close to the ground room again, the red pipe disappeared. It never appears again. Only when the camera is pulled close to the ground, the red pit can be seen under the ground, but it is blocked by the ground. The pit is indeed loaded, but it cannot be displayed normally. I would like to know what are your thoughts? Can this problem be solved? thank you very much.
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello, I get the points inside the screen by dynamically updating the camera changes. By changing the number of points I can really see that every time the camera changes, I get new point data. What is uncertain now is whether the holes dug through these points have changed. But in the browser you can indeed listen to the change of the all array.
viewer.scene.globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({
collections: all,
edgeWidth: 0,
edgeColor: Cesium.Color.WHITE.withAlpha(0.9),
});
In addition, if you stop rendering and updating the pipeline after a period of time is set in the camera change event, then the pipeline can be displayed normally, but the page will be very stuck.
var abc = 0;
viewer.camera.changed.addEventListener(function () {
abc++;
if(abc<5){
...
}
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello @zhwy , I tried again yesterday. I figured out how to remove the multiclippingplanes, clear the data, and then recreate and add the multiclippingplanes. The final result was that multiclippingplanes were indeed removed, but could not be added again. Why is this? Thank you very much.
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello @zhwy , Just now, I tried again and found that there was no problem in cutting the ground for the first time. After a few seconds, I cut the ground for the second time. At this time, the pit for the first time will be covered by the pit for the second time, but there is a problem with the pit for the second time: the display is incomplete
Hello @kk1625846601 , can you upload a screenshot or a gif ? I don't understand "there is a layer of ground above, and I can't see the pipeline below from above the ground". Do you mean the ground is still visible after being clipped?
Hello, I have re studied the whole process and found that the problem lies in the method of generating pits. In the camera change event, the cutting plane can be dynamically updated. There are no problems with your multiclippingplanes.Thanks very much.
Sorry @kk1625846601 , I didn't read comments until now. Glad to know you have solved the problem. BTW, it's brilliant to update clipping planes dynamically to avoid the performance issue!👍
Sorry @kk1625846601 , I didn't read comments until now. Glad to know you have solved the problem. BTW, it's brilliant to update clipping planes dynamically to avoid the performance issue!👍
Hello @zhwy, thank you very much. I can't dig multiple holes without multiclippingplanes.