@cesium/engine 8.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/Build/ThirdParty/Workers/z-worker-pako.js +7 -10
  2. package/Build/Workers/{chunk-F4HFJMGM.js → chunk-2CSEEWHN.js} +6 -6
  3. package/Build/Workers/{chunk-7TC63SJW.js → chunk-34DGOKCO.js} +10 -12
  4. package/Build/Workers/{chunk-7ZFGPDJA.js → chunk-3RZK5NNV.js} +4 -4
  5. package/Build/Workers/{chunk-M7ERACJJ.js → chunk-3S2MFY4B.js} +13 -13
  6. package/Build/Workers/{chunk-BROJAZRZ.js → chunk-4AJGCQFX.js} +13 -13
  7. package/Build/Workers/{chunk-2FWRMUTY.js → chunk-4KIUON73.js} +4 -4
  8. package/Build/Workers/{chunk-5QULIR53.js → chunk-4PHPQRSH.js} +4 -4
  9. package/Build/Workers/{chunk-X4356LRH.js → chunk-66E3H2KU.js} +12 -12
  10. package/Build/Workers/{chunk-G43QFN4Q.js → chunk-6HCAQOVK.js} +6 -6
  11. package/Build/Workers/{chunk-23UFSGND.js → chunk-7LPEGKOF.js} +7 -7
  12. package/Build/Workers/{chunk-DDUQAJ4P.js → chunk-7VZNXIKG.js} +7 -7
  13. package/Build/Workers/{chunk-JURN7NPV.js → chunk-A6NCZSL3.js} +19 -19
  14. package/Build/Workers/{chunk-ZT7KWISZ.js → chunk-AOFMPKUB.js} +4 -4
  15. package/Build/Workers/{chunk-BIKA3NRA.js → chunk-AOIKO5Y7.js} +5 -5
  16. package/Build/Workers/{chunk-YWTJ2B4B.js → chunk-BDUJXBVF.js} +1 -1
  17. package/Build/Workers/{chunk-OGXZVPPM.js → chunk-C5CE4OG6.js} +469 -6
  18. package/Build/Workers/{chunk-FNIRWHJB.js → chunk-CE6GTZ4I.js} +11 -13
  19. package/Build/Workers/{chunk-SH5USDPI.js → chunk-CYAJYEKW.js} +6 -6
  20. package/Build/Workers/{chunk-Y5UQJLYE.js → chunk-FOZQIHZK.js} +6 -6
  21. package/Build/Workers/{chunk-2FRVPMCS.js → chunk-G7CJQKKD.js} +7 -7
  22. package/Build/Workers/{chunk-EERJKOAF.js → chunk-GIFJ77E4.js} +4 -4
  23. package/Build/Workers/{chunk-FJKNFAKQ.js → chunk-I5TDPPC4.js} +7197 -5096
  24. package/Build/Workers/{chunk-3VAZEH7M.js → chunk-IBXGK4WV.js} +2 -2
  25. package/Build/Workers/{chunk-VOXYEYJT.js → chunk-JI2445T5.js} +11 -11
  26. package/Build/Workers/{chunk-PGSJK77E.js → chunk-KPY4F4BW.js} +6 -6
  27. package/Build/Workers/{chunk-I46ZRR5W.js → chunk-LVJCR7DH.js} +17 -17
  28. package/Build/Workers/{chunk-T3XIFPYR.js → chunk-LW7WGHEU.js} +16 -16
  29. package/Build/Workers/{chunk-HU6N6EXB.js → chunk-MWYZ64MH.js} +12 -11
  30. package/Build/Workers/chunk-NI2R52QD.js +961 -0
  31. package/Build/Workers/{chunk-SOWMRMWA.js → chunk-PEABJLCK.js} +1 -1
  32. package/Build/Workers/{chunk-EG6PTBY2.js → chunk-PK7TEP3J.js} +15 -15
  33. package/Build/Workers/{chunk-GRC2ZTAF.js → chunk-POLFRINT.js} +14 -14
  34. package/Build/Workers/{chunk-Z3TIFFGF.js → chunk-PS6AEMBR.js} +7 -7
  35. package/Build/Workers/{chunk-Y2ME2IJV.js → chunk-PWF3YJJ5.js} +13 -13
  36. package/Build/Workers/{chunk-2A75IWRS.js → chunk-QKF7XXEQ.js} +7 -7
  37. package/Build/Workers/{chunk-4H7PY4U5.js → chunk-RL73GOEF.js} +2 -2
  38. package/Build/Workers/{chunk-MDWEGWPA.js → chunk-RR7EOKGZ.js} +10 -10
  39. package/Build/Workers/{chunk-F3YA3Y2Z.js → chunk-S4XDCPKD.js} +1 -1
  40. package/Build/Workers/{chunk-PPH7OFP3.js → chunk-TMMOULW3.js} +5 -5
  41. package/Build/Workers/{chunk-XGI5BXZY.js → chunk-U4IMCOF5.js} +2 -2
  42. package/Build/Workers/{chunk-4DO5W5XZ.js → chunk-UAJEGIWA.js} +6 -6
  43. package/Build/Workers/{chunk-BBWDMCVU.js → chunk-UCPPWV64.js} +1 -1
  44. package/Build/Workers/{chunk-FZRIVR7Y.js → chunk-V7JB576Q.js} +5 -5
  45. package/Build/Workers/{chunk-2UPKWTMJ.js → chunk-WEGCQ5DY.js} +6 -6
  46. package/Build/Workers/{chunk-STW2DGFI.js → chunk-WFICTTOE.js} +2 -2
  47. package/Build/Workers/{chunk-LPR3YNP2.js → chunk-WWP3I7R5.js} +5 -5
  48. package/Build/Workers/{chunk-A5DWLWCY.js → chunk-XHLDDE65.js} +10 -10
  49. package/Build/Workers/{chunk-UEXTBDBE.js → chunk-XWML5Y7N.js} +11 -13
  50. package/Build/Workers/{chunk-EHWHNOEX.js → chunk-YLZTCEBJ.js} +1 -1
  51. package/Build/Workers/{chunk-34FXV7D7.js → chunk-ZC4AGBZK.js} +2 -2
  52. package/Build/Workers/{chunk-GATZHF3K.js → chunk-ZDP32RQI.js} +2 -2
  53. package/Build/Workers/{chunk-KKCR2YOP.js → chunk-ZWPIM77Q.js} +11 -11
  54. package/Build/Workers/combineGeometry.js +22 -24
  55. package/Build/Workers/createBoxGeometry.js +16 -18
  56. package/Build/Workers/createBoxOutlineGeometry.js +14 -16
  57. package/Build/Workers/createCircleGeometry.js +24 -26
  58. package/Build/Workers/createCircleOutlineGeometry.js +17 -19
  59. package/Build/Workers/createCoplanarPolygonGeometry.js +33 -34
  60. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +29 -31
  61. package/Build/Workers/createCorridorGeometry.js +27 -29
  62. package/Build/Workers/createCorridorOutlineGeometry.js +26 -28
  63. package/Build/Workers/createCylinderGeometry.js +18 -20
  64. package/Build/Workers/createCylinderOutlineGeometry.js +16 -18
  65. package/Build/Workers/createEllipseGeometry.js +24 -26
  66. package/Build/Workers/createEllipseOutlineGeometry.js +17 -19
  67. package/Build/Workers/createEllipsoidGeometry.js +17 -19
  68. package/Build/Workers/createEllipsoidOutlineGeometry.js +16 -18
  69. package/Build/Workers/createFrustumGeometry.js +16 -18
  70. package/Build/Workers/createFrustumOutlineGeometry.js +18 -19
  71. package/Build/Workers/createGeometry.js +23 -25
  72. package/Build/Workers/createGroundPolylineGeometry.js +23 -25
  73. package/Build/Workers/createPlaneGeometry.js +14 -16
  74. package/Build/Workers/createPlaneOutlineGeometry.js +13 -15
  75. package/Build/Workers/createPolygonGeometry.js +33 -35
  76. package/Build/Workers/createPolygonOutlineGeometry.js +28 -30
  77. package/Build/Workers/createPolylineGeometry.js +23 -25
  78. package/Build/Workers/createPolylineVolumeGeometry.js +29 -31
  79. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +25 -27
  80. package/Build/Workers/createRectangleGeometry.js +27 -29
  81. package/Build/Workers/createRectangleOutlineGeometry.js +18 -20
  82. package/Build/Workers/createSimplePolylineGeometry.js +21 -23
  83. package/Build/Workers/createSphereGeometry.js +17 -19
  84. package/Build/Workers/createSphereOutlineGeometry.js +16 -18
  85. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  86. package/Build/Workers/createVectorTileClampedPolylines.js +14 -16
  87. package/Build/Workers/createVectorTileGeometries.js +22 -24
  88. package/Build/Workers/createVectorTilePoints.js +12 -12
  89. package/Build/Workers/createVectorTilePolygons.js +20 -22
  90. package/Build/Workers/createVectorTilePolylines.js +14 -16
  91. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +23 -25
  92. package/Build/Workers/createVerticesFromHeightmap.js +23 -25
  93. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +19 -22
  94. package/Build/Workers/createWallGeometry.js +22 -24
  95. package/Build/Workers/createWallOutlineGeometry.js +21 -23
  96. package/Build/Workers/decodeDraco.js +11 -11
  97. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  98. package/Build/Workers/decodeI3S.js +10 -11
  99. package/Build/Workers/transcodeKTX2.js +8 -8
  100. package/Build/Workers/transferTypedArrayTest.js +1 -1
  101. package/Build/Workers/upsampleQuantizedTerrainMesh.js +20 -22
  102. package/Source/Core/Check.d.ts +127 -0
  103. package/Source/Core/Check.js +0 -1
  104. package/Source/Core/Geometry.js +1 -1
  105. package/Source/Core/Ion.js +1 -1
  106. package/Source/Core/PixelFormat.js +1 -0
  107. package/Source/Core/PolygonGeometry.js +1 -1
  108. package/Source/Core/Rectangle.js +89 -0
  109. package/Source/Core/VerticalExaggeration.js +2 -1
  110. package/Source/DataSources/DataSourceDisplay.js +5 -0
  111. package/Source/Renderer/ShaderBuilder.js +6 -3
  112. package/Source/Scene/ArcGisMapService.js +1 -1
  113. package/Source/Scene/Billboard.js +37 -3
  114. package/Source/Scene/BillboardCollection.js +1 -1
  115. package/Source/Scene/BingMapsImageryProvider.js +4 -0
  116. package/Source/Scene/Cesium3DTile.js +65 -0
  117. package/Source/Scene/Cesium3DTilesVoxelProvider.js +2 -9
  118. package/Source/Scene/Cesium3DTileset.js +52 -40
  119. package/Source/Scene/ClippingPolygon.js +212 -0
  120. package/Source/Scene/ClippingPolygonCollection.js +968 -0
  121. package/Source/Scene/Globe.js +14 -67
  122. package/Source/Scene/GlobeSurfaceShaderSet.js +81 -15
  123. package/Source/Scene/GlobeSurfaceTileProvider.js +81 -1
  124. package/Source/Scene/Label.js +33 -0
  125. package/Source/Scene/LabelCollection.js +2 -1
  126. package/Source/Scene/Model/Model.js +83 -0
  127. package/Source/Scene/Model/Model3DTileContent.js +21 -0
  128. package/Source/Scene/Model/ModelClippingPolygonsPipelineStage.js +92 -0
  129. package/Source/Scene/Model/ModelSceneGraph.js +5 -0
  130. package/Source/Scene/Primitive.js +0 -3
  131. package/Source/Scene/SensorVolumePortionToDisplay.js +1 -1
  132. package/Source/Scene/Terrain.js +2 -2
  133. package/Source/Scene/VoxelBoxShape.js +0 -15
  134. package/Source/Scene/VoxelCylinderShape.js +14 -131
  135. package/Source/Scene/VoxelEllipsoidShape.js +136 -227
  136. package/Source/Scene/VoxelPrimitive.js +106 -14
  137. package/Source/Scene/VoxelRenderResources.js +9 -3
  138. package/Source/Scene/VoxelShape.js +0 -10
  139. package/Source/Scene/processVoxelProperties.js +1 -0
  140. package/Source/Shaders/Builtin/CzmBuiltins.js +4 -0
  141. package/Source/Shaders/Builtin/Functions/clipPolygons.glsl +37 -0
  142. package/Source/Shaders/Builtin/Functions/clipPolygons.js +39 -0
  143. package/Source/Shaders/Builtin/Functions/unpackClippingExtents.glsl +14 -0
  144. package/Source/Shaders/Builtin/Functions/unpackClippingExtents.js +15 -0
  145. package/Source/Shaders/GlobeFS.glsl +12 -0
  146. package/Source/Shaders/GlobeFS.js +12 -0
  147. package/Source/Shaders/GlobeVS.glsl +32 -0
  148. package/Source/Shaders/GlobeVS.js +32 -0
  149. package/Source/Shaders/Model/GeometryStageVS.glsl +1 -1
  150. package/Source/Shaders/Model/GeometryStageVS.js +1 -1
  151. package/Source/Shaders/Model/ModelClippingPolygonsStageFS.glsl +6 -0
  152. package/Source/Shaders/Model/ModelClippingPolygonsStageFS.js +8 -0
  153. package/Source/Shaders/Model/ModelClippingPolygonsStageVS.glsl +27 -0
  154. package/Source/Shaders/Model/ModelClippingPolygonsStageVS.js +29 -0
  155. package/Source/Shaders/Model/ModelFS.glsl +6 -0
  156. package/Source/Shaders/Model/ModelFS.js +7 -1
  157. package/Source/Shaders/Model/ModelVS.glsl +4 -0
  158. package/Source/Shaders/Model/ModelVS.js +4 -0
  159. package/Source/Shaders/PolygonSignedDistanceFS.glsl +100 -0
  160. package/Source/Shaders/PolygonSignedDistanceFS.js +101 -0
  161. package/Source/Shaders/Voxels/IntersectBox.glsl +21 -47
  162. package/Source/Shaders/Voxels/IntersectBox.js +21 -47
  163. package/Source/Shaders/Voxels/IntersectClippingPlanes.glsl +1 -1
  164. package/Source/Shaders/Voxels/IntersectClippingPlanes.js +1 -1
  165. package/Source/Shaders/Voxels/IntersectCylinder.glsl +66 -96
  166. package/Source/Shaders/Voxels/IntersectCylinder.js +66 -96
  167. package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +226 -154
  168. package/Source/Shaders/Voxels/IntersectEllipsoid.js +226 -154
  169. package/Source/Shaders/Voxels/IntersectionUtils.glsl +33 -11
  170. package/Source/Shaders/Voxels/IntersectionUtils.js +33 -11
  171. package/Source/Shaders/Voxels/Megatexture.glsl +1 -2
  172. package/Source/Shaders/Voxels/Megatexture.js +1 -2
  173. package/Source/Shaders/Voxels/Octree.glsl +14 -9
  174. package/Source/Shaders/Voxels/Octree.js +14 -9
  175. package/Source/Shaders/Voxels/VoxelFS.glsl +93 -43
  176. package/Source/Shaders/Voxels/VoxelFS.js +93 -43
  177. package/Source/Shaders/Voxels/VoxelUtils.glsl +31 -0
  178. package/Source/Shaders/Voxels/VoxelUtils.js +33 -0
  179. package/Source/Shaders/Voxels/convertUvToBox.glsl +24 -3
  180. package/Source/Shaders/Voxels/convertUvToBox.js +24 -4
  181. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +50 -8
  182. package/Source/Shaders/Voxels/convertUvToCylinder.js +50 -8
  183. package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +82 -53
  184. package/Source/Shaders/Voxels/convertUvToEllipsoid.js +82 -53
  185. package/Source/ThirdParty/Workers/z-worker-pako.js +1 -1
  186. package/Source/Workers/createGeometry.js +1 -1
  187. package/index.d.ts +478 -35
  188. package/index.js +61 -52
  189. package/package.json +2 -2
  190. package/Build/Workers/chunk-BG4UCVXN.js +0 -73
  191. package/Build/Workers/chunk-TTUZP4BO.js +0 -501
  192. package/Build/Workers/chunk-YJEBABKH.js +0 -2977
@@ -1,5 +1,5 @@
1
- // See IntersectionUtils.glsl for the definitions of Ray, Intersections,
2
- // setIntersection, setIntersectionPair, INF_HIT, NO_HIT
1
+ // See IntersectionUtils.glsl for the definitions of Ray, NO_HIT, INF_HIT, Intersections,
2
+ // RayShapeIntersection, setSurfaceIntersection, setShapeIntersection
3
3
  // See IntersectLongitude.glsl for the definitions of intersectHalfPlane,
4
4
  // intersectFlippedWedge, intersectRegularWedge
5
5
 
@@ -14,8 +14,6 @@
14
14
  #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF
15
15
  #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF
16
16
  #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF
17
- #define ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX
18
- #define ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN
19
17
  #define ELLIPSOID_INTERSECTION_INDEX_LONGITUDE
20
18
  #define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX
21
19
  #define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN
@@ -26,133 +24,225 @@
26
24
  #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE)
27
25
  uniform vec2 u_ellipsoidRenderLongitudeMinMax;
28
26
  #endif
29
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF)
30
- uniform vec2 u_ellipsoidRenderLatitudeCosSqrHalfMinMax;
31
- #endif
32
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX)
33
- uniform float u_ellipsoidInverseOuterScaleUv;
34
- #endif
35
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN)
36
- uniform float u_ellipsoidInverseInnerScaleUv;
37
- #endif
27
+ uniform float u_eccentricitySquared;
28
+ uniform vec2 u_ellipsoidRenderLatitudeSinMinMax;
29
+ uniform vec2 u_clipMinMaxHeight;
38
30
 
39
- vec2 intersectZPlane(Ray ray)
40
- {
41
- float o = ray.pos.z;
42
- float d = ray.dir.z;
43
- float t = -o / d;
44
- float s = sign(o);
31
+ RayShapeIntersection intersectZPlane(in Ray ray, in float z) {
32
+ float t = -ray.pos.z / ray.dir.z;
45
33
 
46
- if (t >= 0.0 != s >= 0.0) return vec2(t, +INF_HIT);
47
- else return vec2(-INF_HIT, t);
48
- }
34
+ bool startsOutside = sign(ray.pos.z) == sign(z);
35
+ bool entry = (t >= 0.0) != startsOutside;
49
36
 
50
- vec2 intersectUnitSphere(Ray ray)
51
- {
52
- vec3 o = ray.pos;
53
- vec3 d = ray.dir;
37
+ vec4 intersect = vec4(0.0, 0.0, z, t);
38
+ vec4 farSide = vec4(normalize(ray.dir), INF_HIT);
54
39
 
55
- float b = dot(d, o);
56
- float c = dot(o, o) - 1.0;
57
- float det = b * b - c;
40
+ if (entry) {
41
+ return RayShapeIntersection(intersect, farSide);
42
+ } else {
43
+ return RayShapeIntersection(-1.0 * farSide, intersect);
44
+ }
45
+ }
58
46
 
59
- if (det < 0.0) {
60
- return vec2(NO_HIT);
47
+ RayShapeIntersection intersectHeight(in Ray ray, in float relativeHeight, in bool convex)
48
+ {
49
+ // Scale the ray by the ellipsoid axes to make it a unit sphere
50
+ // Note: approximating ellipsoid + height as an ellipsoid
51
+ vec3 radiiCorrection = u_ellipsoidRadiiUv / (u_ellipsoidRadiiUv + relativeHeight);
52
+ vec3 position = ray.pos * radiiCorrection;
53
+ vec3 direction = ray.dir * radiiCorrection;
54
+
55
+ float a = dot(direction, direction); // ~ 1.0 (or maybe 4.0 if ray is scaled)
56
+ float b = dot(direction, position); // roughly inside [-1.0, 1.0] when zoomed in
57
+ float c = dot(position, position) - 1.0; // ~ 0.0 when zoomed in.
58
+ float determinant = b * b - a * c; // ~ b * b when zoomed in
59
+
60
+ if (determinant < 0.0) {
61
+ vec4 miss = vec4(normalize(direction), NO_HIT);
62
+ return RayShapeIntersection(miss, miss);
61
63
  }
62
64
 
63
- det = sqrt(det);
64
- float t1 = -b - det;
65
- float t2 = -b + det;
65
+ determinant = sqrt(determinant);
66
+
67
+ // Compute larger root using standard formula
68
+ float signB = b < 0.0 ? -1.0 : 1.0;
69
+ // The other root may suffer from subtractive cancellation in the standard formula.
70
+ // Compute it from the first root instead.
71
+ float t1 = (-b - signB * determinant) / a;
72
+ float t2 = c / (a * t1);
66
73
  float tmin = min(t1, t2);
67
74
  float tmax = max(t1, t2);
68
75
 
69
- return vec2(tmin, tmax);
76
+ float directionScale = convex ? 1.0 : -1.0;
77
+ vec3 d1 = directionScale * normalize(position + tmin * direction);
78
+ vec3 d2 = directionScale * normalize(position + tmax * direction);
79
+
80
+ return RayShapeIntersection(vec4(d1, tmin), vec4(d2, tmax));
70
81
  }
71
82
 
72
- vec2 intersectUnitSphereUnnormalizedDirection(Ray ray)
83
+ /**
84
+ * Given a circular cone around the z-axis, with apex at the origin,
85
+ * find the parametric distance(s) along a ray where that ray intersects
86
+ * the cone.
87
+ * The cone opening angle is described by the squared cosine of
88
+ * its half-angle (the angle between the Z-axis and the surface)
89
+ */
90
+ vec2 intersectDoubleEndedCone(in Ray ray, in float cosSqrHalfAngle)
73
91
  {
74
92
  vec3 o = ray.pos;
75
93
  vec3 d = ray.dir;
94
+ float sinSqrHalfAngle = 1.0 - cosSqrHalfAngle;
95
+
96
+ float aSin = d.z * d.z * sinSqrHalfAngle;
97
+ float aCos = -dot(d.xy, d.xy) * cosSqrHalfAngle;
98
+ float a = aSin + aCos;
76
99
 
77
- float a = dot(d, d);
78
- float b = dot(d, o);
79
- float c = dot(o, o) - 1.0;
80
- float det = b * b - a * c;
100
+ float bSin = d.z * o.z * sinSqrHalfAngle;
101
+ float bCos = -dot(o.xy, d.xy) * cosSqrHalfAngle;
102
+ float b = bSin + bCos;
81
103
 
82
- if (det < 0.0) {
104
+ float cSin = o.z * o.z * sinSqrHalfAngle;
105
+ float cCos = -dot(o.xy, o.xy) * cosSqrHalfAngle;
106
+ float c = cSin + cCos;
107
+ // determinant = b * b - a * c. But bSin * bSin = aSin * cSin.
108
+ // Avoid subtractive cancellation by expanding to eliminate these terms
109
+ float determinant = 2.0 * bSin * bCos + bCos * bCos - aSin * cCos - aCos * cSin - aCos * cCos;
110
+
111
+ if (determinant < 0.0) {
83
112
  return vec2(NO_HIT);
113
+ } else if (a == 0.0) {
114
+ // Ray is parallel to cone surface
115
+ return (b == 0.0)
116
+ ? vec2(NO_HIT) // Ray is on cone surface
117
+ : vec2(-0.5 * c / b, NO_HIT);
84
118
  }
85
119
 
86
- det = sqrt(det);
87
- float t1 = (-b - det) / a;
88
- float t2 = (-b + det) / a;
120
+ determinant = sqrt(determinant);
121
+
122
+ // Compute larger root using standard formula
123
+ float signB = b < 0.0 ? -1.0 : 1.0;
124
+ float t1 = (-b - signB * determinant) / a;
125
+ // The other root may suffer from subtractive cancellation in the standard formula.
126
+ // Compute it from the first root instead.
127
+ float t2 = c / (a * t1);
89
128
  float tmin = min(t1, t2);
90
129
  float tmax = max(t1, t2);
91
-
92
130
  return vec2(tmin, tmax);
93
131
  }
94
132
 
95
- vec2 intersectDoubleEndedCone(Ray ray, float cosSqrHalfAngle)
96
- {
97
- vec3 o = ray.pos;
98
- vec3 d = ray.dir;
99
- float a = d.z * d.z - dot(d, d) * cosSqrHalfAngle;
100
- float b = d.z * o.z - dot(o, d) * cosSqrHalfAngle;
101
- float c = o.z * o.z - dot(o, o) * cosSqrHalfAngle;
102
- float det = b * b - a * c;
103
-
104
- if (det < 0.0) {
105
- return vec2(NO_HIT);
106
- }
133
+ /**
134
+ * Given a point on a conical surface, find the surface normal at that point.
135
+ */
136
+ vec3 getConeNormal(in vec3 p, in bool convex) {
137
+ // Start with radial component pointing toward z-axis
138
+ vec2 radial = -abs(p.z) * normalize(p.xy);
139
+ // Z component points toward opening of cone
140
+ float zSign = (p.z < 0.0) ? -1.0 : 1.0;
141
+ float z = length(p.xy) * zSign;
142
+ // Flip normal if shape is convex
143
+ float flip = (convex) ? -1.0 : 1.0;
144
+ return normalize(vec3(radial, z) * flip);
145
+ }
107
146
 
108
- det = sqrt(det);
109
- float t1 = (-b - det) / a;
110
- float t2 = (-b + det) / a;
111
- float tmin = min(t1, t2);
112
- float tmax = max(t1, t2);
113
- return vec2(tmin, tmax);
147
+ /**
148
+ * Compute the shift between the ellipsoid origin and the apex of a cone of latitude
149
+ */
150
+ float getLatitudeConeShift(in float sinLatitude) {
151
+ // Find prime vertical radius of curvature:
152
+ // the distance along the ellipsoid normal to the intersection with the z-axis
153
+ float x2 = u_eccentricitySquared * sinLatitude * sinLatitude;
154
+ float primeVerticalRadius = inversesqrt(1.0 - x2);
155
+
156
+ // Compute a shift from the origin to the intersection of the cone with the z-axis
157
+ return primeVerticalRadius * u_eccentricitySquared * sinLatitude;
114
158
  }
115
159
 
116
- vec4 intersectFlippedCone(Ray ray, float cosSqrHalfAngle) {
160
+ void intersectFlippedCone(in Ray ray, in float cosHalfAngle, out RayShapeIntersection intersections[2]) {
161
+ // Undo the scaling from ellipsoid to sphere
162
+ ray.pos = ray.pos * u_ellipsoidRadiiUv;
163
+ ray.dir = ray.dir * u_ellipsoidRadiiUv;
164
+ // Shift the ray to account for the latitude cone not being centered at the Earth center
165
+ ray.pos.z += getLatitudeConeShift(cosHalfAngle);
166
+
167
+ float cosSqrHalfAngle = cosHalfAngle * cosHalfAngle;
117
168
  vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);
118
169
 
170
+ vec4 miss = vec4(normalize(ray.dir), NO_HIT);
171
+ vec4 farSide = vec4(normalize(ray.dir), INF_HIT);
172
+
173
+ // Initialize output with no intersections
174
+ intersections[0].entry = -1.0 * farSide;
175
+ intersections[0].exit = farSide;
176
+ intersections[1].entry = miss;
177
+ intersections[1].exit = miss;
178
+
119
179
  if (intersect.x == NO_HIT) {
120
- return vec4(-INF_HIT, +INF_HIT, NO_HIT, NO_HIT);
180
+ return;
121
181
  }
122
182
 
123
- vec3 o = ray.pos;
124
- vec3 d = ray.dir;
183
+ // Find the points of intersection
125
184
  float tmin = intersect.x;
126
185
  float tmax = intersect.y;
127
- float zmin = o.z + tmin * d.z;
128
- float zmax = o.z + tmax * d.z;
129
-
130
- // One interval
131
- if (zmin < 0.0 && zmax < 0.0) return vec4(-INF_HIT, +INF_HIT, NO_HIT, NO_HIT);
132
- else if (zmin < 0.0) return vec4(-INF_HIT, tmax, NO_HIT, NO_HIT);
133
- else if (zmax < 0.0) return vec4(tmin, +INF_HIT, NO_HIT, NO_HIT);
134
- // Two intervals
135
- else return vec4(-INF_HIT, tmin, tmax, +INF_HIT);
186
+ vec3 p0 = ray.pos + tmin * ray.dir;
187
+ vec3 p1 = ray.pos + tmax * ray.dir;
188
+
189
+ vec4 intersect0 = vec4(getConeNormal(p0, true), tmin);
190
+ vec4 intersect1 = vec4(getConeNormal(p1, true), tmax);
191
+
192
+ bool p0InShadowCone = sign(p0.z) != sign(cosHalfAngle);
193
+ bool p1InShadowCone = sign(p1.z) != sign(cosHalfAngle);
194
+
195
+ if (p0InShadowCone && p1InShadowCone) {
196
+ // no valid intersections
197
+ } else if (p0InShadowCone) {
198
+ intersections[0].exit = intersect1;
199
+ } else if (p1InShadowCone) {
200
+ intersections[0].entry = intersect0;
201
+ } else {
202
+ intersections[0].exit = intersect0;
203
+ intersections[1].entry = intersect1;
204
+ intersections[1].exit = farSide;
205
+ }
136
206
  }
137
207
 
138
- vec2 intersectRegularCone(Ray ray, float cosSqrHalfAngle) {
208
+ RayShapeIntersection intersectRegularCone(in Ray ray, in float cosHalfAngle, in bool convex) {
209
+ // Undo the scaling from ellipsoid to sphere
210
+ ray.pos = ray.pos * u_ellipsoidRadiiUv;
211
+ ray.dir = ray.dir * u_ellipsoidRadiiUv;
212
+ // Shift the ray to account for the latitude cone not being centered at the Earth center
213
+ ray.pos.z += getLatitudeConeShift(cosHalfAngle);
214
+
215
+ float cosSqrHalfAngle = cosHalfAngle * cosHalfAngle;
139
216
  vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);
140
217
 
218
+ vec4 miss = vec4(normalize(ray.dir), NO_HIT);
219
+ vec4 farSide = vec4(normalize(ray.dir), INF_HIT);
220
+
141
221
  if (intersect.x == NO_HIT) {
142
- return vec2(NO_HIT);
222
+ return RayShapeIntersection(miss, miss);
143
223
  }
144
224
 
145
- vec3 o = ray.pos;
146
- vec3 d = ray.dir;
225
+ // Find the points of intersection
147
226
  float tmin = intersect.x;
148
227
  float tmax = intersect.y;
149
- float zmin = o.z + tmin * d.z;
150
- float zmax = o.z + tmax * d.z;
151
-
152
- if (zmin < 0.0 && zmax < 0.0) return vec2(NO_HIT);
153
- else if (zmin < 0.0) return vec2(tmax, +INF_HIT);
154
- else if (zmax < 0.0) return vec2(-INF_HIT, tmin);
155
- else return vec2(tmin, tmax);
228
+ vec3 p0 = ray.pos + tmin * ray.dir;
229
+ vec3 p1 = ray.pos + tmax * ray.dir;
230
+
231
+ vec4 intersect0 = vec4(getConeNormal(p0, convex), tmin);
232
+ vec4 intersect1 = vec4(getConeNormal(p1, convex), tmax);
233
+
234
+ bool p0InShadowCone = sign(p0.z) != sign(cosHalfAngle);
235
+ bool p1InShadowCone = sign(p1.z) != sign(cosHalfAngle);
236
+
237
+ if (p0InShadowCone && p1InShadowCone) {
238
+ return RayShapeIntersection(miss, miss);
239
+ } else if (p0InShadowCone) {
240
+ return RayShapeIntersection(intersect1, farSide);
241
+ } else if (p1InShadowCone) {
242
+ return RayShapeIntersection(-1.0 * farSide, intersect0);
243
+ } else {
244
+ return RayShapeIntersection(intersect0, intersect1);
245
+ }
156
246
  }
157
247
 
158
248
  void intersectShape(in Ray ray, inout Intersections ix) {
@@ -161,91 +251,73 @@ void intersectShape(in Ray ray, inout Intersections ix) {
161
251
  ray.pos = ray.pos * 2.0 - 1.0;
162
252
  ray.dir *= 2.0;
163
253
 
164
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX)
165
- Ray outerRay = Ray(ray.pos * u_ellipsoidInverseOuterScaleUv, ray.dir * u_ellipsoidInverseOuterScaleUv);
166
- #else
167
- Ray outerRay = ray;
168
- #endif
169
-
170
254
  // Outer ellipsoid
171
- vec2 outerIntersect = intersectUnitSphereUnnormalizedDirection(outerRay);
172
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX, outerIntersect);
255
+ RayShapeIntersection outerIntersect = intersectHeight(ray, u_clipMinMaxHeight.y, true);
256
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX, outerIntersect);
173
257
 
174
258
  // Exit early if the outer ellipsoid was missed.
175
- if (outerIntersect.x == NO_HIT) {
259
+ if (outerIntersect.entry.w == NO_HIT) {
176
260
  return;
177
261
  }
178
262
 
179
263
  // Inner ellipsoid
180
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN)
181
- Ray innerRay = Ray(ray.pos * u_ellipsoidInverseInnerScaleUv, ray.dir * u_ellipsoidInverseInnerScaleUv);
182
- vec2 innerIntersect = intersectUnitSphereUnnormalizedDirection(innerRay);
183
-
184
- if (innerIntersect == vec2(NO_HIT)) {
185
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN, innerIntersect);
186
- } else {
187
- // When the ellipsoid is large and thin it's possible for floating point math
188
- // to cause the ray to intersect the inner ellipsoid before the outer ellipsoid.
189
- // To prevent this from happening, clamp innerIntersect to outerIntersect and
190
- // sandwich the inner ellipsoid intersection inside the outer ellipsoid intersection.
191
-
192
- // Without this special case,
193
- // [outerMin, outerMax, innerMin, innerMax] will bubble sort to
194
- // [outerMin, innerMin, outerMax, innerMax] which will cause the back
195
- // side of the ellipsoid to be invisible because it will think the ray
196
- // is still inside the inner (negative) ellipsoid after exiting the
197
- // outer (positive) ellipsoid.
198
-
199
- // With this special case,
200
- // [outerMin, innerMin, innerMax, outerMax] will bubble sort to
201
- // [outerMin, innerMin, innerMax, outerMax] which will work correctly.
202
-
203
- // Note: If initializeIntersections() changes its sorting function
204
- // from bubble sort to something else, this code may need to change.
205
-
206
- // In theory a similar fix is needed for cylinders, however it's more
207
- // complicated to implement because the inner shape is allowed to be
208
- // intersected first.
209
- innerIntersect.x = max(innerIntersect.x, outerIntersect.x);
210
- innerIntersect.y = min(innerIntersect.y, outerIntersect.y);
211
- setIntersection(ix, 0, outerIntersect.x, true, true); // positive, enter
212
- setIntersection(ix, 1, innerIntersect.x, false, true); // negative, enter
213
- setIntersection(ix, 2, innerIntersect.y, false, false); // negative, exit
214
- setIntersection(ix, 3, outerIntersect.y, true, false); // positive, exit
215
- }
216
- #endif
217
-
218
- // Flip the ray because the intersection function expects a cone growing towards +Z.
219
- #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF)
220
- Ray flippedRay = outerRay;
221
- flippedRay.dir.z *= -1.0;
222
- flippedRay.pos.z *= -1.0;
223
- #endif
264
+ RayShapeIntersection innerIntersect = intersectHeight(ray, u_clipMinMaxHeight.x, false);
265
+
266
+ if (innerIntersect.entry.w == NO_HIT) {
267
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN, innerIntersect);
268
+ } else {
269
+ // When the ellipsoid is large and thin it's possible for floating point math
270
+ // to cause the ray to intersect the inner ellipsoid before the outer ellipsoid.
271
+ // To prevent this from happening, clamp innerIntersect to outerIntersect and
272
+ // sandwich the inner ellipsoid intersection inside the outer ellipsoid intersection.
273
+
274
+ // Without this special case,
275
+ // [outerMin, outerMax, innerMin, innerMax] will bubble sort to
276
+ // [outerMin, innerMin, outerMax, innerMax] which will cause the back
277
+ // side of the ellipsoid to be invisible because it will think the ray
278
+ // is still inside the inner (negative) ellipsoid after exiting the
279
+ // outer (positive) ellipsoid.
280
+
281
+ // With this special case,
282
+ // [outerMin, innerMin, innerMax, outerMax] will bubble sort to
283
+ // [outerMin, innerMin, innerMax, outerMax] which will work correctly.
284
+
285
+ // Note: If initializeIntersections() changes its sorting function
286
+ // from bubble sort to something else, this code may need to change.
287
+ innerIntersect.entry.w = max(innerIntersect.entry.w, outerIntersect.entry.w);
288
+ innerIntersect.exit.w = min(innerIntersect.exit.w, outerIntersect.exit.w);
289
+ setSurfaceIntersection(ix, 0, outerIntersect.entry, true, true); // positive, enter
290
+ setSurfaceIntersection(ix, 1, innerIntersect.entry, false, true); // negative, enter
291
+ setSurfaceIntersection(ix, 2, innerIntersect.exit, false, false); // negative, exit
292
+ setSurfaceIntersection(ix, 3, outerIntersect.exit, true, false); // positive, exit
293
+ }
224
294
 
225
295
  // Bottom cone
226
296
  #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF)
227
- vec2 bottomConeIntersection = intersectRegularCone(flippedRay, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.x);
228
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);
297
+ RayShapeIntersection bottomConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeSinMinMax.x, false);
298
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);
229
299
  #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF)
230
- vec2 bottomConeIntersection = intersectZPlane(flippedRay);
231
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);
300
+ RayShapeIntersection bottomConeIntersection = intersectZPlane(ray, -1.0);
301
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);
232
302
  #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF)
233
- vec4 bottomConeIntersection = intersectFlippedCone(ray, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.x);
234
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 0, bottomConeIntersection.xy);
235
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 1, bottomConeIntersection.zw);
303
+ RayShapeIntersection bottomConeIntersections[2];
304
+ intersectFlippedCone(ray, u_ellipsoidRenderLatitudeSinMinMax.x, bottomConeIntersections);
305
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 0, bottomConeIntersections[0]);
306
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 1, bottomConeIntersections[1]);
236
307
  #endif
237
308
 
238
309
  // Top cone
239
310
  #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF)
240
- vec4 topConeIntersection = intersectFlippedCone(flippedRay, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.y);
241
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 0, topConeIntersection.xy);
242
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 1, topConeIntersection.zw);
311
+ RayShapeIntersection topConeIntersections[2];
312
+ intersectFlippedCone(ray, u_ellipsoidRenderLatitudeSinMinMax.y, topConeIntersections);
313
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 0, topConeIntersections[0]);
314
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 1, topConeIntersections[1]);
243
315
  #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF)
244
- vec2 topConeIntersection = intersectZPlane(ray);
245
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);
316
+ RayShapeIntersection topConeIntersection = intersectZPlane(ray, 1.0);
317
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);
246
318
  #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF)
247
- vec2 topConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.y);
248
- setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);
319
+ RayShapeIntersection topConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeSinMinMax.y, false);
320
+ setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);
249
321
  #endif
250
322
 
251
323
  // Wedge