Skip to content

Commit

Permalink
Merge pull request #4339 from AnalyticalGraphicsInc/noReproject
Browse files Browse the repository at this point in the history
Don't reproject Web Mercator imagery tiles unnecessarily
  • Loading branch information
bagnell authored Oct 19, 2016
2 parents 11f2aa5 + 32c4117 commit a8f0d0f
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 94 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Change Log
* 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.
* Added `CesiumMath.clampToLatitudeRange`. A convenience function to clamp a passed radian angle to valid Latitudes.
* Added `DebugCameraPrimitive` to visualize the view frustum of a camera.
* Added `Rectangle.simpleIntersection`.
* 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.

### 1.25 - 2016-09-01

Expand Down
3 changes: 2 additions & 1 deletion Source/Core/HeightmapTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ define([
var verticesPromise = taskProcessor.scheduleTask({
heightmap : this._buffer,
structure : structure,
includeWebMercatorT : true,
width : this._width,
height : this._height,
nativeRectangle : nativeRectangle,
Expand All @@ -232,7 +233,7 @@ define([
result.maximumHeight,
result.boundingSphere3D,
result.occludeePointInScaledSpace,
6,
result.numberOfAttributes,
result.orientedBoundingBox,
TerrainEncoding.clone(result.encoding),
exaggeration);
Expand Down
28 changes: 24 additions & 4 deletions Source/Core/HeightmapTessellator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ define([
'./OrientedBoundingBox',
'./Rectangle',
'./TerrainEncoding',
'./Transforms'
'./Transforms',
'./WebMercatorProjection',
], function(
AxisAlignedBoundingBox,
BoundingSphere,
Expand All @@ -32,7 +33,8 @@ define([
OrientedBoundingBox,
Rectangle,
TerrainEncoding,
Transforms) {
Transforms,
WebMercatorProjection) {
'use strict';

/**
Expand Down Expand Up @@ -200,6 +202,7 @@ define([

var relativeToCenter = defaultValue(options.relativeToCenter, Cartesian3.ZERO);
var exaggeration = defaultValue(options.exaggeration, 1.0);
var includeWebMercatorT = defaultValue(options.includeWebMercatorT, false);

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

var southMercatorY;
var oneOverMercatorHeight;
if (includeWebMercatorT) {
southMercatorY = WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicSouth);
oneOverMercatorHeight = 1.0 / (WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicNorth) - southMercatorY);
}

var minimum = minimumScratch;
minimum.x = Number.POSITIVE_INFINITY;
minimum.y = Number.POSITIVE_INFINITY;
Expand All @@ -241,6 +251,7 @@ define([
var positions = new Array(size);
var heights = new Array(size);
var uvs = new Array(size);
var webMercatorTs = includeWebMercatorT ? new Array(size) : [];

var startRow = 0;
var endRow = height;
Expand Down Expand Up @@ -280,6 +291,11 @@ define([
var v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);
v = CesiumMath.clamp(v, 0.0, 1.0);

var webMercatorT;
if (includeWebMercatorT) {
webMercatorT = (WebMercatorProjection.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
}

for (var colIndex = startCol; colIndex < endCol; ++colIndex) {
var col = colIndex;
if (col < 0) {
Expand Down Expand Up @@ -351,6 +367,10 @@ define([
u = CesiumMath.clamp(u, 0.0, 1.0);
uvs[index] = new Cartesian2(u, v);

if (includeWebMercatorT) {
webMercatorTs[index] = webMercatorT;
}

index++;

Matrix4.multiplyByPoint(toENU, position, cartesian3Scratch);
Expand All @@ -377,12 +397,12 @@ define([
}

var aaBox = new AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);
var encoding = new TerrainEncoding(aaBox, hMin, maximumHeight, fromENU, false);
var encoding = new TerrainEncoding(aaBox, hMin, maximumHeight, fromENU, false, includeWebMercatorT);
var vertices = new Float32Array(size * encoding.getStride());

var bufferIndex = 0;
for (var j = 0; j < size; ++j) {
bufferIndex = encoding.encode(vertices, bufferIndex, positions[j], uvs[j], heights[j]);
bufferIndex = encoding.encode(vertices, bufferIndex, positions[j], uvs[j], heights[j], undefined, webMercatorTs[j]);
}

return {
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/QuantizedMeshTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ define([
* eastSkirtHeight : 1.0,
* northSkirtHeight : 1.0
* });
*
*
* @see TerrainData
* @see HeightmapTerrainData
*/
Expand Down Expand Up @@ -273,6 +273,7 @@ define([
maximumHeight : this._maximumHeight,
quantizedVertices : this._quantizedVertices,
octEncodedNormals : this._encodedNormals,
includeWebMercatorT : true,
indices : this._indices,
westIndices : this._westIndices,
southIndices : this._southIndices,
Expand Down
47 changes: 46 additions & 1 deletion Source/Core/Rectangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,11 @@ define([
};

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

/**
* Computes a simple intersection of two rectangles. Unlike {@link Rectangle.intersection}, this function
* does not attempt to put the angular coordinates into a consistent range or to account for crossing the
* anti-meridian. As such, it can be used for rectangles where the coordinates are not simply latitude
* and longitude (i.e. projected coordinates).
*
* @param {Rectangle} rectangle On rectangle to find an intersection
* @param {Rectangle} otherRectangle Another rectangle to find an intersection
* @param {Rectangle} [result] The object onto which to store the result.
* @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.
*/
Rectangle.simpleIntersection = function(rectangle, otherRectangle, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(rectangle)) {
throw new DeveloperError('rectangle is required');
}
if (!defined(otherRectangle)) {
throw new DeveloperError('otherRectangle is required.');
}
//>>includeEnd('debug');

var west = Math.max(rectangle.west, otherRectangle.west);
var south = Math.max(rectangle.south, otherRectangle.south);
var east = Math.min(rectangle.east, otherRectangle.east);
var north = Math.min(rectangle.north, otherRectangle.north);

if (south >= north || west >= east) {
return undefined;
}

if (!defined(result)) {
return new Rectangle(west, south, east, north);
}

result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};

/**
* Computes a rectangle that is the union of two rectangles.
*
Expand Down
91 changes: 77 additions & 14 deletions Source/Core/TerrainEncoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ define([
'./Cartesian2',
'./Cartesian3',
'./ComponentDatatype',
'./defaultValue',
'./defined',
'./Math',
'./Matrix3',
Expand All @@ -14,6 +15,7 @@ define([
Cartesian2,
Cartesian3,
ComponentDatatype,
defaultValue,
defined,
CesiumMath,
Matrix3,
Expand Down Expand Up @@ -41,10 +43,11 @@ define([
* @param {Number} maximumHeight The maximum height.
* @param {Matrix4} fromENU The east-north-up to fixed frame matrix at the center of the terrain mesh.
* @param {Boolean} hasVertexNormals If the mesh has vertex normals.
* @param {Boolean} [hasWebMercatorT=false] true if the terrain data includes a Web Mercator texture coordinate; otherwise, false.
*
* @private
*/
function TerrainEncoding(axisAlignedBoundingBox, minimumHeight, maximumHeight, fromENU, hasVertexNormals) {
function TerrainEncoding(axisAlignedBoundingBox, minimumHeight, maximumHeight, fromENU, hasVertexNormals, hasWebMercatorT) {
var quantization;
var center;
var toENU;
Expand Down Expand Up @@ -137,9 +140,15 @@ define([
* @type {Boolean}
*/
this.hasVertexNormals = hasVertexNormals;

/**
* The terrain mesh contains a vertical texture coordinate following the Web Mercator projection.
* @type {Boolean}
*/
this.hasWebMercatorT = defaultValue(hasWebMercatorT, false);
}

TerrainEncoding.prototype.encode = function(vertexBuffer, bufferIndex, position, uv, height, normalToPack) {
TerrainEncoding.prototype.encode = function(vertexBuffer, bufferIndex, position, uv, height, normalToPack, webMercatorT) {
var u = uv.x;
var v = uv.y;

Expand All @@ -165,6 +174,12 @@ define([
vertexBuffer[bufferIndex++] = compressed0;
vertexBuffer[bufferIndex++] = compressed1;
vertexBuffer[bufferIndex++] = compressed2;

if (this.hasWebMercatorT) {
Cartesian2.fromElements(webMercatorT, 0.0, cartesian2Scratch);
var compressed3 = AttributeCompression.compressTextureCoordinates(cartesian2Scratch);
vertexBuffer[bufferIndex++] = compressed3;
}
} else {
Cartesian3.subtract(position, this.center, cartesian3Scratch);

Expand All @@ -174,6 +189,10 @@ define([
vertexBuffer[bufferIndex++] = height;
vertexBuffer[bufferIndex++] = u;
vertexBuffer[bufferIndex++] = v;

if (this.hasWebMercatorT) {
vertexBuffer[bufferIndex++] = webMercatorT;
}
}

if (this.hasVertexNormals) {
Expand Down Expand Up @@ -254,6 +273,10 @@ define([
vertexStride = 6;
}

if (this.hasWebMercatorT) {
++vertexStride;
}

if (this.hasVertexNormals) {
++vertexStride;
}
Expand All @@ -266,17 +289,29 @@ define([
textureCoordAndEncodedNormals : 1
};
var attributes = {
compressed : 0
compressed0 : 0,
compressed1 : 1
};

TerrainEncoding.prototype.getAttributes = function(buffer) {
var datatype = ComponentDatatype.FLOAT;
var sizeInBytes = ComponentDatatype.getSizeInBytes(datatype);
var stride;

if (this.quantization === TerrainQuantization.NONE) {
var sizeInBytes = ComponentDatatype.getSizeInBytes(datatype);
var position3DAndHeightLength = 4;
var numTexCoordComponents = this.hasVertexNormals ? 3 : 2;
var stride = (this.hasVertexNormals ? 7 : 6) * sizeInBytes;
var numTexCoordComponents = 2;

if (this.hasWebMercatorT) {
++numTexCoordComponents;
}

if (this.hasVertexNormals) {
++numTexCoordComponents;
}

stride = (position3DAndHeightLength + numTexCoordComponents) * sizeInBytes;

return [{
index : attributesNone.position3DAndHeight,
vertexBuffer : buffer,
Expand All @@ -294,14 +329,41 @@ define([
}];
}

var numComponents = 3;
numComponents += this.hasVertexNormals ? 1 : 0;
return [{
index : attributes.compressed,
vertexBuffer : buffer,
componentDatatype : datatype,
componentsPerAttribute : numComponents
}];
var numCompressed0 = 3;
var numCompressed1 = 0;

if (this.hasWebMercatorT || this.hasVertexNormals) {
++numCompressed0;
}

if (this.hasWebMercatorT && this.hasVertexNormals) {
++numCompressed1;

stride = (numCompressed0 + numCompressed1) * sizeInBytes;

return [{
index : attributes.compressed0,
vertexBuffer : buffer,
componentDatatype : datatype,
componentsPerAttribute : numCompressed0,
offsetInBytes : 0,
strideInBytes : stride
}, {
index : attributes.compressed1,
vertexBuffer : buffer,
componentDatatype : datatype,
componentsPerAttribute : numCompressed1,
offsetInBytes : numCompressed0 * sizeInBytes,
strideInBytes : stride
}];
} else {
return [{
index : attributes.compressed0,
vertexBuffer : buffer,
componentDatatype : datatype,
componentsPerAttribute : numCompressed0
}];
}
};

TerrainEncoding.prototype.getAttributeLocations = function() {
Expand All @@ -325,6 +387,7 @@ define([
result.fromScaledENU = Matrix4.clone(encoding.fromScaledENU);
result.matrix = Matrix4.clone(encoding.matrix);
result.hasVertexNormals = encoding.hasVertexNormals;
result.hasWebMercatorT = encoding.hasWebMercatorT;
return result;
};

Expand Down
7 changes: 5 additions & 2 deletions Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,16 @@ define([
}
}

vs.defines.push('INCLUDE_WEB_MERCATOR_Y');
fs.defines.push('INCLUDE_WEB_MERCATOR_Y');

if (enableFog) {
vs.defines.push('FOG');
fs.defines.push('FOG');
}

var computeDayColor = '\
vec4 computeDayColor(vec4 initialColor, vec2 textureCoordinates)\n\
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates)\n\
{\n\
vec4 color = initialColor;\n';

Expand All @@ -163,7 +166,7 @@ define([
color = sampleAndBlend(\n\
color,\n\
u_dayTextures[' + i + '],\n\
textureCoordinates,\n\
u_dayTextureUseWebMercatorT[' + i + '] ? textureCoordinates.xz : textureCoordinates.xy,\n\
u_dayTextureTexCoordsRectangle[' + i + '],\n\
u_dayTextureTranslationAndScale[' + i + '],\n\
' + (applyAlpha ? 'u_dayTextureAlpha[' + i + ']' : '1.0') + ',\n\
Expand Down
Loading

0 comments on commit a8f0d0f

Please sign in to comment.