@here/harp-mapview
Version:
Functionality needed to render a map.
135 lines • 6.95 kB
JavaScript
"use strict";
/*
* Copyright (C) 2021 HERE Europe B.V.
* Licensed under Apache 2.0, see full license in LICENSE
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.addGroundPlane = void 0;
const harp_datasource_protocol_1 = require("@here/harp-datasource-protocol");
const EdgeLengthGeometrySubdivisionModifier_1 = require("@here/harp-geometry/lib/EdgeLengthGeometrySubdivisionModifier");
const SphericalGeometrySubdivisionModifier_1 = require("@here/harp-geometry/lib/SphericalGeometrySubdivisionModifier");
const harp_geoutils_1 = require("@here/harp-geoutils");
const harp_materials_1 = require("@here/harp-materials");
const THREE = require("three");
const LodMesh_1 = require("./LodMesh");
const ProjectTilePlaneCorners_1 = require("./ProjectTilePlaneCorners");
const RegisterTileObject_1 = require("./RegisterTileObject");
const tmpV = new THREE.Vector3();
/**
* Creates and adds a background plane mesh for the tile.
* @param tile - The tile to which the ground plane belongs.
* @param renderOrder - The plane render order.
* @param materialOrColor - The plane material or a color for a default material.
* @param opacity - The plane opacity.
* @param createTexCoords - Whether to create texture coordinates.
* @param receiveShadow - Whether the plane should receive shadows.
* @param createMultiLod - Whether to generate multiple LODs for sphere projection.
* @internal
*/
function addGroundPlane(tile, renderOrder, materialOrColor = tile.mapView.clearColor, opacity = 1, createTexCoords = false, receiveShadow = tile.mapView.shadowsEnabled, createMultiLod = tile.mapView.enableMixedLod !== false) {
const mesh = createGroundPlane(tile, createTexCoords, receiveShadow, materialOrColor, createMultiLod, opacity);
mesh.receiveShadow = receiveShadow;
mesh.renderOrder = renderOrder;
RegisterTileObject_1.registerTileObject(tile, mesh, harp_datasource_protocol_1.GeometryKind.Background, { pickability: harp_datasource_protocol_1.Pickability.transient });
tile.objects.push(mesh);
return mesh;
}
exports.addGroundPlane = addGroundPlane;
function createGroundPlane(tile, createTexCoords, receiveShadow, materialOrColor, createMultiLod, opacity) {
const { dataSource, projection } = tile;
const sourceProjection = dataSource.getTilingScheme().projection;
const shouldSubdivide = projection.type === harp_geoutils_1.ProjectionType.Spherical;
const useLocalTargetCoords = !shouldSubdivide;
const material = typeof materialOrColor === "number"
? createGroundPlaneMaterial(new THREE.Color(materialOrColor), receiveShadow, projection.type === harp_geoutils_1.ProjectionType.Spherical, opacity)
: materialOrColor;
const geometry = createGroundPlaneGeometry(tile, useLocalTargetCoords, createTexCoords, receiveShadow);
if (!shouldSubdivide) {
return new THREE.Mesh(geometry, material);
}
const geometries = [];
const sphericalModifier = new SphericalGeometrySubdivisionModifier_1.SphericalGeometrySubdivisionModifier(THREE.MathUtils.degToRad(10), sourceProjection);
if (!createMultiLod) {
sphericalModifier.modify(geometry);
toLocalTargetCoords(geometry, sourceProjection, tile);
return new THREE.Mesh(geometry, material);
}
// Use a [[LodMesh]] to adapt tesselation of tile depending on zoom level
for (let zoomLevelOffset = 0; zoomLevelOffset < 4; ++zoomLevelOffset) {
const subdivision = Math.pow(2, zoomLevelOffset);
const zoomLevelGeometry = geometry.clone();
if (subdivision > 1) {
const edgeModifier = new EdgeLengthGeometrySubdivisionModifier_1.EdgeLengthGeometrySubdivisionModifier(subdivision, tile.geoBox, EdgeLengthGeometrySubdivisionModifier_1.SubdivisionMode.All, sourceProjection);
edgeModifier.modify(zoomLevelGeometry);
}
sphericalModifier.modify(zoomLevelGeometry);
toLocalTargetCoords(zoomLevelGeometry, sourceProjection, tile);
geometries.push(zoomLevelGeometry);
}
return new LodMesh_1.LodMesh(geometries, material);
}
function toLocalTargetCoords(geom, srcProjection, tile) {
const attr = geom.getAttribute("position");
const oldArray = attr.array;
// Convert to single precision before rendering (WebGL does not support double
// precision).
const newArray = new Float32Array(oldArray.length);
for (let i = 0; i < attr.array.length; i += 1) {
tmpV.fromBufferAttribute(attr, i);
tile.projection.reprojectPoint(srcProjection, tmpV, tmpV).sub(tile.center);
tmpV.toArray(newArray, i * 3);
}
attr.array = newArray;
attr.needsUpdate = true;
}
function createGroundPlaneGeometry(tile, useLocalTargetCoords, createTexCoords, receiveShadow) {
const { dataSource, projection } = tile;
const sourceProjection = dataSource.getTilingScheme().projection;
const tmpV = new THREE.Vector3();
const geometry = new THREE.BufferGeometry();
const tileCorners = ProjectTilePlaneCorners_1.projectTilePlaneCorners(tile, sourceProjection);
const cornersArray = [tileCorners.sw, tileCorners.se, tileCorners.nw, tileCorners.ne];
if (useLocalTargetCoords) {
for (const corner of cornersArray) {
projection.reprojectPoint(sourceProjection, corner, corner).sub(tile.center);
}
}
// Use 64bits floats for world coordinates to avoid precision issues on coordinate
// tranformations. The array must be converted to single precision before rendering.
const bufferArray = useLocalTargetCoords ? new Float32Array(12) : new Float64Array(12);
const posAttr = new THREE.BufferAttribute(bufferArray, 3).copyVector3sArray(cornersArray);
geometry.setAttribute("position", posAttr);
if (receiveShadow) {
// Webmercator needs to have it negated to work correctly.
sourceProjection.surfaceNormal(tileCorners.sw, tmpV).negate();
const normAttr = new THREE.BufferAttribute(new Float32Array(12), 3).copyVector3sArray(Array(4).fill(tmpV));
geometry.setAttribute("normal", normAttr);
}
geometry.setIndex(new THREE.BufferAttribute(new Uint16Array([0, 1, 2, 2, 1, 3]), 1));
if (createTexCoords) {
const uvAttr = new THREE.BufferAttribute(new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]), 2);
geometry.setAttribute("uv", uvAttr);
}
return geometry;
}
function createGroundPlaneMaterial(color, receiveShadow, depthWrite, opacity) {
if (receiveShadow) {
return new harp_materials_1.MapMeshStandardMaterial({
color,
visible: true,
depthWrite,
removeDiffuseLight: true,
opacity
});
}
else {
return new harp_materials_1.MapMeshBasicMaterial({
color,
visible: true,
depthWrite,
opacity
});
}
}
//# sourceMappingURL=AddGroundPlane.js.map