convertUvToEllipsoid.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //This file is automatically rebuilt by the Cesium build process.
  2. export default "/* Ellipsoid defines (set in Scene/VoxelEllipsoidShape.js)\n\
  3. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY\n\
  4. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY\n\
  5. #define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE\n\
  6. #define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO\n\
  7. #define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED\n\
  8. #define ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE\n\
  9. #define ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO\n\
  10. #define ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN\n\
  11. #define ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_FLAT\n\
  12. #define ELLIPSOID_IS_SPHERE\n\
  13. */\n\
  14. \n\
  15. uniform vec3 u_ellipsoidRadiiUv; // [0,1]\n\
  16. #if !defined(ELLIPSOID_IS_SPHERE)\n\
  17. uniform vec3 u_ellipsoidInverseRadiiSquaredUv;\n\
  18. #endif\n\
  19. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY) || defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED)\n\
  20. uniform vec3 u_ellipsoidShapeUvLongitudeMinMaxMid;\n\
  21. #endif\n\
  22. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n\
  23. uniform vec2 u_ellipsoidUvToShapeUvLongitude; // x = scale, y = offset\n\
  24. #endif\n\
  25. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n\
  26. uniform vec2 u_ellipsoidUvToShapeUvLatitude; // x = scale, y = offset\n\
  27. #endif\n\
  28. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN) && !defined(ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_FLAT)\n\
  29. uniform float u_ellipsoidInverseHeightDifferenceUv;\n\
  30. uniform vec2 u_ellipseInnerRadiiUv; // [0,1]\n\
  31. #endif\n\
  32. \n\
  33. // robust iterative solution without trig functions\n\
  34. // https://github.com/0xfaded/ellipse_demo/issues/1\n\
  35. // https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse\n\
  36. // Pro: Good when radii.x ~= radii.y\n\
  37. // Con: Breaks at pos.x ~= 0.0, especially inside the ellipse\n\
  38. // Con: Inaccurate with exterior points and thin ellipses\n\
  39. float ellipseDistanceIterative (vec2 pos, vec2 radii) {\n\
  40. vec2 p = abs(pos);\n\
  41. vec2 invRadii = 1.0 / radii;\n\
  42. vec2 a = vec2(1.0, -1.0) * (radii.x * radii.x - radii.y * radii.y) * invRadii;\n\
  43. vec2 t = vec2(0.70710678118); // sqrt(2) / 2\n\
  44. vec2 v = radii * t;\n\
  45. \n\
  46. const int iterations = 3;\n\
  47. for (int i = 0; i < iterations; ++i) {\n\
  48. vec2 e = a * pow(t, vec2(3.0));\n\
  49. vec2 q = normalize(p - e) * length(v - e);\n\
  50. t = normalize((q + e) * invRadii);\n\
  51. v = radii * t;\n\
  52. }\n\
  53. return length(v * sign(pos) - pos) * sign(p.y - v.y);\n\
  54. }\n\
  55. \n\
  56. vec3 convertUvToShapeUvSpace(in vec3 positionUv) {\n\
  57. // Compute position and normal.\n\
  58. // Convert positionUv [0,1] to local space [-1,+1] to \"normalized\" cartesian space [-a,+a] where a = (radii + height) / (max(radii) + height).\n\
  59. // A point on the largest ellipsoid axis would be [-1,+1] and everything else would be smaller.\n\
  60. vec3 positionLocal = positionUv * 2.0 - 1.0;\n\
  61. #if defined(ELLIPSOID_IS_SPHERE)\n\
  62. vec3 posEllipsoid = positionLocal * u_ellipsoidRadiiUv.x;\n\
  63. vec3 normal = normalize(posEllipsoid);\n\
  64. #else\n\
  65. vec3 posEllipsoid = positionLocal * u_ellipsoidRadiiUv;\n\
  66. vec3 normal = normalize(posEllipsoid * u_ellipsoidInverseRadiiSquaredUv); // geodetic surface normal\n\
  67. #endif\n\
  68. \n\
  69. // Compute longitude\n\
  70. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO)\n\
  71. float longitude = 1.0;\n\
  72. #else\n\
  73. float longitude = (atan(normal.y, normal.x) + czm_pi) / czm_twoPi;\n\
  74. \n\
  75. // Correct the angle when max < min\n\
  76. // Technically this should compare against min longitude - but it has precision problems so compare against the middle of empty space.\n\
  77. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED)\n\
  78. longitude += float(longitude < u_ellipsoidShapeUvLongitudeMinMaxMid.z);\n\
  79. #endif\n\
  80. \n\
  81. // Avoid flickering from reading voxels from both sides of the -pi/+pi discontinuity.\n\
  82. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY)\n\
  83. longitude = longitude > u_ellipsoidShapeUvLongitudeMinMaxMid.z ? u_ellipsoidShapeUvLongitudeMinMaxMid.x : longitude;\n\
  84. #endif\n\
  85. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY)\n\
  86. longitude = longitude < u_ellipsoidShapeUvLongitudeMinMaxMid.z ? u_ellipsoidShapeUvLongitudeMinMaxMid.y : longitude;\n\
  87. #endif\n\
  88. \n\
  89. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n\
  90. longitude = longitude * u_ellipsoidUvToShapeUvLongitude.x + u_ellipsoidUvToShapeUvLongitude.y;\n\
  91. #endif\n\
  92. #endif\n\
  93. \n\
  94. // Compute latitude\n\
  95. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO)\n\
  96. float latitude = 1.0;\n\
  97. #else\n\
  98. float latitude = (asin(normal.z) + czm_piOverTwo) / czm_pi;\n\
  99. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n\
  100. latitude = latitude * u_ellipsoidUvToShapeUvLatitude.x + u_ellipsoidUvToShapeUvLatitude.y;\n\
  101. #endif\n\
  102. #endif\n\
  103. \n\
  104. // Compute height\n\
  105. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_FLAT)\n\
  106. // TODO: This breaks down when minBounds == maxBounds. To fix it, this\n\
  107. // function would have to know if ray is intersecting the front or back of the shape\n\
  108. // and set the shape space position to 1 (front) or 0 (back) accordingly.\n\
  109. float height = 1.0;\n\
  110. #else\n\
  111. #if defined(ELLIPSOID_IS_SPHERE)\n\
  112. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN)\n\
  113. float height = (length(posEllipsoid) - u_ellipseInnerRadiiUv.x) * u_ellipsoidInverseHeightDifferenceUv;\n\
  114. #else\n\
  115. float height = length(posEllipsoid);\n\
  116. #endif\n\
  117. #else\n\
  118. #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN)\n\
  119. // Convert the 3D position to a 2D position relative to the ellipse (radii.x, radii.z) (assuming radii.x == radii.y which is true for WGS84).\n\
  120. // This is an optimization so that math can be done with ellipses instead of ellipsoids.\n\
  121. vec2 posEllipse = vec2(length(posEllipsoid.xy), posEllipsoid.z);\n\
  122. float height = ellipseDistanceIterative(posEllipse, u_ellipseInnerRadiiUv) * u_ellipsoidInverseHeightDifferenceUv;\n\
  123. #else\n\
  124. // TODO: this is probably not correct\n\
  125. float height = length(posEllipsoid);\n\
  126. #endif\n\
  127. #endif\n\
  128. #endif\n\
  129. \n\
  130. return vec3(longitude, latitude, height);\n\
  131. }\n\
  132. ";