| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 | void clipLineSegmentToNearPlane(    vec3 p0,    vec3 p1,    out vec4 positionWC,    out bool clipped,    out bool culledByNearPlane,    out vec4 clippedPositionEC){    culledByNearPlane = false;    clipped = false;    vec3 p0ToP1 = p1 - p0;    float magnitude = length(p0ToP1);    vec3 direction = normalize(p0ToP1);    // Distance that p0 is behind the near plane. Negative means p0 is    // in front of the near plane.    float endPoint0Distance =  czm_currentFrustum.x + p0.z;    // Camera looks down -Z.    // When moving a point along +Z: LESS VISIBLE    //   * Points in front of the camera move closer to the camera.    //   * Points behind the camrea move farther away from the camera.    // When moving a point along -Z: MORE VISIBLE    //   * Points in front of the camera move farther away from the camera.    //   * Points behind the camera move closer to the camera.    // Positive denominator: -Z, becoming more visible    // Negative denominator: +Z, becoming less visible    // Nearly zero: parallel to near plane    float denominator = -direction.z;    if (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7)    {        // p0 is behind the near plane and the line to p1 is nearly parallel to        // the near plane, so cull the segment completely.        culledByNearPlane = true;    }    else if (endPoint0Distance > 0.0)    {        // p0 is behind the near plane, and the line to p1 is moving distinctly        // toward or away from it.        // t = (-plane distance - dot(plane normal, ray origin)) / dot(plane normal, ray direction)        float t = endPoint0Distance / denominator;        if (t < 0.0 || t > magnitude)        {            // Near plane intersection is not between the two points.            // We already confirmed p0 is behind the naer plane, so now            // we know the entire segment is behind it.            culledByNearPlane = true;        }        else        {            // Segment crosses the near plane, update p0 to lie exactly on it.            p0 = p0 + t * direction;            // Numerical noise might put us a bit on the wrong side of the near plane.            // Don't let that happen.            p0.z = min(p0.z, -czm_currentFrustum.x);            clipped = true;        }    }    clippedPositionEC = vec4(p0, 1.0);    positionWC = czm_eyeToWindowCoordinates(clippedPositionEC);}vec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle){    // expandDirection +1 is to the _left_ when looking from positionEC toward nextEC.#ifdef POLYLINE_DASH    // Compute the window coordinates of the points.    vec4 positionWindow = czm_eyeToWindowCoordinates(positionEC);    vec4 previousWindow = czm_eyeToWindowCoordinates(prevEC);    vec4 nextWindow = czm_eyeToWindowCoordinates(nextEC);    // Determine the relative screen space direction of the line.    vec2 lineDir;    if (usePrevious) {        lineDir = normalize(positionWindow.xy - previousWindow.xy);    }    else {        lineDir = normalize(nextWindow.xy - positionWindow.xy);    }    angle = atan(lineDir.x, lineDir.y) - 1.570796327; // precomputed atan(1,0)    // Quantize the angle so it doesn't change rapidly between segments.    angle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour;#endif    vec4 clippedPrevWC, clippedPrevEC;    bool prevSegmentClipped, prevSegmentCulled;    clipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC);    vec4 clippedNextWC, clippedNextEC;    bool nextSegmentClipped, nextSegmentCulled;    clipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC);    bool segmentClipped, segmentCulled;    vec4 clippedPositionWC, clippedPositionEC;    clipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC);    if (segmentCulled)    {        return vec4(0.0, 0.0, 0.0, 1.0);    }    vec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy);    vec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy);    // If a segment was culled, we can't use the corresponding direction    // computed above. We should never see both of these be true without    // `segmentCulled` above also being true.    if (prevSegmentCulled)    {        directionToPrevWC = -directionToNextWC;    }    else if (nextSegmentCulled)    {        directionToNextWC = -directionToPrevWC;    }    vec2 thisSegmentForwardWC, otherSegmentForwardWC;    if (usePrevious)    {        thisSegmentForwardWC = -directionToPrevWC;        otherSegmentForwardWC = directionToNextWC;    }    else    {        thisSegmentForwardWC = directionToNextWC;        otherSegmentForwardWC =  -directionToPrevWC;    }    vec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x);    vec2 leftWC = thisSegmentLeftWC;    float expandWidth = width * 0.5;    // When lines are split at the anti-meridian, the position may be at the    // same location as the next or previous position, and we need to handle    // that to avoid producing NaNs.    if (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1))    {        vec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x);        vec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC;        float leftSumLength = length(leftSumWC);        leftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength);        // The sine of the angle between the two vectors is given by the formula        //         |a x b| = |a||b|sin(theta)        // which is        //     float sinAngle = length(cross(vec3(leftWC, 0.0), vec3(-thisSegmentForwardWC, 0.0)));        // Because the z components of both vectors are zero, the x and y coordinate will be zero.        // Therefore, the sine of the angle is just the z component of the cross product.        vec2 u = -thisSegmentForwardWC;        vec2 v = leftWC;        float sinAngle = abs(u.x * v.y - u.y * v.x);        expandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0);    }    vec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio;    return vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w;}vec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle){    vec4 positionEC = czm_modelViewRelativeToEye * position;    vec4 prevEC = czm_modelViewRelativeToEye * previous;    vec4 nextEC = czm_modelViewRelativeToEye * next;    return getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle);}
 |