scene/AltitudeNearPlaneStrategy.tstypescript
import type { PlanetCamera } from "../camera/PlanetCamera";
export interface INearPlaneStrategy {
applyNear(camera: PlanetCamera): void;
}
export interface IAltitudeNearPlaneRule {
maxAltitude: number;
near: number;
}
export interface IAltitudeNearPlaneStrategyParams {
rules?: IAltitudeNearPlaneRule[];
}
const DEFAULT_RULES: IAltitudeNearPlaneRule[] = [
{ maxAltitude: 100, near: 0.1 },
{ maxAltitude: 1000, near: 1.0 },
{ maxAltitude: 10000, near: 50.0 },
{ maxAltitude: 100000, near: 100.0 },
{ maxAltitude: 2000000, near: 2000.0 },
{ maxAltitude: Number.POSITIVE_INFINITY, near: 3500.0 }
];
export class AltitudeNearPlaneStrategy implements INearPlaneStrategy {
protected readonly _rules: IAltitudeNearPlaneRule[];
constructor(params: IAltitudeNearPlaneStrategyParams = {}) {
this._rules = (params.rules || DEFAULT_RULES).slice().sort((a, b) => a.maxAltitude - b.maxAltitude);
}
public applyNear(camera: PlanetCamera): void {
if (camera.frustums.length !== 1) {
return;
}
const firstFrustum = camera.frustums[0];
const altitude = Math.max(0.0, camera.getAltitude());
const targetNear = this._resolveNear(altitude);
let targetFar = firstFrustum.far;
if (camera.isOrthographic) {
targetFar = altitude + camera.planet.ellipsoid.getEquatorialSize() * 2.0;
}
if (firstFrustum.near === targetNear && firstFrustum.far === targetFar) {
return;
}
camera.setNearFar(targetNear, targetFar);
}
protected _resolveNear(altitude: number): number {
for (let i = 0; i < this._rules.length; i++) {
if (altitude <= this._rules[i].maxAltitude) {
return this._rules[i].near;
}
}
return this._rules[this._rules.length - 1].near;
}
}