Skip to content

Commit

Permalink
Initial samples
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Aug 4, 2016
1 parent 7e68220 commit 3d8df8b
Show file tree
Hide file tree
Showing 32 changed files with 723 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
# NPM
node_modules
npm-debug.log

# WebStorm user-specific
.idea
9 changes: 9 additions & 0 deletions LICENSE.md
@@ -0,0 +1,9 @@
Copyright 2016-2016 Analytical Graphics, Inc. and Contributors

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.

See the `README.txt` in each tileset's directory for usage restrictions.
39 changes: 39 additions & 0 deletions README.md
@@ -1,2 +1,41 @@
# 3d-tiles-samples
Sample tilesets for learning how to use 3D Tiles :books:

## Instructions

Clone this repo and install [Node.js](http://nodejs.org/). From the root directory of this repo, run:
```
npm install
```

Then to host the tilesets locally, run:
```
npm start
```

The tilesets are hosted at `http://localhost:8003/tilesets/`.

To load a tileset within Cesium:
```
var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url : 'http://localhost:8003/tilesets/TilesetWithDiscreteLOD/'
}));
Cesium.when(tileset.readyPromise).then(function(tileset) {
viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 0));
});
```

See the `README.txt` in each tileset's directory for usage restrictions.

| Model | Screenshot | Description|
|-----------------------------------------------|-----------------------------------------------------------------------|------------|
| [Discrete LOD](tilesets/TilesetWithDiscreteLOD) | ![](tilesets/TilesetWithDiscreteLOD/screenshot/screenshot.gif) | Tileset with discrete LODs. |
| [Expiration](tilesets/TilesetWithExpiration) | ![](tilesets/TilesetWithExpiration/screenshot/screenshot.gif) | Tileset that expires and re-requests new content every five seconds. |
| [Request Volume](tilesets/TilesetWithRequestVolume) | ![](tilesets/TilesetWithRequestVolume/screenshot/screenshot.gif) | Tileset with request volumes. |
| [Tree Billboards](tilesets/TilesetWithTreeBillboards) | ![](tilesets/TilesetWithTreeBillboards/screenshot/screenshot.gif) | Tileset that combines instanced 3D models and billboards. |

## Contributions

Pull requests are appreciated! Please use the same [Contributor License Agreement (CLA)](https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTING.md) and [Coding Guide](https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Documentation/Contributors/CodingGuide/README.md) used for [Cesium](http://cesiumjs.org/).
2 changes: 2 additions & 0 deletions index.js
@@ -0,0 +1,2 @@
module.exports = {
};
36 changes: 36 additions & 0 deletions package.json
@@ -0,0 +1,36 @@
{
"name": "3d-tiles-samples",
"version": "0.1.0",
"license": "Apache-2.0",
"description": "Sample tilesets for learning how to use 3D Tiles.",
"author": {
"name": "Analytical Graphics, Inc. and Contributors"
},
"keywords": [
"3D Tiles"
],
"homepage": "https://github.com/AnalyticalGraphicsInc/3d-tiles-samples",
"repository": {
"type": "git",
"url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-samples.git"
},
"bugs": {
"url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-samples/issues"
},
"main": "index.js",
"engines": {
"node": ">=4.0.0"
},
"dependencies": {
"async": "2.0.1",
"cesium": "1.24.0",
"compression": "1.6.2",
"express": "4.14.x",
"nodemon": "1.10.0",
"request": "2.74.0",
"yargs": "4.8.1"
},
"scripts": {
"start": "nodemon --watch bin --watch lib --watch index.js server.js"
}
}
169 changes: 169 additions & 0 deletions server.js
@@ -0,0 +1,169 @@
(function() {
'use strict';
/*global console,require,__dirname,process*/
/*jshint es3:false*/

var express = require('express');
var compression = require('compression');
var url = require('url');
var request = require('request');

var yargs = require('yargs').options({
'port' : {
'default' : process.env.PORT || 8003,
'description' : 'Port to listen on.'
},
'public' : {
'type' : 'boolean',
'description' : 'Run a public server that listens on all interfaces.'
},
'upstream-proxy' : {
'description' : 'A standard proxy server that will be used to retrieve data. Specify a URL including port, e.g. "http://proxy:8000".'
},
'bypass-upstream-proxy-hosts' : {
'description' : 'A comma separated list of hosts that will bypass the specified upstream_proxy, e.g. "lanhost1,lanhost2"'
},
'help' : {
'alias' : 'h',
'type' : 'boolean',
'description' : 'Show this help.'
}
});
var argv = yargs.argv;

if (argv.help) {
return yargs.showHelp();
}

// eventually this mime type configuration will need to change
// https://github.com/visionmedia/send/commit/d2cb54658ce65948b0ed6e5fb5de69d022bef941
var mime = express.static.mime;
mime.define({
'application/json' : ['czml', 'json', 'geojson', 'topojson'],
'model/vnd.gltf+json' : ['gltf'],
'model/vnd.gltf.binary' : ['glb'],
'application/octet-stream' : ['b3dm', 'pnts', 'i3dm', 'cmpt'],
'text/plain' : ['glsl']
});

var app = express();
app.use(compression());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.static(__dirname));

function getRemoteUrlFromParam(req) {
var remoteUrl = req.params[0];
if (remoteUrl) {
// add http:// to the URL if no protocol is present
if (!/^https?:\/\//.test(remoteUrl)) {
remoteUrl = 'http://' + remoteUrl;
}
remoteUrl = url.parse(remoteUrl);
// copy query string
remoteUrl.search = url.parse(req.url).search;
}
return remoteUrl;
}

var dontProxyHeaderRegex = /^(?:Host|Proxy-Connection|Connection|Keep-Alive|Transfer-Encoding|TE|Trailer|Proxy-Authorization|Proxy-Authenticate|Upgrade)$/i;

function filterHeaders(req, headers) {
var result = {};
// filter out headers that are listed in the regex above
Object.keys(headers).forEach(function(name) {
if (!dontProxyHeaderRegex.test(name)) {
result[name] = headers[name];
}
});
return result;
}

var upstreamProxy = argv['upstream-proxy'];
var bypassUpstreamProxyHosts = {};
if (argv['bypass-upstream-proxy-hosts']) {
argv['bypass-upstream-proxy-hosts'].split(',').forEach(function(host) {
bypassUpstreamProxyHosts[host.toLowerCase()] = true;
});
}

app.get('/proxy/*', function(req, res, next) {
// look for request like http://localhost:8080/proxy/http://example.com/file?query=1
var remoteUrl = getRemoteUrlFromParam(req);
if (!remoteUrl) {
// look for request like http://localhost:8080/proxy/?http%3A%2F%2Fexample.com%2Ffile%3Fquery%3D1
remoteUrl = Object.keys(req.query)[0];
if (remoteUrl) {
remoteUrl = url.parse(remoteUrl);
}
}

if (!remoteUrl) {
return res.send(400, 'No url specified.');
}

if (!remoteUrl.protocol) {
remoteUrl.protocol = 'http:';
}

var proxy;
if (upstreamProxy && !(remoteUrl.host in bypassUpstreamProxyHosts)) {
proxy = upstreamProxy;
}

// encoding : null means "body" passed to the callback will be raw bytes

request.get({
url : url.format(remoteUrl),
headers : filterHeaders(req, req.headers),
encoding : null,
proxy : proxy
}, function(error, response, body) {
var code = 500;

if (response) {
code = response.statusCode;
res.header(filterHeaders(req, response.headers));
}

res.send(code, body);
});
});

var server = app.listen(argv.port, argv.public ? undefined : 'localhost', function() {
if (argv.public) {
console.log('Cesium development server running publicly. Connect to http://localhost:%d/', server.address().port);
} else {
console.log('Cesium development server running locally. Connect to http://localhost:%d/', server.address().port);
}
});

server.on('error', function (e) {
if (e.code === 'EADDRINUSE') {
console.log('Error: Port %d is already in use, select a different port.', argv.port);
console.log('Example: node server.js --port %d', argv.port + 1);
} else if (e.code === 'EACCES') {
console.log('Error: This process does not have permission to listen on port %d.', argv.port);
if (argv.port < 1024) {
console.log('Try a port number higher than 1024.');
}
}
console.log(e);
process.exit(1);
});

server.on('close', function() {
console.log('Cesium development server stopped.');
});

process.on('SIGINT', function() {
server.close(function() {
process.exit(0);
});
});

})();

14 changes: 14 additions & 0 deletions tilesets/TilesetWithDiscreteLOD/README.md
@@ -0,0 +1,14 @@
# Tileset with discrete LODs
## Description
The tileset contains three tiles each with a different decimation of the Stanford Dragon mesh.
* Root tile - highly decimated dragon
* Child tile - medium decimated dragon
* Grandchild tile - original dragon

When a tile's screen space error is met, it is replaced it's higher LOD child.

When running in Cesium, use the `3d-tiles-transform` branch.

## Screenshot

![screenshot](screenshot/screenshot.gif)
Binary file added tilesets/TilesetWithDiscreteLOD/dragon_high.b3dm
Binary file not shown.
Binary file added tilesets/TilesetWithDiscreteLOD/dragon_low.b3dm
Binary file not shown.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions tilesets/TilesetWithDiscreteLOD/tileset.json
@@ -0,0 +1,95 @@
{
"asset": {
"version": "0.0"
},
"geometricError": 500,
"root": {
"transform": [
96.86356343768793,
24.848542777253734,
0,
0,
-15.986465724980844,
62.317780594908875,
76.5566922962899,
0,
19.02322243409411,
-74.15554020821229,
64.3356267137516,
0,
1215107.7612304366,
-4736682.902037748,
4081926.095098698,
1
],
"boundingVolume": {
"box": [
0,
0,
0,
14.191,
0,
0,
0,
6.281,
0,
0,
0,
10.075
]
},
"geometricError": 100,
"refine": "replace",
"content": {
"url": "dragon_low.b3dm"
},
"children": [
{
"boundingVolume": {
"box": [
0,
0,
0,
14.191,
0,
0,
0,
6.281,
0,
0,
0,
10.075
]
},
"geometricError": 10,
"content": {
"url": "dragon_medium.b3dm"
},
"children": [
{
"boundingVolume": {
"box": [
0,
0,
0,
14.191,
0,
0,
0,
6.281,
0,
0,
0,
10.075
]
},
"geometricError": 0,
"content": {
"url": "dragon_high.b3dm"
}
}
]
}
]
}
}
9 changes: 9 additions & 0 deletions tilesets/TilesetWithExpiration/README.md
@@ -0,0 +1,9 @@
# Tileset with expiration
## Description
The tileset contains a single tile with `expire.duration` set to five seconds.

This sample currently runs on an experimental branch with a custom `server.js`. This sample will be updated to account for these soon.

## Screenshot

![screenshot](screenshot/screenshot.gif)
Binary file added tilesets/TilesetWithExpiration/points.pnts
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3d8df8b

Please sign in to comment.