IntersectEllipsoid.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //This file is automatically rebuilt by the Cesium build process.
  2. export default "// See IntersectionUtils.glsl for the definitions of Ray, Intersections,\n\
  3. // setIntersection, setIntersectionPair, INF_HIT, NO_HIT\n\
  4. \n\
  5. /* Ellipsoid defines (set in Scene/VoxelEllipsoidShape.js)\n\
  6. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE\n\
  7. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO\n\
  8. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF\n\
  9. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_HALF\n\
  10. #define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF\n\
  11. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE\n\
  12. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF\n\
  13. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF\n\
  14. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF\n\
  15. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF\n\
  16. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF\n\
  17. #define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF\n\
  18. #define ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX\n\
  19. #define ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN\n\
  20. #define ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_FLAT\n\
  21. #define ELLIPSOID_INTERSECTION_INDEX_LONGITUDE\n\
  22. #define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX\n\
  23. #define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN\n\
  24. #define ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX\n\
  25. #define ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN\n\
  26. */\n\
  27. \n\
  28. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE)\n\
  29. uniform vec2 u_ellipsoidRenderLongitudeMinMax;\n\
  30. #endif\n\
  31. #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)\n\
  32. uniform vec2 u_ellipsoidRenderLatitudeCosSqrHalfMinMax;\n\
  33. #endif\n\
  34. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX)\n\
  35. uniform float u_ellipsoidInverseOuterScaleUv;\n\
  36. #endif\n\
  37. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN)\n\
  38. uniform float u_ellipsoidInverseInnerScaleUv;\n\
  39. #endif\n\
  40. \n\
  41. vec2 intersectZPlane(Ray ray)\n\
  42. {\n\
  43. float o = ray.pos.z;\n\
  44. float d = ray.dir.z;\n\
  45. float t = -o / d;\n\
  46. float s = sign(o);\n\
  47. \n\
  48. if (t >= 0.0 != s >= 0.0) return vec2(t, +INF_HIT);\n\
  49. else return vec2(-INF_HIT, t);\n\
  50. }\n\
  51. \n\
  52. vec4 intersectHalfPlane(Ray ray, float angle) {\n\
  53. vec2 o = ray.pos.xy;\n\
  54. vec2 d = ray.dir.xy;\n\
  55. vec2 planeDirection = vec2(cos(angle), sin(angle));\n\
  56. vec2 planeNormal = vec2(planeDirection.y, -planeDirection.x);\n\
  57. \n\
  58. float a = dot(o, planeNormal);\n\
  59. float b = dot(d, planeNormal);\n\
  60. float t = -a / b;\n\
  61. \n\
  62. vec2 p = o + t * d;\n\
  63. bool outside = dot(p, planeDirection) < 0.0;\n\
  64. if (outside) return vec4(-INF_HIT, +INF_HIT, NO_HIT, NO_HIT);\n\
  65. \n\
  66. return vec4(-INF_HIT, t, t, +INF_HIT);\n\
  67. }\n\
  68. \n\
  69. vec2 intersectHalfSpace(Ray ray, float angle)\n\
  70. {\n\
  71. vec2 o = ray.pos.xy;\n\
  72. vec2 d = ray.dir.xy;\n\
  73. vec2 n = vec2(sin(angle), -cos(angle));\n\
  74. \n\
  75. float a = dot(o, n);\n\
  76. float b = dot(d, n);\n\
  77. float t = -a / b;\n\
  78. float s = sign(a);\n\
  79. \n\
  80. if (t >= 0.0 != s >= 0.0) return vec2(t, +INF_HIT);\n\
  81. else return vec2(-INF_HIT, t);\n\
  82. }\n\
  83. \n\
  84. vec2 intersectRegularWedge(Ray ray, float minAngle, float maxAngle)\n\
  85. {\n\
  86. vec2 o = ray.pos.xy;\n\
  87. vec2 d = ray.dir.xy;\n\
  88. vec2 n1 = vec2(sin(minAngle), -cos(minAngle));\n\
  89. vec2 n2 = vec2(-sin(maxAngle), cos(maxAngle));\n\
  90. \n\
  91. float a1 = dot(o, n1);\n\
  92. float a2 = dot(o, n2);\n\
  93. float b1 = dot(d, n1);\n\
  94. float b2 = dot(d, n2);\n\
  95. \n\
  96. float t1 = -a1 / b1;\n\
  97. float t2 = -a2 / b2;\n\
  98. float s1 = sign(a1);\n\
  99. float s2 = sign(a2);\n\
  100. \n\
  101. float tmin = min(t1, t2);\n\
  102. float tmax = max(t1, t2);\n\
  103. float smin = tmin == t1 ? s1 : s2;\n\
  104. float smax = tmin == t1 ? s2 : s1;\n\
  105. \n\
  106. bool e = tmin >= 0.0;\n\
  107. bool f = tmax >= 0.0;\n\
  108. bool g = smin >= 0.0;\n\
  109. bool h = smax >= 0.0;\n\
  110. \n\
  111. if (e != g && f == h) return vec2(tmin, tmax);\n\
  112. else if (e == g && f == h) return vec2(-INF_HIT, tmin);\n\
  113. else if (e != g && f != h) return vec2(tmax, +INF_HIT);\n\
  114. else return vec2(NO_HIT);\n\
  115. }\n\
  116. \n\
  117. vec4 intersectFlippedWedge(Ray ray, float minAngle, float maxAngle)\n\
  118. {\n\
  119. vec2 planeIntersectMin = intersectHalfSpace(ray, minAngle);\n\
  120. vec2 planeIntersectMax = intersectHalfSpace(ray, maxAngle + czm_pi);\n\
  121. return vec4(planeIntersectMin, planeIntersectMax);\n\
  122. }\n\
  123. \n\
  124. vec2 intersectUnitSphere(Ray ray)\n\
  125. {\n\
  126. vec3 o = ray.pos;\n\
  127. vec3 d = ray.dir;\n\
  128. \n\
  129. float b = dot(d, o);\n\
  130. float c = dot(o, o) - 1.0;\n\
  131. float det = b * b - c;\n\
  132. \n\
  133. if (det < 0.0) {\n\
  134. return vec2(NO_HIT);\n\
  135. }\n\
  136. \n\
  137. det = sqrt(det);\n\
  138. float t1 = -b - det;\n\
  139. float t2 = -b + det;\n\
  140. float tmin = min(t1, t2);\n\
  141. float tmax = max(t1, t2);\n\
  142. \n\
  143. return vec2(tmin, tmax);\n\
  144. }\n\
  145. \n\
  146. vec2 intersectUnitSphereUnnormalizedDirection(Ray ray)\n\
  147. {\n\
  148. vec3 o = ray.pos;\n\
  149. vec3 d = ray.dir;\n\
  150. \n\
  151. float a = dot(d, d);\n\
  152. float b = dot(d, o);\n\
  153. float c = dot(o, o) - 1.0;\n\
  154. float det = b * b - a * c;\n\
  155. \n\
  156. if (det < 0.0) {\n\
  157. return vec2(NO_HIT);\n\
  158. }\n\
  159. \n\
  160. det = sqrt(det);\n\
  161. float t1 = (-b - det) / a;\n\
  162. float t2 = (-b + det) / a;\n\
  163. float tmin = min(t1, t2);\n\
  164. float tmax = max(t1, t2);\n\
  165. \n\
  166. return vec2(tmin, tmax);\n\
  167. }\n\
  168. \n\
  169. vec2 intersectDoubleEndedCone(Ray ray, float cosSqrHalfAngle)\n\
  170. {\n\
  171. vec3 o = ray.pos;\n\
  172. vec3 d = ray.dir;\n\
  173. float a = d.z * d.z - dot(d, d) * cosSqrHalfAngle;\n\
  174. float b = d.z * o.z - dot(o, d) * cosSqrHalfAngle;\n\
  175. float c = o.z * o.z - dot(o, o) * cosSqrHalfAngle;\n\
  176. float det = b * b - a * c;\n\
  177. \n\
  178. if (det < 0.0) {\n\
  179. return vec2(NO_HIT);\n\
  180. }\n\
  181. \n\
  182. det = sqrt(det);\n\
  183. float t1 = (-b - det) / a;\n\
  184. float t2 = (-b + det) / a;\n\
  185. float tmin = min(t1, t2);\n\
  186. float tmax = max(t1, t2);\n\
  187. return vec2(tmin, tmax);\n\
  188. }\n\
  189. \n\
  190. vec4 intersectFlippedCone(Ray ray, float cosSqrHalfAngle) {\n\
  191. vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);\n\
  192. \n\
  193. if (intersect.x == NO_HIT) {\n\
  194. return vec4(-INF_HIT, +INF_HIT, NO_HIT, NO_HIT);\n\
  195. }\n\
  196. \n\
  197. vec3 o = ray.pos;\n\
  198. vec3 d = ray.dir;\n\
  199. float tmin = intersect.x;\n\
  200. float tmax = intersect.y;\n\
  201. float zmin = o.z + tmin * d.z;\n\
  202. float zmax = o.z + tmax * d.z;\n\
  203. \n\
  204. // One interval\n\
  205. if (zmin < 0.0 && zmax < 0.0) return vec4(-INF_HIT, +INF_HIT, NO_HIT, NO_HIT);\n\
  206. else if (zmin < 0.0) return vec4(-INF_HIT, tmax, NO_HIT, NO_HIT);\n\
  207. else if (zmax < 0.0) return vec4(tmin, +INF_HIT, NO_HIT, NO_HIT);\n\
  208. // Two intervals\n\
  209. else return vec4(-INF_HIT, tmin, tmax, +INF_HIT);\n\
  210. }\n\
  211. \n\
  212. vec2 intersectRegularCone(Ray ray, float cosSqrHalfAngle) {\n\
  213. vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);\n\
  214. \n\
  215. if (intersect.x == NO_HIT) {\n\
  216. return vec2(NO_HIT);\n\
  217. }\n\
  218. \n\
  219. vec3 o = ray.pos;\n\
  220. vec3 d = ray.dir;\n\
  221. float tmin = intersect.x;\n\
  222. float tmax = intersect.y;\n\
  223. float zmin = o.z + tmin * d.z;\n\
  224. float zmax = o.z + tmax * d.z;\n\
  225. \n\
  226. if (zmin < 0.0 && zmax < 0.0) return vec2(NO_HIT);\n\
  227. else if (zmin < 0.0) return vec2(tmax, +INF_HIT);\n\
  228. else if (zmax < 0.0) return vec2(-INF_HIT, tmin);\n\
  229. else return vec2(tmin, tmax);\n\
  230. }\n\
  231. \n\
  232. void intersectShape(in Ray ray, inout Intersections ix) {\n\
  233. // Position is converted from [0,1] to [-1,+1] because shape intersections assume unit space is [-1,+1].\n\
  234. // Direction is scaled as well to be in sync with position.\n\
  235. ray.pos = ray.pos * 2.0 - 1.0;\n\
  236. ray.dir *= 2.0;\n\
  237. \n\
  238. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX)\n\
  239. Ray outerRay = Ray(ray.pos * u_ellipsoidInverseOuterScaleUv, ray.dir * u_ellipsoidInverseOuterScaleUv);\n\
  240. #else\n\
  241. Ray outerRay = ray;\n\
  242. #endif\n\
  243. \n\
  244. // Outer ellipsoid\n\
  245. vec2 outerIntersect = intersectUnitSphereUnnormalizedDirection(outerRay);\n\
  246. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX, outerIntersect);\n\
  247. \n\
  248. // Exit early if the outer ellipsoid was missed.\n\
  249. if (outerIntersect.x == NO_HIT) {\n\
  250. return;\n\
  251. }\n\
  252. \n\
  253. // Inner ellipsoid\n\
  254. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_FLAT)\n\
  255. // When the ellipsoid is perfectly thin it's necessary to sandwich the\n\
  256. // inner ellipsoid intersection inside the outer ellipsoid intersection.\n\
  257. \n\
  258. // Without this special case,\n\
  259. // [outerMin, outerMax, innerMin, innerMax] will bubble sort to\n\
  260. // [outerMin, innerMin, outerMax, innerMax] which will cause the back\n\
  261. // side of the ellipsoid to be invisible because it will think the ray\n\
  262. // is still inside the inner (negative) ellipsoid after exiting the\n\
  263. // outer (positive) ellipsoid.\n\
  264. \n\
  265. // With this special case,\n\
  266. // [outerMin, innerMin, innerMax, outerMax] will bubble sort to\n\
  267. // [outerMin, innerMin, innerMax, outerMax] which will work correctly.\n\
  268. \n\
  269. // Note: If initializeIntersections() changes its sorting function\n\
  270. // from bubble sort to something else, this code may need to change.\n\
  271. setIntersection(ix, 0, outerIntersect.x, true, true); // positive, enter\n\
  272. setIntersection(ix, 1, outerIntersect.x, false, true); // negative, enter\n\
  273. setIntersection(ix, 2, outerIntersect.y, false, false); // negative, exit\n\
  274. setIntersection(ix, 3, outerIntersect.y, true, false); // positive, exit\n\
  275. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN)\n\
  276. Ray innerRay = Ray(ray.pos * u_ellipsoidInverseInnerScaleUv, ray.dir * u_ellipsoidInverseInnerScaleUv);\n\
  277. vec2 innerIntersect = intersectUnitSphereUnnormalizedDirection(innerRay);\n\
  278. \n\
  279. if (innerIntersect == vec2(NO_HIT)) {\n\
  280. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN, innerIntersect);\n\
  281. } else {\n\
  282. // When the ellipsoid is very large and thin it's possible for floating\n\
  283. // point math to cause the ray to intersect the inner ellipsoid before\n\
  284. // the outer ellipsoid. To prevent this from happening, clamp innerIntersect\n\
  285. // to outerIntersect and sandwhich the intersections like described above.\n\
  286. //\n\
  287. // In theory a similar fix is needed for cylinders, however it's more\n\
  288. // complicated to implement because the inner shape is allowed to be\n\
  289. // intersected first.\n\
  290. innerIntersect.x = max(innerIntersect.x, outerIntersect.x);\n\
  291. innerIntersect.y = min(innerIntersect.y, outerIntersect.y);\n\
  292. setIntersection(ix, 0, outerIntersect.x, true, true); // positive, enter\n\
  293. setIntersection(ix, 1, innerIntersect.x, false, true); // negative, enter\n\
  294. setIntersection(ix, 2, innerIntersect.y, false, false); // negative, exit\n\
  295. setIntersection(ix, 3, outerIntersect.y, true, false); // positive, exit\n\
  296. }\n\
  297. #endif\n\
  298. \n\
  299. // Flip the ray because the intersection function expects a cone growing towards +Z.\n\
  300. #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)\n\
  301. Ray flippedRay = outerRay;\n\
  302. flippedRay.dir.z *= -1.0;\n\
  303. flippedRay.pos.z *= -1.0;\n\
  304. #endif\n\
  305. \n\
  306. // Bottom cone\n\
  307. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF)\n\
  308. vec2 bottomConeIntersection = intersectRegularCone(flippedRay, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.x);\n\
  309. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);\n\
  310. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF)\n\
  311. vec2 bottomConeIntersection = intersectZPlane(flippedRay);\n\
  312. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);\n\
  313. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF)\n\
  314. vec4 bottomConeIntersection = intersectFlippedCone(ray, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.x);\n\
  315. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 0, bottomConeIntersection.xy);\n\
  316. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 1, bottomConeIntersection.zw);\n\
  317. #endif\n\
  318. \n\
  319. // Top cone\n\
  320. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF)\n\
  321. vec4 topConeIntersection = intersectFlippedCone(flippedRay, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.y);\n\
  322. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 0, topConeIntersection.xy);\n\
  323. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 1, topConeIntersection.zw);\n\
  324. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF)\n\
  325. vec2 topConeIntersection = intersectZPlane(ray);\n\
  326. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);\n\
  327. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF)\n\
  328. vec2 topConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeCosSqrHalfMinMax.y);\n\
  329. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);\n\
  330. #endif\n\
  331. \n\
  332. // Wedge\n\
  333. #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO)\n\
  334. vec4 wedgeIntersect = intersectHalfPlane(ray, u_ellipsoidRenderLongitudeMinMax.x);\n\
  335. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 0, wedgeIntersect.xy);\n\
  336. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 1, wedgeIntersect.zw);\n\
  337. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF)\n\
  338. vec2 wedgeIntersect = intersectRegularWedge(ray, u_ellipsoidRenderLongitudeMinMax.x, u_ellipsoidRenderLongitudeMinMax.y);\n\
  339. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE, wedgeIntersect);\n\
  340. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_HALF)\n\
  341. vec2 wedgeIntersect = intersectHalfSpace(ray, u_ellipsoidRenderLongitudeMinMax.x);\n\
  342. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE, wedgeIntersect);\n\
  343. #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF)\n\
  344. vec4 wedgeIntersect = intersectFlippedWedge(ray, u_ellipsoidRenderLongitudeMinMax.x, u_ellipsoidRenderLongitudeMinMax.y);\n\
  345. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 0, wedgeIntersect.xy);\n\
  346. setIntersectionPair(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 1, wedgeIntersect.zw);\n\
  347. #endif\n\
  348. }\n\
  349. ";