Skip to content

Commit a8f0d0f

Browse files
authored
Merge pull request #4339 from AnalyticalGraphicsInc/noReproject
Don't reproject Web Mercator imagery tiles unnecessarily
2 parents 11f2aa5 + 32c4117 commit a8f0d0f

15 files changed

+436
-94
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Change Log
3535
* Fixed a bug that was incorrectly clamping Latitudes in KML <GroundOverlay>(s) to the range -PI..PI. Now correctly clamps to -PI/2..PI/2.
3636
* Added `CesiumMath.clampToLatitudeRange`. A convenience function to clamp a passed radian angle to valid Latitudes.
3737
* Added `DebugCameraPrimitive` to visualize the view frustum of a camera.
38+
* Added `Rectangle.simpleIntersection`.
39+
* Removed an unnecessary reprojection of Web Mercator imagery tiles to the Geographic projection on load. This should improve both visual quality and load performance slightly.
3840

3941
### 1.25 - 2016-09-01
4042

Source/Core/HeightmapTerrainData.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ define([
206206
var verticesPromise = taskProcessor.scheduleTask({
207207
heightmap : this._buffer,
208208
structure : structure,
209+
includeWebMercatorT : true,
209210
width : this._width,
210211
height : this._height,
211212
nativeRectangle : nativeRectangle,
@@ -232,7 +233,7 @@ define([
232233
result.maximumHeight,
233234
result.boundingSphere3D,
234235
result.occludeePointInScaledSpace,
235-
6,
236+
result.numberOfAttributes,
236237
result.orientedBoundingBox,
237238
TerrainEncoding.clone(result.encoding),
238239
exaggeration);

Source/Core/HeightmapTessellator.js

+24-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ define([
1515
'./OrientedBoundingBox',
1616
'./Rectangle',
1717
'./TerrainEncoding',
18-
'./Transforms'
18+
'./Transforms',
19+
'./WebMercatorProjection',
1920
], function(
2021
AxisAlignedBoundingBox,
2122
BoundingSphere,
@@ -32,7 +33,8 @@ define([
3233
OrientedBoundingBox,
3334
Rectangle,
3435
TerrainEncoding,
35-
Transforms) {
36+
Transforms,
37+
WebMercatorProjection) {
3638
'use strict';
3739

3840
/**
@@ -200,6 +202,7 @@ define([
200202

201203
var relativeToCenter = defaultValue(options.relativeToCenter, Cartesian3.ZERO);
202204
var exaggeration = defaultValue(options.exaggeration, 1.0);
205+
var includeWebMercatorT = defaultValue(options.includeWebMercatorT, false);
203206

204207
var structure = defaultValue(options.structure, HeightmapTessellator.DEFAULT_STRUCTURE);
205208
var heightScale = defaultValue(structure.heightScale, HeightmapTessellator.DEFAULT_STRUCTURE.heightScale);
@@ -223,6 +226,13 @@ define([
223226
var fromENU = Transforms.eastNorthUpToFixedFrame(relativeToCenter, ellipsoid);
224227
var toENU = Matrix4.inverseTransformation(fromENU, matrix4Scratch);
225228

229+
var southMercatorY;
230+
var oneOverMercatorHeight;
231+
if (includeWebMercatorT) {
232+
southMercatorY = WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicSouth);
233+
oneOverMercatorHeight = 1.0 / (WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicNorth) - southMercatorY);
234+
}
235+
226236
var minimum = minimumScratch;
227237
minimum.x = Number.POSITIVE_INFINITY;
228238
minimum.y = Number.POSITIVE_INFINITY;
@@ -241,6 +251,7 @@ define([
241251
var positions = new Array(size);
242252
var heights = new Array(size);
243253
var uvs = new Array(size);
254+
var webMercatorTs = includeWebMercatorT ? new Array(size) : [];
244255

245256
var startRow = 0;
246257
var endRow = height;
@@ -280,6 +291,11 @@ define([
280291
var v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);
281292
v = CesiumMath.clamp(v, 0.0, 1.0);
282293

294+
var webMercatorT;
295+
if (includeWebMercatorT) {
296+
webMercatorT = (WebMercatorProjection.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
297+
}
298+
283299
for (var colIndex = startCol; colIndex < endCol; ++colIndex) {
284300
var col = colIndex;
285301
if (col < 0) {
@@ -351,6 +367,10 @@ define([
351367
u = CesiumMath.clamp(u, 0.0, 1.0);
352368
uvs[index] = new Cartesian2(u, v);
353369

370+
if (includeWebMercatorT) {
371+
webMercatorTs[index] = webMercatorT;
372+
}
373+
354374
index++;
355375

356376
Matrix4.multiplyByPoint(toENU, position, cartesian3Scratch);
@@ -377,12 +397,12 @@ define([
377397
}
378398

379399
var aaBox = new AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);
380-
var encoding = new TerrainEncoding(aaBox, hMin, maximumHeight, fromENU, false);
400+
var encoding = new TerrainEncoding(aaBox, hMin, maximumHeight, fromENU, false, includeWebMercatorT);
381401
var vertices = new Float32Array(size * encoding.getStride());
382402

383403
var bufferIndex = 0;
384404
for (var j = 0; j < size; ++j) {
385-
bufferIndex = encoding.encode(vertices, bufferIndex, positions[j], uvs[j], heights[j]);
405+
bufferIndex = encoding.encode(vertices, bufferIndex, positions[j], uvs[j], heights[j], undefined, webMercatorTs[j]);
386406
}
387407

388408
return {

Source/Core/QuantizedMeshTerrainData.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ define([
104104
* eastSkirtHeight : 1.0,
105105
* northSkirtHeight : 1.0
106106
* });
107-
*
107+
*
108108
* @see TerrainData
109109
* @see HeightmapTerrainData
110110
*/
@@ -273,6 +273,7 @@ define([
273273
maximumHeight : this._maximumHeight,
274274
quantizedVertices : this._quantizedVertices,
275275
octEncodedNormals : this._encodedNormals,
276+
includeWebMercatorT : true,
276277
indices : this._indices,
277278
westIndices : this._westIndices,
278279
southIndices : this._southIndices,

Source/Core/Rectangle.js

+46-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,11 @@ define([
597597
};
598598

599599
/**
600-
* Computes the intersection of two rectangles
600+
* Computes the intersection of two rectangles. This function assumes that the rectangle's coordinates are
601+
* latitude and longitude in radians and produces a correct intersection, taking into account the fact that
602+
* the same angle can be represented with multiple values as well as the wrapping of longitude at the
603+
* anti-meridian. For a simple intersection that ignores these factors and can be used with projected
604+
* coordinates, see {@link Rectangle.simpleIntersection}.
601605
*
602606
* @param {Rectangle} rectangle On rectangle to find an intersection
603607
* @param {Rectangle} otherRectangle Another rectangle to find an intersection
@@ -656,6 +660,47 @@ define([
656660
return result;
657661
};
658662

663+
/**
664+
* Computes a simple intersection of two rectangles. Unlike {@link Rectangle.intersection}, this function
665+
* does not attempt to put the angular coordinates into a consistent range or to account for crossing the
666+
* anti-meridian. As such, it can be used for rectangles where the coordinates are not simply latitude
667+
* and longitude (i.e. projected coordinates).
668+
*
669+
* @param {Rectangle} rectangle On rectangle to find an intersection
670+
* @param {Rectangle} otherRectangle Another rectangle to find an intersection
671+
* @param {Rectangle} [result] The object onto which to store the result.
672+
* @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.
673+
*/
674+
Rectangle.simpleIntersection = function(rectangle, otherRectangle, result) {
675+
//>>includeStart('debug', pragmas.debug);
676+
if (!defined(rectangle)) {
677+
throw new DeveloperError('rectangle is required');
678+
}
679+
if (!defined(otherRectangle)) {
680+
throw new DeveloperError('otherRectangle is required.');
681+
}
682+
//>>includeEnd('debug');
683+
684+
var west = Math.max(rectangle.west, otherRectangle.west);
685+
var south = Math.max(rectangle.south, otherRectangle.south);
686+
var east = Math.min(rectangle.east, otherRectangle.east);
687+
var north = Math.min(rectangle.north, otherRectangle.north);
688+
689+
if (south >= north || west >= east) {
690+
return undefined;
691+
}
692+
693+
if (!defined(result)) {
694+
return new Rectangle(west, south, east, north);
695+
}
696+
697+
result.west = west;
698+
result.south = south;
699+
result.east = east;
700+
result.north = north;
701+
return result;
702+
};
703+
659704
/**
660705
* Computes a rectangle that is the union of two rectangles.
661706
*

Source/Core/TerrainEncoding.js

+77-14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ define([
44
'./Cartesian2',
55
'./Cartesian3',
66
'./ComponentDatatype',
7+
'./defaultValue',
78
'./defined',
89
'./Math',
910
'./Matrix3',
@@ -14,6 +15,7 @@ define([
1415
Cartesian2,
1516
Cartesian3,
1617
ComponentDatatype,
18+
defaultValue,
1719
defined,
1820
CesiumMath,
1921
Matrix3,
@@ -41,10 +43,11 @@ define([
4143
* @param {Number} maximumHeight The maximum height.
4244
* @param {Matrix4} fromENU The east-north-up to fixed frame matrix at the center of the terrain mesh.
4345
* @param {Boolean} hasVertexNormals If the mesh has vertex normals.
46+
* @param {Boolean} [hasWebMercatorT=false] true if the terrain data includes a Web Mercator texture coordinate; otherwise, false.
4447
*
4548
* @private
4649
*/
47-
function TerrainEncoding(axisAlignedBoundingBox, minimumHeight, maximumHeight, fromENU, hasVertexNormals) {
50+
function TerrainEncoding(axisAlignedBoundingBox, minimumHeight, maximumHeight, fromENU, hasVertexNormals, hasWebMercatorT) {
4851
var quantization;
4952
var center;
5053
var toENU;
@@ -137,9 +140,15 @@ define([
137140
* @type {Boolean}
138141
*/
139142
this.hasVertexNormals = hasVertexNormals;
143+
144+
/**
145+
* The terrain mesh contains a vertical texture coordinate following the Web Mercator projection.
146+
* @type {Boolean}
147+
*/
148+
this.hasWebMercatorT = defaultValue(hasWebMercatorT, false);
140149
}
141150

142-
TerrainEncoding.prototype.encode = function(vertexBuffer, bufferIndex, position, uv, height, normalToPack) {
151+
TerrainEncoding.prototype.encode = function(vertexBuffer, bufferIndex, position, uv, height, normalToPack, webMercatorT) {
143152
var u = uv.x;
144153
var v = uv.y;
145154

@@ -165,6 +174,12 @@ define([
165174
vertexBuffer[bufferIndex++] = compressed0;
166175
vertexBuffer[bufferIndex++] = compressed1;
167176
vertexBuffer[bufferIndex++] = compressed2;
177+
178+
if (this.hasWebMercatorT) {
179+
Cartesian2.fromElements(webMercatorT, 0.0, cartesian2Scratch);
180+
var compressed3 = AttributeCompression.compressTextureCoordinates(cartesian2Scratch);
181+
vertexBuffer[bufferIndex++] = compressed3;
182+
}
168183
} else {
169184
Cartesian3.subtract(position, this.center, cartesian3Scratch);
170185

@@ -174,6 +189,10 @@ define([
174189
vertexBuffer[bufferIndex++] = height;
175190
vertexBuffer[bufferIndex++] = u;
176191
vertexBuffer[bufferIndex++] = v;
192+
193+
if (this.hasWebMercatorT) {
194+
vertexBuffer[bufferIndex++] = webMercatorT;
195+
}
177196
}
178197

179198
if (this.hasVertexNormals) {
@@ -254,6 +273,10 @@ define([
254273
vertexStride = 6;
255274
}
256275

276+
if (this.hasWebMercatorT) {
277+
++vertexStride;
278+
}
279+
257280
if (this.hasVertexNormals) {
258281
++vertexStride;
259282
}
@@ -266,17 +289,29 @@ define([
266289
textureCoordAndEncodedNormals : 1
267290
};
268291
var attributes = {
269-
compressed : 0
292+
compressed0 : 0,
293+
compressed1 : 1
270294
};
271295

272296
TerrainEncoding.prototype.getAttributes = function(buffer) {
273297
var datatype = ComponentDatatype.FLOAT;
298+
var sizeInBytes = ComponentDatatype.getSizeInBytes(datatype);
299+
var stride;
274300

275301
if (this.quantization === TerrainQuantization.NONE) {
276-
var sizeInBytes = ComponentDatatype.getSizeInBytes(datatype);
277302
var position3DAndHeightLength = 4;
278-
var numTexCoordComponents = this.hasVertexNormals ? 3 : 2;
279-
var stride = (this.hasVertexNormals ? 7 : 6) * sizeInBytes;
303+
var numTexCoordComponents = 2;
304+
305+
if (this.hasWebMercatorT) {
306+
++numTexCoordComponents;
307+
}
308+
309+
if (this.hasVertexNormals) {
310+
++numTexCoordComponents;
311+
}
312+
313+
stride = (position3DAndHeightLength + numTexCoordComponents) * sizeInBytes;
314+
280315
return [{
281316
index : attributesNone.position3DAndHeight,
282317
vertexBuffer : buffer,
@@ -294,14 +329,41 @@ define([
294329
}];
295330
}
296331

297-
var numComponents = 3;
298-
numComponents += this.hasVertexNormals ? 1 : 0;
299-
return [{
300-
index : attributes.compressed,
301-
vertexBuffer : buffer,
302-
componentDatatype : datatype,
303-
componentsPerAttribute : numComponents
304-
}];
332+
var numCompressed0 = 3;
333+
var numCompressed1 = 0;
334+
335+
if (this.hasWebMercatorT || this.hasVertexNormals) {
336+
++numCompressed0;
337+
}
338+
339+
if (this.hasWebMercatorT && this.hasVertexNormals) {
340+
++numCompressed1;
341+
342+
stride = (numCompressed0 + numCompressed1) * sizeInBytes;
343+
344+
return [{
345+
index : attributes.compressed0,
346+
vertexBuffer : buffer,
347+
componentDatatype : datatype,
348+
componentsPerAttribute : numCompressed0,
349+
offsetInBytes : 0,
350+
strideInBytes : stride
351+
}, {
352+
index : attributes.compressed1,
353+
vertexBuffer : buffer,
354+
componentDatatype : datatype,
355+
componentsPerAttribute : numCompressed1,
356+
offsetInBytes : numCompressed0 * sizeInBytes,
357+
strideInBytes : stride
358+
}];
359+
} else {
360+
return [{
361+
index : attributes.compressed0,
362+
vertexBuffer : buffer,
363+
componentDatatype : datatype,
364+
componentsPerAttribute : numCompressed0
365+
}];
366+
}
305367
};
306368

307369
TerrainEncoding.prototype.getAttributeLocations = function() {
@@ -325,6 +387,7 @@ define([
325387
result.fromScaledENU = Matrix4.clone(encoding.fromScaledENU);
326388
result.matrix = Matrix4.clone(encoding.matrix);
327389
result.hasVertexNormals = encoding.hasVertexNormals;
390+
result.hasWebMercatorT = encoding.hasWebMercatorT;
328391
return result;
329392
};
330393

Source/Scene/GlobeSurfaceShaderSet.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,16 @@ define([
148148
}
149149
}
150150

151+
vs.defines.push('INCLUDE_WEB_MERCATOR_Y');
152+
fs.defines.push('INCLUDE_WEB_MERCATOR_Y');
153+
151154
if (enableFog) {
152155
vs.defines.push('FOG');
153156
fs.defines.push('FOG');
154157
}
155158

156159
var computeDayColor = '\
157-
vec4 computeDayColor(vec4 initialColor, vec2 textureCoordinates)\n\
160+
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates)\n\
158161
{\n\
159162
vec4 color = initialColor;\n';
160163

@@ -163,7 +166,7 @@ define([
163166
color = sampleAndBlend(\n\
164167
color,\n\
165168
u_dayTextures[' + i + '],\n\
166-
textureCoordinates,\n\
169+
u_dayTextureUseWebMercatorT[' + i + '] ? textureCoordinates.xz : textureCoordinates.xy,\n\
167170
u_dayTextureTexCoordsRectangle[' + i + '],\n\
168171
u_dayTextureTranslationAndScale[' + i + '],\n\
169172
' + (applyAlpha ? 'u_dayTextureAlpha[' + i + ']' : '1.0') + ',\n\

0 commit comments

Comments
 (0)