Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't reproject Web Mercator imagery tiles unnecessarily #4339

Merged
merged 30 commits into from Oct 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
294a83f
Switch to depth first traversal, add SSE to Sandcastle example.
kring Aug 1, 2016
9ab3fd1
Traverse and load near-to-far.
kring Aug 1, 2016
918c59a
Remove manual tile sorting code.
kring Aug 1, 2016
ca333b3
Don't reproject web mercator to geographic unnecessarily.
kring Aug 2, 2016
0fd3f21
Remove default Bing Maps gamma correction.
kring Aug 2, 2016
bcf6f81
Fix a bug that prevented zooming past the terrain level.
kring Aug 3, 2016
e2a4119
Change max SSE to 4/3, add wireframe option to Terrain example.
kring Aug 3, 2016
e7c65b6
Fix heightmap based terrain.
kring Aug 3, 2016
3cf3faa
Add clarifying comment.
kring Aug 3, 2016
fb269ad
Fix tiles with 12 bit attributes.
kring Sep 16, 2016
205a043
Fix quantized mesh terrain with normals.
kring Sep 16, 2016
8eb8e96
Remove TODOs.
kring Sep 16, 2016
0c09753
Cleanup.
kring Sep 16, 2016
7195f28
Revert changes accidentally pulled from 3d-tiles.
kring Sep 16, 2016
acdf984
Merge remote-tracking branch 'origin/master' into noReproject
kring Sep 16, 2016
bd42b71
Fix computation of veryCloseX and veryCloseY.
kring Sep 19, 2016
5f1888b
Fix test failure.
kring Sep 19, 2016
ce0e458
Merge remote-tracking branch 'origin/master' into noReproject
kring Sep 19, 2016
6b04032
Remove unneeded changes.
kring Sep 19, 2016
8480d01
Update CHANGES.md.
kring Sep 19, 2016
0534ee6
Fix jshint warning.
kring Sep 19, 2016
bd6a1f4
Y -> T
kring Sep 19, 2016
1bbe7ca
Merge remote-tracking branch 'origin/master' into noReproject
kring Sep 21, 2016
091bca3
Update CHANGES.md, fix formatting.
kring Sep 22, 2016
783ea9a
Fix formatting better.
kring Sep 22, 2016
5dd34a3
Merge remote-tracking branch 'origin/master' into noReproject
kring Sep 22, 2016
1f22ed7
Add some specs.
kring Sep 22, 2016
9b79102
Tweak wording of CHANGES.md.
kring Sep 22, 2016
23dc61d
Fix jshint warning.
kring Sep 22, 2016
32c4117
Merge remote-tracking branch 'origin/master' into noReproject
kring Sep 29, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -13,6 +13,8 @@ Change Log
* Fixed a bug that could lead to incorrect terrain heights when using `HeightmapTerrainData` with an encoding in which actual heights were equal to the minimum representable height.
* Fixed a bug in `AttributeCompression.compressTextureCoordinates` and `decompressTextureCoordinates` that could cause a small inaccuracy in the encoded texture coordinates.
* 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
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
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
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
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to CHANGES.md please.

//>>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
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
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