Skip to content

Commit 929bda2

Browse files
authored
ImageOverlayPlugin: Fix Mercator overlay (#1538)
* Add fix * Fix mercator case * Fix the mercator projection * Cleanup
1 parent 2589822 commit 929bda2

File tree

3 files changed

+25
-32
lines changed

3 files changed

+25
-32
lines changed

src/three/plugins/images/ImageOverlayPlugin.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ export class ImageOverlayPlugin {
120120

121121
}
122122

123-
// TODO: we could prioritize by overlay order here to ensure consistency
124-
125123
};
126124

127125
// save variables
@@ -710,11 +708,6 @@ export class ImageOverlayPlugin {
710708
// create a sphere bounding volume
711709
if ( tile.boundingVolume.box || tile.boundingVolume.sphere ) {
712710

713-
// TODO: we create a sphere even when a region is present because currently the handling of region volumes
714-
// is a bit flaky especially at small scales. OBBs are generated which can be imperfect resulting rays passing
715-
// through tiles. The same may be the case with frustum checks. In theory, though, we should not need a sphere
716-
// bounds if a region bounds are present.
717-
718711
// compute the sphere center
719712
_box
720713
.setFromObject( result, true )
@@ -1010,13 +1003,13 @@ export class ImageOverlayPlugin {
10101003

10111004
} else if ( tile.boundingVolume.region ) {
10121005

1013-
// If the tile has a region bounding volume then mark the tiles to preload
1006+
// If the tile has a region bounding volume then mark the tiles to preload, clamped to the extents of
1007+
// the overlay image
10141008
const [ minLon, minLat, maxLon, maxLat ] = tile.boundingVolume.region;
1015-
const range = overlay.projection.toNormalizedRange( [ minLon, minLat, maxLon, maxLat ] );
1009+
let range = [ minLon, minLat, maxLon, maxLat ];
1010+
range = overlay.projection.clampToBounds( range );
1011+
range = overlay.projection.toNormalizedRange( range );
10161012

1017-
// TODO: locking the texture here causes compositing to happen immediately which can be performance intensive,
1018-
// particularly in cases like GeoJSON loader. Ideally the compositing / final drw step to "lock" would be deferred
1019-
// as well, just like the tile image loads.
10201013
info.range = range;
10211014
overlay.lockTexture( range, tile );
10221015

@@ -1101,8 +1094,7 @@ export class ImageOverlayPlugin {
11011094

11021095
}
11031096

1104-
( { range, uvs } = getMeshesCartographicRange( meshes, ellipsoid, _matrix, projection ) );
1105-
range = projection.toNormalizedRange( range );
1097+
( { range, uvs } = getMeshesCartographicRange( meshes, ellipsoid, _matrix, projection, info.range ) );
11061098
heightInRange = true;
11071099

11081100
}
@@ -1113,10 +1105,6 @@ export class ImageOverlayPlugin {
11131105
info.range = range;
11141106
overlay.lockTexture( range, tile );
11151107

1116-
} else {
1117-
1118-
range = info.range;
1119-
11201108
}
11211109

11221110
// if the image projection is outside the 0, 1 uvw range or there are no textures to draw in

src/three/plugins/images/overlays/utils.js

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function getGeometryCartographicChannel( geometry, geomToEllipsoidMatrix, ellips
101101

102102
}
103103

104-
export function getMeshesCartographicRange( meshes, ellipsoid, meshToEllipsoidMatrix = null, projection = null ) {
104+
export function getMeshesCartographicRange( meshes, ellipsoid, meshToEllipsoidMatrix = null, projection = null, normalizedRange = null ) {
105105

106106
// find the lat / lon ranges
107107
let minLat = Infinity;
@@ -138,18 +138,21 @@ export function getMeshesCartographicRange( meshes, ellipsoid, meshToEllipsoidMa
138138

139139
} );
140140

141-
let clampedRange = [ minLon, minLat, maxLon, maxLat ];
142141
if ( projection !== null ) {
143142

144-
// Clamp the lat lon range to the bounds of the projection scheme. Note that clamping the data
145-
// allows for "stretching" the texture look at the edges of the projection which leads to a nicer
146-
// looking overlay. Eg at the poles of a web-mercator projection - otherwise there will be gaps
147-
// that show the underlying tile data. It's arguable which one is better but in all supported
148-
// ellipsoid projections (Web mercator, equirect) the projection ranges always span the entire
149-
// globe range.
150-
// const clampedRange = [ minLon, minLat, maxLon, maxLat ];
151-
clampedRange = projection.clampToBounds( [ minLon, minLat, maxLon, maxLat ] );
152-
const [ minU, minV, maxU, maxV ] = projection.toNormalizedRange( clampedRange );
143+
// Clamp the mesh vertex range to the projection's valid bounds (e.g. ~±85° for Mercator) to
144+
// avoid NaN UV values for vertices that fall outside the projection range. This also stretches
145+
// the texture at the projection boundary rather than leaving gaps.
146+
147+
// takes generate a normalized range if not already provided
148+
if ( normalizedRange === null ) {
149+
150+
normalizedRange = projection.clampToBounds( [ minLon, minLat, maxLon, maxLat ] );
151+
normalizedRange = projection.toNormalizedRange( normalizedRange );
152+
153+
}
154+
155+
const [ minU, minV, maxU, maxV ] = normalizedRange;
153156
uvs.forEach( uv => {
154157

155158
for ( let i = 0, l = uv.length; i < l; i += 3 ) {
@@ -158,7 +161,9 @@ export function getMeshesCartographicRange( meshes, ellipsoid, meshToEllipsoidMa
158161
const lat = uv[ i + 1 ];
159162
const h = uv[ i + 2 ];
160163

161-
const [ u, v ] = projection.toNormalizedPoint( lon, lat );
164+
let [ u, v ] = projection.toNormalizedPoint( lon, lat );
165+
u = MathUtils.clamp( u, 0, 1 );
166+
v = MathUtils.clamp( v, 0, 1 );
162167
uv[ i + 0 ] = MathUtils.mapLinear( u, minU, maxU, 0, 1 );
163168
uv[ i + 1 ] = MathUtils.mapLinear( v, minV, maxV, 0, 1 );
164169
uv[ i + 2 ] = MathUtils.mapLinear( h, minHeight, maxHeight, 0, 1 );
@@ -171,7 +176,7 @@ export function getMeshesCartographicRange( meshes, ellipsoid, meshToEllipsoidMa
171176

172177
return {
173178
uvs,
174-
range: clampedRange,
179+
range: normalizedRange,
175180
region: [ minLon, minLat, maxLon, maxLat, minHeight, maxHeight ],
176181
};
177182

src/three/plugins/images/utils/ProjectionScheme.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ export class ProjectionScheme {
235235

236236
const [ minX, minY, maxX, maxY ] = clampBounds;
237237
result[ 0 ] = MathUtils.clamp( result[ 0 ], minX, maxX );
238-
result[ 1 ] = MathUtils.clamp( result[ 1 ], minY, maxY );
239238
result[ 2 ] = MathUtils.clamp( result[ 2 ], minX, maxX );
239+
result[ 1 ] = MathUtils.clamp( result[ 1 ], minY, maxY );
240240
result[ 3 ] = MathUtils.clamp( result[ 3 ], minY, maxY );
241241

242242
return result;

0 commit comments

Comments
 (0)