Skip to content

Commit 3063925

Browse files
committed
doc(tutorials): Improve tutorial and add two tutorials for 3D tiles
1 parent 9ee991c commit 3063925

15 files changed

+704
-102
lines changed

docs/config.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
"FileSource",
7070
"OrientedImageSource",
7171
"PotreeSource",
72-
"VectorTilesSource"
72+
"VectorTilesSource",
73+
"EntwinePointTileSource"
7374
],
7475

7576
"Provider": [
@@ -158,6 +159,14 @@
158159
"Vector-data-on-ground": {
159160
"sectionTitle": "Vector visualization",
160161
"sectionId": 2
162+
},
163+
"3DTiles-mesh-b3dm": {
164+
"sectionTitle": "3D Tiles visualization",
165+
"sectionId": 3
166+
},
167+
"3DTiles-point-cloud-pnts": {
168+
"sectionTitle": "3D Tiles visualization",
169+
"sectionId": 3
161170
}
162171
}
163172
},

docs/tutorials/3DTiles-mesh-b3dm.md

+279
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
The goal of this tutorial is to learn how to visualize 3D tiles textured mesh data (in the b3dm format).
2+
We will use a [data set](https://github.com/iTowns/iTowns2-sample-data/tree/master/3DTiles/lyon_1_3946_textured_draco) representing buildings of the 1st borrough of Lyon.
3+
The original data are openly available on [Lyon metropolis open data](https://data.grandlyon.com/) and have been transformed in 3D tiles with [py3dtilers](https://github.com/VCityTeam/py3dtilers/).
4+
5+
## Preparing the webpage
6+
7+
The webpage we want to display data on should be structured as follows :
8+
```html
9+
<!DOCTYPE html>
10+
<html>
11+
<head>
12+
<meta charset="UTF-8">
13+
<title>Display 3D Tiles b3dm dataset with iTowns</title>
14+
<style>
15+
html { height: 100%; }
16+
body { margin: 0; overflow: hidden; height: 100%; }
17+
#viewerDiv { margin: auto; height: 100%; width: 100%; padding: 0; }
18+
canvas { display: block }
19+
</style>
20+
</head>
21+
<body>
22+
<div id="viewerDiv"></div>
23+
<script src="../dist/itowns.js"></script>
24+
<script type="text/javascript">
25+
// Tutorial code should go here
26+
</script>
27+
</body>
28+
</html>
29+
```
30+
31+
To work as is, this web page should be placed in the `examples/` folder of [itowns](https://github.com/iTowns/itowns) but you can put it anywhere else as
32+
long as you have a local web server and that you adapt the link to itowns (`<script src="../dist/itowns.js"></script>`).
33+
34+
35+
## Preparing the field
36+
37+
We will first create a view, add a layer with ortho images and a digital elevation model (DEM).
38+
The 3D Tiles dataset we are using is in the `EPSG:3946` CRS, so we will use a `{@link PlanarView}` in this CRS to display it.
39+
40+
We won't go into the details of creating the view, adding the ortho images and the DEM. For more information on this part, see the [Raster visualization in Lambert Conformical conic projection]{@tutorial Raster-data-Lambert93} in which we do the same but in the `EPSG:2154` projection. You can use the following code that prepared the field with such data:
41+
42+
```js
43+
// Define crs projection that we will use (taken from https://epsg.io/3946, Proj4js section)
44+
itowns.proj4.defs('EPSG:3946',
45+
'+proj=lcc +lat_1=45.25 +lat_2=46.75 +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80' +
46+
'+towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
47+
48+
// Define geographic extent: CRS, min/max X, min/max Y
49+
var extent = new itowns.Extent( 'EPSG:3946',
50+
1837816.94334, 1847692.32501,
51+
5170036.4587, 5178412.82698);
52+
53+
// `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
54+
var viewerDiv = document.getElementById('viewerDiv');
55+
56+
// Instanciate PlanarView*
57+
var cameraCoord = new itowns.Coordinates('EPSG:3946', 1841980,
58+
5175682, 3000)
59+
var view = new itowns.PlanarView(viewerDiv, extent, { placement: {
60+
coord: cameraCoord, heading: 30, range: 4000, tilt: 30 } });
61+
62+
// Add a WMS imagery source
63+
var wmsImagerySource = new itowns.WMSSource({
64+
extent: extent,
65+
name: 'Ortho2009_vue_ensemble_16cm_CC46',
66+
url: 'https://download.data.grandlyon.com/wms/grandlyon',
67+
version: '1.3.0',
68+
crs: 'EPSG:3946',
69+
format: 'image/jpeg',
70+
});
71+
72+
// Add a WMS imagery layer
73+
var wmsImageryLayer = new itowns.ColorLayer('wms_imagery', {
74+
updateStrategy: {
75+
type: itowns.STRATEGY_DICHOTOMY,
76+
options: {},
77+
},
78+
source: wmsImagerySource,
79+
});
80+
81+
view.addLayer(wmsImageryLayer);
82+
83+
// Add a WMS elevation source
84+
var wmsElevationSource = new itowns.WMSSource({
85+
extent: extent,
86+
url: 'https://download.data.grandlyon.com/wms/grandlyon',
87+
name: 'MNT2012_Altitude_10m_CC46',
88+
crs: 'EPSG:3946',
89+
width: 256,
90+
format: 'image/jpeg',
91+
});
92+
93+
// Add a WMS elevation layer
94+
var wmsElevationLayer = new itowns.ElevationLayer('wms_elevation', {
95+
useColorTextureElevation: true,
96+
colorTextureElevationMinZ: 144,
97+
colorTextureElevationMaxZ: 622,
98+
source: wmsElevationSource,
99+
});
100+
101+
view.addLayer(wmsElevationLayer);
102+
```
103+
104+
## Adding the 3D Tiles Layer
105+
106+
The 3D Tiles dataset we are using in this example has a geometry that is compressed with
107+
[Draco compression](https://google.github.io/draco/) for better performances. Therefore, we need to enable the draco
108+
decoder:
109+
110+
```js
111+
itowns.enableDracoLoader('./libs/draco/');
112+
```
113+
114+
As for every data displayed in iTowns, we first need to define a data `Source`.
115+
Our data is in the 3d-tiles format, so we can use iTowns `{@link C3DTilesSource}` :
116+
117+
```js
118+
const buildingsSource = new itowns.C3DTilesSource({
119+
url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/' +
120+
'3DTiles/lyon_1_3946_textured_draco/tileset.json',
121+
});
122+
```
123+
124+
It is worth noting that the 3d-tiles data we want to display on a given `{@link View}` must be in the same Coordinates
125+
Reference System (CRS) as the `{@link View}`.
126+
Here, our 3d-tiles data are in [RGF93 / CC46](https://epsg.io/3946) projection, just like our `{@link PlanarView}`.
127+
This is the reason why we do not need to specify a `crs` parameter when instantiating our `{@link C3DTilesSource}`.
128+
129+
Now that the source of our data is set, we need to create a `{@link Layer}` which will contain the data.
130+
To display 3d-tiles data, iTowns comes with a `{@link C3DTilesLayer}`, which we can use as such :
131+
132+
```js
133+
const buildingsLayer = new itowns.C3DTilesLayer('buildings', {
134+
source: buildingsSource,
135+
}, view);
136+
itowns.View.prototype.addLayer.call(view, buildingsLayer);
137+
```
138+
139+
When instantiating a `{@link C3DTilesLayer}`, we need to specify which `{@link View}` it is added to.
140+
We also need to call the generic `addLayer` method from `{@link View}`, and not the specific one from
141+
`{@link PlanarView}`.
142+
This is because both 3d-tiles data and `{@link PlanarView}` have their own spatial subdivision.
143+
Therefore, 3d-tiles data must not use specific `{@link PlanarView}` spatial subdivision (which is by default the case when using the `addLayer` method of `PlanarView` or `GlobeView`).
144+
145+
The code above results in the following :
146+
147+
![3D Tiles b3dm mesh without lights](images/3DTiles-mesh-b3dm-1.png)
148+
149+
We can see our buildings, but they are all black.
150+
In order to improve their visualisation, we can add light effects to our view.
151+
152+
## Add light effects
153+
154+
We can use ThreeJS [`DirectionalLight`](https://threejs.org/docs/index.html#api/en/lights/DirectionalLight) and
155+
[`AmbientLight`](https://threejs.org/docs/index.html#api/en/lights/AmbientLight) to add light effects to our view.
156+
We just need to implement them as we would in any [ThreeJS](https://threejs.org/) application :
157+
158+
```js
159+
const directionalLight = new itowns.THREE.DirectionalLight(0xffffff, 1);
160+
directionalLight.position.set(-0.9, 0.3, 1);
161+
directionalLight.updateMatrixWorld();
162+
view.scene.add(directionalLight);
163+
164+
const ambientLight = new itowns.THREE.AmbientLight(0xffffff, 1);
165+
view.scene.add(ambientLight);
166+
```
167+
168+
We can now see our buildings with some light effects :
169+
170+
![3D Tiles b3dm mesh](images/3DTiles-mesh-b3dm-2.png)
171+
172+
## Result
173+
174+
By reaching here, you are now able to display some mesh data in 3d-tiles format.
175+
The final code to do so is the following :
176+
177+
```html
178+
<!DOCTYPE html>
179+
<html>
180+
<head>
181+
<meta charset="UTF-8">
182+
<title>Display 3D Tiles b3dm dataset with iTowns</title>
183+
<style>
184+
html { height: 100%; }
185+
body { margin: 0; overflow: hidden; height: 100%; }
186+
#viewerDiv { margin: auto; height: 100%; width: 100%; padding: 0; }
187+
canvas { display: block }
188+
</style>
189+
</head>
190+
<body>
191+
<div id="viewerDiv"></div>
192+
<script src="../dist/itowns.js"></script>
193+
<script type="text/javascript">
194+
// Define crs projection that we will use (taken from https://epsg.io/3946, Proj4js section)
195+
itowns.proj4.defs('EPSG:3946',
196+
'+proj=lcc +lat_1=45.25 +lat_2=46.75 +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80' +
197+
'+towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
198+
199+
// Define geographic extent: CRS, min/max X, min/max Y
200+
var extent = new itowns.Extent( 'EPSG:3946',
201+
1837816.94334, 1847692.32501,
202+
5170036.4587, 5178412.82698);
203+
204+
// `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
205+
var viewerDiv = document.getElementById('viewerDiv');
206+
207+
// Instanciate PlanarView*
208+
var cameraCoord = new itowns.Coordinates('EPSG:3946', 1841980,
209+
5175682, 3000)
210+
var view = new itowns.PlanarView(viewerDiv, extent, { placement: {
211+
coord: cameraCoord, heading: 30, range: 4000, tilt: 30 } });
212+
213+
// Add a WMS imagery source
214+
var wmsImagerySource = new itowns.WMSSource({
215+
extent: extent,
216+
name: 'Ortho2009_vue_ensemble_16cm_CC46',
217+
url: 'https://download.data.grandlyon.com/wms/grandlyon',
218+
version: '1.3.0',
219+
crs: 'EPSG:3946',
220+
format: 'image/jpeg',
221+
});
222+
223+
// Add a WMS imagery layer
224+
var wmsImageryLayer = new itowns.ColorLayer('wms_imagery', {
225+
updateStrategy: {
226+
type: itowns.STRATEGY_DICHOTOMY,
227+
options: {},
228+
},
229+
source: wmsImagerySource,
230+
});
231+
232+
view.addLayer(wmsImageryLayer);
233+
234+
// Add a WMS elevation source
235+
var wmsElevationSource = new itowns.WMSSource({
236+
extent: extent,
237+
url: 'https://download.data.grandlyon.com/wms/grandlyon',
238+
name: 'MNT2012_Altitude_10m_CC46',
239+
crs: 'EPSG:3946',
240+
width: 256,
241+
format: 'image/jpeg',
242+
});
243+
244+
// Add a WMS elevation layer
245+
var wmsElevationLayer = new itowns.ElevationLayer('wms_elevation', {
246+
useColorTextureElevation: true,
247+
colorTextureElevationMinZ: 144,
248+
colorTextureElevationMaxZ: 622,
249+
source: wmsElevationSource,
250+
});
251+
252+
view.addLayer(wmsElevationLayer);
253+
254+
// Add 3D Tiles layer
255+
// This 3D Tiles tileset uses the draco compression that is an
256+
// extension of gltf. We need to enable it.
257+
itowns.enableDracoLoader('./libs/draco/');
258+
259+
const buildingsSource = new itowns.C3DTilesSource({
260+
url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/' +
261+
'master/3DTiles/lyon_1_3946_textured_draco/tileset.json',
262+
});
263+
264+
const buildingsLayer = new itowns.C3DTilesLayer('buildings', {
265+
source: buildingsSource,
266+
}, view);
267+
itowns.View.prototype.addLayer.call(view, buildingsLayer);
268+
269+
const directionalLight = new itowns.THREE.DirectionalLight(0xffffff, 1);
270+
directionalLight.position.set(-0.9, 0.3, 1);
271+
directionalLight.updateMatrixWorld();
272+
view.scene.add(directionalLight);
273+
274+
const ambientLight = new itowns.THREE.AmbientLight(0xffffff, 1);
275+
view.scene.add(ambientLight);
276+
</script>
277+
</body>
278+
</html>
279+
```

0 commit comments

Comments
 (0)