-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(TileBuilder): convert to TypeScript
Improve performance by using statically-sized ArrayBuffers. Reorganize code to get rid of some of the params/builder mess. Cleanup computeBuffers function. Squashed commit history (oldest to youngest): - fix: UV_1 generation - refacto(wip): cleanup and optimize computeBuffers - refacto(wip): improve index generation - wip: correct offset, off-by-one still at large - fix: change calls to allow camera debug - fix: found the error, off by a power of 2 actually - fix(uv): correct indices passed to UV buffering - fix(index): only generate buffer when needed - wip: enable cache - fix(computeBuffers): group tile and skirt together - fix(wip): squash rogue private field access - refacto: convert TileGeometry to TypeScript - style(builders): make method visibility explicit - refactor(exports): remove default exports
- Loading branch information
1 parent
c862ca7
commit 9d9b3c8
Showing
15 changed files
with
943 additions
and
564 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import * as THREE from 'three'; | ||
import Coordinates from 'Core/Geographic/Coordinates'; | ||
import Extent from 'Core/Geographic/Extent'; | ||
import { | ||
Projected, | ||
ShareableExtent, | ||
TileBuilder, | ||
TileBuilderParams, | ||
} from '../TileBuilder'; | ||
|
||
const PI_OV_FOUR = Math.PI / 4; | ||
const INV_TWO_PI = 1.0 / (Math.PI * 2); | ||
const axisZ = new THREE.Vector3(0, 0, 1); | ||
const axisY = new THREE.Vector3(0, 1, 0); | ||
const quatToAlignLongitude = new THREE.Quaternion(); | ||
const quatToAlignLatitude = new THREE.Quaternion(); | ||
const quatNormalToZ = new THREE.Quaternion(); | ||
|
||
function WGS84ToOneSubY(latitude: number) { | ||
return 1.0 - (0.5 - Math.log(Math.tan( | ||
PI_OV_FOUR + THREE.MathUtils.degToRad(latitude) * 0.5, | ||
)) * INV_TWO_PI); | ||
} | ||
|
||
export interface GlobeTileBuilderParams extends TileBuilderParams { | ||
nbRow: number; | ||
deltaUV1: number; | ||
quatNormalToZ: THREE.Quaternion; | ||
} | ||
|
||
export class GlobeTileBuilder | ||
implements TileBuilder<GlobeTileBuilderParams> { | ||
private _crs: string; | ||
private _transform: { | ||
coords: Coordinates[]; | ||
position: THREE.Vector3; | ||
dimension: THREE.Vector2; | ||
}; | ||
|
||
public computeExtraOffset?: (params: GlobeTileBuilderParams) => number; | ||
|
||
public get crs(): string { | ||
return this._crs; | ||
} | ||
|
||
public constructor(options: { | ||
crs: string, | ||
uvCount: number, | ||
}) { | ||
this._transform = { | ||
coords: [ | ||
new Coordinates('EPSG:4326', 0, 0), | ||
new Coordinates('EPSG:4326', 0, 0), | ||
], | ||
position: new THREE.Vector3(), | ||
dimension: new THREE.Vector2(), | ||
}; | ||
|
||
this._crs = options.crs; | ||
// Order crs projection on tiles | ||
|
||
// UV: Normalized coordinates (from degree) on the entire tile | ||
// EPSG:4326 | ||
// Offset: Float row coordinate from Pseudo mercator coordinates | ||
// EPSG:3857 | ||
if (options.uvCount > 1) { | ||
this.computeExtraOffset = GlobeTileBuilder._computeExtraOffset; | ||
} | ||
} | ||
|
||
private static _computeExtraOffset(params: GlobeTileBuilderParams): number { | ||
const t = WGS84ToOneSubY(params.projected.latitude) * params.nbRow; | ||
return (!isFinite(t) ? 0 : t) - params.deltaUV1; | ||
} | ||
|
||
// prepare params | ||
// init projected object -> params.projected | ||
public prepare(params: TileBuilderParams): GlobeTileBuilderParams { | ||
const nbRow = 2 ** (params.level + 1.0); | ||
let st1 = WGS84ToOneSubY(params.extent.south); | ||
|
||
if (!isFinite(st1)) { st1 = 0; } | ||
|
||
const sizeTexture = 1.0 / nbRow; | ||
|
||
const start = (st1 % (sizeTexture)); | ||
|
||
const newParams = { | ||
nbRow, | ||
deltaUV1: (st1 - start) * nbRow, | ||
// transformation to align tile's normal to z axis | ||
quatNormalToZ: quatNormalToZ.setFromAxisAngle( | ||
axisY, | ||
-(Math.PI * 0.5 - THREE.MathUtils.degToRad( | ||
params.extent.center().latitude, | ||
))), | ||
// let's avoid building too much temp objects | ||
projected: new Projected(), | ||
}; | ||
|
||
params.extent.planarDimensions(this._transform.dimension); | ||
|
||
return { ...params, ...newParams }; | ||
} | ||
|
||
// get center tile in cartesian 3D | ||
public center(extent: Extent) { | ||
return extent.center(this._transform.coords[0]) | ||
.as(this.crs, this._transform.coords[1]) | ||
.toVector3(); | ||
} | ||
|
||
// get position 3D cartesian | ||
public vertexPosition(position: THREE.Vector2): THREE.Vector3 { | ||
return this._transform.coords[0] | ||
.setFromValues(position.x, position.y) | ||
.as(this.crs, this._transform.coords[1]) | ||
.toVector3(this._transform.position); | ||
} | ||
|
||
// get normal for last vertex | ||
public vertexNormal() { | ||
return this._transform.coords[1].geodesicNormal; | ||
} | ||
|
||
// coord u tile to projected | ||
public uProject(u: number, extent: Extent): number { | ||
return extent.west + u * this._transform.dimension.x; | ||
} | ||
|
||
// coord v tile to projected | ||
public vProject(v: number, extent: Extent): number { | ||
return extent.south + v * this._transform.dimension.y; | ||
} | ||
|
||
public computeShareableExtent(extent: Extent): ShareableExtent { | ||
// Compute shareable extent to pool the geometries | ||
// the geometry in common extent is identical to the existing input | ||
// with a transformation (translation, rotation) | ||
|
||
// TODO: It should be possible to use equatorial plan symetrie, | ||
// but we should be reverse UV on tile | ||
// Common geometry is looking for only on longitude | ||
const sizeLongitude = Math.abs(extent.west - extent.east) / 2; | ||
const shareableExtent = new Extent( | ||
extent.crs, | ||
-sizeLongitude, sizeLongitude, | ||
extent.south, extent.north, | ||
); | ||
|
||
// compute rotation to transform tile to position on ellipsoid | ||
// this transformation takes into account the transformation of the | ||
// parents | ||
const rotLon = THREE.MathUtils.degToRad( | ||
extent.west - shareableExtent.west, | ||
); | ||
const rotLat = THREE.MathUtils.degToRad( | ||
90 - extent.center(this._transform.coords[0]).latitude, | ||
); | ||
quatToAlignLongitude.setFromAxisAngle(axisZ, rotLon); | ||
quatToAlignLatitude.setFromAxisAngle(axisY, rotLat); | ||
quatToAlignLongitude.multiply(quatToAlignLatitude); | ||
|
||
return { | ||
shareableExtent, | ||
quaternion: quatToAlignLongitude.clone(), | ||
position: this.center(extent), | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.