@cesium/engine
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
196 lines (195 loc) • 9.88 kB
JavaScript
//This file is automatically rebuilt by the Cesium build process.
export default "/* Ellipsoid defines (set in Scene/VoxelEllipsoidShape.js)\n\
#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY\n\
#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY\n\
#define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE\n\
#define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED\n\
#define ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE\n\
*/\n\
\n\
uniform vec3 u_cameraPositionCartographic; // (longitude, latitude, height) in radians and meters\n\
uniform vec2 u_ellipsoidCurvatureAtLatitude;\n\
uniform mat3 u_ellipsoidEcToEastNorthUp;\n\
uniform vec3 u_ellipsoidRadii;\n\
uniform vec2 u_evoluteScale; // (radii.x ^ 2 - radii.z ^ 2) * vec2(1.0, -1.0) / radii;\n\
uniform vec3 u_ellipsoidInverseRadiiSquared;\n\
#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\
uniform vec3 u_ellipsoidShapeUvLongitudeMinMaxMid;\n\
#endif\n\
#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n\
uniform vec2 u_ellipsoidLocalToShapeUvLongitude; // x = scale, y = offset\n\
uniform float u_ellipsoidShapeUvLongitudeRangeOrigin;\n\
#endif\n\
#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n\
uniform vec2 u_ellipsoidLocalToShapeUvLatitude; // x = scale, y = offset\n\
#endif\n\
uniform float u_ellipsoidInverseHeightDifference;\n\
\n\
uniform ivec4 u_cameraTileCoordinates;\n\
uniform vec3 u_cameraTileUv;\n\
\n\
// robust iterative solution without trig functions\n\
// https://github.com/0xfaded/ellipse_demo/issues/1\n\
// https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse\n\
// Extended to return radius of curvature along with the point\n\
vec3 nearestPointAndRadiusOnEllipse(vec2 pos, vec2 radii) {\n\
vec2 p = abs(pos);\n\
vec2 inverseRadii = 1.0 / radii;\n\
\n\
// We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))\n\
// but store the cos and sin of t in a vec2 for efficiency.\n\
// Initial guess: t = pi/4\n\
vec2 tTrigs = vec2(0.7071067811865476);\n\
// Initial guess of point on ellipsoid\n\
vec2 v = radii * tTrigs;\n\
// Center of curvature of the ellipse at v\n\
vec2 evolute = u_evoluteScale * tTrigs * tTrigs * tTrigs;\n\
\n\
const int iterations = 3;\n\
for (int i = 0; i < iterations; ++i) {\n\
// Find the (approximate) intersection of p - evolute with the ellipsoid.\n\
vec2 q = normalize(p - evolute) * length(v - evolute);\n\
// Update the estimate of t.\n\
tTrigs = (q + evolute) * inverseRadii;\n\
tTrigs = normalize(clamp(tTrigs, 0.0, 1.0));\n\
v = radii * tTrigs;\n\
evolute = u_evoluteScale * tTrigs * tTrigs * tTrigs;\n\
}\n\
\n\
return vec3(v * sign(pos), length(v - evolute));\n\
}\n\
\n\
mat3 convertLocalToShapeSpaceDerivative(in vec3 position) {\n\
vec3 east = normalize(vec3(-position.y, position.x, 0.0));\n\
\n\
// Convert the 3D position to a 2D position relative to the ellipse (radii.x, radii.z)\n\
// (assume radii.y == radii.x) and find the nearest point on the ellipse and its normal\n\
float distanceFromZAxis = length(position.xy);\n\
vec2 posEllipse = vec2(distanceFromZAxis, position.z);\n\
vec3 surfacePointAndRadius = nearestPointAndRadiusOnEllipse(posEllipse, u_ellipsoidRadii.xz);\n\
vec2 surfacePoint = surfacePointAndRadius.xy;\n\
\n\
vec2 normal2d = normalize(surfacePoint * u_ellipsoidInverseRadiiSquared.xz);\n\
vec3 north = vec3(-normal2d.y * normalize(position.xy), abs(normal2d.x));\n\
\n\
float heightSign = length(posEllipse) < length(surfacePoint) ? -1.0 : 1.0;\n\
float height = heightSign * length(posEllipse - surfacePoint);\n\
vec3 up = normalize(cross(east, north));\n\
\n\
return mat3(east / distanceFromZAxis, north / (surfacePointAndRadius.z + height), up);\n\
}\n\
\n\
vec3 scaleShapeUvToShapeSpace(in vec3 shapeUv) {\n\
// Convert from [0, 1] to radians [-pi, pi]\n\
float longitude = shapeUv.x * czm_twoPi;\n\
#if defined (ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n\
longitude /= u_ellipsoidLocalToShapeUvLongitude.x;\n\
#endif\n\
\n\
// Convert from [0, 1] to radians [-pi/2, pi/2]\n\
float latitude = shapeUv.y * czm_pi;\n\
#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n\
latitude /= u_ellipsoidLocalToShapeUvLatitude.x;\n\
#endif\n\
\n\
float height = shapeUv.z / u_ellipsoidInverseHeightDifference;\n\
\n\
return vec3(longitude, latitude, height);\n\
}\n\
\n\
vec3 convertEcToDeltaShape(in vec3 positionEC) {\n\
vec3 enu = u_ellipsoidEcToEastNorthUp * positionEC;\n\
\n\
// 1. Compute the change in longitude from the camera to the ENU point\n\
// First project the camera and ENU positions to the equatorial XY plane,\n\
// positioning the camera on the +x axis, so that enu.x projects along the +y axis\n\
float cosLatitude = cos(u_cameraPositionCartographic.y);\n\
float sinLatitude = sin(u_cameraPositionCartographic.y);\n\
float primeVerticalRadius = 1.0 / u_ellipsoidCurvatureAtLatitude.x;\n\
vec2 cameraXY = vec2((primeVerticalRadius + u_cameraPositionCartographic.z) * cosLatitude, 0.0);\n\
// Note precision loss in positionXY.x if length(enu) << length(cameraXY)\n\
vec2 positionXY = cameraXY + vec2(-enu.y * sinLatitude + enu.z * cosLatitude, enu.x);\n\
float dLongitude = atan(positionXY.y, positionXY.x);\n\
\n\
// 2. Find the longitude component of positionXY, by rotating about Z until the y component is zero.\n\
// Use the versine to compute the change in x directly from the change in angle:\n\
// versine(angle) = 2 * sin^2(angle/2)\n\
float sinHalfLongitude = sin(dLongitude / 2.0);\n\
float dx = length(positionXY) * 2.0 * sinHalfLongitude * sinHalfLongitude;\n\
// Rotate longitude component back to ENU North and Up, and remove from enu\n\
enu += vec3(-enu.x, -dx * sinLatitude, dx * cosLatitude);\n\
\n\
// 3. Compute the change in latitude from the camera to the ENU point.\n\
// First project the camera and ENU positions to the meridional ZX plane,\n\
// positioning the camera on the +Z axis, so that enu.y maps to the +X axis.\n\
float meridionalRadius = 1.0 / u_ellipsoidCurvatureAtLatitude.y;\n\
vec2 cameraZX = vec2(meridionalRadius + u_cameraPositionCartographic.z, 0.0);\n\
vec2 positionZX = cameraZX + vec2(enu.z, enu.y);\n\
float dLatitude = atan(positionZX.y, positionZX.x);\n\
\n\
// 4. Compute the change in height above the ellipsoid\n\
// Find the change in enu.z associated with rotating the point to the latitude of the camera\n\
float sinHalfLatitude = sin(dLatitude / 2.0);\n\
float dz = length(positionZX) * 2.0 * sinHalfLatitude * sinHalfLatitude;\n\
// The remaining change in enu.z is the change in height above the ellipsoid\n\
float dHeight = enu.z + dz;\n\
\n\
return vec3(dLongitude, dLatitude, dHeight);\n\
}\n\
\n\
vec3 convertEcToDeltaTile(in vec3 positionEC) {\n\
vec3 deltaShape = convertEcToDeltaShape(positionEC);\n\
// Convert to tileset coordinates in [0, 1]\n\
float dx = deltaShape.x / czm_twoPi;\n\
\n\
#if (defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE))\n\
// Wrap to ensure dx is not crossing through the unoccupied angle range, where\n\
// angle to tile coordinate conversions would be more complicated\n\
float cameraUvLongitude = (u_cameraPositionCartographic.x + czm_pi) / czm_twoPi;\n\
float cameraUvLongitudeShift = fract(cameraUvLongitude - u_ellipsoidShapeUvLongitudeRangeOrigin);\n\
float rawOutputUvLongitude = cameraUvLongitudeShift + dx;\n\
float rotation = floor(rawOutputUvLongitude);\n\
dx -= rotation;\n\
dx *= u_ellipsoidLocalToShapeUvLongitude.x;\n\
#endif\n\
\n\
float dy = deltaShape.y / czm_pi;\n\
#if (defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE))\n\
dy *= u_ellipsoidLocalToShapeUvLatitude.x;\n\
#endif\n\
\n\
float dz = u_ellipsoidInverseHeightDifference * deltaShape.z;\n\
// Convert to tile coordinate changes\n\
return vec3(dx, dy, dz) * float(1 << u_cameraTileCoordinates.w);\n\
}\n\
\n\
TileAndUvCoordinate getTileAndUvCoordinate(in vec3 positionEC) {\n\
vec3 deltaTileCoordinate = convertEcToDeltaTile(positionEC);\n\
vec3 tileUvSum = u_cameraTileUv + deltaTileCoordinate;\n\
ivec3 tileCoordinate = u_cameraTileCoordinates.xyz + ivec3(floor(tileUvSum));\n\
int maxTileCoordinate = (1 << u_cameraTileCoordinates.w) - 1;\n\
tileCoordinate.y = min(max(0, tileCoordinate.y), maxTileCoordinate);\n\
tileCoordinate.z = min(max(0, tileCoordinate.z), maxTileCoordinate);\n\
#if (!defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE))\n\
ivec3 tileCoordinateChange = tileCoordinate - u_cameraTileCoordinates.xyz;\n\
if (tileCoordinate.x < 0) {\n\
tileCoordinate.x += (maxTileCoordinate + 1);\n\
} else if (tileCoordinate.x > maxTileCoordinate) {\n\
tileCoordinate.x -= (maxTileCoordinate + 1);\n\
}\n\
#else\n\
tileCoordinate.x = min(max(0, tileCoordinate.x), maxTileCoordinate);\n\
ivec3 tileCoordinateChange = tileCoordinate - u_cameraTileCoordinates.xyz;\n\
#endif\n\
vec3 tileUv = tileUvSum - vec3(tileCoordinateChange);\n\
#if (!defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE))\n\
// If there is only one tile spanning 2*PI angle, the coordinate wraps around\n\
tileUv.x = (u_cameraTileCoordinates.w == 0) ? fract(tileUv.x) : clamp(tileUv.x, 0.0, 1.0);\n\
#else\n\
tileUv.x = clamp(tileUv.x, 0.0, 1.0);\n\
#endif\n\
tileUv.y = clamp(tileUv.y, 0.0, 1.0);\n\
tileUv.z = clamp(tileUv.z, 0.0, 1.0);\n\
return TileAndUvCoordinate(ivec4(tileCoordinate, u_cameraTileCoordinates.w), tileUv);\n\
}\n\
";