cesium icon indicating copy to clipboard operation
cesium copied to clipboard

Precision of position attribute in Point Cloud is good on Y axis, but bad on X and Z axis

Open anne-gropler opened this issue 1 year ago • 5 comments

What happened?

I want to color the points of a point cloud based on their distance to a certain position. You can also have a look at this community forum post to see how this position is calculated.

I expected a nice gradient, from yellow to red, but instead got those "patches":

3c384dd277155132e7a3734fbe182b8dc0dcf05c

I used a Point Cloud Style for that.

I also wanted to color the points of a point cloud based on their distance to the ground. I used a custom shader for that.

I expected a nice rainbow gradient, however, I got "patches" again:

d6c57bf59df6ce6d9e120e69955c39be151cbc5a

3f380f08ec8f9dd686e36ed70667b2df12758efb

To me, it seems to be a precision issue. Interestingly, this issue only happens in x direction and z direction:

5f96aeffe03baeb1e2f11e7cc72f9830247a3521_2_690x381 84ed531ee1f28299abc872ceb753d519a90e30cc_2_690x381

However, the y direction yields a nice gradient (especially noticeable at the smaller tower to the right) : 7a02b170a114e40bdd75b0ca3b82ed5de556db78_2_690x381

I expect the precision of the x and z direction be as high as the y direction.

Reproduction steps

  1. Open provided Sandcastle.
  2. Change line 57 to float distance = abs(point.x - positionAbsolute.x);, float distance = abs(point.y - positionAbsolute.y); or float distance = abs(point.z - positionAbsolute.z); to see the precision differences in axis directions in the rainbow gradient.
  3. Uncomment Line 88 and comment line 87 to see the example with the yellow-red gradient, this time defined by a point cloud style, instead of the custom shader.

Sandcastle example

https://sandcastle.cesium.com/#c=pRdrU9s48K9omM7UuTOKHTsPKO0cl6YlAxSGBPolM8GxlUR3spST5YTQ4b/fSrKdF+1wc/mAtat9v7TU67eCcoW6TOQJmqzRrRRTjG6JIhKdM0a4i7qC5emERuie0yWRGVVrdCcmQtE4Q1fRBKNBHHFO+UwLOGfkr4gnUqChFHEsGEUAoutIEYq6VMSRZJTgEY8FzxRaUrICVR8RJyvUJRnNU/xgcM7oKDZwV3AVUU7k6MhFP0YcITBOAua0ZBhaGE+lSL8LyZIC4dTcEX+pfRjxEV9GEs3BEravbRBLQvhgEcWktyRcXVgix1qGs5hwgsHBZZRpSYUMnBHV54tcnceKCu5Mc24PRMuoWTsR0lrBYwWqIg56d4QuaPz3rYB4Vnx4UYBak+bXQRKMYCZmTiVHX764P7N/uF4QfNX7Mhx3r/rdS+s9+L/rTkpkpH3QsXaMsQnJFOWR1n66HZ9uqTZwrE1h6PntMMStMPTDZuCHrsU3Gk2v6ePQ99qdE9/3mo3iImyeNMOGh4N22O6EYRBodM1cCknB5EOlFyRKoKBuqYrnd4KxQnUTlLbaQdDxml5w0m62Cw3HHm60Wy2v7TeDTnDS6bSKixZudHywpdNuhp7ndZql6q2qyNSaEchNkbKETKHYMnRaIgySZiriMQHse6cEnHc/bm8G/WH/5tv4/M/BzdX9sAd5WZI4cEyQvBC3PTCs0+kErokPYBqtk7bfALOaLdeGJgCylt/wANOo1WqojhrvreoXtywDJqTWndInxwDQHWvCmFiNjmouKlGSJAZ+96O08aX2vpCx0I0+oM8ExDQ08qWKwFRGsxTyMJhHCZFD8qQgHI9wJ2hSXV7rhvpSAKb00TQzXxdRLgCMn9NxKhLCdLNLGjGUFofaiEMwR6qEcUKn0zzTUdceLcdg7oJFa8M+1gmB5I+NVy7aZ3KRh33TAyP+WPkAk0mRp30P7JCZMhEp9PXu/HO/9204vuj1v14MgaCBvbI7IGdoni0bcjZxDBCbHh4pAEJ0qVsXDo6PPVezQY4CffQ3R/hjakoZ9gVwRJPMgejFyonx09MT+h1d4qf1cw39BnXpoWMAV6uVZZJE5ZKjGD/DrY7JpWaBzLIoXTgLQ2wQXqFWZx2vizAUqbIxMIl6MEebpuVP0mRpbnJlieyhGF3WCfM2fPyfFW1CXEm08+26q8Vau3CklKSTHKYM3tx/OOA5n8AoBKrSoMoPiJhJzobZRqjUbNNftbBNjPENon18IB8/7zLOc83jgKqq8939YjJdu4fbeABFBRK2y0sXEqgG0cbUjb3A8YtmACkgoahZVOUMV71dFXXVG7YD4jxTIrXdsfv8dbdunGLiMTqbw1swu9bRrV7Zq20svv921R8WoyXndCpkmu2MzHy8mmWd8IaTG6jLO5jndPBPHsGI2iHTPwVPVqXm3gozz9hDrxu4u7TLiOUb4h5jdJFB7ePvXwedEItDbVv85TgtvzA31uDQrt31OhrYmBdjV82hCGgG7ziLcwbDKIFGKnoNZTakesWJFgvYbMxlOTOL643wXyW3curBmrUfgcrqvUl3eoApCA/H+ukruM1jOOJKrm0obNUoygjsCLpjVhFVVcmYT/B5aK/N2tWH/sn0TpQ4fits+LaWCwF4r/y2wQ864GfH//FXBDtDEdKL3kSs0ExC0sEzrRdElqrL13275Lfs16kmjiGqvdmULe32EbYdg1ZUzSH7+hXW3bmz60mawpRZwoyLksQprDPjGwoLthzkwM4qZG0T/3Lve+zpCwSzSK9EpWOn8MgbjpdHK+VNS96b1rzDBe+13e5wrasVdffmpe5wnXttkztc4mpFyR65R2cmdZ/KDvuDpgshFcolczCuK5IudMdm9Uke/60LMcvK1fqsvs16ltAlosnHV/7p0G9wlsHNNGdMD9nR0aezOtAfsBYp0hMIWlyTzf1PVxaJMT6rA/g6pxKCTSK5J/lf

Environment

Browser: Firefox, Chrome CesiumJS Version: 1.113 locally, and the current one in the sandcastle is 1.114 Operating System: Windows

anne-gropler avatar Feb 08 '24 09:02 anne-gropler

Just a note: We had a look and found out, that the Y coordinate is simply 10 times smaller than the X and Z values. That's just because of the ECEF coordinate system. So at other places the X or Z precision might be much better than the Y one. This means the precision problem is not better or worse for any "direction" (x, y, z). It's just about the size of the respective coordinate value.

So the question is not, why X/Z values have worse precision, but how could we achieve better precision in general? Is it possible to somehow get better precision in the shader based on something like RTC_CENTER, like Cesium does when actually placing the points in the 3D scene?

UniquePanda avatar Feb 08 '24 10:02 UniquePanda

The relevant shader lines are:

  vec3 point = vec3(4401704.702768883, 225004.26971228156, 4595434.761201562);

  vec3 positionMC = vsInput.attributes.positionMC;
  vec3 positionAbsolute = vec3(czm_model * vec4(positionMC, 1.0));

  float distance = abs(point.z - positionAbsolute.z);

The problem is that point and positionAbsolute are both in world coordinates. So the distance calculation is subtracting two numbers that are very large, and very similar. This results in precision loss due to subtractive cancellation.

You can avoid it by defining the reference point in model coordinates, and compare to positionMC. In this way the distance calculation will be subtracting smaller numbers with a larger relative difference between them.

  vec3 referencePointMC = vec3(0.0, 0.0, 50.0);

  vec3 positionMC = vsInput.attributes.positionMC;

  float distance = abs(referencePointMC.z - positionMC.z);

See this updated Sandcastle demonstrating the model coordinates approach in the custom shader.

image

jjhembd avatar Feb 08 '24 17:02 jjhembd

Thanks @jjhembd for your idea. Unfortunately, this does not work, since the values might be different per tile. I guess this is because the model matrix should be different?

It becomes more apparent if you set HEIGHT_GRADIENT to 20.0 in your updated sandcastle and move around to trigger loading tiles, you might find views like this:

grafik

anne-gropler avatar Feb 09 '24 09:02 anne-gropler

Hi @anne-gropler @jjhembd , is there any progress on this issue?

In this post, I also face similar precision loss issues:

I want to convert the model coordinates to world coordinates in CustomShader, complete some operations in the world coordinate system, and then convert the world coordinates to model coordinates, but I lost precision during this process.

const modelShader = new Cesium.CustomShader({
  vertexShaderText: `
    void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput)
    {
      vec4 positionWC = czm_model * vec4(vsInput.attributes.positionMC, 1.0);
      vsOutput.positionMC = (czm_inverseModel * positionWC).xyz;
    }
    `,
});

Cesium Sandcastle:

Snipaste_2024-04-18_15-18-57

syzdev avatar Apr 19 '24 01:04 syzdev

Hello @syzdev , no, we still have the same problems and we don't know how to solve them.

anne-gropler avatar Apr 19 '24 06:04 anne-gropler