CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.95k stars 3.49k forks source link

Add support for concave /convex clipping planes + holes in CesiumJS #8751

Closed Samulus closed 6 months ago

Samulus commented 4 years ago

The user should be able to define a 2D clipping polygon with zero or more holes.

We should support:

We should disallow:

OmarShehata commented 4 years ago

Requested on the forum here: https://community.cesium.com/t/how-to-clipping-multiple-polygon-on-the-cesium3dtileset/9182/2

NotEmptyWKL commented 4 years ago

I also need support for concave polygon

OmarShehata commented 4 years ago

@NotEmptyWKL can you describe your use case?

NotEmptyWKL commented 4 years ago

@NotEmptyWKL您可以描述您的用例吗? After supporting concave polygon clipping, I can cut the earth into the scope of a country without showing the whole earth

hpinkos commented 3 years ago

Another request for multiple disjoint clipping polygons came from https://community.cesium.com/t/multiple-clippingplanes/11809

zhwy commented 3 years ago

I urgently need multiple clipping on the globe!. Here is a simple effect I achieved. image

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:

  1. Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
  2. It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons. The star below is actually two triangles. image
  3. It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
  4. Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
  5. Having too many clipping collections or too many clipping planes in one collection will cause performance issues.
  6. 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.

andrevall commented 3 years ago

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

zhwy commented 3 years ago

You are welcome, Andrea. @andrevall

abcdweiok commented 3 years ago

I urgently need multiple clipping on the globe!. Here is a simple effect I achieved. image

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:

  1. Different styles and model matrix on each ClippingPlaneCollection are not supportive. They're set on the ClippingPlaneCollection and are the same for each collection.
  2. It dosen't support concave polygon directly. But you could try decomposing the polygon into convex polygons. The star below is actually two triangles. image
  3. It only works on the globe terrain with every ClippingPlaneCollection's unionClippingRegions set to false. I didn't rewrite the union function.
  4. Clipping on 3dtiles and models is out of scope, but I think the concept is similar.
  5. 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?

zhwy commented 3 years ago

@abcdweiok Sorry, I'm not working on it now, might take some time to figure this out.

qjh999 commented 3 years ago

@Samulus Hi, When will this capability be supported?

andrevall commented 3 years ago

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:

  1. 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

multiplanes_ios_min

  1. 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 😌

zhwy commented 3 years ago

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

raulvigueras commented 3 years ago

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. imagen

At the moment I can only apply a transparency when I approach the mouth of the tunnel. imagen

zhwy commented 3 years ago

Hi @raulvigueras,

Sorry for my replying late. You may try to use the MultiClippingPlaneCollection to clip the holes of tunnels.

clipping

Yet the effect is not very good, it's hard to fit the tunnel holes very well.

raulvigueras commented 2 years ago

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?

zhwy commented 2 years ago

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 Githubissues.

  • Githubissues is a development platform for aggregating issues.