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

Guard against negative height samples in HeightmapTerrainData #4103

Merged
merged 17 commits into from
Sep 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions Source/Core/ArcGisImageServerTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ define([
* proxy : new Cesium.DefaultProxy('/terrain/')
* });
* viewer.terrainProvider = terrainProvider;
*
*
* @see TerrainProvider
*/
function ArcGisImageServerTerrainProvider(options) {
Expand Down Expand Up @@ -91,7 +91,9 @@ define([
elementsPerHeight : 3,
stride : 4,
elementMultiplier : 256.0,
isBigEndian : true
isBigEndian : true,
lowestEncodedHeight : 0,
highestEncodedHeight : 256 * 256 * 256
};

this._errorEvent = new Event();
Expand Down
8 changes: 5 additions & 3 deletions Source/Core/CesiumTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ define([
* url : 'https://assets.agi.com/stk-terrain/world',
* requestVertexNormals : true
* });
*
*
* // Terrain geometry near the surface of the globe is difficult to view when using NaturalEarthII imagery,
* // unless the TerrainProvider provides additional lighting information to shade the terrain (as shown above).
* var imageryProvider = Cesium.createTileMapServiceImageryProvider({
Expand All @@ -91,7 +91,7 @@ define([
*
* // The globe must enable lighting to make use of the terrain's vertex normals
* viewer.scene.globe.enableLighting = true;
*
*
* @see TerrainProvider
*/
function CesiumTerrainProvider(options) {
Expand Down Expand Up @@ -180,7 +180,9 @@ define([
elementsPerHeight : 1,
stride : 1,
elementMultiplier : 256.0,
isBigEndian : false
isBigEndian : false,
lowestEncodedHeight : 0,
highestEncodedHeight : 256 * 256
};
that._hasWaterMask = true;
that._requestWaterMask = true;
Expand Down
9 changes: 8 additions & 1 deletion Source/Core/HeightmapTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ define([
* childTileMask : childTileMask,
* waterMask : waterMask
* });
*
*
* @see TerrainData
* @see QuantizedMeshTerrainData
*/
Expand Down Expand Up @@ -350,6 +350,12 @@ define([
for (var i = 0; i < width; ++i) {
var longitude = CesiumMath.lerp(destinationRectangle.west, destinationRectangle.east, i / (width - 1));
var heightSample = interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration);

// Use conditionals here instead of Math.min and Math.max so that an undefined
// lowestEncodedHeight or highestEncodedHeight has no effect.
heightSample = heightSample < structure.lowestEncodedHeight ? structure.lowestEncodedHeight : heightSample;
heightSample = heightSample > structure.highestEncodedHeight ? structure.highestEncodedHeight : heightSample;

setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, heightSample);
}
}
Expand Down Expand Up @@ -448,6 +454,7 @@ define([
}

function interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration) {
// returns a height encoded according to the structure's heightScale and heightOffset.
var fromWest = (longitude - sourceRectangle.west) * (width - 1) / (sourceRectangle.east - sourceRectangle.west);
var fromSouth = (latitude - sourceRectangle.south) * (height - 1) / (sourceRectangle.north - sourceRectangle.south);

Expand Down
6 changes: 4 additions & 2 deletions Source/Core/VRTheWorldTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ define([
* url : 'https://www.vr-theworld.com/vr-theworld/tiles1.0.0/73/'
* });
* viewer.terrainProvider = terrainProvider;
*
*
* @see TerrainProvider
*/
function VRTheWorldTerrainProvider(options) {
Expand All @@ -90,7 +90,9 @@ define([
elementsPerHeight : 3,
stride : 4,
elementMultiplier : 256.0,
isBigEndian : true
isBigEndian : true,
lowestEncodedHeight : 0,
highestEncodedHeight : 256 * 256 * 256
};

var credit = options.credit;
Expand Down
23 changes: 23 additions & 0 deletions Specs/Core/HeightmapTerrainDataSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,29 @@ defineSuite([
expect(upsampled._buffer).toEqual([2, 1, 0, 3, 1, 0, 3, 1, 0, 4, 1, 0, 4, 1, 0, 5, 1, 0, 5, 1, 0, 6, 1, 0, 6, 1, 0, 7, 1, 0, 7, 1, 0, 8, 1, 0, 8, 1, 0, 9, 1, 0, 9, 1, 0, 10, 1, 0]);
});
});

it('upsample clamps out of range data', function() {
data = new HeightmapTerrainData({
buffer : new Float32Array([-1.0, -2.0, -3.0, -4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0]),
width : 4,
height : 4,
structure : {
stride: 1,
elementsPerHeight: 1,
lowestEncodedHeight : 1,
highestEncodedHeight : 7
}
});

return data.createMesh(tilingScheme, 0, 0, 0, 1).then(function() {
return data.upsample(tilingScheme, 0, 0, 0, 0, 0, 1);
}).then(function(upsampled) {
expect(upsampled.wasCreatedByUpsampling()).toBe(true);
expect(upsampled._width).toBe(4);
expect(upsampled._height).toBe(4);
expect(upsampled._buffer).toEqual([1, 1, 1, 1, 2, 1.5, 2, 1.5, 5, 5.5, 6, 6.5, 7, 7, 7, 7]);
});
});
});

describe('isChildAvailable', function() {
Expand Down