Skip to content

Commit

Permalink
Merge 0fd8180 into c20ba58
Browse files Browse the repository at this point in the history
  • Loading branch information
Xintong Xia committed Apr 29, 2019
2 parents c20ba58 + 0fd8180 commit 97aba00
Show file tree
Hide file tree
Showing 15 changed files with 1,791 additions and 67 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module.exports = {
parserOptions: {
ecmaVersion: 2018
},
extends: ['eslint-config-uber-es2015', 'prettier'],
plugins: ['react'],
extends: ['uber-jsx', 'eslint-config-uber-es2015', 'prettier', 'prettier/react'],
rules: {
'guard-for-in': 0,
'generator-star-spacing': 0,
Expand Down
136 changes: 100 additions & 36 deletions examples/3d-tiles/app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable no-unused-vars */
/* global fetch */
import React, {PureComponent} from 'react';
import {render} from 'react-dom';
import DeckGL, {COORDINATE_SYSTEM, PointCloudLayer, OrbitView, LinearInterpolator} from 'deck.gl';

import {Tile3DLoader} from '@loaders.gl/3d-tiles';
import {load, registerLoaders} from '@loaders.gl/core';

import ControlPanel from './control-panel';

function parseSync(arrayBuffer, options, url, loader) {
const result = Tile3DLoader.parseSync(arrayBuffer, options, url, loader);
return result;
Expand All @@ -20,7 +22,8 @@ export const MeshTile3DLoader = {

registerLoaders(MeshTile3DLoader);

const PNTS_URL = `./PointCloudNormals/PointCloudNormals.pnts`;
// eslint-disable-next-line no-undef
const INDEX_FILE = `${DATA_URI}/modules/3d-tiles/test/data/index.json`;

const INITIAL_VIEW_STATE = {
target: [0, 0, 0],
Expand Down Expand Up @@ -58,17 +61,30 @@ export class App extends PureComponent {

this.state = {
viewState: INITIAL_VIEW_STATE,
pointsCount: 0,
constantRGBA: null,
colors: null,
positions: null
tile: null,
example: 'PointCloudNormals',
category: 'PointCloud'
};

this._deckRef = null;

this._onLoad = this._onLoad.bind(this);
this._onViewStateChange = this._onViewStateChange.bind(this);
this._rotateCamera = this._rotateCamera.bind(this);

load(PNTS_URL).then(this._onLoad);
this._loadExample = this._loadExample.bind(this);
this._onSelectExample = this._onSelectExample.bind(this);
}

componentDidMount() {
// fetch index file
fetch(INDEX_FILE)
.then(resp => resp.json())
.then(data => {
this.setState({data});
const {category, example} = this.state;
this._loadExample(category, example);
});
}

_onViewStateChange({viewState}) {
Expand All @@ -88,8 +104,18 @@ export class App extends PureComponent {
});
}

_onLoad({positions, colors, normals, constantRGBA, featureTableJson}) {
const {mins, maxs} = getDataRange(positions);
_loadExample(category, example) {
const {data} = this.state;
if (data && category && example) {
const selectedExample = data[category].examples[example];
// eslint-disable-next-line no-undef
const url = `${DATA_URI}/${selectedExample.path}/${selectedExample.files[0]}`;
load(url).then(this._onLoad);
}
}

_onLoad(tile) {
const {mins, maxs} = getDataRange(tile.positions);
let {viewState} = this.state;

if (mins && maxs) {
Expand All @@ -102,51 +128,72 @@ export class App extends PureComponent {
};
}

tile.pointsCount = tile.featureTableJson.POINTS_LENGTH;
this.setState(
{
pointsCount: featureTableJson.POINTS_LENGTH,
positions,
colors,
constantRGBA,
normals,
tile,
viewState
},
this._rotateCamera
);
}

_getColor({index, data, target}) {
const {colors, isRGB565, constantRGBA, batchTable, batchIds} = this.state.tile;
if (colors) {
if (isRGB565) {
const color16 = data.colors.value[index];
const r5 = color16 & 31;
const g6 = (color16 >> 5) & 63;
const b5 = (color16 >> 11) & 31;
target[0] = Math.round((r5 * 255) / 32);
target[1] = Math.round((g6 * 255) / 64);
target[2] = Math.round((b5 * 255) / 32);
target[3] = 255;
} else {
target[0] = data.colors.value[index * 3];
target[1] = data.colors.value[index * 3 + 1];
target[2] = data.colors.value[index * 3 + 2];
target[3] = data.colors.size === 4 ? data.colors[index * 3 + 4] : 255;
}

return target;
}

if (constantRGBA) {
return constantRGBA;
}

if (batchIds) {
const batchId = batchIds[index];
// TODO figure out what is `dimensions` used for
const dimensions = batchTable.getProperty(batchId, 'dimensions');
const color = dimensions.map(d => d * 255);
return [...color, 255];
}

return [255, 255, 255];
}

_renderLayers() {
const {pointsCount, positions, colors, constantRGBA, normals} = this.state;
if (!this.state.tile) {
return null;
}
const {pointsCount, positions, colors, normals} = this.state.tile;

return (
positions &&
new PointCloudLayer({
data: {
positions: {value: positions, size: 3},
colors: {value: positions, size: 4},
colors: {value: colors, size: 4},
normals: {value: positions, size: 3},
length: positions.length / 3
},
id: '3d-point-cloud-layer',
coordinateSystem: COORDINATE_SYSTEM.IDENTITY,
numInstances: pointsCount,
getPosition: (object, {index, data, target}) => {
target[0] = data.positions.value[index * 3];
target[1] = data.positions.value[index * 3 + 1];
target[2] = data.positions.value[index * 3 + 2];
return target;
},
getColor: colors
? (object, {index, data, target}) => {
target[0] = data.colors.value[index * 3];
target[1] = data.colors.value[index * 3 + 1];
target[2] = data.colors.value[index * 3 + 2];
target[3] = data.colors.size === 4 ? data.colors[index * 3 + 4] : 255;
return target;
}
: constantRGBA
? constantRGBA
: [255, 255, 255],
instancePositions: positions,
getColor: (object, {index, data, target}) => this._getColor({index, data, target}),
getNormal: normals
? (object, {index, data, target}) => {
target[0] = data.normals[index * 3];
Expand All @@ -161,11 +208,21 @@ export class App extends PureComponent {
);
}

_onSelectExample({category, example}) {
this.setState({category, example}, () => {
const {data} = this.state;
if (data && category && example) {
this._loadExample(category, example);
}
});
}

render() {
const {viewState} = this.state;
const {viewState, data, example, category} = this.state;

return (
<DeckGL
ref={_ => (this._deckRef = _)}
views={new OrbitView()}
viewState={viewState}
controller={true}
Expand All @@ -174,7 +231,14 @@ export class App extends PureComponent {
parameters={{
clearColor: [0.07, 0.14, 0.19, 1]
}}
/>
>
<ControlPanel
data={data}
category={category}
example={example}
onChange={this._onSelectExample}
/>
</DeckGL>
);
}
}
Expand Down
22 changes: 22 additions & 0 deletions examples/3d-tiles/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

module.exports = function babelConfig(api) {
api.cache(() => process.env.NODE_ENV === 'production'); // eslint-disable-line

return {
presets: ['@babel/preset-env'],
plugins: [['@babel/plugin-proposal-class-properties', {loose: false}]]
};
};
58 changes: 58 additions & 0 deletions examples/3d-tiles/control-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import styled from 'styled-components';
import React, {PureComponent} from 'react';

const Container = styled.div`
display: flex;
flex-direction: column;
position: absolute;
top: 0;
right: 0;
max-width: 320px;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
padding: 12px 24px;
margin: 20px;
font-size: 13px;
line-height: 2;
color: #6b6b76;
text-transform: uppercase;
outline: none;
z-index: 100;
`;

export default class ControlPanel extends PureComponent {
_renderByCategories() {
const {category, example, onChange, data} = this.props;
const categories = Object.keys(data);

return (
<select
defaultValue={`${category}.${example}`}
onChange={evt => {
const categoryExample = evt.target.value;
const value = categoryExample.split('.');
onChange({category: value.category, example: value.example});
}}
>
{categories.map((c, i) => {
const categoryExamples = data[c].examples;
return (
<optgroup key={i} label={c}>
{Object.keys(categoryExamples).map((e, j) => {
return (
<option key={j} value={`${c}.${e}`}>
{e}
</option>
);
})}
</optgroup>
);
})}
</select>
);
}

render() {
return <Container>{this._renderByCategories()}</Container>;
}
}
43 changes: 43 additions & 0 deletions examples/3d-tiles/generate-index/args.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const {ArgumentParser} = require('argparse');

const parser = new ArgumentParser({
addHelp: true,
description: 'Data converter'
});

parser.addArgument(['-i', '--input'], {
required: true,
help: 'Path to raw data.'
});

parser.addArgument(['-o', '--output'], {
required: true,
help: 'Path to generated index file.'
});

// extract args from user input
module.exports = function getArgs() {
const args = parser.parseArgs();
const inputDir = args.input;
const outputFilePath = args.output;

console.log(inputDir, outputFilePath); // eslint-disable-line
return {
inputDir,
outputFilePath
};
};
7 changes: 7 additions & 0 deletions examples/3d-tiles/generate-index/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require('@babel/register');
require('babel-polyfill');

const args = require('./args');
const main = require('./main');

main(args());
33 changes: 33 additions & 0 deletions examples/3d-tiles/generate-index/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import fs from 'fs';
import path from 'path';

function main({inputDir, outputFilePath}) {
const indexMap = {};
const categories = fs.readdirSync(inputDir);
categories.forEach(cat => {
const catDir = path.join(inputDir, cat);
if (fs.lstatSync(catDir).isDirectory()) {
const examples = fs.readdirSync(catDir);
indexMap[cat] = {
name: cat,
path: catDir,
examples: examples.reduce((resMap, e) => {
const exampleDir = path.join(catDir, e);
if (fs.lstatSync(exampleDir).isDirectory()) {
const files = fs.readdirSync(exampleDir);
resMap[e] = {
name: e,
path: exampleDir,
files
};
}
return resMap;
}, {})
};
}
});

fs.writeFileSync(outputFilePath, JSON.stringify(indexMap, null, 2));
}

module.exports = main;
Loading

0 comments on commit 97aba00

Please sign in to comment.