@here/harp-mapview
Version:
Functionality needed to render a map.
151 lines • 6.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MapViewFog = void 0;
const harp_materials_1 = require("@here/harp-materials");
const RawShaderMaterial_1 = require("@here/harp-materials/lib/RawShaderMaterial");
const harp_utils_1 = require("@here/harp-utils");
const THREE = require("three");
/**
* Manages the fog display in {@link MapView}.
*/
class MapViewFog {
/**
* Constructs a `MapViewFog` instance.
*
* @param m_scene - The scene used in {@link MapView} that contains the map objects.
*/
constructor(m_scene) {
this.m_scene = m_scene;
this.m_enabled = true;
this.m_fog = new THREE.Fog(0x000000); // Default color asked by DefinitelyTyped.
this.m_fogIsDefined = false;
}
/**
* Allows for disabling the fog, even if it is defined in the theme. Use this property for
* custom views like the demo app's debug camera. However, if the theme does not define a
* fog, enabling this property here has no effect.
*
* @param value - A boolean that specifies whether the fog should be enabled or disabled.
*/
set enabled(enableFog) {
this.m_enabled = enableFog;
if (enableFog && this.m_fogIsDefined && this.m_scene.fog === null) {
this.add();
}
else if (!enableFog && this.m_scene.fog !== null) {
this.remove();
}
}
/**
* Returns the current fog status, enabled or disabled.
*/
get enabled() {
return this.m_enabled;
}
/**
* Sets the fog depending on the {@link @here/harp-datasource-protocol#Theme}
* instance provided. This function is called when a
* theme is loaded. Fog is added only if the theme contains a fog definition with a:
* - `color` property, used to set the fog color.
* - `startRatio` property, used to set the start distance of the fog as a ratio of the far
* clipping plane distance.
*
* @param theme - A {@link @here/harp-datasource-protocol#Theme} instance.
*/
reset(fog) {
this.m_cachedFog = fog;
if (fog !== undefined && fog.color !== undefined && fog.startRatio !== undefined) {
this.m_fogIsDefined = true;
this.m_fog.color.set(fog.color);
if (this.m_enabled && this.m_scene.fog === null) {
this.add();
}
}
else {
this.m_fogIsDefined = false;
if (this.m_scene.fog !== null) {
this.remove();
}
}
}
/**
* Updates the fog at runtime, depending on the camera.
*
* @param camera - An instance of a `THREE.Camera` with a `far` property.
*/
update(mapView, viewDistance) {
if (this.m_scene.fog !== null &&
this.m_cachedFog !== undefined &&
this.m_cachedFog &&
this.m_cachedFog.startRatio !== undefined &&
(mapView.camera.far !== undefined || viewDistance !== undefined)) {
// If maximum visibility range is available use it instead of camera.far distance,
// this makes fog independent from dynamic camera planes and keeps consistent
// distance based "melting" (fog) effect during a tilt.
const viewRange = viewDistance !== undefined ? viewDistance : mapView.camera.far;
// TODO: We may move below constants to theme Fog definition
// Density of the fog when viewing straight along the horizon line.
const horizontalDensity = 1.0;
// Theoretical density of the fog when viewing straight from top to down.
const verticalDensity = 0.0;
// The fraction of the maximum viewing distance along the eye vector
// to start applying the fog.
const startRatio = this.m_cachedFog.startRatio;
// The fraction of maximum viewing range at which fog fully covers geometry.
const endRatio = 1.0;
harp_utils_1.assert(startRatio <= endRatio);
const t = Math.abs(Math.cos(mapView.tilt));
const density = harp_utils_1.MathUtils.smoothStep(horizontalDensity, verticalDensity, t);
this.m_fog.near = THREE.MathUtils.lerp(viewRange * startRatio, viewRange, 1.0 - density);
this.m_fog.far = THREE.MathUtils.lerp(viewRange * endRatio, viewRange, density);
this.m_fog.near = Math.min(this.m_fog.near, mapView.camera.far);
this.m_fog.far = Math.min(this.m_fog.far, mapView.camera.far);
}
}
/**
* Handles fog addition.
*/
add() {
// When the fog is changed, ThreeJS takes care of recompiling its built-in materials...
this.m_scene.fog = this.m_fog;
// ...except the `RawShaderMaterial`, on purpose, so it needs to be updated from the app.
this.setFogInRawShaderMaterials(true);
}
/**
* Handles fog removal.
*/
remove() {
// When the fog is changed, ThreeJS takes care of recompiling its built-in materials...
this.m_scene.fog = null;
// ...except the `RawShaderMaterial`, on purpose, so it needs to be updated from the app.
this.setFogInRawShaderMaterials(false);
}
/**
* ThreeJS lets users manage the `RawShaderMaterial` themselves, so they need to be modified
* explicitly.
*
* @see https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLProgram.js#L298
*/
setFogInRawShaderMaterials(enableFog) {
this.m_scene.traverse(object => {
if (object instanceof THREE.Mesh) {
const material = object.material;
if (material instanceof THREE.Material &&
// HighPrecisionLineMaterial does not support fog:
!(material instanceof harp_materials_1.HighPrecisionLineMaterial) &&
// We may skip redundant updates:
material.fog !== enableFog) {
material.fog = enableFog;
if (material instanceof RawShaderMaterial_1.RawShaderMaterial) {
// Fog properties can't be easily changed at runtime (once the material
// is rendered at least once) and thus requires building of new shader
// program - force material update.
material.invalidateFog();
}
}
}
});
}
}
exports.MapViewFog = MapViewFog;
//# sourceMappingURL=MapViewFog.js.map