Skip to content

Commit 9acb731

Browse files
authored
Refactor "calculateTileViewError" (#1459)
* Add clarifying comments * Some simplification * Add distance support * Clarification and simplification * Write out distance * Simplification
1 parent bb2a74e commit 9acb731

File tree

2 files changed

+92
-24
lines changed

2 files changed

+92
-24
lines changed

src/three/plugins/LoadRegionPlugin.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,29 @@ export class LoadRegionPlugin {
5757
const boundingVolume = tile.engineData.boundingVolume;
5858
const { regions, tiles } = this;
5959

60+
// "inShape" indicates whether the tile intersects the given shape.
61+
// "inMask" indicates whether the tile is _within_ a mask if boolean, if
62+
// null then it is ignored.
63+
// "maxError" is the maximum error from the shapes.
6064
let inShape = false;
6165
let inMask = null;
62-
let maxError = - Infinity;
66+
let maxError = 0;
67+
let minDistance = Infinity;
6368
for ( const region of regions ) {
6469

70+
// TODO: we should only set the error if it is "intersected".
71+
6572
// Check if the tile is intersecting the shape and calculate the
6673
// view and error values.
6774
const intersects = region.intersectsTile( boundingVolume, tile, tiles );
6875
inShape = inShape || intersects;
69-
maxError = Math.max( region.calculateError( tile, tiles ), maxError );
76+
77+
if ( intersects ) {
78+
79+
maxError = Math.max( region.calculateError( tile, tiles ), maxError );
80+
minDistance = Math.min( region.calculateDistance( boundingVolume, tile, tiles ) );
81+
82+
}
7083

7184
// Store whether the tile is in a "mask" shape if they exist. If "inMask" is
7285
// still "null" by the end of the loop then there are no mask elements.
@@ -82,6 +95,7 @@ export class LoadRegionPlugin {
8295
// are no masks.
8396
target.inView = inShape && inMask !== false;
8497
target.error = maxError;
98+
target.distance = minDistance;
8599

86100
// Returning "false" indicates "no operation" and all results will be ignored.
87101
return target.inView || inMask !== null;
@@ -118,7 +132,17 @@ export class BaseRegion {
118132

119133
}
120134

121-
intersectsTile() {}
135+
intersectsTile( boundingVolume, tile, tiles ) {
136+
137+
return false;
138+
139+
}
140+
141+
calculateDistance( boundingVolume, tile, tiles ) {
142+
143+
return Infinity;
144+
145+
}
122146

123147
calculateError( tile, tilesRenderer ) {
124148

src/three/renderer/tiles/TilesRenderer.js

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ const tempMat = /* @__PURE__ */ new Matrix4();
2929
const tempVector = /* @__PURE__ */ new Vector3();
3030
const tempVector2 = /* @__PURE__ */ new Vector2();
3131
const viewErrorTarget = {
32-
inView: false,
33-
error: Infinity,
32+
inView: true,
33+
error: 0,
34+
distance: Infinity,
3435
};
3536

3637
const X_AXIS = /* @__PURE__ */ new Vector3( 1, 0, 0 );
@@ -917,10 +918,10 @@ export class TilesRenderer extends TilesRendererBase {
917918
const boundingVolume = engineData.boundingVolume;
918919

919920
let inView = false;
920-
let inViewError = - Infinity;
921+
let inViewError = 0;
921922
let inViewDistance = Infinity;
922-
let maxError = - Infinity;
923-
let minDistance = Infinity;
923+
let maxCameraError = 0;
924+
let minCameraDistance = Infinity;
924925

925926
for ( let i = 0, l = cameras.length; i < l; i ++ ) {
926927

@@ -955,42 +956,85 @@ export class TilesRenderer extends TilesRendererBase {
955956

956957
}
957958

958-
maxError = Math.max( maxError, error );
959-
minDistance = Math.min( minDistance, distance );
959+
maxCameraError = Math.max( maxCameraError, error );
960+
minCameraDistance = Math.min( minCameraDistance, distance );
960961

961962
}
962963

963-
// check the plugin visibility
964+
if ( inView ) {
965+
966+
// write the in-camera error and distance parameters
967+
target.inView = true;
968+
target.error = inViewError;
969+
target.distanceFromCamera = inViewDistance;
970+
971+
} else {
972+
973+
// otherwise write variables for load priority
974+
target.inView = false;
975+
target.error = maxCameraError;
976+
target.distanceFromCamera = minCameraDistance;
977+
978+
}
979+
980+
//
981+
982+
// TODO: this logic is extremely complex. It may be more simple to have the plugin
983+
// return a "should mask" field that indicates its "false" values should be respected
984+
// rather than the function returning a "no-op" boolean.
985+
// check the plugin visibility - each plugin will mask between themselves
986+
let inRegion = null;
987+
let inRegionError = 0;
988+
let inRegionDistance = Infinity;
964989
this.invokeAllPlugins( plugin => {
965990

966-
if ( plugin !== this && plugin.calculateTileViewError && plugin.calculateTileViewError( tile, viewErrorTarget ) ) {
991+
if ( plugin !== this && plugin.calculateTileViewError ) {
967992

968-
// Tile shall be traversed if inView for at least one plugin.
969-
inView = inView && viewErrorTarget.inView;
970-
maxError = Math.max( maxError, viewErrorTarget.error );
993+
// if function returns false it means "no operation"
994+
viewErrorTarget.inView = true;
995+
viewErrorTarget.error = 0;
996+
viewErrorTarget.distance = Infinity;
997+
if ( plugin.calculateTileViewError( tile, viewErrorTarget ) ) {
971998

972-
if ( viewErrorTarget.inView ) {
999+
if ( inRegion === null ) {
9731000

974-
inViewError = Math.max( inViewError, viewErrorTarget.error );
1001+
inRegion = true;
1002+
1003+
}
1004+
1005+
// Plugins can set "inView" to false in order to mask the visible tiles
1006+
inRegion = inRegion && viewErrorTarget.inView;
1007+
if ( viewErrorTarget.inView ) {
1008+
1009+
inRegionDistance = Math.min( inRegionDistance, viewErrorTarget.distance );
1010+
inRegionError = Math.max( inRegionError, viewErrorTarget.error );
1011+
1012+
}
9751013

9761014
}
9771015

9781016
}
9791017

9801018
} );
9811019

982-
// If the tiles are out of view then use the global distance and error calculated
983-
if ( inView ) {
1020+
if ( target.inView && inRegion !== false ) {
1021+
1022+
// if the tile is in camera view and we haven't encountered a region (null) or
1023+
// the region is in view (true). regionInView === false means the tile is masked out.
1024+
target.error = Math.max( target.error, inRegionError );
1025+
target.distanceFromCamera = Math.min( target.distanceFromCamera, inRegionDistance );
1026+
1027+
} else if ( inRegion ) {
9841028

1029+
// if the tile is in a region then display it
9851030
target.inView = true;
986-
target.error = inViewError;
987-
target.distanceFromCamera = inViewDistance;
1031+
target.error = inRegionError;
1032+
target.distanceFromCamera = inRegionDistance;
9881033

9891034
} else {
9901035

991-
target.inView = viewErrorTarget.inView;
992-
target.error = maxError;
993-
target.distanceFromCamera = minDistance;
1036+
// otherwise write variables for load priority
1037+
target.inView = false;
9941038

9951039
}
9961040

0 commit comments

Comments
 (0)