Skip to content

Commit

Permalink
Merge d4793a1 into 1d1d32b
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Sep 4, 2019
2 parents 1d1d32b + d4793a1 commit 9ffea1b
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 89 deletions.
111 changes: 49 additions & 62 deletions examples/3d-tiles/app.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global URL */
import '@babel/polyfill';

import React, {PureComponent} from 'react';
Expand All @@ -16,21 +17,21 @@ import Tile3DLayer from './tile-3d-layer/tile-3d-layer';
import ControlPanel from './components/control-panel';
import fileDrop from './components/file-drop';

import {loadExampleIndex, DATA_URI} from './examples';
import {loadExampleIndex} from './examples';

export const INITIAL_EXAMPLE_CATEGORY = 'ion';
export const INITIAL_EXAMPLE_NAME = 'Mount St Helens (Cesium Ion PointCloud)';
export const INITIAL_EXAMPLE_NAME = 'Mount St Helens (PointCloud)';

// Set your mapbox token here
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line

const MAP_STYLES = {
'Satellite Base Map': 'mapbox://styles/mapbox/satellite-v9',
'Light Base Map': 'mapbox://styles/mapbox/light-v9',
'Dark Base Map': 'mapbox://styles/mapbox/dark-v9'
'Base Map: Satellite': 'mapbox://styles/mapbox/satellite-v9',
'Base Map: Light': 'mapbox://styles/mapbox/light-v9',
'Base Map: Dark': 'mapbox://styles/mapbox/dark-v9'
};

const INITIAL_MAP_STYLE = MAP_STYLES['Dark Base Map'];
const INITIAL_MAP_STYLE = MAP_STYLES['Base Map: Dark'];
const TRANSITION_DURAITON = 4000;
const EXAMPLES_VIEWSTATE = {
latitude: 40.04248558075302,
Expand All @@ -57,7 +58,7 @@ export default class App extends PureComponent {
batchTable: null,
droppedFile: null,
examplesByCategory: null,
tilesetExampleProps: {},
selectedExample: {},
category: INITIAL_EXAMPLE_CATEGORY,
name: INITIAL_EXAMPLE_NAME,
selectedMapStyle: INITIAL_MAP_STYLE
Expand Down Expand Up @@ -93,7 +94,17 @@ export default class App extends PureComponent {
});

await this._loadExampleIndex();
await this._loadInitialTileset();

// Check if a tileset is specified in the query params
if (this._selectTilesetFromQueryParams()) {
return;
}

// if not, select the default example tileset
const {category, name} = this.state;
const {examplesByCategory} = this.state;
const selectedExample = examplesByCategory[category].examples[name];
this.setState({selectedExample});
}

// load the index file that lists example tilesets
Expand All @@ -102,73 +113,42 @@ export default class App extends PureComponent {
this.setState({examplesByCategory});
}

async _loadInitialTileset() {
/* global URL */
// Check URL query params and select the "custom example" if appropriate
_selectTilesetFromQueryParams() {
const parsedUrl = new URL(window.location.href);
const ionAccessToken = parsedUrl.searchParams.get('ionAccessToken');
const ionAssetId = parsedUrl.searchParams.get('ionAssetId');
if (ionAccessToken && ionAssetId) {
await this._loadTilesetFromIonAsset(ionAccessToken, ionAssetId);
return;
this.setState({
selectedExample: {ionAccessToken, ionAssetId},
category: 'custom',
name: 'ION Tileset'
});
return true;
}

const tilesetUrl = parsedUrl.searchParams.get('tileset');
if (tilesetUrl) {
// load the tileset specified in the URL
await this._loadTilesetFromUrl(tilesetUrl);
return;
}

// load the default example tileset
const {category, name} = this.state;
await this._loadExampleTileset(category, name);
}

async _loadExampleTileset(category, name) {
const {examplesByCategory} = this.state;
const selectedExample = examplesByCategory[category].examples[name];
// TODO - avoid this fixup
if (selectedExample && selectedExample.tileset) {
selectedExample.tilesetUrl = `${DATA_URI}/${selectedExample.path}/${selectedExample.tileset}`;
this.setState({
selectedExample: {tilesetUrl},
category: 'custom',
name: 'URL Tileset'
});
return true;
}
this.setState({tilesetExampleProps: selectedExample});
}

async _loadTilesetFromIonAsset(ionAccessToken, ionAssetId) {
this.setState({
tilesetExampleProps: {
ionAccessToken,
ionAssetId
},
category: 'custom',
name: 'ION Tileset'
});
}

async _loadTilesetFromUrl(tilesetUrl) {
this.setState({
tilesetExampleProps: {
tilesetUrl
},
category: 'custom',
name: 'Custom Tileset'
});
return false;
}

// Updates stats, called every frame
_updateStatWidgets() {
if (this._tilesetStatsWidget) {
this._tilesetStatsWidget.update();
}
if (this._memWidget) {
this._memWidget.update();
}
this._memWidget.update();
this._tilesetStatsWidget.update();
}

// Called by ControlPanel when user selects a new example
async _onSelectExample({category, name}) {
this.setState({category, name});
await this._loadExampleTileset(category, name);
async _onSelectExample({example, category, name}) {
this.setState({selectedExample: example, category, name});
}

// Called by ControlPanel when user selects a new map style
Expand All @@ -179,17 +159,24 @@ export default class App extends PureComponent {
// Called by Tile3DLayer when a new tileset is loaded
_onTilesetLoad(tileset) {
this._tilesetStatsWidget.setStats(tileset.stats);
this._centerViewOnTileset(tileset);
}

// Recenter to cover the new tileset, with a nice fly to transition
// Recenter view to cover the new tileset, with a fly-to transition
_centerViewOnTileset(tileset) {
const {cartographicCenter, zoom} = tileset;
this.setState({
viewState: {
...this.state.viewState,

// Update deck.gl viewState, moving the camera to the new tileset
longitude: cartographicCenter[0],
latitude: cartographicCenter[1],
zoom: zoom + 1.5, // TODO - remove adjustment when Tileset3D calculates correct zoom
bearing: INITIAL_VIEW_STATE.bearing,
pitch: INITIAL_VIEW_STATE.pitch,

// Tells deck.gl to animate the camera move to the new tileset
transitionDuration: TRANSITION_DURAITON,
transitionInterpolator: new FlyToInterpolator()
}
Expand Down Expand Up @@ -249,12 +236,12 @@ export default class App extends PureComponent {
}

_renderTile3DLayer() {
const {tilesetExampleProps} = this.state;
if (!tilesetExampleProps) {
const {selectedExample} = this.state;
if (!selectedExample) {
return null;
}

const {tilesetUrl, ionAssetId, ionAccessToken, coordinateOrigin} = tilesetExampleProps;
const {tilesetUrl, ionAssetId, ionAccessToken, coordinateOrigin} = selectedExample;

return new Tile3DLayer({
id: 'tile-3d-layer',
Expand Down
25 changes: 19 additions & 6 deletions examples/3d-tiles/components/control-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ const DropDown = styled.select`
margin-bottom: 12px;
`;

const TilesetDropDown = styled.select`
margin-bottom: 12px;
font-weight: 800;
font-size: medium;
`;

const propTypes = {
category: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
data: PropTypes.object.isRequired,
droppedFile: PropTypes.string,
attributions: PropTypes.array,
mapStyles: PropTypes.object.isRequired,
selectedMapStyle: PropTypes.string.isRequired,
droppedFile: PropTypes.string,
onExampleChange: PropTypes.func,
onMapStyleChange: PropTypes.func,
children: PropTypes.node
Expand All @@ -47,12 +54,17 @@ export default class ControlPanel extends PureComponent {
const selectedValue = `${category}.${name}`;

return (
<DropDown
<TilesetDropDown
value={selectedValue}
onChange={evt => {
const selected = evt.target.value;
const value = selected.split('.');
onExampleChange({category: value[0], name: value[1]});
const [newCategory, newName] = selected.split('.');
const categoryExamples = data[newCategory].examples;
onExampleChange({
category: newCategory,
name: newName,
example: categoryExamples[newName]
});
}}
>
{categories.map((c, i) => {
Expand All @@ -70,7 +82,7 @@ export default class ControlPanel extends PureComponent {
</optgroup>
);
})}
</DropDown>
</TilesetDropDown>
);
}

Expand Down Expand Up @@ -104,9 +116,10 @@ export default class ControlPanel extends PureComponent {
render() {
return (
<Container>
{this._renderMapStyles()}
{this._renderByCategories()}
{this._renderDropped()}
<div style={{marginBottom: '0.5cm'}} />
{this._renderMapStyles()}
{this.props.children}
</Container>
);
Expand Down
22 changes: 16 additions & 6 deletions examples/3d-tiles/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@ const ION_TOKEN_1 =
const ION_TOKEN_2 =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzMGY4ODczYy1mNTk4LTRiMDUtYmIxYy0xZWYwOWZmMGY4NjQiLCJpZCI6NDQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJhc3NldHMiOlsxLDIsMyw0LDYxOTMsNjI3Myw3MTYyLDczNTMsNzE0Ml0sImlhdCI6MTU0MTYxODM0NX0.lWnGs9ySXO4QK3HagcMsDpZ8L01DpmUDQm38-2QAQuE';

export const DATA_URI = 'https://raw.githubusercontent.com/uber-web/loaders.gl/master';
const DATA_URI = 'https://raw.githubusercontent.com/uber-web/loaders.gl/master';

const EXAMPLE_INDEX_URL = `${DATA_URI}/modules/3d-tiles/test/data/index.json`;

const ADDITIONAL_EXAMPLES = {
github: {
examples: {
'Royal Exhibition Building (Github Pages)': {
tilesetUrl: `${DECK_DATA_URI}/3d-tiles/RoyalExhibitionBuilding/tileset.json`
tileset: `${DECK_DATA_URI}/3d-tiles/RoyalExhibitionBuilding/tileset.json`
}
}
},
ion: {
name: 'Cesium ION',
examples: {
'Mount St Helens (Cesium Ion PointCloud)': {ionAssetId: 33301, ionAccessToken: ION_TOKEN_1},
'Montreal (Cesium Ion PointCloud)': {ionAssetId: 28945, ionAccessToken: ION_TOKEN_1},
'New York Buildings 1 (Cesium Ion Photogrammetry)': {
'Mount St Helens (PointCloud)': {ionAssetId: 33301, ionAccessToken: ION_TOKEN_1},
'Montreal (PointCloud)': {ionAssetId: 28945, ionAccessToken: ION_TOKEN_1},
'New York 1 (3D Photogrammetry)': {
ionAssetId: 6193,
ionAccessToken: ION_TOKEN_2
},
'New York Buildings 2 (Cesium Ion Photogrammetry)': {
'New York 2 (3D Photogrammetry)': {
ionAssetId: 7162,
ionAccessToken: ION_TOKEN_2
}
Expand Down Expand Up @@ -59,6 +59,8 @@ export async function loadExampleIndex() {
// TODO - We should fix rendering of composite tiles, not hard
delete testExamples.Composite;

resolveUrls(testExamples);

return {
...testExamples,
...ADDITIONAL_EXAMPLES,
Expand All @@ -71,3 +73,11 @@ export async function loadExampleIndex() {
}
};
}

function resolveUrls(exampleIndex) {
for (const category of Object.values(exampleIndex)) {
for (const example of Object.values(category.examples)) {
example.tilesetUrl = `${DATA_URI}/${example.path}/${example.tileset}`;
}
}
}
32 changes: 17 additions & 15 deletions modules/3d-tiles/src/tileset/tileset-3d.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ export default class Tileset3D {
this._requestedTiles = [];
this._selectedTilesToStyle = [];

this.asset = {}; // Metadata for the entire tileset
this.credits = {};

// EXTRACTED FROM TILESET
this._root = undefined;
this._asset = undefined; // Metadata for the entire tileset
this._properties = undefined; // Metadata for per-model/point/etc properties
this._extensionsUsed = undefined;
this._gltfUpAxis = undefined;
Expand All @@ -153,7 +155,6 @@ export default class Tileset3D {
this._timeSinceLoad = 0.0;
this._updatedVisibilityFrame = 0;
this._extras = undefined;
this._credits = undefined;

this._allTilesAdditive = true;
this._hasMixedContent = false;
Expand All @@ -178,9 +179,9 @@ export default class Tileset3D {
}

// Gets the tileset's asset object property, which contains metadata about the tileset.
get asset() {
return this._asset;
}
// get asset() {
// return this._asset;
// }

// Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.
get properties() {
Expand Down Expand Up @@ -306,29 +307,30 @@ export default class Tileset3D {

// eslint-disable-next-line max-statements
_initializeTileSet(tilesetJson, options) {
const asset = tilesetJson.asset;
if (!asset) {
this.asset = tilesetJson.asset;
if (!this.asset) {
throw new Error('Tileset must have an asset property.');
}
if (asset.version !== '0.0' && asset.version !== '1.0') {
if (this.asset.version !== '0.0' && this.asset.version !== '1.0') {
throw new Error('The tileset must be 3D Tiles version 0.0 or 1.0.');
}

// Note: `asset.tilesetVersion` is version of the tileset itself (not the version of the 3D TILES standard)
// We add this version as a query param to fetch the right version and not get an older cached version
if ('tilesetVersion' in asset) {
this._queryParams.v = asset.tilesetVersion;
// We add this version as a `v=1.0` query param to fetch the right version and not get an older cached version
if ('tilesetVersion' in this.asset) {
this._queryParams.v = this.asset.tilesetVersion;
}

this._asset = tilesetJson.asset;
// TODO - ion resources have a credits property we can use for additional attribution.
this.credits = {
attributions: options.attributions || []
};

this._properties = tilesetJson.properties;
this.geometricError = tilesetJson.geometricError;
this._extensionsUsed = tilesetJson.extensionsUsed;
this._extras = tilesetJson.extras;

// TODO - ion resources have a credits property we can use for additional attribution.
this._credits = {}; // resource.credits;

// TODO - handle configurable glTF up axis
// const gltfUpAxis = defined(tilesetJson.asset.gltfUpAxis)
// ? Axis.fromName(tilesetJson.asset.gltfUpAxis)
Expand Down

0 comments on commit 9ffea1b

Please sign in to comment.