Skip to content
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
import * as THREE from 'three';
import TileMesh from 'Core/TileMesh';
import { LayeredMaterial } from 'Renderer/LayeredMaterial';
import { newTileGeometry } from 'Core/Prefab/TileBuilder';
import { newTileGeometry, TileBuilder, TileBuilderParams } from 'Core/Prefab/TileBuilder';
import ReferLayerProperties from 'Layer/ReferencingLayerProperties';
import { geoidLayerIsVisible } from 'Layer/GeoidLayer';

import type { Extent } from '@itowns/geographic';
import type { LayeredMaterialParameters } from 'Renderer/LayeredMaterial';

const dimensions = new THREE.Vector2();

function setTileFromTiledLayer(tile, tileLayer) {
// A simplified interface for TiledGeometryLayer.
// It is used to avoid a dependency on the full TiledGeometryLayer type.
interface TileLayerLike {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a simplified, POD version of TiledGeometryLayer? If so, we could mention it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since TiledGeometryLayer is not typed yet, I decided to go for an sub-type for this function.

diffuse: THREE.Color;
showOutline: boolean;
isGlobeLayer: boolean;
segments: number;
disableSkirt: boolean;
hideSkirt: boolean;
tileMatrixSets: string[];
materialOptions: LayeredMaterialParameters;
builder: TileBuilder<TileBuilderParams>;
}

function setTileFromTiledLayer(tile: TileMesh, tileLayer: TileLayerLike) {
if (tileLayer.diffuse) {
tile.material.diffuse = tileLayer.diffuse;
tile.material.setUniform('diffuse', tileLayer.diffuse);
}

if (__DEBUG__) {
Expand All @@ -32,7 +49,7 @@ function setTileFromTiledLayer(tile, tileLayer) {
}

export default {
convert(requester, extent, layer) {
convert(requester: TileMesh, extent: Extent, layer: TileLayerLike) {
const builder = layer.builder;
const parent = requester;
const level = (parent !== undefined) ? (parent.level + 1) : 0;
Expand Down
1 change: 0 additions & 1 deletion packages/Main/src/Core/Prefab/Planar/PlanarTileBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ type Transform = {

/** Specialized parameters for the [PlanarTileBuilder]. */
export interface PlanarTileBuilderParams extends TileBuilderParams {
crs: string;
uvCount?: number;
nbRow: number;
}
Expand Down
22 changes: 12 additions & 10 deletions packages/Main/src/Core/Prefab/TileBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,33 @@ export type ShareableExtent = {
position: THREE.Vector3;
};

export interface TileBuilderParams {
export interface TileBuilderPrepareParams {
/** Whether to build the skirt. */
disableSkirt: boolean;
/** Whether to render the skirt. */
hideSkirt: boolean;
/** Number of segments (edge loops) inside tiles. */
segments: number;
// TODO: Move this out of the interface
/** Buffer for projected points. */
coordinates: Coordinates;
extent: Extent;
level: number;
}

export interface TileBuilderParams extends TileBuilderPrepareParams {
center: THREE.Vector3;
coordinates: Coordinates;
}

export interface TileBuilder<SpecializedParams extends TileBuilderParams> {
export interface TileBuilder<SpecializedParams extends TileBuilderParams = TileBuilderParams> {
crs: string;

/** Convert builder-agnostic params to specialized ones. */
prepare(params: TileBuilderParams): SpecializedParams;
prepare(params: TileBuilderPrepareParams): SpecializedParams;
/**
* Computes final offset of the second texture set.
* Only relevant in the case of more than one texture sets.
*/
computeExtraOffset?: (params: SpecializedParams) => number;
computeExtraOffset?(params: SpecializedParams): number;
/** Get the center of the current tile as a 3D vector. */
center(extent: Extent): THREE.Vector3;
/** Converts an x/y tile-space position to its equivalent in 3D space. */
Expand All @@ -73,8 +75,8 @@ export interface TileBuilder<SpecializedParams extends TileBuilderParams> {
}

export function newTileGeometry(
builder: TileBuilder<TileBuilderParams>,
params: TileBuilderParams,
builder: TileBuilder,
params: TileBuilderPrepareParams,
) {
const { shareableExtent, quaternion, position } =
builder.computeShareableExtent(params.extent);
Expand All @@ -94,7 +96,7 @@ export function newTileGeometry(
cacheTile.set(key, promiseGeometry);

params.extent = shareableExtent;
params.center = builder.center(params.extent).clone();
const center = builder.center(params.extent).clone();
// Read previously cached values (index and uv.wgs84 only
// depend on the # of triangles)
let cachedBuffers = cacheBuffer.get(bufferKey);
Expand All @@ -103,7 +105,7 @@ export function newTileGeometry(
try {
buffers = computeBuffers(
builder,
params,
{ ...params, center },
cachedBuffers !== undefined
? {
index: cachedBuffers.index.array as
Expand Down
36 changes: 20 additions & 16 deletions packages/Main/src/Core/Prefab/computeBufferTileGeometry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TileBuilder, TileBuilderParams } from 'Core/Prefab/TileBuilder';
import * as THREE from 'three';
import type { TileBuilder, TileBuilderPrepareParams } from 'Core/Prefab/TileBuilder';

export function getBufferIndexSize(segments: number, noSkirt: boolean): number {
const triangles = (segments) * (segments) * 2
Expand Down Expand Up @@ -48,7 +48,7 @@ type BufferCache = {
function allocateIndexBuffer(
nVertex: number,
nSeg: number,
params: TileBuilderParams,
params: { disableSkirt: boolean },
cache?: BufferCache['index'],
): { index: IndexArray, skirt: IndexArray } {
const indexBufferSize = getBufferIndexSize(nSeg, params.disableSkirt);
Expand All @@ -66,7 +66,7 @@ function allocateIndexBuffer(
tileLen
// Skirt
+ (params.disableSkirt ? 0 : skirtLen)
) * indexConstructor!.BYTES_PER_ELEMENT);
) * indexConstructor.BYTES_PER_ELEMENT);

const index = new indexConstructor(indexBuffer);
const skirt = !params.disableSkirt
Expand All @@ -82,8 +82,8 @@ function allocateIndexBuffer(
function allocateBuffers(
nVertex: number,
nSeg: number,
builder: TileBuilder<TileBuilderParams>,
params: TileBuilderParams,
builder: TileBuilder,
params: { disableSkirt: boolean },
cache?: BufferCache,
): BuffersAndSkirt {
const {
Expand Down Expand Up @@ -133,11 +133,15 @@ function initComputeUv1(value: number): (uv: Float32Array, id: number) => void {
type ComputeUvs =
[typeof computeUv0 | (() => void), ReturnType<typeof initComputeUv1>?];

interface ComputeBuffersParams extends TileBuilderPrepareParams {
center: THREE.Vector3;
}

/** Compute buffers describing a tile according to a builder and its params. */
// TODO: Split this even further into subfunctions
export function computeBuffers(
builder: TileBuilder<TileBuilderParams>,
params: TileBuilderParams,
builder: TileBuilder,
params: ComputeBuffersParams,
cache?: BufferCache,
): Buffers {
// n seg, n+1 vert + <- skirt, n verts per side
Expand Down Expand Up @@ -171,36 +175,36 @@ export function computeBuffers(
const computeUvs: ComputeUvs =
[cache === undefined ? computeUv0 : () => { }];

params = builder.prepare(params);
const preparedParams = builder.prepare(params);

for (let y = 0; y <= nSeg; y++) {
const v = y / nSeg;

params.coordinates.y = builder.vProject(v, params.extent);
preparedParams.coordinates.y = builder.vProject(v, params.extent);

if (builder.computeExtraOffset !== undefined) {
computeUvs[1] = initComputeUv1(
builder.computeExtraOffset(params) as number,
builder.computeExtraOffset(preparedParams) as number,
);
}

for (let x = 0; x <= nSeg; x++) {
const u = x / nSeg;
const id_m3 = (y * nVertex + x) * 3;

params.coordinates.x = builder.uProject(u, params.extent);
preparedParams.coordinates.x = builder.uProject(u, preparedParams.extent);

const vertex = builder.vertexPosition(params.coordinates);
const vertex = builder.vertexPosition(preparedParams.coordinates);
const normal = builder.vertexNormal();

// move geometry to center world
vertex.sub(params.center);
vertex.sub(preparedParams.center);

// align normal to z axis
// HACK: this check style is not great
if ('quatNormalToZ' in params) {
if ('quatNormalToZ' in preparedParams) {
const quat =
params.quatNormalToZ as THREE.Quaternion;
preparedParams.quatNormalToZ as THREE.Quaternion;
vertex.applyQuaternion(quat);
normal.applyQuaternion(quat);
}
Expand All @@ -217,7 +221,7 @@ export function computeBuffers(
}

// Fill skirt index buffer
if (cache === undefined && !params.disableSkirt) {
if (cache === undefined && !preparedParams.disableSkirt) {
for (let x = 0; x < nVertex; x++) {
// -------->
// 0---1---2
Expand Down
21 changes: 10 additions & 11 deletions packages/Main/src/Core/TileGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { LRUCache } from 'lru-cache';

import OBB from 'Renderer/OBB';

type PartialTileBuilderParams =
Pick<TileBuilderParams, 'extent' | 'level'>
& Partial<TileBuilderParams>;
type PartialParams<
Params extends TileBuilderParams,
Keys extends keyof Params = 'extent' | 'level'
> = Pick<Params, Keys> & Partial<Params>;

function defaultBuffers(
builder: TileBuilder<TileBuilderParams>,
params: PartialTileBuilderParams,
builder: TileBuilder,
params: PartialParams<TileBuilderParams>,
): GpuBufferAttributes {
const fullParams = {
disableSkirt: false,
Expand Down Expand Up @@ -70,8 +71,8 @@ export class TileGeometry extends THREE.BufferGeometry {
} | null;

public constructor(
builder: TileBuilder<TileBuilderParams>,
params: TileBuilderParams,
builder: TileBuilder,
params: PartialParams<TileBuilderParams, 'extent' | 'level' | 'segments'>,
bufferAttributes: GpuBufferAttributes = defaultBuffers(builder, params),
) {
super();
Expand All @@ -88,9 +89,7 @@ export class TileGeometry extends THREE.BufferGeometry {

this.computeBoundingBox();
this.OBB = null;
if (params.hideSkirt) {
this.hideSkirt = params.hideSkirt;
}
this.hideSkirt = params.hideSkirt ?? false;

this._refCount = null;
}
Expand All @@ -111,7 +110,7 @@ export class TileGeometry extends THREE.BufferGeometry {
* @param keys - The [south, level, epsg] key of this geometry.
*/
public initRefCount(
cacheTile: LRUCache<string, Promise<TileGeometry>>,
cacheTile: LRUCache<string, Promise<this>>,
key: string,
): void {
if (this._refCount !== null) {
Expand Down
Loading