123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945 |
- import BoundingSphere from "../Core/BoundingSphere.js";
- import Cartesian2 from "../Core/Cartesian2.js";
- import Cartesian3 from "../Core/Cartesian3.js";
- import Check from "../Core/Check.js";
- import Ellipsoid from "../Core/Ellipsoid.js";
- import CesiumMath from "../Core/Math.js";
- import Matrix3 from "../Core/Matrix3.js";
- import Matrix4 from "../Core/Matrix4.js";
- import OrientedBoundingBox from "../Core/OrientedBoundingBox.js";
- import Rectangle from "../Core/Rectangle.js";
- import defaultValue from "../Core/defaultValue.js";
- /**
- * An ellipsoid {@link VoxelShape}.
- *
- * @alias VoxelEllipsoidShape
- * @constructor
- *
- * @see VoxelShape
- * @see VoxelBoxShape
- * @see VoxelCylinderShape
- * @see VoxelShapeType
- *
- * @private
- */
- function VoxelEllipsoidShape() {
- /**
- * An oriented bounding box containing the bounded shape.
- * The update function must be called before accessing this value.
- * @type {OrientedBoundingBox}
- * @readonly
- */
- this.orientedBoundingBox = new OrientedBoundingBox();
- /**
- * A bounding sphere containing the bounded shape.
- * The update function must be called before accessing this value.
- * @type {BoundingSphere}
- * @readonly
- */
- this.boundingSphere = new BoundingSphere();
- /**
- * A transformation matrix containing the bounded shape.
- * The update function must be called before accessing this value.
- * @type {Matrix4}
- * @readonly
- */
- this.boundTransform = new Matrix4();
- /**
- * A transformation matrix containing the shape, ignoring the bounds.
- * The update function must be called before accessing this value.
- * @type {Matrix4}
- * @readonly
- */
- this.shapeTransform = new Matrix4();
- /**
- * @type {Rectangle}
- */
- this._rectangle = new Rectangle();
- /**
- * @type {number}
- * @private
- */
- this._minimumHeight = VoxelEllipsoidShape.DefaultMinBounds.z;
- /**
- * @type {number}
- * @private
- */
- this._maximumHeight = VoxelEllipsoidShape.DefaultMaxBounds.z;
- /**
- * @type {Ellipsoid}
- * @private
- */
- this._ellipsoid = new Ellipsoid();
- /**
- * @type {Cartesian3}
- */
- this._translation = new Cartesian3();
- /**
- * @type {Matrix3}
- */
- this._rotation = new Matrix3();
- /**
- * @type {Object<string, any>}
- * @readonly
- */
- this.shaderUniforms = {
- ellipsoidRadiiUv: new Cartesian3(),
- ellipsoidInverseRadiiSquaredUv: new Cartesian3(),
- ellipsoidRenderLongitudeMinMax: new Cartesian2(),
- ellipsoidShapeUvLongitudeMinMaxMid: new Cartesian3(),
- ellipsoidUvToShapeUvLongitude: new Cartesian2(),
- ellipsoidUvToShapeUvLatitude: new Cartesian2(),
- ellipsoidRenderLatitudeCosSqrHalfMinMax: new Cartesian2(),
- ellipsoidInverseHeightDifferenceUv: 0.0,
- ellipseInnerRadiiUv: new Cartesian2(),
- ellipsoidInverseInnerScaleUv: 0.0,
- ellipsoidInverseOuterScaleUv: 0.0,
- };
- /**
- * @type {Object<string, any>}
- * @readonly
- */
- this.shaderDefines = {
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN: undefined,
- ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_FLAT: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN: undefined,
- ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_FLAT: undefined,
- ELLIPSOID_IS_SPHERE: undefined,
- ELLIPSOID_INTERSECTION_INDEX_LONGITUDE: undefined,
- ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX: undefined,
- ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN: undefined,
- ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX: undefined,
- ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN: undefined,
- };
- /**
- * The maximum number of intersections against the shape for any ray direction.
- * @type {number}
- * @readonly
- */
- this.shaderMaximumIntersectionsLength = 0; // not known until update
- }
- const scratchScale = new Cartesian3();
- const scratchRotationScale = new Matrix3();
- const scratchShapeOuterExtent = new Cartesian3();
- const scratchShapeInnerExtent = new Cartesian3();
- const scratchRenderOuterExtent = new Cartesian3();
- const scratchRenderInnerExtent = new Cartesian3();
- const scratchRenderRectangle = new Rectangle();
- /**
- * Update the shape's state.
- *
- * @param {Matrix4} modelMatrix The model matrix.
- * @param {Cartesian3} minBounds The minimum bounds.
- * @param {Cartesian3} maxBounds The maximum bounds.
- * @param {Cartesian3} [clipMinBounds=VoxelEllipsoidShape.DefaultMinBounds] The minimum clip bounds.
- * @param {Cartesian3} [clipMaxBounds=VoxelEllipsoidShape.DefaultMaxBounds] The maximum clip bounds.
- * @returns {boolean} Whether the shape is visible.
- */
- VoxelEllipsoidShape.prototype.update = function (
- modelMatrix,
- minBounds,
- maxBounds,
- clipMinBounds,
- clipMaxBounds
- ) {
- clipMinBounds = defaultValue(
- clipMinBounds,
- VoxelEllipsoidShape.DefaultMinBounds
- );
- clipMaxBounds = defaultValue(
- clipMaxBounds,
- VoxelEllipsoidShape.DefaultMaxBounds
- );
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("modelMatrix", modelMatrix);
- Check.typeOf.object("minBounds", minBounds);
- Check.typeOf.object("maxBounds", maxBounds);
- //>>includeEnd('debug');
- const defaultMinLongitude = VoxelEllipsoidShape.DefaultMinBounds.x;
- const defaultMaxLongitude = VoxelEllipsoidShape.DefaultMaxBounds.x;
- const defaultLongitudeRange = defaultMaxLongitude - defaultMinLongitude;
- const defaultLongitudeRangeHalf = 0.5 * defaultLongitudeRange;
- const defaultMinLatitude = VoxelEllipsoidShape.DefaultMinBounds.y;
- const defaultMaxLatitude = VoxelEllipsoidShape.DefaultMaxBounds.y;
- const defaultLatitudeRange = defaultMaxLatitude - defaultMinLatitude;
- const epsilonZeroScale = CesiumMath.EPSILON10;
- const epsilonLongitudeDiscontinuity = CesiumMath.EPSILON3; // 0.001 radians = 0.05729578 degrees
- const epsilonLongitude = CesiumMath.EPSILON10;
- const epsilonLatitude = CesiumMath.EPSILON10;
- const epsilonLatitudeFlat = CesiumMath.EPSILON3; // 0.001 radians = 0.05729578 degrees
- // Clamp the longitude / latitude to the valid range
- const shapeMinLongitude = CesiumMath.clamp(
- minBounds.x,
- defaultMinLongitude,
- defaultMaxLongitude
- );
- const shapeMaxLongitude = CesiumMath.clamp(
- maxBounds.x,
- defaultMinLongitude,
- defaultMaxLongitude
- );
- const clipMinLongitude = CesiumMath.clamp(
- clipMinBounds.x,
- defaultMinLongitude,
- defaultMaxLongitude
- );
- const clipMaxLongitude = CesiumMath.clamp(
- clipMaxBounds.x,
- defaultMinLongitude,
- defaultMaxLongitude
- );
- const renderMinLongitude = Math.max(shapeMinLongitude, clipMinLongitude);
- const renderMaxLongitude = Math.min(shapeMaxLongitude, clipMaxLongitude);
- const shapeMinLatitude = CesiumMath.clamp(
- minBounds.y,
- defaultMinLatitude,
- defaultMaxLatitude
- );
- const shapeMaxLatitude = CesiumMath.clamp(
- maxBounds.y,
- defaultMinLatitude,
- defaultMaxLatitude
- );
- const clipMinLatitude = CesiumMath.clamp(
- clipMinBounds.y,
- defaultMinLatitude,
- defaultMaxLatitude
- );
- const clipMaxLatitude = CesiumMath.clamp(
- clipMaxBounds.y,
- defaultMinLatitude,
- defaultMaxLatitude
- );
- const renderMinLatitude = Math.max(shapeMinLatitude, clipMinLatitude);
- const renderMaxLatitude = Math.min(shapeMaxLatitude, clipMaxLatitude);
- // Don't let the height go below the center of the ellipsoid.
- const radii = Matrix4.getScale(modelMatrix, scratchScale);
- const isSphere = radii.x === radii.y && radii.y === radii.z;
- const minRadius = Cartesian3.minimumComponent(radii);
- const shapeMinHeight = Math.max(minBounds.z, -minRadius);
- const shapeMaxHeight = Math.max(maxBounds.z, -minRadius);
- const clipMinHeight = Math.max(clipMinBounds.z, -minRadius);
- const clipMaxHeight = Math.max(clipMaxBounds.z, -minRadius);
- const renderMinHeight = Math.max(shapeMinHeight, clipMinHeight);
- const renderMaxHeight = Math.min(shapeMaxHeight, clipMaxHeight);
- // Compute the closest and farthest a point can be from the center of the ellipsoid.
- const shapeInnerExtent = Cartesian3.add(
- radii,
- Cartesian3.fromElements(
- shapeMinHeight,
- shapeMinHeight,
- shapeMinHeight,
- scratchShapeInnerExtent
- ),
- scratchShapeInnerExtent
- );
- const shapeOuterExtent = Cartesian3.add(
- radii,
- Cartesian3.fromElements(
- shapeMaxHeight,
- shapeMaxHeight,
- shapeMaxHeight,
- scratchShapeOuterExtent
- ),
- scratchShapeOuterExtent
- );
- const shapeMaxExtent = Cartesian3.maximumComponent(shapeOuterExtent);
- const renderInnerExtent = Cartesian3.add(
- radii,
- Cartesian3.fromElements(
- renderMinHeight,
- renderMinHeight,
- renderMinHeight,
- scratchRenderInnerExtent
- ),
- scratchRenderInnerExtent
- );
- const renderOuterExtent = Cartesian3.add(
- radii,
- Cartesian3.fromElements(
- renderMaxHeight,
- renderMaxHeight,
- renderMaxHeight,
- scratchRenderOuterExtent
- ),
- scratchRenderOuterExtent
- );
- // Exit early if the shape is not visible.
- // Note that minLongitude may be greater than maxLongitude when crossing the 180th meridian.
- if (
- renderMinLatitude > renderMaxLatitude ||
- renderMinLatitude === defaultMaxLatitude ||
- renderMaxLatitude === defaultMinLatitude ||
- renderMinHeight > renderMaxHeight ||
- CesiumMath.equalsEpsilon(
- renderOuterExtent,
- Cartesian3.ZERO,
- undefined,
- epsilonZeroScale
- )
- ) {
- return false;
- }
- this._rectangle = Rectangle.fromRadians(
- shapeMinLongitude,
- shapeMinLatitude,
- shapeMaxLongitude,
- shapeMaxLatitude
- );
- this._translation = Matrix4.getTranslation(modelMatrix, this._translation);
- this._rotation = Matrix4.getRotation(modelMatrix, this._rotation);
- this._ellipsoid = Ellipsoid.fromCartesian3(radii, this._ellipsoid);
- this._minimumHeight = shapeMinHeight;
- this._maximumHeight = shapeMaxHeight;
- const renderRectangle = Rectangle.fromRadians(
- renderMinLongitude,
- renderMinLatitude,
- renderMaxLongitude,
- renderMaxLatitude,
- scratchRenderRectangle
- );
- this.orientedBoundingBox = getEllipsoidChunkObb(
- renderRectangle,
- renderMinHeight,
- renderMaxHeight,
- this._ellipsoid,
- this._translation,
- this._rotation,
- this.orientedBoundingBox
- );
- this.shapeTransform = Matrix4.fromRotationTranslation(
- Matrix3.setScale(this._rotation, shapeOuterExtent, scratchRotationScale),
- this._translation,
- this.shapeTransform
- );
- this.boundTransform = Matrix4.fromRotationTranslation(
- this.orientedBoundingBox.halfAxes,
- this.orientedBoundingBox.center,
- this.boundTransform
- );
- this.boundingSphere = BoundingSphere.fromOrientedBoundingBox(
- this.orientedBoundingBox,
- this.boundingSphere
- );
- // Longitude
- const renderIsLongitudeReversed = renderMaxLongitude < renderMinLongitude;
- const renderLongitudeRange =
- renderMaxLongitude -
- renderMinLongitude +
- renderIsLongitudeReversed * defaultLongitudeRange;
- const renderIsLongitudeRangeZero = renderLongitudeRange <= epsilonLongitude;
- const renderIsLongitudeRangeUnderHalf =
- renderLongitudeRange > defaultLongitudeRangeHalf + epsilonLongitude &&
- renderLongitudeRange < defaultLongitudeRange - epsilonLongitude;
- const renderIsLongitudeRangeHalf =
- renderLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude &&
- renderLongitudeRange <= defaultLongitudeRangeHalf + epsilonLongitude;
- const renderIsLongitudeRangeOverHalf =
- renderLongitudeRange > epsilonLongitude &&
- renderLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
- const renderHasLongitude =
- renderIsLongitudeRangeZero ||
- renderIsLongitudeRangeUnderHalf ||
- renderIsLongitudeRangeHalf ||
- renderIsLongitudeRangeOverHalf;
- const shapeIsLongitudeReversed = shapeMaxLongitude < shapeMinLongitude;
- const shapeLongitudeRange =
- shapeMaxLongitude -
- shapeMinLongitude +
- shapeIsLongitudeReversed * defaultLongitudeRange;
- const shapeIsLongitudeRangeZero = shapeLongitudeRange <= epsilonLongitude;
- const shapeIsLongitudeRangeUnderHalf =
- shapeLongitudeRange > defaultLongitudeRangeHalf + epsilonLongitude &&
- shapeLongitudeRange < defaultLongitudeRange - epsilonLongitude;
- const shapeIsLongitudeRangeHalf =
- shapeLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude &&
- shapeLongitudeRange <= defaultLongitudeRangeHalf + epsilonLongitude;
- const shapeIsLongitudeRangeOverHalf =
- shapeLongitudeRange > epsilonLongitude &&
- shapeLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
- const shapeHasLongitude =
- shapeIsLongitudeRangeZero ||
- shapeIsLongitudeRangeUnderHalf ||
- shapeIsLongitudeRangeHalf ||
- shapeIsLongitudeRangeOverHalf;
- // Latitude
- const renderIsLatitudeMaxUnderHalf = renderMaxLatitude < -epsilonLatitudeFlat;
- const renderIsLatitudeMaxHalf =
- renderMaxLatitude >= -epsilonLatitudeFlat &&
- renderMaxLatitude <= +epsilonLatitudeFlat;
- const renderIsLatitudeMaxOverHalf =
- renderMaxLatitude > +epsilonLatitudeFlat &&
- renderMaxLatitude < defaultMaxLatitude - epsilonLatitude;
- const renderHasLatitudeMax =
- renderIsLatitudeMaxUnderHalf ||
- renderIsLatitudeMaxHalf ||
- renderIsLatitudeMaxOverHalf;
- const renderIsLatitudeMinUnderHalf =
- renderMinLatitude > defaultMinLatitude + epsilonLatitude &&
- renderMinLatitude < -epsilonLatitudeFlat;
- const renderIsLatitudeMinHalf =
- renderMinLatitude >= -epsilonLatitudeFlat &&
- renderMinLatitude <= +epsilonLatitudeFlat;
- const renderIsLatitudeMinOverHalf = renderMinLatitude > +epsilonLatitudeFlat;
- const renderHasLatitudeMin =
- renderIsLatitudeMinUnderHalf ||
- renderIsLatitudeMinHalf ||
- renderIsLatitudeMinOverHalf;
- const renderHasLatitude = renderHasLatitudeMax || renderHasLatitudeMin;
- const shapeLatitudeRange = shapeMaxLatitude - shapeMinLatitude;
- const shapeIsLatitudeMaxUnderHalf = shapeMaxLatitude < -epsilonLatitudeFlat;
- const shapeIsLatitudeMaxHalf =
- shapeMaxLatitude >= -epsilonLatitudeFlat &&
- shapeMaxLatitude <= +epsilonLatitudeFlat;
- const shapeIsLatitudeMaxOverHalf =
- shapeMaxLatitude > +epsilonLatitudeFlat &&
- shapeMaxLatitude < defaultMaxLatitude - epsilonLatitude;
- const shapeHasLatitudeMax =
- shapeIsLatitudeMaxUnderHalf ||
- shapeIsLatitudeMaxHalf ||
- shapeIsLatitudeMaxOverHalf;
- const shapeIsLatitudeMinUnderHalf =
- shapeMinLatitude > defaultMinLatitude + epsilonLatitude &&
- shapeMinLatitude < -epsilonLatitudeFlat;
- const shapeIsLatitudeMinHalf =
- shapeMinLatitude >= -epsilonLatitudeFlat &&
- shapeMinLatitude <= +epsilonLatitudeFlat;
- const shapeIsLatitudeMinOverHalf = shapeMinLatitude > +epsilonLatitudeFlat;
- const shapeHasLatitudeMin =
- shapeIsLatitudeMinUnderHalf ||
- shapeIsLatitudeMinHalf ||
- shapeIsLatitudeMinOverHalf;
- const shapeHasLatitude = shapeHasLatitudeMax || shapeHasLatitudeMin;
- // Height
- const renderHasMinHeight = !Cartesian3.equals(
- renderInnerExtent,
- Cartesian3.ZERO
- );
- const renderHasMaxHeight = !Cartesian3.equals(
- renderOuterExtent,
- Cartesian3.ZERO
- );
- const renderHasHeight = renderHasMinHeight || renderHasMaxHeight;
- const renderHeightRange = renderMaxHeight - renderMinHeight;
- const shapeHasMinHeight = !Cartesian3.equals(
- shapeInnerExtent,
- Cartesian3.ZERO
- );
- const shapeHasMaxHeight = !Cartesian3.equals(
- shapeOuterExtent,
- Cartesian3.ZERO
- );
- const shapeHasHeight = shapeHasMinHeight || shapeHasMaxHeight;
- const shaderUniforms = this.shaderUniforms;
- const shaderDefines = this.shaderDefines;
- // To keep things simple, clear the defines every time
- for (const key in shaderDefines) {
- if (shaderDefines.hasOwnProperty(key)) {
- shaderDefines[key] = undefined;
- }
- }
- // The ellipsoid radii scaled to [0,1]. The max ellipsoid radius will be 1.0 and others will be less.
- shaderUniforms.ellipsoidRadiiUv = Cartesian3.divideByScalar(
- shapeOuterExtent,
- shapeMaxExtent,
- shaderUniforms.ellipsoidRadiiUv
- );
- // Used to compute geodetic surface normal.
- shaderUniforms.ellipsoidInverseRadiiSquaredUv = Cartesian3.divideComponents(
- Cartesian3.ONE,
- Cartesian3.multiplyComponents(
- shaderUniforms.ellipsoidRadiiUv,
- shaderUniforms.ellipsoidRadiiUv,
- shaderUniforms.ellipsoidInverseRadiiSquaredUv
- ),
- shaderUniforms.ellipsoidInverseRadiiSquaredUv
- );
- // Keep track of how many intersections there are going to be.
- let intersectionCount = 0;
- // Intersects an outer ellipsoid for the max height.
- shaderDefines["ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX"] = intersectionCount;
- intersectionCount += 1;
- if (renderHasHeight) {
- if (renderHeightRange === 0.0) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_FLAT"] = true;
- }
- if (renderHasMinHeight) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MIN"] = true;
- shaderDefines[
- "ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN"
- ] = intersectionCount;
- intersectionCount += 1;
- // The inverse of the percent of space that is taken up by the inner ellipsoid, relative to the shape bounds
- // 1.0 / (1.0 - thickness) // thickness = percent of space that is between the min and max height.
- // 1.0 / (1.0 - (shapeMaxHeight - renderMinHeight) / shapeMaxExtent)
- // shapeMaxExtent / (shapeMaxExtent - (shapeMaxHeight - renderMinHeight))
- shaderUniforms.ellipsoidInverseInnerScaleUv =
- shapeMaxExtent / (shapeMaxExtent - (shapeMaxHeight - renderMinHeight));
- }
- if (renderHasMaxHeight) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_HEIGHT_MAX"] = true;
- shaderUniforms.ellipsoidInverseOuterScaleUv =
- shapeMaxExtent / (shapeMaxExtent - (shapeMaxHeight - renderMaxHeight));
- }
- }
- if (shapeHasHeight) {
- if (shapeHasMinHeight) {
- shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_MIN"] = true;
- // The percent of space that is between the inner and outer ellipsoid.
- const thickness = (shapeMaxHeight - shapeMinHeight) / shapeMaxExtent;
- shaderUniforms.ellipsoidInverseHeightDifferenceUv = 1.0 / thickness;
- shaderUniforms.ellipseInnerRadiiUv = Cartesian2.fromElements(
- shaderUniforms.ellipsoidRadiiUv.x * (1.0 - thickness),
- shaderUniforms.ellipsoidRadiiUv.z * (1.0 - thickness),
- shaderUniforms.ellipseInnerRadiiUv
- );
- }
- if (shapeMinHeight === shapeMaxHeight) {
- shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_HEIGHT_FLAT"] = true;
- }
- }
- // Intersects a wedge for the min and max longitude.
- if (renderHasLongitude) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE"] = true;
- shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LONGITUDE"] = intersectionCount;
- if (renderIsLongitudeRangeUnderHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF"
- ] = true;
- intersectionCount += 1;
- } else if (renderIsLongitudeRangeOverHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF"
- ] = true;
- intersectionCount += 2;
- } else if (renderIsLongitudeRangeHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_HALF"
- ] = true;
- intersectionCount += 1;
- } else if (renderIsLongitudeRangeZero) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO"
- ] = true;
- intersectionCount += 2;
- }
- shaderUniforms.ellipsoidRenderLongitudeMinMax = Cartesian2.fromElements(
- renderMinLongitude,
- renderMaxLongitude,
- shaderUniforms.ellipsoidRenderLongitudeMinMax
- );
- }
- if (shapeHasLongitude) {
- shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE"] = true;
- const shapeIsLongitudeReversed = shapeMaxLongitude < shapeMinLongitude;
- if (shapeIsLongitudeReversed) {
- shaderDefines[
- "ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED"
- ] = true;
- }
- // delerp(longitudeUv, minLongitudeUv, maxLongitudeUv)
- // (longitudeUv - minLongitudeUv) / (maxLongitudeUv - minLongitudeUv)
- // longitudeUv / (maxLongitudeUv - minLongitudeUv) - minLongitudeUv / (maxLongitudeUv - minLongitudeUv)
- // scale = 1.0 / (maxLongitudeUv - minLongitudeUv)
- // scale = 1.0 / (((maxLongitude - pi) / (2.0 * pi)) - ((minLongitude - pi) / (2.0 * pi)))
- // scale = 2.0 * pi / (maxLongitude - minLongitude)
- // offset = -minLongitudeUv / (maxLongitudeUv - minLongitudeUv)
- // offset = -((minLongitude - pi) / (2.0 * pi)) / (((maxLongitude - pi) / (2.0 * pi)) - ((minLongitude - pi) / (2.0 * pi)))
- // offset = -(minLongitude - pi) / (maxLongitude - minLongitude)
- const scale = defaultLongitudeRange / shapeLongitudeRange;
- const offset =
- -(shapeMinLongitude - defaultMinLongitude) / shapeLongitudeRange;
- shaderUniforms.ellipsoidUvToShapeUvLongitude = Cartesian2.fromElements(
- scale,
- offset,
- shaderUniforms.ellipsoidUvToShapeUvLongitude
- );
- }
- if (renderHasLongitude) {
- const renderIsMinLongitudeDiscontinuity = CesiumMath.equalsEpsilon(
- renderMinLongitude,
- defaultMinLongitude,
- undefined,
- epsilonLongitudeDiscontinuity
- );
- const renderIsMaxLongitudeDiscontinuity = CesiumMath.equalsEpsilon(
- renderMaxLongitude,
- defaultMaxLongitude,
- undefined,
- epsilonLongitudeDiscontinuity
- );
- if (renderIsMinLongitudeDiscontinuity) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY"
- ] = true;
- }
- if (renderIsMaxLongitudeDiscontinuity) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY"
- ] = true;
- }
- const uvShapeMinLongitude =
- (shapeMinLongitude - defaultMinLongitude) / defaultLongitudeRange;
- const uvShapeMaxLongitude =
- (shapeMaxLongitude - defaultMinLongitude) / defaultLongitudeRange;
- const uvRenderMaxLongitude =
- (renderMaxLongitude - defaultMinLongitude) / defaultLongitudeRange;
- const uvRenderLongitudeRangeZero =
- 1.0 - renderLongitudeRange / defaultLongitudeRange;
- const uvRenderLongitudeRangeZeroMid =
- (uvRenderMaxLongitude + 0.5 * uvRenderLongitudeRangeZero) % 1.0;
- shaderUniforms.ellipsoidShapeUvLongitudeMinMaxMid = Cartesian3.fromElements(
- uvShapeMinLongitude,
- uvShapeMaxLongitude,
- uvRenderLongitudeRangeZeroMid,
- shaderUniforms.ellipsoidShapeUvLongitudeMinMaxMid
- );
- }
- if (renderHasLatitude) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE"] = true;
- // Intersects a cone for min latitude
- if (renderHasLatitudeMin) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN"] = true;
- shaderDefines[
- "ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN"
- ] = intersectionCount;
- if (renderIsLatitudeMinUnderHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF"
- ] = true;
- intersectionCount += 1;
- } else if (renderIsLatitudeMinHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF"
- ] = true;
- intersectionCount += 1;
- } else if (renderIsLatitudeMinOverHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF"
- ] = true;
- intersectionCount += 2;
- }
- }
- // Intersects a cone for max latitude
- if (renderHasLatitudeMax) {
- shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX"] = true;
- shaderDefines[
- "ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX"
- ] = intersectionCount;
- if (renderIsLatitudeMaxUnderHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF"
- ] = true;
- intersectionCount += 2;
- } else if (renderIsLatitudeMaxHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF"
- ] = true;
- intersectionCount += 1;
- } else if (renderIsLatitudeMaxOverHalf) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF"
- ] = true;
- intersectionCount += 1;
- }
- }
- if (renderMinLatitude === renderMaxLatitude) {
- shaderDefines[
- "ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO"
- ] = true;
- }
- const minCosHalfAngleSqr = Math.pow(
- Math.cos(CesiumMath.PI_OVER_TWO - Math.abs(renderMinLatitude)),
- 2.0
- );
- const maxCosHalfAngleSqr = Math.pow(
- Math.cos(CesiumMath.PI_OVER_TWO - Math.abs(renderMaxLatitude)),
- 2.0
- );
- shaderUniforms.ellipsoidRenderLatitudeCosSqrHalfMinMax = Cartesian2.fromElements(
- minCosHalfAngleSqr,
- maxCosHalfAngleSqr,
- shaderUniforms.ellipsoidRenderLatitudeCosSqrHalfMinMax
- );
- }
- if (shapeHasLatitude) {
- shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE"] = true;
- if (shapeMinLatitude === shapeMaxLatitude) {
- shaderDefines[
- "ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE_RANGE_EQUAL_ZERO"
- ] = true;
- }
- // delerp(latitudeUv, minLatitudeUv, maxLatitudeUv)
- // (latitudeUv - minLatitudeUv) / (maxLatitudeUv - minLatitudeUv)
- // latitudeUv / (maxLatitudeUv - minLatitudeUv) - minLatitudeUv / (maxLatitudeUv - minLatitudeUv)
- // scale = 1.0 / (maxLatitudeUv - minLatitudeUv)
- // scale = 1.0 / (((maxLatitude - pi) / (2.0 * pi)) - ((minLatitude - pi) / (2.0 * pi)))
- // scale = 2.0 * pi / (maxLatitude - minLatitude)
- // offset = -minLatitudeUv / (maxLatitudeUv - minLatitudeUv)
- // offset = -((minLatitude - -pi) / (2.0 * pi)) / (((maxLatitude - pi) / (2.0 * pi)) - ((minLatitude - pi) / (2.0 * pi)))
- // offset = -(minLatitude - -pi) / (maxLatitude - minLatitude)
- // offset = (-pi - minLatitude) / (maxLatitude - minLatitude)
- const scale = defaultLatitudeRange / shapeLatitudeRange;
- const offset = (defaultMinLatitude - shapeMinLatitude) / shapeLatitudeRange;
- shaderUniforms.ellipsoidUvToShapeUvLatitude = Cartesian2.fromElements(
- scale,
- offset,
- shaderUniforms.ellipsoidUvToShapeUvLatitude
- );
- }
- if (isSphere) {
- shaderDefines["ELLIPSOID_IS_SPHERE"] = true;
- }
- this.shaderMaximumIntersectionsLength = intersectionCount;
- return true;
- };
- const scratchRectangle = new Rectangle();
- /**
- * Computes an oriented bounding box for a specified tile.
- * The update function must be called before calling this function.
- *
- * @param {number} tileLevel The tile's level.
- * @param {number} tileX The tile's x coordinate.
- * @param {number} tileY The tile's y coordinate.
- * @param {number} tileZ The tile's z coordinate.
- * @param {OrientedBoundingBox} result The oriented bounding box that will be set to enclose the specified tile
- * @returns {OrientedBoundingBox} The oriented bounding box.
- */
- VoxelEllipsoidShape.prototype.computeOrientedBoundingBoxForTile = function (
- tileLevel,
- tileX,
- tileY,
- tileZ,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.number("tileLevel", tileLevel);
- Check.typeOf.number("tileX", tileX);
- Check.typeOf.number("tileY", tileY);
- Check.typeOf.number("tileZ", tileZ);
- Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- const sizeAtLevel = 1.0 / Math.pow(2.0, tileLevel);
- const minLongitudeLerp = tileX * sizeAtLevel;
- const maxLongitudeLerp = (tileX + 1) * sizeAtLevel;
- const minLatitudeLerp = tileY * sizeAtLevel;
- const maxLatitudeLerp = (tileY + 1) * sizeAtLevel;
- const minHeightLerp = tileZ * sizeAtLevel;
- const maxHeightLerp = (tileZ + 1) * sizeAtLevel;
- const rectangle = Rectangle.subsection(
- this._rectangle,
- minLongitudeLerp,
- minLatitudeLerp,
- maxLongitudeLerp,
- maxLatitudeLerp,
- scratchRectangle
- );
- const minHeight = CesiumMath.lerp(
- this._minimumHeight,
- this._maximumHeight,
- minHeightLerp
- );
- const maxHeight = CesiumMath.lerp(
- this._minimumHeight,
- this._maximumHeight,
- maxHeightLerp
- );
- return getEllipsoidChunkObb(
- rectangle,
- minHeight,
- maxHeight,
- this._ellipsoid,
- this._translation,
- this._rotation,
- result
- );
- };
- /**
- * Computes an approximate step size for raymarching the root tile of a voxel grid.
- * The update function must be called before calling this function.
- *
- * @param {Cartesian3} dimensions The voxel grid dimensions for a tile.
- * @returns {number} The step size.
- */
- VoxelEllipsoidShape.prototype.computeApproximateStepSize = function (
- dimensions
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("dimensions", dimensions);
- //>>includeEnd('debug');
- const ellipsoid = this._ellipsoid;
- const ellipsoidMaximumRadius = ellipsoid.maximumRadius;
- const minimumHeight = this._minimumHeight;
- const maximumHeight = this._maximumHeight;
- const shellToEllipsoidRatio =
- (maximumHeight - minimumHeight) / (ellipsoidMaximumRadius + maximumHeight);
- const stepSize = (0.5 * shellToEllipsoidRatio) / dimensions.z;
- return stepSize;
- };
- /**
- * Computes an {@link OrientedBoundingBox} for a subregion of the shape.
- *
- * @function
- *
- * @param {Rectangle} rectangle The rectangle.
- * @param {number} minHeight The minimumZ.
- * @param {number} maxHeight The maximumZ.
- * @param {Ellipsoid} ellipsoid The ellipsoid.
- * @param {Cartesian3} translation The translation applied to the shape
- * @param {Matrix3} rotation The rotation applied to the shape
- * @param {OrientedBoundingBox} result The object onto which to store the result.
- * @returns {OrientedBoundingBox} The oriented bounding box that contains this subregion.
- *
- * @private
- */
- function getEllipsoidChunkObb(
- rectangle,
- minHeight,
- maxHeight,
- ellipsoid,
- translation,
- rotation,
- result
- ) {
- result = OrientedBoundingBox.fromRectangle(
- rectangle,
- minHeight,
- maxHeight,
- ellipsoid,
- result
- );
- result.center = Cartesian3.add(result.center, translation, result.center);
- result.halfAxes = Matrix3.multiply(
- result.halfAxes,
- rotation,
- result.halfAxes
- );
- return result;
- }
- /**
- * Defines the minimum bounds of the shape. Corresponds to minimum longitude, latitude, height.
- *
- * @type {Cartesian3}
- * @constant
- * @readonly
- */
- VoxelEllipsoidShape.DefaultMinBounds = Object.freeze(
- new Cartesian3(-CesiumMath.PI, -CesiumMath.PI_OVER_TWO, -Number.MAX_VALUE)
- );
- /**
- * Defines the maximum bounds of the shape. Corresponds to maximum longitude, latitude, height.
- *
- * @type {Cartesian3}
- * @constant
- * @readonly
- */
- VoxelEllipsoidShape.DefaultMaxBounds = Object.freeze(
- new Cartesian3(+CesiumMath.PI, +CesiumMath.PI_OVER_TWO, +Number.MAX_VALUE)
- );
- export default VoxelEllipsoidShape;
|