PolylineCommon.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //This file is automatically rebuilt by the Cesium build process.
  2. export default "void clipLineSegmentToNearPlane(\n\
  3. vec3 p0,\n\
  4. vec3 p1,\n\
  5. out vec4 positionWC,\n\
  6. out bool clipped,\n\
  7. out bool culledByNearPlane,\n\
  8. out vec4 clippedPositionEC)\n\
  9. {\n\
  10. culledByNearPlane = false;\n\
  11. clipped = false;\n\
  12. \n\
  13. vec3 p0ToP1 = p1 - p0;\n\
  14. float magnitude = length(p0ToP1);\n\
  15. vec3 direction = normalize(p0ToP1);\n\
  16. \n\
  17. // Distance that p0 is behind the near plane. Negative means p0 is\n\
  18. // in front of the near plane.\n\
  19. float endPoint0Distance = czm_currentFrustum.x + p0.z;\n\
  20. \n\
  21. // Camera looks down -Z.\n\
  22. // When moving a point along +Z: LESS VISIBLE\n\
  23. // * Points in front of the camera move closer to the camera.\n\
  24. // * Points behind the camrea move farther away from the camera.\n\
  25. // When moving a point along -Z: MORE VISIBLE\n\
  26. // * Points in front of the camera move farther away from the camera.\n\
  27. // * Points behind the camera move closer to the camera.\n\
  28. \n\
  29. // Positive denominator: -Z, becoming more visible\n\
  30. // Negative denominator: +Z, becoming less visible\n\
  31. // Nearly zero: parallel to near plane\n\
  32. float denominator = -direction.z;\n\
  33. \n\
  34. if (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7)\n\
  35. {\n\
  36. // p0 is behind the near plane and the line to p1 is nearly parallel to\n\
  37. // the near plane, so cull the segment completely.\n\
  38. culledByNearPlane = true;\n\
  39. }\n\
  40. else if (endPoint0Distance > 0.0)\n\
  41. {\n\
  42. // p0 is behind the near plane, and the line to p1 is moving distinctly\n\
  43. // toward or away from it.\n\
  44. \n\
  45. // t = (-plane distance - dot(plane normal, ray origin)) / dot(plane normal, ray direction)\n\
  46. float t = endPoint0Distance / denominator;\n\
  47. if (t < 0.0 || t > magnitude)\n\
  48. {\n\
  49. // Near plane intersection is not between the two points.\n\
  50. // We already confirmed p0 is behind the naer plane, so now\n\
  51. // we know the entire segment is behind it.\n\
  52. culledByNearPlane = true;\n\
  53. }\n\
  54. else\n\
  55. {\n\
  56. // Segment crosses the near plane, update p0 to lie exactly on it.\n\
  57. p0 = p0 + t * direction;\n\
  58. \n\
  59. // Numerical noise might put us a bit on the wrong side of the near plane.\n\
  60. // Don't let that happen.\n\
  61. p0.z = min(p0.z, -czm_currentFrustum.x);\n\
  62. \n\
  63. clipped = true;\n\
  64. }\n\
  65. }\n\
  66. \n\
  67. clippedPositionEC = vec4(p0, 1.0);\n\
  68. positionWC = czm_eyeToWindowCoordinates(clippedPositionEC);\n\
  69. }\n\
  70. \n\
  71. vec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle)\n\
  72. {\n\
  73. // expandDirection +1 is to the _left_ when looking from positionEC toward nextEC.\n\
  74. \n\
  75. #ifdef POLYLINE_DASH\n\
  76. // Compute the window coordinates of the points.\n\
  77. vec4 positionWindow = czm_eyeToWindowCoordinates(positionEC);\n\
  78. vec4 previousWindow = czm_eyeToWindowCoordinates(prevEC);\n\
  79. vec4 nextWindow = czm_eyeToWindowCoordinates(nextEC);\n\
  80. \n\
  81. // Determine the relative screen space direction of the line.\n\
  82. vec2 lineDir;\n\
  83. if (usePrevious) {\n\
  84. lineDir = normalize(positionWindow.xy - previousWindow.xy);\n\
  85. }\n\
  86. else {\n\
  87. lineDir = normalize(nextWindow.xy - positionWindow.xy);\n\
  88. }\n\
  89. angle = atan(lineDir.x, lineDir.y) - 1.570796327; // precomputed atan(1,0)\n\
  90. \n\
  91. // Quantize the angle so it doesn't change rapidly between segments.\n\
  92. angle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour;\n\
  93. #endif\n\
  94. \n\
  95. vec4 clippedPrevWC, clippedPrevEC;\n\
  96. bool prevSegmentClipped, prevSegmentCulled;\n\
  97. clipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC);\n\
  98. \n\
  99. vec4 clippedNextWC, clippedNextEC;\n\
  100. bool nextSegmentClipped, nextSegmentCulled;\n\
  101. clipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC);\n\
  102. \n\
  103. bool segmentClipped, segmentCulled;\n\
  104. vec4 clippedPositionWC, clippedPositionEC;\n\
  105. clipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC);\n\
  106. \n\
  107. if (segmentCulled)\n\
  108. {\n\
  109. return vec4(0.0, 0.0, 0.0, 1.0);\n\
  110. }\n\
  111. \n\
  112. vec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy);\n\
  113. vec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy);\n\
  114. \n\
  115. // If a segment was culled, we can't use the corresponding direction\n\
  116. // computed above. We should never see both of these be true without\n\
  117. // `segmentCulled` above also being true.\n\
  118. if (prevSegmentCulled)\n\
  119. {\n\
  120. directionToPrevWC = -directionToNextWC;\n\
  121. }\n\
  122. else if (nextSegmentCulled)\n\
  123. {\n\
  124. directionToNextWC = -directionToPrevWC;\n\
  125. }\n\
  126. \n\
  127. vec2 thisSegmentForwardWC, otherSegmentForwardWC;\n\
  128. if (usePrevious)\n\
  129. {\n\
  130. thisSegmentForwardWC = -directionToPrevWC;\n\
  131. otherSegmentForwardWC = directionToNextWC;\n\
  132. }\n\
  133. else\n\
  134. {\n\
  135. thisSegmentForwardWC = directionToNextWC;\n\
  136. otherSegmentForwardWC = -directionToPrevWC;\n\
  137. }\n\
  138. \n\
  139. vec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x);\n\
  140. \n\
  141. vec2 leftWC = thisSegmentLeftWC;\n\
  142. float expandWidth = width * 0.5;\n\
  143. \n\
  144. // When lines are split at the anti-meridian, the position may be at the\n\
  145. // same location as the next or previous position, and we need to handle\n\
  146. // that to avoid producing NaNs.\n\
  147. if (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1))\n\
  148. {\n\
  149. vec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x);\n\
  150. \n\
  151. vec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC;\n\
  152. float leftSumLength = length(leftSumWC);\n\
  153. leftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength);\n\
  154. \n\
  155. // The sine of the angle between the two vectors is given by the formula\n\
  156. // |a x b| = |a||b|sin(theta)\n\
  157. // which is\n\
  158. // float sinAngle = length(cross(vec3(leftWC, 0.0), vec3(-thisSegmentForwardWC, 0.0)));\n\
  159. // Because the z components of both vectors are zero, the x and y coordinate will be zero.\n\
  160. // Therefore, the sine of the angle is just the z component of the cross product.\n\
  161. vec2 u = -thisSegmentForwardWC;\n\
  162. vec2 v = leftWC;\n\
  163. float sinAngle = abs(u.x * v.y - u.y * v.x);\n\
  164. expandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0);\n\
  165. }\n\
  166. \n\
  167. vec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio;\n\
  168. return vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w;\n\
  169. }\n\
  170. \n\
  171. vec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle)\n\
  172. {\n\
  173. vec4 positionEC = czm_modelViewRelativeToEye * position;\n\
  174. vec4 prevEC = czm_modelViewRelativeToEye * previous;\n\
  175. vec4 nextEC = czm_modelViewRelativeToEye * next;\n\
  176. return getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle);\n\
  177. }\n\
  178. ";