Skip to content

Commit

Permalink
GlobeSurfaceShaderSet.jsMerge branch 'projections'
Browse files Browse the repository at this point in the history
  • Loading branch information
shisaiqun committed Jul 29, 2022
1 parent cba1deb commit b450fb7
Show file tree
Hide file tree
Showing 61 changed files with 2,656 additions and 541 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
Apps/HelloWorld.html
Apps/Sandcastle/ThirdParty/**
Apps/SampleData/**
Build/**
Documentation/**
Source/Scene/GltfPipeline/**
Source/Shaders/**
Source/ThirdParty/**
Source/Workers/cesiumWorkerBootstrapper.js
Specs/Data/**
Source/Workers/**
!Source/Workers/transferTypedArrayTest.js
Specs/jasmine/**
Expand Down
43 changes: 43 additions & 0 deletions Source/Core/BoundingSphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,20 @@ BoundingSphere.fromRectangle2D = function (rectangle, projection, result) {
);
};

const INTERVAL_COUNT = 9;
const HALF_PROJECTED_POINTS_COUNT = INTERVAL_COUNT * INTERVAL_COUNT;
const PROJECTED_POINTS_COUNT = HALF_PROJECTED_POINTS_COUNT * 2;
const projectedPointsScratch = new Array(PROJECTED_POINTS_COUNT);
for (
let projectedPointIndex = 0;
projectedPointIndex < PROJECTED_POINTS_COUNT;
projectedPointIndex++
) {
projectedPointsScratch[projectedPointIndex] = new Cartesian3();
}
const sampleScratch = new Cartographic();
const cornerScratch = new Cartographic();

/**
* Computes a bounding sphere from a rectangle projected in 2D. The bounding sphere accounts for the
* object's minimum and maximum heights over the rectangle.
Expand Down Expand Up @@ -277,6 +291,35 @@ BoundingSphere.fromRectangleWithHeights2D = function (

projection = defaultValue(projection, defaultProjection);

if (!projection.isNormalCylindrical) {
const southwest = Rectangle.southwest(rectangle, cornerScratch);
const widthStep = rectangle.width / (INTERVAL_COUNT - 1);
const heightStep = rectangle.height / (INTERVAL_COUNT - 1);
const sample = sampleScratch;
let index = 0;

// Project points in a grid over the Rectangle
for (let x = 0; x < INTERVAL_COUNT; x++) {
for (let y = 0; y < INTERVAL_COUNT; y++) {
sample.longitude = southwest.longitude + x * widthStep;
sample.latitude = southwest.latitude + y * heightStep;
sample.height = minimumHeight;

projection.project(sample, projectedPointsScratch[index]);

sample.height = maximumHeight;
projection.project(
sample,
projectedPointsScratch[index + HALF_PROJECTED_POINTS_COUNT]
);

index++;
}
}

return BoundingSphere.fromPoints(projectedPointsScratch, result);
}

Rectangle.southwest(rectangle, fromRectangle2DSouthwest);
fromRectangle2DSouthwest.height = minimumHeight;
Rectangle.northeast(rectangle, fromRectangle2DNortheast);
Expand Down
43 changes: 43 additions & 0 deletions Source/Core/GeographicProjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import defaultValue from "./defaultValue.js";
import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
import Ellipsoid from "./Ellipsoid.js";
import MapProjectionType from "./MapProjectionType.js";
import SerializedMapProjection from "./SerializedMapProjection.js";

/**
* A simple map projection where longitude and latitude are linearly mapped to X and Y by multiplying
Expand Down Expand Up @@ -38,8 +40,49 @@ Object.defineProperties(GeographicProjection.prototype, {
return this._ellipsoid;
},
},
/**
* Gets whether or not the projection evenly maps meridians to vertical lines.
* Geographic projections are cylindrical about the equator.
*
* @memberof GeographicProjection.prototype
*
* @type {Boolean}
* @readonly
* @private
*/
isNormalCylindrical: {
get: function () {
return true;
},
},
});

/**
* Returns a JSON object that can be messaged to a web worker.
*
* @private
* @returns {SerializedMapProjection} A JSON object from which the MapProjection can be rebuilt.
*/
GeographicProjection.prototype.serialize = function () {
return new SerializedMapProjection(
MapProjectionType.GEOGRAPHIC,
Ellipsoid.pack(this.ellipsoid, [])
);
};

/**
* Reconstructs a <code>GeographicProjection</object> object from the input JSON.
*
* @private
* @param {SerializedMapProjection} serializedMapProjection A JSON object from which the MapProjection can be rebuilt.
* @returns {Promise.<GeographicProjection>} A Promise that resolves to a MapProjection that is ready for use, or rejects if the SerializedMapProjection is malformed.
*/
GeographicProjection.deserialize = function (serializedMapProjection) {
return Promise.resolve(
new GeographicProjection(Ellipsoid.unpack(serializedMapProjection.json))
);
};

/**
* Projects a set of {@link Cartographic} coordinates, in radians, to map coordinates, in meters.
* X and Y are the longitude and latitude, respectively, multiplied by the maximum radius of the
Expand Down
7 changes: 7 additions & 0 deletions Source/Core/GoogleEarthEnterpriseTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ const rectangleScratch = new Rectangle();
* @param {Number} options.x The X coordinate of the tile for which to create the terrain data.
* @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.
* @param {Number} options.level The level of the tile for which to create the terrain data.
* @param {SerializedMapProjection} options.serializedMapProjection Serialized map projection.
* @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.
* @param {Number} [options.exaggerationRelativeHeight=0.0] The height from which terrain is exaggerated.
* @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.
Expand All @@ -152,12 +153,17 @@ GoogleEarthEnterpriseTerrainData.prototype.createMesh = function (options) {
Check.typeOf.number("options.x", options.x);
Check.typeOf.number("options.y", options.y);
Check.typeOf.number("options.level", options.level);
Check.typeOf.object(
"options.serializedMapProjection",
options.serializedMapProjection
);
//>>includeEnd('debug');

const tilingScheme = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const serializedMapProjection = options.serializedMapProjection;
const exaggeration = defaultValue(options.exaggeration, 1.0);
const exaggerationRelativeHeight = defaultValue(
options.exaggerationRelativeHeight,
Expand Down Expand Up @@ -194,6 +200,7 @@ GoogleEarthEnterpriseTerrainData.prototype.createMesh = function (options) {
includeWebMercatorT: true,
negativeAltitudeExponentBias: this._negativeAltitudeExponentBias,
negativeElevationThreshold: this._negativeElevationThreshold,
serializedMapProjection: serializedMapProjection,
});

if (!defined(verticesPromise)) {
Expand Down
54 changes: 8 additions & 46 deletions Source/Core/GroundPolylineGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import ComponentDatatype from "./ComponentDatatype.js";
import defaultValue from "./defaultValue.js";
import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
import Ellipsoid from "./Ellipsoid.js";
import EllipsoidGeodesic from "./EllipsoidGeodesic.js";
import EllipsoidRhumbLine from "./EllipsoidRhumbLine.js";
import EncodedCartesian3 from "./EncodedCartesian3.js";
Expand All @@ -22,13 +21,10 @@ import Matrix3 from "./Matrix3.js";
import Plane from "./Plane.js";
import Quaternion from "./Quaternion.js";
import Rectangle from "./Rectangle.js";
import WebMercatorProjection from "./WebMercatorProjection.js";

const PROJECTIONS = [GeographicProjection, WebMercatorProjection];
const PROJECTION_COUNT = PROJECTIONS.length;

const MITER_BREAK_SMALL = Math.cos(CesiumMath.toRadians(30.0));
const MITER_BREAK_LARGE = Math.cos(CesiumMath.toRadians(150.0));
const defaultProjection = new GeographicProjection();

// Initial heights for constructing the wall.
// Keeping WALL_INITIAL_MIN_HEIGHT near the ellipsoid surface helps
Expand Down Expand Up @@ -121,10 +117,7 @@ function GroundPolylineGeometry(options) {
*/
this.arcType = defaultValue(options.arcType, ArcType.GEODESIC);

this._ellipsoid = Ellipsoid.WGS84;

// MapProjections can't be packed, so store the index to a known MapProjection.
this._projectionIndex = 0;
this._projection = defaultProjection;
this._workerName = "createGroundPolylineGeometry";

// Used by GroundPolylinePrimitive to signal worker that scenemode is 3D only.
Expand All @@ -141,42 +134,24 @@ Object.defineProperties(GroundPolylineGeometry.prototype, {
*/
packedLength: {
get: function () {
return (
1.0 +
this._positions.length * 3 +
1.0 +
1.0 +
1.0 +
Ellipsoid.packedLength +
1.0 +
1.0
);
return 1.0 + this._positions.length * 3 + 1.0 + 1.0 + 1.0 + 1.0;
},
},
});

/**
* Set the GroundPolylineGeometry's projection and ellipsoid.
* Set the GroundPolylineGeometry's projection.
* Used by GroundPolylinePrimitive to signal scene information to the geometry for generating 2D attributes.
*
* @param {GroundPolylineGeometry} groundPolylineGeometry GroundPolylinGeometry describing a polyline on terrain or 3D Tiles.
* @param {Projection} mapProjection A MapProjection used for projecting cartographic coordinates to 2D.
* @private
*/
GroundPolylineGeometry.setProjectionAndEllipsoid = function (
GroundPolylineGeometry.setProjection = function (
groundPolylineGeometry,
mapProjection
) {
let projectionIndex = 0;
for (let i = 0; i < PROJECTION_COUNT; i++) {
if (mapProjection instanceof PROJECTIONS[i]) {
projectionIndex = i;
break;
}
}

groundPolylineGeometry._projectionIndex = projectionIndex;
groundPolylineGeometry._ellipsoid = mapProjection.ellipsoid;
groundPolylineGeometry._projection = mapProjection;
};

const cart3Scratch1 = new Cartesian3();
Expand Down Expand Up @@ -312,11 +287,6 @@ GroundPolylineGeometry.pack = function (value, array, startingIndex) {
array[index++] = value.granularity;
array[index++] = value.loop ? 1.0 : 0.0;
array[index++] = value.arcType;

Ellipsoid.pack(value._ellipsoid, array, index);
index += Ellipsoid.packedLength;

array[index++] = value._projectionIndex;
array[index++] = value._scene3DOnly ? 1.0 : 0.0;

return array;
Expand Down Expand Up @@ -347,10 +317,6 @@ GroundPolylineGeometry.unpack = function (array, startingIndex, result) {
const loop = array[index++] === 1.0;
const arcType = array[index++];

const ellipsoid = Ellipsoid.unpack(array, index);
index += Ellipsoid.packedLength;

const projectionIndex = array[index++];
const scene3DOnly = array[index++] === 1.0;

if (!defined(result)) {
Expand All @@ -363,8 +329,6 @@ GroundPolylineGeometry.unpack = function (array, startingIndex, result) {
result.granularity = granularity;
result.loop = loop;
result.arcType = arcType;
result._ellipsoid = ellipsoid;
result._projectionIndex = projectionIndex;
result._scene3DOnly = scene3DOnly;

return result;
Expand Down Expand Up @@ -460,10 +424,8 @@ GroundPolylineGeometry.createGeometry = function (groundPolylineGeometry) {
let loop = groundPolylineGeometry.loop;
const ellipsoid = groundPolylineGeometry._ellipsoid;
const granularity = groundPolylineGeometry.granularity;
const projection = groundPolylineGeometry._projection;
const arcType = groundPolylineGeometry.arcType;
const projection = new PROJECTIONS[groundPolylineGeometry._projectionIndex](
ellipsoid
);

const minHeight = WALL_INITIAL_MIN_HEIGHT;
const maxHeight = WALL_INITIAL_MAX_HEIGHT;
Expand Down Expand Up @@ -838,6 +800,7 @@ function projectNormal(
projectedPosition,
result
) {
const ellipsoid = projection.ellipsoid;
const position = Cartographic.toCartesian(
cartographic,
projection._ellipsoid,
Expand All @@ -846,7 +809,6 @@ function projectNormal(
let normalEndpoint = Cartesian3.add(position, normal, normalEndpointScratch);
let flipNormal = false;

const ellipsoid = projection._ellipsoid;
let normalEndpointCartographic = ellipsoid.cartesianToCartographic(
normalEndpoint,
endPosCartographicScratch
Expand Down
41 changes: 26 additions & 15 deletions Source/Core/HeightmapTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ const createMeshTaskProcessorThrottle = new TaskProcessor(
* @param {Number} options.x The X coordinate of the tile for which to create the terrain data.
* @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.
* @param {Number} options.level The level of the tile for which to create the terrain data.
* @param {SerializedMapProjection} options.serializedMapProjection Serialized map projection.
* @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.
* @param {Number} [options.exaggerationRelativeHeight=0.0] The height relative to which terrain is exaggerated.
* @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.
Expand All @@ -215,12 +216,17 @@ HeightmapTerrainData.prototype.createMesh = function (options) {
Check.typeOf.number("options.x", options.x);
Check.typeOf.number("options.y", options.y);
Check.typeOf.number("options.level", options.level);
Check.typeOf.object(
"options.serializedMapProjection",
options.serializedMapProjection
);
//>>includeEnd('debug');

const tilingScheme = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const serializedMapProjection = options.serializedMapProjection;
const exaggeration = defaultValue(options.exaggeration, 1.0);
const exaggerationRelativeHeight = defaultValue(
options.exaggerationRelativeHeight,
Expand Down Expand Up @@ -263,6 +269,7 @@ HeightmapTerrainData.prototype.createMesh = function (options) {
isGeographic: tilingScheme.projection instanceof GeographicProjection,
exaggeration: exaggeration,
exaggerationRelativeHeight: exaggerationRelativeHeight,
serializedMapProjection: serializedMapProjection,
encoding: this._encoding,
});

Expand Down Expand Up @@ -332,6 +339,7 @@ HeightmapTerrainData.prototype._createMeshSync = function (options) {
Check.typeOf.number("options.x", options.x);
Check.typeOf.number("options.y", options.y);
Check.typeOf.number("options.level", options.level);
Check.defined("options.mapProjection", options.mapProjection);
//>>includeEnd('debug');

const tilingScheme = options.tilingScheme;
Expand Down Expand Up @@ -361,21 +369,24 @@ HeightmapTerrainData.prototype._createMeshSync = function (options) {
const thisLevelMaxError = levelZeroMaxError / (1 << level);
this._skirtHeight = Math.min(thisLevelMaxError * 4.0, 1000.0);

const result = HeightmapTessellator.computeVertices({
heightmap: this._buffer,
structure: structure,
includeWebMercatorT: true,
width: this._width,
height: this._height,
nativeRectangle: nativeRectangle,
rectangle: rectangle,
relativeToCenter: center,
ellipsoid: ellipsoid,
skirtHeight: this._skirtHeight,
isGeographic: tilingScheme.projection instanceof GeographicProjection,
exaggeration: exaggeration,
exaggerationRelativeHeight: exaggerationRelativeHeight,
});
const result = HeightmapTessellator.computeVertices(
{
heightmap: this._buffer,
structure: structure,
includeWebMercatorT: true,
width: this._width,
height: this._height,
nativeRectangle: nativeRectangle,
rectangle: rectangle,
relativeToCenter: center,
ellipsoid: ellipsoid,
skirtHeight: this._skirtHeight,
isGeographic: tilingScheme.projection instanceof GeographicProjection,
exaggeration: exaggeration,
exaggerationRelativeHeight: exaggerationRelativeHeight,
},
options.mapProjection
);

// Free memory received from server after mesh is created.
this._buffer = undefined;
Expand Down
Loading

0 comments on commit b450fb7

Please sign in to comment.