diff --git a/CHANGES.md b/CHANGES.md index 72c8db6b448e..1447f33c6e7a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Change Log * Fixed terrain tile culling problems when under ellipsoid. [#8397](https://github.com/AnalyticalGraphicsInc/cesium/pull/8397) * Fixed primitive culling when below the ellipsoid but above terrain. [#8398](https://github.com/AnalyticalGraphicsInc/cesium/pull/8398) * Improved the translucency calculation for the Water material type. [#8455](https://github.com/AnalyticalGraphicsInc/cesium/pull/8455) +* Fixed globe picking so that it returns the closest intersecting triangle instead of the first intersecting triangle. [#8390](https://github.com/AnalyticalGraphicsInc/cesium/pull/8390) ### 1.64.0 - 2019-12-02 diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js index 31c32bf16c05..d6a0b15b74e3 100644 --- a/Source/Scene/GlobeSurfaceTile.js +++ b/Source/Scene/GlobeSurfaceTile.js @@ -7,6 +7,7 @@ import IndexDatatype from '../Core/IndexDatatype.js'; import IntersectionTests from '../Core/IntersectionTests.js'; import OrientedBoundingBox from '../Core/OrientedBoundingBox.js'; import PixelFormat from '../Core/PixelFormat.js'; +import Ray from '../Core/Ray.js'; import Request from '../Core/Request.js'; import RequestState from '../Core/RequestState.js'; import RequestType from '../Core/RequestType.js'; @@ -139,7 +140,6 @@ import TerrainState from './TerrainState.js'; var scratchV0 = new Cartesian3(); var scratchV1 = new Cartesian3(); var scratchV2 = new Cartesian3(); - var scratchResult = new Cartesian3(); GlobeSurfaceTile.prototype.pick = function(ray, mode, projection, cullBackFaces, result) { var mesh = this.renderedMesh; @@ -150,9 +150,11 @@ import TerrainState from './TerrainState.js'; var vertices = mesh.vertices; var indices = mesh.indices; var encoding = mesh.encoding; + var indicesLength = indices.length; - var length = indices.length; - for (var i = 0; i < length; i += 3) { + var minT = Number.MAX_VALUE; + + for (var i = 0; i < indicesLength; i += 3) { var i0 = indices[i]; var i1 = indices[i + 1]; var i2 = indices[i + 2]; @@ -161,13 +163,13 @@ import TerrainState from './TerrainState.js'; var v1 = getPosition(encoding, mode, projection, vertices, i1, scratchV1); var v2 = getPosition(encoding, mode, projection, vertices, i2, scratchV2); - var intersection = IntersectionTests.rayTriangle(ray, v0, v1, v2, cullBackFaces, scratchResult); - if (defined(intersection)) { - return Cartesian3.clone(intersection, result); + var t = IntersectionTests.rayTriangleParametric(ray, v0, v1, v2, cullBackFaces); + if (defined(t) && t < minT) { + minT = t; } } - return undefined; + return minT < Number.MAX_VALUE ? Ray.getPoint(ray, minT, result) : undefined; }; GlobeSurfaceTile.prototype.freeResources = function() { diff --git a/Specs/Scene/GlobeSurfaceTileSpec.js b/Specs/Scene/GlobeSurfaceTileSpec.js index fe1517578778..96bc1c2555ee 100644 --- a/Specs/Scene/GlobeSurfaceTileSpec.js +++ b/Specs/Scene/GlobeSurfaceTileSpec.js @@ -5,6 +5,7 @@ import { Cartesian3 } from '../../Source/Cesium.js'; import { Cartesian4 } from '../../Source/Cesium.js'; import { createWorldTerrain } from '../../Source/Cesium.js'; import { Ellipsoid } from '../../Source/Cesium.js'; +import { EllipsoidTerrainProvider } from '../../Source/Cesium.js'; import { GeographicTilingScheme } from '../../Source/Cesium.js'; import { Ray } from '../../Source/Cesium.js'; import { GlobeSurfaceTile } from '../../Source/Cesium.js'; @@ -308,6 +309,32 @@ describe('Scene/GlobeSurfaceTile', function() { expect(cartographic.height).toBeGreaterThan(-500.0); }); }); + + it('gets correct result when a closer triangle is processed after a farther triangle', function() { + // Pick root tile (0,0). It will intersect a triangle on the east and the west side. + // The east triangle is closer and should be the pick result even though the west triangle is checked first. + var terrainProvider = new EllipsoidTerrainProvider(); + + var tile = new QuadtreeTile({ + tilingScheme : new GeographicTilingScheme(), + level : 0, + x : 0, + y : 0 + }); + + processor.frameState = scene.frameState; + processor.terrainProvider = terrainProvider; + + return processor.process([tile]).then(function() { + var ray = new Ray( + new Cartesian3(50000000.0, 0.0, 0.0), + // nudge the direction to be pointing at the (0,0) tile + new Cartesian3(-0.9999422718925407, -0.007344489332226594, -0.007842917749982258)); + var cullBackFaces = false; + var pickResult = tile.data.pick(ray, undefined, undefined, cullBackFaces); + expect(pickResult.x).toBeGreaterThan(0.0); + }); + }); }, 'WebGL'); describe('eligibleForUnloading', function() {