├── LICENSE.md
├── README.md
├── figures
├── Cesium3DTiles.png
└── cesium.png
├── samples-generator
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .idea
│ ├── 3d-tiles-samples-generator.iml
│ ├── encodings.xml
│ ├── jsLibraryMappings.xml
│ ├── jsLinters
│ │ └── jshint.xml
│ ├── libraries
│ │ └── TypeScriptDefinitions.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── vcs.xml
├── .npmignore
├── .npmrc
├── CHANGES.md
├── LICENSE.md
├── README.md
├── bin
│ └── 3d-tiles-samples-generator.js
├── data
│ ├── box.glb
│ ├── building.glb
│ ├── dragon_high.glb
│ ├── dragon_low.glb
│ ├── dragon_medium.glb
│ ├── house
│ │ ├── door0.gltf
│ │ ├── door1.gltf
│ │ ├── door2.gltf
│ │ ├── door3.gltf
│ │ ├── doorknob0.gltf
│ │ ├── doorknob1.gltf
│ │ ├── doorknob2.gltf
│ │ ├── doorknob3.gltf
│ │ ├── roof.gltf
│ │ └── wall.gltf
│ ├── red_box.glb
│ ├── textured_box.glb
│ ├── textured_box_separate
│ │ ├── Cesium_Logo_Flat.png
│ │ └── textured_box.glb
│ ├── tree.glb
│ ├── tree_billboard.glb
│ └── wood_red.jpg
├── gulpfile.js
├── index.js
├── lib
│ ├── Extensions.js
│ ├── Material.js
│ ├── Mesh.js
│ ├── createB3dm.js
│ ├── createBatchTableHierarchy.js
│ ├── createBuildings.js
│ ├── createBuildingsTile.js
│ ├── createCmpt.js
│ ├── createGltf.js
│ ├── createI3dm.js
│ ├── createInstancesTile.js
│ ├── createPnts.js
│ ├── createPointCloudTile.js
│ ├── createTilesetJsonSingle.js
│ ├── getBufferPadded.js
│ ├── getJsonBufferPadded.js
│ ├── getProperties.js
│ ├── saveTile.js
│ ├── saveTilesetJson.js
│ └── utility.js
├── package.json
└── specs
│ ├── .eslintrc.json
│ ├── bin
│ └── generatorSpec.js
│ ├── jasmine.json
│ └── matchers
│ ├── addDefaultMatchers.js
│ ├── customizeJasmine.js
│ ├── equals.js
│ ├── equalsMethodEqualityTester.js
│ ├── expectPromise.js
│ └── nodeHelper.js
├── tools
├── .eslintignore
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .idea
│ ├── encodings.xml
│ ├── jsLibraryMappings.xml
│ ├── jsLinters
│ │ └── jshint.xml
│ ├── modules.xml
│ ├── tools.iml
│ └── vcs.xml
├── .npmignore
├── .npmrc
├── .travis.yml
├── CHANGES.md
├── LICENSE.md
├── README.md
├── bin
│ └── 3d-tiles-tools.js
├── gulpfile.js
├── index.js
├── lib
│ ├── bufferToJson.js
│ ├── combineTileset.js
│ ├── databaseToTileset.js
│ ├── directoryExists.js
│ ├── extractB3dm.js
│ ├── extractCmpt.js
│ ├── extractI3dm.js
│ ├── fileExists.js
│ ├── getBufferPadded.js
│ ├── getDefaultWriteCallback.js
│ ├── getFilesInDirectory.js
│ ├── getJsonBufferPadded.js
│ ├── getMagic.js
│ ├── getWorkingDirectory.js
│ ├── glbToB3dm.js
│ ├── glbToI3dm.js
│ ├── gzipTileset.js
│ ├── isGzipped.js
│ ├── isGzippedFile.js
│ ├── isJson.js
│ ├── isTile.js
│ ├── makeCompositeTile.js
│ ├── optimizeGlb.js
│ ├── readFile.js
│ ├── runPipeline.js
│ ├── tilesetToDatabase.js
│ ├── upgradeTileset.js
│ └── walkDirectory.js
├── package.json
├── specs
│ ├── .eslintrc.json
│ ├── data
│ │ ├── BatchedDeprecated1
│ │ │ ├── batchedDeprecated1.b3dm
│ │ │ └── tileset.json
│ │ ├── BatchedDeprecated2
│ │ │ ├── batchedDeprecated2.b3dm
│ │ │ └── tileset.json
│ │ ├── CesiumTexturedBox
│ │ │ └── CesiumTexturedBox.glb
│ │ ├── Textured
│ │ │ ├── batchedTextured.b3dm
│ │ │ └── instancedTextured.i3dm
│ │ ├── TilesetOfTilesets
│ │ │ ├── lr.b3dm
│ │ │ ├── parent.b3dm
│ │ │ ├── tileset.json
│ │ │ ├── tileset2.json
│ │ │ ├── tileset3
│ │ │ │ ├── ll.b3dm
│ │ │ │ └── tileset3.json
│ │ │ ├── ul.b3dm
│ │ │ └── ur.b3dm
│ │ ├── batchedWithBatchTableBinary.b3dm
│ │ ├── composite.cmpt
│ │ ├── compositeOfComposite.cmpt
│ │ ├── instancedWithBatchTableBinary.i3dm
│ │ ├── pipeline.json
│ │ └── tileset.3dtiles
│ ├── jasmine.json
│ ├── lib
│ │ ├── combineTilesetSpec.js
│ │ ├── databaseToTilesetSpec.js
│ │ ├── extractB3dmSpec.js
│ │ ├── extractCmptSpec.js
│ │ ├── extractI3dmSpec.js
│ │ ├── glbToB3dmSpec.js
│ │ ├── glbToI3dmSpec.js
│ │ ├── gzipTilesetSpec.js
│ │ ├── makeCompositeTileSpec.js
│ │ ├── optimizeGlbSpec.js
│ │ ├── runPipelineSpec.js
│ │ ├── tilesetToDatabseSpec.js
│ │ └── upgradeTilesetSpec.js
│ └── matchers
│ │ ├── addDefaultMatchers.js
│ │ ├── customizeJasmine.js
│ │ ├── equals.js
│ │ ├── equalsMethodEqualityTester.js
│ │ ├── expectPromise.js
│ │ └── nodeHelper.js
└── tools
│ └── jsdoc
│ └── conf.json
└── validator
├── .eslintignore
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .idea
├── 3d-tiles-validator.iml
├── encodings.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── jsLibraryMappings.xml
├── jsLinters
│ └── jshint.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── .npmignore
├── .npmrc
├── .travis.yml
├── CHANGES.md
├── LICENSE.md
├── README.md
├── bin
└── 3d-tiles-validator.js
├── gulpfile.js
├── index.js
├── lib
├── isGzipped.js
└── readTile.js
├── package.json
├── specs
├── .eslintrc.json
├── data
│ └── Tileset
│ │ ├── ll.b3dm
│ │ ├── lr.b3dm
│ │ ├── parent.b3dm
│ │ ├── tileset.json
│ │ ├── ul.b3dm
│ │ └── ur.b3dm
├── jasmine.json
├── lib
│ ├── isGzippedSpec.js
│ └── readTileSpec.js
└── matchers
│ ├── addDefaultMatchers.js
│ ├── customizeJasmine.js
│ ├── equals.js
│ ├── equalsMethodEqualityTester.js
│ ├── expectPromise.js
│ └── nodeHelper.js
└── tools
└── jsdoc
└── conf.json
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 3D Tiles Tools
4 |
5 | Upcoming tools for [3D Tiles](https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/README.md) tilesets:
6 | * Manipulating tilesets, e.g., extracting glTF, gzipping, etc. See [tools/README.md](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/master/tools/README.md).
7 | * Validating that a tileset conforms to the specification. See [validator/README.md](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/master/validator/README.md).
8 | * Generate the sample tilesets in [3d-tiles-samples](https://github.com/AnalyticalGraphicsInc/3d-tiles-samples) and [Cesium](https://github.com/AnalyticalGraphicsInc/cesium). See [samples-generator/README.md](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/master/samples-generator/README.md).
9 |
10 | See the [roadmap](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/issues/1).
11 |
12 | Created by the Cesium team and University of Pennsylvania students.
13 |
14 | ## Contributions
15 |
16 | 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/).
17 |
18 | ---
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/figures/Cesium3DTiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/figures/Cesium3DTiles.png
--------------------------------------------------------------------------------
/figures/cesium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/figures/cesium.png
--------------------------------------------------------------------------------
/samples-generator/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cesium/node"
3 | }
4 |
--------------------------------------------------------------------------------
/samples-generator/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | package.json text eol=lf
--------------------------------------------------------------------------------
/samples-generator/.gitignore:
--------------------------------------------------------------------------------
1 | # NPM
2 | node_modules
3 | npm-debug.log
4 | package-lock.json
5 |
6 | # WebStorm user-specific
7 | .idea/workspace.xml
8 | .idea/tasks.xml
9 |
10 | # Generated files
11 | .nyc_output
12 | .eslintcache
13 | coverage
14 | output
15 | *.tgz
16 | *.zip
17 |
--------------------------------------------------------------------------------
/samples-generator/.idea/3d-tiles-samples-generator.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples-generator/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples-generator/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/samples-generator/.idea/jsLinters/jshint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/samples-generator/.idea/libraries/TypeScriptDefinitions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples-generator/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/samples-generator/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples-generator/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples-generator/.npmignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /output
3 | /.idea
4 | .eslintrc.json
5 | .gitattributes
6 | .npmignore
7 | gulpfile.js
8 | *.tgz
9 | *.zip
10 | .eslintcache
11 | .nyc_output
12 |
--------------------------------------------------------------------------------
/samples-generator/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/samples-generator/CHANGES.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 |
4 | ### 0.1.0 - 2017-02-07
5 |
6 | * Initial release.
7 |
--------------------------------------------------------------------------------
/samples-generator/README.md:
--------------------------------------------------------------------------------
1 | # 3D Tiles Samples Generator
2 |
3 | The tilesets generated here are included in [3d-tiles-samples](https://github.com/AnalyticalGraphicsInc/3d-tiles-samples) and [Cesium](https://github.com/AnalyticalGraphicsInc/cesium).
4 |
5 | ## Instructions
6 |
7 | Clone this repo and install [Node.js](http://nodejs.org/). From the root directory of this repo, run:
8 |
9 | ```
10 | npm install
11 |
12 | node bin/3d-tiles-samples-generator.js
13 | ```
14 |
15 | This commands generates a set of tilesets and saves them in a folder called `output`. The `Batched`, `Composite`, `Instanced`, `PointCloud`, and `Tilesets` folders may be copied directly to Cesium's `Specs/Data/Cesium3DTiles/` folder for testing with Cesium. The tilesets in the `Samples` folder may be copied to the `tilesets` folder in `3d-tiles-samples`.
16 |
17 | Run the tests:
18 | ```
19 | npm run test
20 | ```
21 | To run ESLint on the entire codebase, run:
22 | ```
23 | npm run eslint
24 | ```
25 | To run ESLint automatically when a file is saved, run the following and leave it open in a console window:
26 | ```
27 | npm run eslint-watch
28 | ```
29 |
30 | ## Contributions
31 |
32 | 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/).
33 |
34 | ---
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/samples-generator/data/box.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/box.glb
--------------------------------------------------------------------------------
/samples-generator/data/building.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/building.glb
--------------------------------------------------------------------------------
/samples-generator/data/dragon_high.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/dragon_high.glb
--------------------------------------------------------------------------------
/samples-generator/data/dragon_low.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/dragon_low.glb
--------------------------------------------------------------------------------
/samples-generator/data/dragon_medium.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/dragon_medium.glb
--------------------------------------------------------------------------------
/samples-generator/data/house/door0.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 72,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 45
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 46,
21 | "min": [
22 | -0.3696739971637726,
23 | 0,
24 | -1.0869100093841553
25 | ],
26 | "max": [
27 | 0.3696739971637726,
28 | 1.3130379915237427,
29 | -0.9400410056114197
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 552,
36 | "componentType": 5126,
37 | "count": 46,
38 | "type": "VEC3",
39 | "min": [
40 | -1,
41 | -1,
42 | -1
43 | ],
44 | "max": [
45 | 1,
46 | 1,
47 | 1
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 1248,
58 | "uri": "data:application/octet-stream;base64,6UW9vqERqD+HpnC/6UW9vqERqD/eH4u/6UW9vgAAAADeH4u/6UW9vgAAAACHpnC/6UW9vqERqD/eH4u/6UW9PqERqD/eH4u/7fVePhXjND/eH4u/7fVePpmCkz/eH4u/6UW9vgAAAADeH4u/6UW9PgAAAADeH4u/6UW9PqERqD/eH4u/6UW9PqERqD+HpnC/6UW9PgAAAACHpnC/6UW9PgAAAADeH4u/6UW9PqERqD+HpnC/6UW9vqERqD+HpnC/6UW9vgAAAACHpnC/6UW9PgAAAACHpnC/6UW9vgAAAACHpnC/6UW9vgAAAADeH4u/6UW9PgAAAADeH4u/6UW9PgAAAACHpnC/6UW9PqERqD+HpnC/6UW9PqERqD/eH4u/6UW9vqERqD/eH4u/6UW9vqERqD+HpnC/hpJpvpmCkz987YG/hpJpvhXjND987YG/hpJpvhXjND/eH4u/hpJpvpmCkz/eH4u/7fVePpmCkz987YG/7fVePhXjND987YG/hpJpvhXjND987YG/hpJpvpmCkz987YG/hpJpvhXjND987YG/7fVePhXjND987YG/7fVePhXjND/eH4u/hpJpvhXjND/eH4u/7fVePpmCkz987YG/hpJpvpmCkz987YG/hpJpvpmCkz/eH4u/7fVePpmCkz/eH4u/7fVePhXjND/eH4u/7fVePhXjND987YG/7fVePpmCkz987YG/7fVePpmCkz/eH4u/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcABQAIAAQABQAJAAgACgALAAwACgAMAA0ADgAPABAADgAQABEAEgATABQAEgAUABUAFgAXABgAFgAYABkAGgAbABwAGgAcAB0AHgAfACAAHgAgACEAIgAjACQAIgAkACUAJgAnACgAJgAoACkAKgArACwAKgAsAC0A"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 1104,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 144,
72 | "byteOffset": 1104,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.45435,
81 | 0.245963,
82 | 0.171126,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/house/door1.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 72,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 45
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 46,
21 | "min": [
22 | 0.9400410056114197,
23 | 0,
24 | -0.3696739971637726
25 | ],
26 | "max": [
27 | 1.0869100093841553,
28 | 1.3130379915237427,
29 | 0.3696739971637726
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 552,
36 | "componentType": 5126,
37 | "count": 46,
38 | "type": "VEC3",
39 | "min": [
40 | -1,
41 | -1,
42 | -1
43 | ],
44 | "max": [
45 | 1,
46 | 1,
47 | 1
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 1248,
58 | "uri": "data:application/octet-stream;base64,h6ZwP6ERqD/pRb2+3h+LP6ERqD/pRb2+3h+LPwAAAADpRb2+h6ZwPwAAAADpRb2+3h+LP6ERqD/pRb2+3h+LP6ERqD/pRb0+3h+LPxXjND/t9V4+3h+LP5mCkz/t9V4+3h+LPwAAAADpRb2+3h+LPwAAAADpRb0+3h+LP6ERqD/pRb0+h6ZwP6ERqD/pRb0+h6ZwPwAAAADpRb0+3h+LPwAAAADpRb0+h6ZwP6ERqD/pRb0+h6ZwP6ERqD/pRb2+h6ZwPwAAAADpRb2+h6ZwPwAAAADpRb0+h6ZwPwAAAADpRb2+3h+LPwAAAADpRb2+3h+LPwAAAADpRb0+h6ZwPwAAAADpRb0+h6ZwP6ERqD/pRb0+3h+LP6ERqD/pRb0+3h+LP6ERqD/pRb2+h6ZwP6ERqD/pRb2+fO2BP5mCkz+Gkmm+fO2BPxXjND+Gkmm+3h+LPxXjND+Gkmm+3h+LP5mCkz+Gkmm+fO2BP5mCkz/t9V4+fO2BPxXjND/t9V4+fO2BPxXjND+Gkmm+fO2BP5mCkz+Gkmm+fO2BPxXjND+Gkmm+fO2BPxXjND/t9V4+3h+LPxXjND/t9V4+3h+LPxXjND+Gkmm+fO2BP5mCkz/t9V4+fO2BP5mCkz+Gkmm+3h+LP5mCkz+Gkmm+3h+LP5mCkz/t9V4+3h+LPxXjND/t9V4+fO2BPxXjND/t9V4+fO2BP5mCkz/t9V4+3h+LP5mCkz/t9V4+AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAABAAIAAAACAAMABAAFAAYABAAGAAcABQAIAAQABQAJAAgACgALAAwACgAMAA0ADgAPABAADgAQABEAEgATABQAEgAUABUAFgAXABgAFgAYABkAGgAbABwAGgAcAB0AHgAfACAAHgAgACEAIgAjACQAIgAkACUAJgAnACgAJgAoACkAKgArACwAKgAsAC0A"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 1104,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 144,
72 | "byteOffset": 1104,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.45435,
81 | 0.245963,
82 | 0.171126,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/house/door2.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 72,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 45
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 46,
21 | "min": [
22 | -0.3696739971637726,
23 | 0,
24 | 0.9400410056114197
25 | ],
26 | "max": [
27 | 0.3696739971637726,
28 | 1.3130379915237427,
29 | 1.0869100093841553
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 552,
36 | "componentType": 5126,
37 | "count": 46,
38 | "type": "VEC3",
39 | "min": [
40 | -1,
41 | -1,
42 | -1
43 | ],
44 | "max": [
45 | 1,
46 | 1,
47 | 1
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 1248,
58 | "uri": "data:application/octet-stream;base64,6UW9PqERqD+HpnA/6UW9PqERqD/eH4s/6UW9PgAAAADeH4s/6UW9PgAAAACHpnA/6UW9PqERqD/eH4s/6UW9vqERqD/eH4s/7fVevhXjND/eH4s/7fVevpmCkz/eH4s/6UW9PgAAAADeH4s/6UW9vgAAAADeH4s/6UW9vqERqD/eH4s/6UW9vqERqD+HpnA/6UW9vgAAAACHpnA/6UW9vgAAAADeH4s/6UW9vqERqD+HpnA/6UW9PqERqD+HpnA/6UW9PgAAAACHpnA/6UW9vgAAAACHpnA/6UW9PgAAAACHpnA/6UW9PgAAAADeH4s/6UW9vgAAAADeH4s/6UW9vgAAAACHpnA/6UW9vqERqD+HpnA/6UW9vqERqD/eH4s/6UW9PqERqD/eH4s/6UW9PqERqD+HpnA/hpJpPpmCkz987YE/hpJpPhXjND987YE/hpJpPhXjND/eH4s/hpJpPpmCkz/eH4s/7fVevpmCkz987YE/7fVevhXjND987YE/hpJpPhXjND987YE/hpJpPpmCkz987YE/hpJpPhXjND987YE/7fVevhXjND987YE/7fVevhXjND/eH4s/hpJpPhXjND/eH4s/7fVevpmCkz987YE/hpJpPpmCkz987YE/hpJpPpmCkz/eH4s/7fVevpmCkz/eH4s/7fVevhXjND/eH4s/7fVevhXjND987YE/7fVevpmCkz987YE/7fVevpmCkz/eH4s/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcABQAIAAQABQAJAAgACgALAAwACgAMAA0ADgAPABAADgAQABEAEgATABQAEgAUABUAFgAXABgAFgAYABkAGgAbABwAGgAcAB0AHgAfACAAHgAgACEAIgAjACQAIgAkACUAJgAnACgAJgAoACkAKgArACwAKgAsAC0A"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 1104,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 144,
72 | "byteOffset": 1104,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.45435,
81 | 0.245963,
82 | 0.171126,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/house/door3.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 72,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 45
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 46,
21 | "min": [
22 | -1.0869100093841553,
23 | 0,
24 | -0.3696739971637726
25 | ],
26 | "max": [
27 | -0.9400410056114197,
28 | 1.3130379915237427,
29 | 0.3696739971637726
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 552,
36 | "componentType": 5126,
37 | "count": 46,
38 | "type": "VEC3",
39 | "min": [
40 | -1,
41 | -1,
42 | -1
43 | ],
44 | "max": [
45 | 1,
46 | 1,
47 | 1
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 1248,
58 | "uri": "data:application/octet-stream;base64,h6Zwv6ERqD/pRb0+3h+Lv6ERqD/pRb0+3h+LvwAAAADpRb0+h6ZwvwAAAADpRb0+3h+Lv6ERqD/pRb0+3h+Lv6ERqD/pRb2+3h+LvxXjND/t9V6+3h+Lv5mCkz/t9V6+3h+LvwAAAADpRb0+3h+LvwAAAADpRb2+3h+Lv6ERqD/pRb2+h6Zwv6ERqD/pRb2+h6ZwvwAAAADpRb2+3h+LvwAAAADpRb2+h6Zwv6ERqD/pRb2+h6Zwv6ERqD/pRb0+h6ZwvwAAAADpRb0+h6ZwvwAAAADpRb2+h6ZwvwAAAADpRb0+3h+LvwAAAADpRb0+3h+LvwAAAADpRb2+h6ZwvwAAAADpRb2+h6Zwv6ERqD/pRb2+3h+Lv6ERqD/pRb2+3h+Lv6ERqD/pRb0+h6Zwv6ERqD/pRb0+fO2Bv5mCkz+Gkmk+fO2BvxXjND+Gkmk+3h+LvxXjND+Gkmk+3h+Lv5mCkz+Gkmk+fO2Bv5mCkz/t9V6+fO2BvxXjND/t9V6+fO2BvxXjND+Gkmk+fO2Bv5mCkz+Gkmk+fO2BvxXjND+Gkmk+fO2BvxXjND/t9V6+3h+LvxXjND/t9V6+3h+LvxXjND+Gkmk+fO2Bv5mCkz/t9V6+fO2Bv5mCkz+Gkmk+3h+Lv5mCkz+Gkmk+3h+Lv5mCkz/t9V6+3h+LvxXjND/t9V6+fO2BvxXjND/t9V6+fO2Bv5mCkz/t9V6+3h+Lv5mCkz/t9V6+AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAABAAIAAAACAAMABAAFAAYABAAGAAcABQAIAAQABQAJAAgACgALAAwACgAMAA0ADgAPABAADgAQABEAEgATABQAEgAUABUAFgAXABgAFgAYABkAGgAbABwAGgAcAB0AHgAfACAAHgAgACEAIgAjACQAIgAkACUAJgAnACgAJgAoACkAKgArACwAKgAsAC0A"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 1104,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 144,
72 | "byteOffset": 1104,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.45435,
81 | 0.245963,
82 | 0.171126,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/house/roof.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 18,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 15
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 16,
21 | "min": [
22 | -1,
23 | 2,
24 | -1
25 | ],
26 | "max": [
27 | 1,
28 | 2.979520082473755,
29 | 1
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 192,
36 | "componentType": 5126,
37 | "count": 16,
38 | "type": "VEC3",
39 | "min": [
40 | -0.6997694373130798,
41 | -1,
42 | -0.6997694373130798
43 | ],
44 | "max": [
45 | 0.6997694373130798,
46 | 0.7143687605857849,
47 | 0.6997694373130798
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 420,
58 | "uri": "data:application/octet-stream;base64,AAAAAHWwPkAAAAAAAACAvwAAAEAAAIC/AACAvwAAAEAAAIA/AAAAAHWwPkAAAAAAAACAPwAAAEAAAIC/AACAvwAAAEAAAIC/AAAAAHWwPkAAAAAAAACAPwAAAEAAAIA/AACAPwAAAEAAAIC/AAAAAHWwPkAAAAAAAACAvwAAAEAAAIA/AACAPwAAAEAAAIA/AACAvwAAAEAAAIA/AACAvwAAAEAAAIC/AACAPwAAAEAAAIC/AACAPwAAAEAAAIA/FyQzv9/gNj8AAAAAFyQzv9/gNj8AAAAAFyQzv9/gNj8AAAAAAAAAAN/gNj8XJDO/AAAAAN/gNj8XJDO/AAAAAN/gNj8XJDO/FyQzP9/gNj8AAAAAFyQzP9/gNj8AAAAAFyQzP9/gNj8AAAAAAAAAAN/gNj8XJDM/AAAAAN/gNj8XJDM/AAAAAN/gNj8XJDM/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADAAOAA8A"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 384,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 36,
72 | "byteOffset": 384,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.64,
81 | 0.204491,
82 | 0.219181,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/house/wall.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "accessors": [
3 | {
4 | "bufferView": 1,
5 | "byteOffset": 0,
6 | "componentType": 5123,
7 | "count": 36,
8 | "type": "SCALAR",
9 | "min": [
10 | 0
11 | ],
12 | "max": [
13 | 23
14 | ]
15 | },
16 | {
17 | "bufferView": 0,
18 | "byteOffset": 0,
19 | "componentType": 5126,
20 | "count": 24,
21 | "min": [
22 | -1,
23 | 0,
24 | -1
25 | ],
26 | "max": [
27 | 1,
28 | 2,
29 | 1
30 | ],
31 | "type": "VEC3"
32 | },
33 | {
34 | "bufferView": 0,
35 | "byteOffset": 288,
36 | "componentType": 5126,
37 | "count": 24,
38 | "type": "VEC3",
39 | "min": [
40 | -1,
41 | -1,
42 | -1
43 | ],
44 | "max": [
45 | 1,
46 | 1,
47 | 1
48 | ]
49 | }
50 | ],
51 | "asset": {
52 | "generator": "OBJ2GLTF",
53 | "version": "2.0"
54 | },
55 | "buffers": [
56 | {
57 | "byteLength": 648,
58 | "uri": "data:application/octet-stream;base64,AACAvwAAAEAAAIA/AACAvwAAAEAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIA/AACAvwAAAEAAAIC/AACAPwAAAEAAAIC/AACAPwAAAAAAAIC/AACAvwAAAAAAAIC/AACAPwAAAEAAAIC/AACAPwAAAEAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAIC/AACAPwAAAEAAAIA/AACAvwAAAEAAAIA/AACAvwAAAAAAAIA/AACAPwAAAAAAAIA/AACAvwAAAAAAAIA/AACAvwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIA/AACAPwAAAEAAAIA/AACAPwAAAEAAAIC/AACAvwAAAEAAAIC/AACAvwAAAEAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA"
59 | }
60 | ],
61 | "bufferViews": [
62 | {
63 | "buffer": 0,
64 | "byteLength": 576,
65 | "byteOffset": 0,
66 | "target": 34962,
67 | "byteStride": 12
68 | },
69 | {
70 | "buffer": 0,
71 | "byteLength": 72,
72 | "byteOffset": 576,
73 | "target": 34963
74 | }
75 | ],
76 | "materials": [
77 | {
78 | "pbrMetallicRoughness": {
79 | "baseColorFactor": [
80 | 0.8,
81 | 0.431283,
82 | 0.253046,
83 | 1
84 | ],
85 | "metallicFactor": 0,
86 | "roughnessFactor": 1
87 | },
88 | "emissiveFactor": [
89 | 0,
90 | 0,
91 | 0
92 | ],
93 | "alphaMode": "OPAQUE",
94 | "doubleSided": false
95 | }
96 | ],
97 | "meshes": [
98 | {
99 | "primitives": [
100 | {
101 | "attributes": {
102 | "POSITION": 1,
103 | "NORMAL": 2
104 | },
105 | "indices": 0,
106 | "material": 0,
107 | "mode": 4
108 | }
109 | ]
110 | }
111 | ],
112 | "nodes": [
113 | {
114 | "mesh": 0
115 | }
116 | ],
117 | "scene": 0,
118 | "scenes": [
119 | {
120 | "nodes": [
121 | 0
122 | ]
123 | }
124 | ]
125 | }
126 |
--------------------------------------------------------------------------------
/samples-generator/data/red_box.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/red_box.glb
--------------------------------------------------------------------------------
/samples-generator/data/textured_box.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/textured_box.glb
--------------------------------------------------------------------------------
/samples-generator/data/textured_box_separate/Cesium_Logo_Flat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/textured_box_separate/Cesium_Logo_Flat.png
--------------------------------------------------------------------------------
/samples-generator/data/textured_box_separate/textured_box.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/textured_box_separate/textured_box.glb
--------------------------------------------------------------------------------
/samples-generator/data/tree.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/tree.glb
--------------------------------------------------------------------------------
/samples-generator/data/tree_billboard.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/tree_billboard.glb
--------------------------------------------------------------------------------
/samples-generator/data/wood_red.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/samples-generator/data/wood_red.jpg
--------------------------------------------------------------------------------
/samples-generator/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Promise = require('bluebird');
4 | var Cesium = require('cesium');
5 | var child_process = require('child_process');
6 | var gulp = require('gulp');
7 | var Jasmine = require('jasmine');
8 | var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
9 | var path = require('path');
10 | var yargs = require('yargs');
11 | var fsExtra = require('fs-extra');
12 | var open = require('open');
13 |
14 | var defined = Cesium.defined;
15 | var argv = yargs.argv;
16 |
17 | // Add third-party node module binaries to the system path
18 | // since some tasks need to call them directly.
19 | var environmentSeparator = process.platform === 'win32' ? ';' : ':';
20 | var nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
21 | process.env.PATH += environmentSeparator + nodeBinaries;
22 |
23 | var specFiles = ['**/*.js', '!node_modules/**'];
24 |
25 | gulp.task('test', function (done) {
26 | var jasmine = new Jasmine();
27 | jasmine.loadConfigFile('specs/jasmine.json');
28 | jasmine.addReporter(new SpecReporter({
29 | displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
30 | }));
31 | jasmine.execute();
32 | jasmine.onComplete(function (passed) {
33 | done(argv.failTaskOnError && !passed ? 1 : 0);
34 | });
35 | });
36 |
37 | gulp.task('test-watch', function () {
38 | gulp.watch(specFiles).on('change', function () {
39 | // We can't simply depend on the test task because Jasmine
40 | // does not like being run multiple times in the same process.
41 | try {
42 | child_process.execSync('jasmine JASMINE_CONFIG_PATH=specs/jasmine.json', {
43 | stdio: [process.stdin, process.stdout, process.stderr]
44 | });
45 | } catch (exception) {
46 | console.log('Tests failed to execute.');
47 | }
48 | });
49 | });
50 |
51 | gulp.task('coverage', function () {
52 | fsExtra.removeSync('coverage');
53 | child_process.execSync('nyc' +
54 | ' --all' +
55 | ' --reporter=lcov' +
56 | ' --dir coverage' +
57 | ' -x "specs/**"' +
58 | ' -x "coverage/**"' +
59 | ' -x "gulpfile.js"' +
60 | ' -x "index.js"' +
61 | ' node_modules/jasmine/bin/jasmine.js' +
62 | ' JASMINE_CONFIG_PATH=specs/jasmine.json', {
63 | stdio: [process.stdin, process.stdout, process.stderr]
64 | });
65 | open('coverage/lcov-report/index.html');
66 | });
67 |
68 | gulp.task('cloc', function() {
69 | var cmdLine;
70 | var clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
71 |
72 | //Run cloc on primary Source files only
73 | var source = new Promise(function(resolve, reject) {
74 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
75 | ' lib/ bin/';
76 |
77 | child_process.exec(cmdLine, function(error, stdout, stderr) {
78 | if (error) {
79 | console.log(stderr);
80 | return reject(error);
81 | }
82 | console.log('Source:');
83 | console.log(stdout);
84 | resolve();
85 | });
86 | });
87 |
88 | //If running cloc on source succeeded, also run it on the tests.
89 | return source.then(function() {
90 | return new Promise(function(resolve, reject) {
91 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
92 | ' specs/lib/ specs/bin/';
93 | child_process.exec(cmdLine, function(error, stdout, stderr) {
94 | if (error) {
95 | console.log(stderr);
96 | return reject(error);
97 | }
98 | console.log('Specs:');
99 | console.log(stdout);
100 | resolve();
101 | });
102 | });
103 | });
104 | });
105 |
--------------------------------------------------------------------------------
/samples-generator/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = {
3 | };
4 |
--------------------------------------------------------------------------------
/samples-generator/lib/Extensions.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defined = Cesium.defined;
5 |
6 | module.exports = Extensions;
7 |
8 | function Extensions() { }
9 |
10 | /**
11 | * Add an extension to the list of extensions used for a tileset JSON.
12 | * @param {Object} tilesetJson The root tileset JSON object to which to add the extension.
13 | * @param {String} extensionName The name of the extension to add.
14 | */
15 | Extensions.addExtensionsUsed = function(tilesetJson, extensionName) {
16 | var extensionsUsed = tilesetJson.extensionsUsed;
17 |
18 | if (!defined(extensionsUsed)) {
19 | extensionsUsed = tilesetJson.extensionsUsed = [];
20 | }
21 |
22 | extensionsUsed.push(extensionName);
23 | };
24 |
25 | /**
26 | * Add an extension to the list of extensions required for a tileset JSON.
27 | * @param {Object} tilesetJson The root tileset JSON object to which to add the extension.
28 | * @param {String} extensionName The name of the extension to add.
29 | */
30 | Extensions.addExtensionsRequired = function(tilesetJson, extensionName) {
31 | var extensionsRequired = tilesetJson.extensionsRequired;
32 |
33 | if (!defined(extensionsRequired)) {
34 | extensionsRequired = tilesetJson.extensionsRequired = [];
35 | }
36 |
37 | extensionsRequired.push(extensionName);
38 | };
39 |
40 | /**
41 | * Add an extension to the extensions dictionary object for a JSON object.
42 | * @param {Object} tilesetJson The JSON object to which to add the extension.
43 | * @param {String} extensionName The name of the extension to add.
44 | * @param {*} extension The contents of the extension.
45 | */
46 | Extensions.addExtension = function(tilesetJson, extensionName, extension) {
47 | var extensions = tilesetJson.extensions;
48 |
49 | if (!defined(extensions)) {
50 | extensions = tilesetJson.extensions = {};
51 | }
52 |
53 | extensions[extensionName] = extension;
54 | };
55 |
--------------------------------------------------------------------------------
/samples-generator/lib/Material.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 |
6 | module.exports = Material;
7 |
8 | /**
9 | * A material that is applied to a mesh.
10 | *
11 | * @param {Object} [options] An object with the following properties:
12 | * @param {Array|String} [options.baseColor] The base color or base color texture path.
13 | *
14 | * @constructor
15 | */
16 | function Material(options) {
17 | options = defaultValue(options, defaultValue.EMPTY_OBJECT);
18 | this.baseColor = defaultValue(options.baseColor, [0.5, 0.5, 0.5, 1.0]);
19 | }
20 |
21 | /**
22 | * Creates a Material from a glTF material. This utility is designed only for simple glTFs like those in the data folder.
23 | *
24 | * @param {Object} material The glTF material.
25 | * @returns {Material} The material.
26 | */
27 | Material.fromGltf = function(material) {
28 | return new Material({
29 | baseColor : material.pbrMetallicRoughness.baseColorFactor
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/samples-generator/lib/createB3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var getBufferPadded = require('./getBufferPadded');
4 | var getJsonBufferPadded = require('./getJsonBufferPadded');
5 |
6 | var defaultValue = Cesium.defaultValue;
7 |
8 | module.exports = createB3dm;
9 |
10 | /**
11 | * Create a Batched 3D Model (b3dm) tile from a binary glTF and per-feature metadata.
12 | *
13 | * @param {Object} options An object with the following properties:
14 | * @param {Buffer} options.glb The binary glTF buffer.
15 | * @param {Object} [options.featureTableJson] Feature table JSON.
16 | * @param {Buffer} [options.featureTableBinary] Feature table binary.
17 | * @param {Object} [options.batchTableJson] Batch table describing the per-feature metadata.
18 | * @param {Buffer} [options.batchTableBinary] The batch table binary.
19 | * @param {Boolean} [options.deprecated1=false] Save the b3dm with the deprecated 20-byte header.
20 | * @param {Boolean} [options.deprecated2=false] Save the b3dm with the deprecated 24-byte header.
21 | * @returns {Buffer} The generated b3dm tile buffer.
22 | */
23 | function createB3dm(options) {
24 | var glb = options.glb;
25 | var defaultFeatureTable = {
26 | BATCH_LENGTH : 0
27 | };
28 | var featureTableJson = defaultValue(options.featureTableJson, defaultFeatureTable);
29 | var batchLength = featureTableJson.BATCH_LENGTH;
30 |
31 | var headerByteLength = 28;
32 | var featureTableJsonBuffer = getJsonBufferPadded(featureTableJson, headerByteLength);
33 | var featureTableBinary = getBufferPadded(options.featureTableBinary);
34 | var batchTableJsonBuffer = getJsonBufferPadded(options.batchTableJson);
35 | var batchTableBinary = getBufferPadded(options.batchTableBinary);
36 |
37 | var deprecated1 = defaultValue(options.deprecated1, false);
38 | var deprecated2 = defaultValue(options.deprecated2, false);
39 |
40 | if (deprecated1) {
41 | return createB3dmDeprecated1(glb, batchLength, batchTableJsonBuffer);
42 | } else if (deprecated2) {
43 | return createB3dmDeprecated2(glb, batchLength, batchTableJsonBuffer, batchTableBinary);
44 | }
45 |
46 | return createB3dmCurrent(glb, featureTableJsonBuffer, featureTableBinary, batchTableJsonBuffer, batchTableBinary);
47 | }
48 |
49 | function createB3dmCurrent(glb, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary) {
50 | var version = 1;
51 | var headerByteLength = 28;
52 | var featureTableJsonByteLength = featureTableJson.length;
53 | var featureTableBinaryByteLength = featureTableBinary.length;
54 | var batchTableJsonByteLength = batchTableJson.length;
55 | var batchTableBinaryByteLength = batchTableBinary.length;
56 | var gltfByteLength = glb.length;
57 | var byteLength = headerByteLength + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJsonByteLength + batchTableBinaryByteLength + gltfByteLength;
58 |
59 | var header = Buffer.alloc(headerByteLength);
60 | header.write('b3dm', 0);
61 | header.writeUInt32LE(version, 4);
62 | header.writeUInt32LE(byteLength, 8);
63 | header.writeUInt32LE(featureTableJsonByteLength, 12);
64 | header.writeUInt32LE(featureTableBinaryByteLength, 16);
65 | header.writeUInt32LE(batchTableJsonByteLength, 20);
66 | header.writeUInt32LE(batchTableBinaryByteLength, 24);
67 |
68 | return Buffer.concat([header, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary, glb]);
69 | }
70 |
71 | function createB3dmDeprecated1(glb, batchLength, batchTableJson) {
72 | var version = 1;
73 | var headerByteLength = 20;
74 | var batchTableJsonByteLength = batchTableJson.length;
75 | var gltfByteLength = glb.length;
76 | var byteLength = headerByteLength + batchTableJsonByteLength + gltfByteLength;
77 |
78 | var header = Buffer.alloc(headerByteLength);
79 | header.write('b3dm', 0);
80 | header.writeUInt32LE(version, 4);
81 | header.writeUInt32LE(byteLength, 8);
82 | header.writeUInt32LE(batchLength, 12);
83 | header.writeUInt32LE(batchTableJsonByteLength, 16);
84 |
85 | return Buffer.concat([header, batchTableJson, glb]);
86 | }
87 |
88 | function createB3dmDeprecated2(glb, batchLength, batchTableJson, batchTableBinary) {
89 | var version = 1;
90 | var headerByteLength = 24;
91 | var batchTableJsonByteLength = batchTableJson.length;
92 | var batchTableBinaryByteLength = batchTableBinary.length;
93 | var gltfByteLength = glb.length;
94 | var byteLength = headerByteLength + batchTableJsonByteLength + batchTableBinaryByteLength + gltfByteLength;
95 |
96 | var header = Buffer.alloc(headerByteLength);
97 | header.write('b3dm', 0);
98 | header.writeUInt32LE(version, 4);
99 | header.writeUInt32LE(byteLength, 8);
100 | header.writeUInt32LE(batchTableJsonByteLength, 12);
101 | header.writeUInt32LE(batchTableBinaryByteLength, 16);
102 | header.writeUInt32LE(batchLength, 20);
103 |
104 | return Buffer.concat([header, batchTableJson, batchTableBinary, glb]);
105 | }
106 |
--------------------------------------------------------------------------------
/samples-generator/lib/createCmpt.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var getBufferPadded = require('./getBufferPadded');
3 |
4 | module.exports = createCmpt;
5 |
6 | /**
7 | * Create a Composite (cmpt) tile from a set of tiles.
8 | *
9 | * @param {Buffer[]} tiles An array of buffers holding tile data.
10 | * @returns {Buffer} The generated cmpt tile buffer.
11 | */
12 | function createCmpt(tiles) {
13 | var byteLength = 0;
14 | var buffers = [];
15 | var tilesLength = tiles.length;
16 | for (var i = 0; i < tilesLength; i++) {
17 | var tile = getBufferPadded(tiles[i]);
18 | var tileByteLength = tile.length;
19 | tile.writeUInt32LE(tileByteLength, 8); // Edit the tile's byte length
20 | buffers.push(tile);
21 | byteLength += tileByteLength;
22 | }
23 |
24 | var version = 1;
25 | var headerByteLength = 16;
26 | byteLength += headerByteLength;
27 |
28 | var header = Buffer.alloc(headerByteLength);
29 | header.write('cmpt', 0);
30 | header.writeUInt32LE(version, 4);
31 | header.writeUInt32LE(byteLength, 8);
32 | header.writeUInt32LE(tilesLength, 12);
33 |
34 | buffers.unshift(header); // Add header first
35 |
36 | return Buffer.concat(buffers);
37 | }
38 |
--------------------------------------------------------------------------------
/samples-generator/lib/createI3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var getJsonBufferPadded = require('./getJsonBufferPadded');
4 | var getBufferPadded = require('./getBufferPadded');
5 |
6 | var defined = Cesium.defined;
7 |
8 | module.exports = createI3dm;
9 |
10 | /**
11 | * Create an Instanced 3D Model (i3dm) tile from a feature table, batch table, and gltf buffer or uri.
12 | *
13 | * @param {Object} options An object with the following properties:
14 | * @param {Object} options.featureTableJson The feature table JSON.
15 | * @param {Buffer} options.featureTableBinary The feature table binary.
16 | * @param {Object} [options.batchTableJson] Batch table describing the per-feature metadata.
17 | * @param {Buffer} [options.batchTableBinary] The batch table binary.
18 | * @param {Buffer} [options.glb] The binary glTF buffer.
19 | * @param {String} [options.uri] Uri to an external glTF model when options.glb is not specified.
20 | * @returns {Buffer} The generated i3dm tile buffer.
21 | */
22 | function createI3dm(options) {
23 | var featureTableJson = getJsonBufferPadded(options.featureTableJson);
24 | var featureTableBinary = getBufferPadded(options.featureTableBinary);
25 | var batchTableJson = getJsonBufferPadded(options.batchTableJson);
26 | var batchTableBinary = getBufferPadded(options.batchTableBinary);
27 |
28 | var gltfFormat = defined(options.glb) ? 1 : 0;
29 | var gltfBuffer = defined(options.glb) ? options.glb : getGltfUriBuffer(options.uri);
30 |
31 | var version = 1;
32 | var headerByteLength = 32;
33 | var featureTableJsonByteLength = featureTableJson.length;
34 | var featureTableBinaryByteLength = featureTableBinary.length;
35 | var batchTableJsonByteLength = batchTableJson.length;
36 | var batchTableBinaryByteLength = batchTableBinary.length;
37 | var gltfByteLength = gltfBuffer.length;
38 | var byteLength = headerByteLength + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJsonByteLength + batchTableBinaryByteLength + gltfByteLength;
39 |
40 | var header = Buffer.alloc(headerByteLength);
41 | header.write('i3dm', 0);
42 | header.writeUInt32LE(version, 4);
43 | header.writeUInt32LE(byteLength, 8);
44 | header.writeUInt32LE(featureTableJsonByteLength, 12);
45 | header.writeUInt32LE(featureTableBinaryByteLength, 16);
46 | header.writeUInt32LE(batchTableJsonByteLength, 20);
47 | header.writeUInt32LE(batchTableBinaryByteLength, 24);
48 | header.writeUInt32LE(gltfFormat, 28);
49 |
50 | return Buffer.concat([header, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary, gltfBuffer]);
51 | }
52 |
53 | function getGltfUriBuffer(uri) {
54 | uri = uri.replace(/\\/g, '/');
55 | return Buffer.from(uri);
56 | }
57 |
--------------------------------------------------------------------------------
/samples-generator/lib/createPnts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var getJsonBufferPadded = require('./getJsonBufferPadded');
3 | var getBufferPadded = require('./getBufferPadded');
4 |
5 | module.exports = createPnts;
6 |
7 | /**
8 | * Create a Point Cloud (pnts) tile from a feature table and batch table.
9 | *
10 | * @param {Object} options An object with the following properties:
11 | * @param {Object} options.featureTableJson The feature table JSON.
12 | * @param {Buffer} options.featureTableBinary The feature table binary.
13 | * @param {Object} [options.batchTableJson] Batch table describing the per-point metadata.
14 | * @param {Buffer} [options.batchTableBinary] The batch table binary.
15 | * @returns {Buffer} The generated pnts tile buffer.
16 | */
17 | function createPnts(options) {
18 | var featureTableJson = getJsonBufferPadded(options.featureTableJson);
19 | var featureTableBinary = getBufferPadded(options.featureTableBinary);
20 | var batchTableJson = getJsonBufferPadded(options.batchTableJson);
21 | var batchTableBinary = getBufferPadded(options.batchTableBinary);
22 |
23 | var version = 1;
24 | var headerByteLength = 28;
25 | var featureTableJsonByteLength = featureTableJson.length;
26 | var featureTableBinaryByteLength = featureTableBinary.length;
27 | var batchTableJsonByteLength = batchTableJson.length;
28 | var batchTableBinaryByteLength = batchTableBinary.length;
29 | var byteLength = headerByteLength + featureTableJsonByteLength + featureTableBinaryByteLength + batchTableJsonByteLength + batchTableBinaryByteLength;
30 |
31 | var header = Buffer.alloc(headerByteLength);
32 | header.write('pnts', 0);
33 | header.writeUInt32LE(version, 4);
34 | header.writeUInt32LE(byteLength, 8);
35 | header.writeUInt32LE(featureTableJsonByteLength, 12);
36 | header.writeUInt32LE(featureTableBinaryByteLength, 16);
37 | header.writeUInt32LE(batchTableJsonByteLength, 20);
38 | header.writeUInt32LE(batchTableBinaryByteLength, 24);
39 |
40 | return Buffer.concat([header, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary]);
41 | }
42 |
--------------------------------------------------------------------------------
/samples-generator/lib/createTilesetJsonSingle.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 | var defined = Cesium.defined;
6 | var Matrix4 = Cesium.Matrix4;
7 |
8 | module.exports = createTilesetJsonSingle;
9 |
10 | var defaultTilesetVersion = '1.0';
11 |
12 | /**
13 | * Create a tileset JSON for a single tile.
14 | *
15 | * @param {Object} options Object with the following properties:
16 | * @param {String} options.contentUri The content URI of the root tile. This may be a relative filepath or a data URI.
17 | * @param {Number} options.geometricError Geometric error of the tile.
18 | * @param {String} options.versionNumber The 3D Tiles version number string.
19 | * @param {Object} [options.region] Bounding region of the tile.
20 | * @param {Object} [options.box] Bounding box of the tile.
21 | * @param {Object} [options.sphere] Bounding sphere of the tile.
22 | * @param {Matrix4} [options.transform=Matrix4.IDENTITY] The tile transform.
23 | * @param {Object} [options.properties] An object containing the min and max values for each property in the batch table.
24 | * @param {Object} [options.extensions] An object containing extensionsUsed, extensionsRequired, and extensions properties.
25 | * @param {Object} [options.expire] Tile expiration options.
26 | *
27 | * @returns {Object} The tileset JSON.
28 | */
29 | function createTilesetJsonSingle(options) {
30 | var transform = defaultValue(options.transform, Matrix4.IDENTITY);
31 | var transformArray = (defined(transform) && !Matrix4.equals(transform, Matrix4.IDENTITY)) ? Matrix4.pack(transform, new Array(16)) : undefined;
32 | var boundingVolume = getBoundingVolume(options.region, options.box, options.sphere);
33 | var extensions = defaultValue(options.extensions, defaultValue.EMPTY_OBJECT);
34 |
35 | var tilesetJson = {
36 | asset : {
37 | version : defaultValue(options.versionNumber, defaultTilesetVersion)
38 | },
39 | properties : options.properties,
40 | extensionsUsed : extensions.extensionsUsed,
41 | extensionsRequired : extensions.extensionsRequired,
42 | extensions : extensions.extensions,
43 | geometricError : options.geometricError,
44 | root : {
45 | transform : transformArray,
46 | expire : options.expire,
47 | refine : 'ADD',
48 | boundingVolume : boundingVolume,
49 | geometricError : 0.0,
50 | content : {
51 | uri : options.contentUri
52 | }
53 | }
54 | };
55 |
56 | return tilesetJson;
57 | }
58 |
59 | function getBoundingVolume(region, box, sphere) {
60 | if (defined(region)) {
61 | return {
62 | region : region
63 | };
64 | } else if (defined(box)) {
65 | return {
66 | box : box
67 | };
68 | } else if (defined(sphere)) {
69 | return {
70 | sphere : sphere
71 | };
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/samples-generator/lib/getBufferPadded.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 | var defined = Cesium.defined;
6 |
7 | module.exports = getBufferPadded;
8 |
9 | /**
10 | * Pad the buffer to the next 8-byte boundary to ensure proper alignment for the section that follows.
11 | *
12 | * @param {Buffer} buffer The buffer.
13 | * @param {Number} [byteOffset=0] The byte offset on which the buffer starts.
14 | * @returns {Buffer} The padded buffer.
15 | */
16 | function getBufferPadded(buffer, byteOffset) {
17 | if (!defined(buffer)) {
18 | return Buffer.alloc(0);
19 | }
20 |
21 | byteOffset = defaultValue(byteOffset, 0);
22 |
23 | var boundary = 8;
24 | var byteLength = buffer.length;
25 | var remainder = (byteOffset + byteLength) % boundary;
26 | var padding = (remainder === 0) ? 0 : boundary - remainder;
27 | var emptyBuffer = Buffer.alloc(padding);
28 | return Buffer.concat([buffer, emptyBuffer]);
29 | }
30 |
--------------------------------------------------------------------------------
/samples-generator/lib/getJsonBufferPadded.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 | var defined = Cesium.defined;
6 |
7 | module.exports = getJsonBufferPadded;
8 |
9 | /**
10 | * Convert the JSON object to a padded buffer.
11 | *
12 | * Pad the JSON with extra whitespace to fit the next 8-byte boundary. This ensures proper alignment
13 | * for the section that follows (for example, batch table binary or feature table binary).
14 | *
15 | * @param {Object} [json] The JSON object.
16 | * @param {Number} [byteOffset=0] The byte offset on which the buffer starts.
17 | * @returns {Buffer} The padded JSON buffer.
18 | */
19 | function getJsonBufferPadded(json, byteOffset) {
20 | if (!defined(json)) {
21 | return Buffer.alloc(0);
22 | }
23 |
24 | byteOffset = defaultValue(byteOffset, 0);
25 | var string = JSON.stringify(json);
26 |
27 | var boundary = 8;
28 | var byteLength = Buffer.byteLength(string);
29 | var remainder = (byteOffset + byteLength) % boundary;
30 | var padding = (remainder === 0) ? 0 : boundary - remainder;
31 | var whitespace = '';
32 | for (var i = 0; i < padding; ++i) {
33 | whitespace += ' ';
34 | }
35 | string += whitespace;
36 |
37 | return Buffer.from(string);
38 | }
39 |
--------------------------------------------------------------------------------
/samples-generator/lib/getProperties.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defined = Cesium.defined;
5 |
6 | module.exports = getProperties;
7 |
8 | /**
9 | * Get the minimum and maximum values for each property in the batch table.
10 | * Ignore properties in the batch table binary for now. Also ignore non-number values.
11 | *
12 | * @param {Object|Object[]} batchTable The batch table(s).
13 | * @returns {Object} An object with the minimum and maximum values for each property in the batch table.
14 | */
15 | function getProperties(batchTable) {
16 | if (!defined(batchTable)) {
17 | return undefined;
18 | }
19 | var properties = {};
20 | var batchTables = Array.isArray(batchTable) ? batchTable : [batchTable];
21 | var batchTablesLength = batchTables.length;
22 | for (var i = 0; i < batchTablesLength; ++i) {
23 | batchTable = batchTables[i];
24 | for (var name in batchTable) {
25 | if (batchTable.hasOwnProperty(name)) {
26 | var values = batchTable[name];
27 | if (Array.isArray(values)) {
28 | if (typeof values[0] === 'number') {
29 | if (!defined(properties[name])) {
30 | properties[name] = {
31 | minimum : Number.POSITIVE_INFINITY,
32 | maximum : Number.NEGATIVE_INFINITY
33 | };
34 | }
35 | var min = properties[name].minimum;
36 | var max = properties[name].maximum;
37 | var length = values.length;
38 | for (var j = 0; j < length; ++j) {
39 | var value = values[j];
40 | min = Math.min(value, min);
41 | max = Math.max(value, max);
42 | }
43 | properties[name].minimum = min;
44 | properties[name].maximum = max;
45 | }
46 | }
47 | }
48 | }
49 | }
50 | if (Object.keys(properties).length === 0) {
51 | return undefined;
52 | }
53 | return properties;
54 | }
55 |
--------------------------------------------------------------------------------
/samples-generator/lib/saveTile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var zlib = require('zlib');
5 |
6 | var defaultValue = Cesium.defaultValue;
7 |
8 | module.exports = saveTile;
9 |
10 | /**
11 | * Save a tile to disk.
12 | *
13 | * @param {String} path The tile path.
14 | * @param {Buffer} contents The contents of the tile.
15 | * @param {Boolean} [gzip=false] Whether to gzip the tile.
16 | *
17 | * @returns {Promise} A promise that resolves when the tile is saved.
18 | */
19 | function saveTile(path, contents, gzip) {
20 | gzip = defaultValue(gzip, false);
21 | if (gzip) {
22 | contents = zlib.gzipSync(contents);
23 | }
24 | return fsExtra.outputFile(path, contents);
25 | }
26 |
--------------------------------------------------------------------------------
/samples-generator/lib/saveTilesetJson.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 |
5 | var defaultValue = Cesium.defaultValue;
6 |
7 | module.exports = saveTilesetJson;
8 |
9 | /**
10 | * Save a tileset.json file to disk.
11 | *
12 | * @param {String} path The path to save the tileset.json.
13 | * @param {Object} json The JSON.
14 | * @param {Boolean} [prettyJson=true] Whether to prettify the JSON.
15 | *
16 | * @returns {Promise} A promise that resolves when the tileset.json is saved.
17 | */
18 | function saveTilesetJson(path, json, prettyJson) {
19 | prettyJson = defaultValue(prettyJson, true);
20 | var options = {};
21 | if (prettyJson) {
22 | options.spaces = 2;
23 | }
24 | return fsExtra.outputJson(path, json, options);
25 | }
26 |
--------------------------------------------------------------------------------
/samples-generator/lib/utility.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var Cartesian3 = Cesium.Cartesian3;
5 | var HeadingPitchRoll = Cesium.HeadingPitchRoll;
6 | var Transforms = Cesium.Transforms;
7 |
8 | module.exports = {
9 | metersToLongitude : metersToLongitude,
10 | metersToLatitude : metersToLatitude,
11 | wgs84Transform : wgs84Transform,
12 | lowercase : lowercase,
13 | typeToNumberOfComponents : typeToNumberOfComponents
14 | };
15 |
16 | function metersToLongitude(meters, latitude) {
17 | return meters * 0.000000156785 / Math.cos(latitude);
18 | }
19 |
20 | function metersToLatitude(meters) {
21 | return meters * 0.000000157891;
22 | }
23 |
24 | function wgs84Transform(longitude, latitude, height) {
25 | return Transforms.headingPitchRollToFixedFrame(Cartesian3.fromRadians(longitude, latitude, height), new HeadingPitchRoll());
26 | }
27 |
28 | function lowercase(s) {
29 | return s[0].toLowerCase() + s.slice(1);
30 | }
31 |
32 | function typeToNumberOfComponents(type) {
33 | switch (type) {
34 | case 'SCALAR':
35 | return 1;
36 | case 'VEC2':
37 | return 2;
38 | case 'VEC3':
39 | return 3;
40 | case 'VEC4':
41 | return 4;
42 | case 'MAT2':
43 | return 4;
44 | case 'MAT3':
45 | return 9;
46 | case 'MAT4':
47 | return 16;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/samples-generator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "3d-tiles-samples-generator",
3 | "version": "0.1.0",
4 | "license": "Apache-2.0",
5 | "description": "Tools for generating sample 3D Tiles tilesets.",
6 | "author": {
7 | "name": "Analytical Graphics, Inc. and Contributors",
8 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/graphs/contributors"
9 | },
10 | "keywords": [
11 | "3D Tiles"
12 | ],
13 | "homepage": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools.git"
17 | },
18 | "bugs": {
19 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/issues"
20 | },
21 | "main": "index.js",
22 | "engines": {
23 | "node": ">=4.0.0"
24 | },
25 | "dependencies": {
26 | "bluebird": "^3.5.1",
27 | "cesium": "^1.39",
28 | "draco3d": "^1.3.3",
29 | "fs-extra": "^4.0.2",
30 | "gltf-pipeline": "^2.0.0",
31 | "mime": "^2.0.3",
32 | "simplex-noise": "^2.3.0"
33 | },
34 | "devDependencies": {
35 | "cloc": "^2.3.3",
36 | "datauri": "^1.1.0",
37 | "eslint": "^4.10.0",
38 | "eslint-config-cesium": "^2.0.1",
39 | "gulp": "^3.9.1",
40 | "jasmine": "^2.8.0",
41 | "jasmine-spec-reporter": "^4.2.1",
42 | "nyc": "^11.3.0",
43 | "open": "^0.0.5",
44 | "requirejs": "^2.3.5",
45 | "yargs": "^10.0.3"
46 | },
47 | "scripts": {
48 | "eslint": "eslint \"./**/*.js\" --cache --quiet",
49 | "test": "gulp test",
50 | "test-watch": "gulp test-watch",
51 | "coverage": "gulp coverage",
52 | "cloc": "gulp cloc"
53 | },
54 | "bin": {
55 | "3d-tiles-samples-generator": "./bin/3d-tiles-samples-generator"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/samples-generator/specs/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.eslintrc.json",
3 | "env": {
4 | "jasmine": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/samples-generator/specs/bin/generatorSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var child_process = require('child_process');
3 | var path = require('path');
4 |
5 | var scriptPath = path.join(__dirname, '../../bin/3d-tiles-samples-generator.js');
6 |
7 | describe('3d-tiles-samples-generator', function () {
8 | it('runs', function (done) {
9 | var command = 'node';
10 | var args = [scriptPath];
11 | var child = child_process.spawn(command, args);
12 | child.once('error', function (e) {
13 | fail(e);
14 | });
15 | child.once('exit', function (code) {
16 | if (code !== 0) {
17 | fail('3d-tiles-samples-generator.js exited with an error code of ' + code);
18 | } else {
19 | done();
20 | }
21 | });
22 | }, 20000);
23 | });
24 |
--------------------------------------------------------------------------------
/samples-generator/specs/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "specs",
3 | "spec_files": [
4 | "**/*Spec.js"
5 | ],
6 | "helpers": [
7 | "matchers/nodeHelper.js"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/samples-generator/specs/matchers/customizeJasmine.js:
--------------------------------------------------------------------------------
1 | /*eslint strict: ["error", "function"]*/
2 | /*eslint-env amd*/
3 | define([
4 | './addDefaultMatchers',
5 | './equalsMethodEqualityTester'
6 | ], function (addDefaultMatchers,
7 | equalsMethodEqualityTester) {
8 | 'use strict';
9 |
10 | return function (env) {
11 | env.beforeEach(function () {
12 | addDefaultMatchers(true).call(env);
13 | env.addCustomEqualityTester(equalsMethodEqualityTester);
14 | });
15 | };
16 | });
17 |
--------------------------------------------------------------------------------
/samples-generator/specs/matchers/equals.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equals.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/FeatureDetection'
6 | ], function(
7 | FeatureDetection) {
8 | 'use strict';
9 | /*global CanvasPixelArray*/
10 |
11 | var typedArrayTypes = [];
12 |
13 | // Earlier versions of IE do not support typed arrays
14 | if (FeatureDetection.supportsTypedArrays()) {
15 | typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
16 |
17 | if (typeof Uint8ClampedArray !== 'undefined') {
18 | typedArrayTypes.push(Uint8ClampedArray);
19 | }
20 |
21 | if (typeof CanvasPixelArray !== 'undefined') {
22 | typedArrayTypes.push(CanvasPixelArray);
23 | }
24 | }
25 |
26 | function isTypedArray(o) {
27 | return typedArrayTypes.some(function(type) {
28 | return o instanceof type;
29 | });
30 | }
31 |
32 | function typedArrayToArray(array) {
33 | if (array !== null && typeof array === 'object' && isTypedArray(array)) {
34 | return Array.prototype.slice.call(array, 0);
35 | }
36 | return array;
37 | }
38 |
39 | function equals(util, customEqualiyTesters, a, b) {
40 | a = typedArrayToArray(a);
41 | b = typedArrayToArray(b);
42 | return util.equals(a, b, customEqualiyTesters);
43 | }
44 |
45 | return equals;
46 | });
47 |
--------------------------------------------------------------------------------
/samples-generator/specs/matchers/equalsMethodEqualityTester.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equalsMethodEqualityTester.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/defined'
6 | ], function(
7 | defined) {
8 | 'use strict';
9 |
10 | return function(a, b) {
11 | var to_run;
12 | // if either a or b have an equals method, call it.
13 | if (a !== null && defined(a)) {
14 | if (typeof a.equals === 'function') {
15 | return a.equals(b);
16 | } else if(a instanceof Object) {
17 | // Check if the current object has a static function named 'equals'
18 | to_run = Object.getPrototypeOf(a).constructor.equals;
19 | if( typeof to_run === 'function') {
20 | return to_run(a, b);
21 | }
22 | }
23 | }
24 |
25 | if (b !== null && defined(b)) {
26 | if (typeof b.equals === 'function') {
27 | return b.equals(a);
28 | } else if(b instanceof Object) {
29 | // Check if the current object has a static function named 'equals'
30 | to_run = Object.getPrototypeOf(b).constructor.equals;
31 | if( typeof to_run === 'function') {
32 | return to_run(b, a);
33 | }
34 | }
35 | }
36 |
37 | // fall back to default equality checks.
38 | return undefined;
39 | };
40 | });
41 |
--------------------------------------------------------------------------------
/samples-generator/specs/matchers/expectPromise.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 |
5 | var defined = Cesium.defined;
6 | var defaultValue = Cesium.defaultValue;
7 |
8 | module.exports = function expectPromise(promise, done) {
9 | return {
10 | toResolve: function toResolve() {
11 | return promise
12 | .then(done)
13 | .catch(function(err){
14 | done.fail('Expected promise to resolve' + err);
15 | });
16 | },
17 | toResolveWith: function toResolveWith(expectedValue) {
18 | return promise
19 | .then(function (result) {
20 | expect(result).toEqual(expectedValue);
21 | done();
22 | })
23 | .catch(function(err){
24 | done.fail('Expected promise to resolve' + err);
25 | });
26 | },
27 | toRejectWith: function toRejectWith(ErrorType, errorMessage) {
28 | var typeName = defaultValue(ErrorType.displayName, ErrorType.name);
29 |
30 | promise
31 | .then(function () {
32 | done.fail('expected promise to reject with ' + typeName);
33 | })
34 | .catch(function (error) {
35 | if (!(error instanceof ErrorType)) {
36 | done.fail(defaultValue(defaultValue(error.displayName, error.name), ErrorType) + ' to be instance of ' + typeName);
37 | console.log(error);
38 | }
39 |
40 | if (defined(errorMessage)) {
41 | expect(error.message).toEqual(errorMessage);
42 | }
43 | done();
44 | });
45 | }
46 | };
47 | };
48 |
--------------------------------------------------------------------------------
/samples-generator/specs/matchers/nodeHelper.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var requirejs = require('requirejs');
5 |
6 | var expectPromise = require('./expectPromise');
7 |
8 | //Since Jasmine matchers are shared between client and server code
9 | //We need to use requirejs to bring them into node.
10 | requirejs.config({
11 | baseUrl: path.join(__dirname, '../..'),
12 | paths: {
13 | 'Cesium': 'node_modules/cesium/source'
14 | },
15 | nodeRequire: require
16 | });
17 |
18 | var customizeJasmine = requirejs('./specs/matchers/customizeJasmine');
19 |
20 | var env = jasmine.getEnv();
21 | customizeJasmine(env);
22 |
23 | var oldExpect = global.expect;
24 | global.expect = function (promise, done) {
25 | //We can't use instanceof Promise here because promise
26 | //may not be a bluebird-defined Promise
27 | if (promise && promise.then && done) {
28 | return expectPromise(promise, done);
29 | }
30 |
31 | //If it wasn't a promise, call original implementation
32 | return oldExpect.apply(global, arguments);
33 | };
34 |
--------------------------------------------------------------------------------
/tools/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 | coverage/**
3 | doc/**
4 |
--------------------------------------------------------------------------------
/tools/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cesium/node"
3 | }
4 |
--------------------------------------------------------------------------------
/tools/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | package.json text eol=lf
--------------------------------------------------------------------------------
/tools/.gitignore:
--------------------------------------------------------------------------------
1 | # NPM
2 | node_modules
3 | npm-debug.log
4 | package-lock.json
5 |
6 | # WebStorm user-specific
7 | .idea/workspace.xml
8 | .idea/tasks.xml
9 |
10 | # Generated files
11 | .nyc_output
12 | .eslintcache
13 | doc
14 | coverage
15 | output
16 | *.tgz
17 | *.zip
18 |
19 | # User files
20 | test
--------------------------------------------------------------------------------
/tools/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tools/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tools/.idea/jsLinters/jshint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/tools/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tools/.idea/tools.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tools/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tools/.npmignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /doc
3 | /output
4 | /test
5 | /specs
6 | /tools
7 | /.idea
8 | .eslintrc.json
9 | .gitattributes
10 | .npmignore
11 | .travis.yml
12 | gulpfile.js
13 | *.tgz
14 | .eslintcache
15 | .nyc_output
16 |
--------------------------------------------------------------------------------
/tools/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/tools/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 8
4 | script:
5 | - npm run eslint
6 | - npm run test -- --failTaskOnError --suppressPassed
7 | after_success: 'npm run coverage'
--------------------------------------------------------------------------------
/tools/CHANGES.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 |
4 | ### 0.1.3 - 2017-04-14
5 |
6 | * Cleaned up project files and upgraded dependencies. [#70](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/70)
7 |
8 | ### 0.1.2 - 2017-04-07
9 |
10 | * Breaking changes
11 | * `extractB3dm` and `extractI3dm` now return the feature table JSON and batch table JSON instead of buffers.
12 | * `glbToB3dm` and `glbToI3dm` now take feature table JSON and batch table JSON instead of buffers.
13 | * Handle b3dm tiles with the legacy 24-byte header. [#69](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/69)
14 |
15 | ### 0.1.1 - 2017-03-15
16 |
17 | * Breaking changes
18 | * Renamed `tileset2sqlite3` to `tilesetToDatabase`.
19 | * Added `databaseToTileset` for unpacking a .3dtiles file to a tileset directory. [#62](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/62)
20 | * Added `glbToI3dm` and `optimizeI3dm` command line tools. [#46](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/46)
21 | * Handle b3dm tiles with the legacy 20-byte header. [#45](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/45)
22 | * Added `extractCmpt` to extract inner tiles from a cmpt tile and the `cmptToGlb` command line tool. [#42](https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/pull/42)
23 |
24 | ### 0.1.0 - 2016-12-16
25 |
26 | * Initial release.
--------------------------------------------------------------------------------
/tools/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 | var child_process = require('child_process');
5 | var fsExtra = require('fs-extra');
6 | var gulp = require('gulp');
7 | var Jasmine = require('jasmine');
8 | var jasmineSpecReporter = require('jasmine-spec-reporter');
9 | var open = require('open');
10 | var path = require('path');
11 | var Promise = require('bluebird');
12 | var yargs = require('yargs');
13 |
14 | var defined = Cesium.defined;
15 | var argv = yargs.argv;
16 |
17 | // Add third-party node module binaries to the system path
18 | // since some tasks need to call them directly.
19 | var environmentSeparator = process.platform === 'win32' ? ';' : ':';
20 | var nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
21 | process.env.PATH += environmentSeparator + nodeBinaries;
22 |
23 | var specFiles = ['**/*.js', '!node_modules/**', '!coverage/**'];
24 |
25 | gulp.task('test', function (done) {
26 | var jasmine = new Jasmine();
27 | jasmine.loadConfigFile('specs/jasmine.json');
28 | jasmine.addReporter(new jasmineSpecReporter.SpecReporter({
29 | displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
30 | }));
31 | jasmine.execute();
32 | jasmine.onComplete(function (passed) {
33 | done(argv.failTaskOnError && !passed ? 1 : 0);
34 | });
35 | });
36 |
37 | gulp.task('test-watch', function () {
38 | gulp.watch(specFiles).on('change', function () {
39 | // We can't simply depend on the test task because Jasmine
40 | // does not like being run multiple times in the same process.
41 | try {
42 | child_process.execSync('jasmine JASMINE_CONFIG_PATH=specs/jasmine.json', {
43 | stdio: [process.stdin, process.stdout, process.stderr]
44 | });
45 | } catch (exception) {
46 | console.log('Tests failed to execute.');
47 | }
48 | });
49 | });
50 |
51 | gulp.task('coverage', function () {
52 | fsExtra.removeSync('coverage/server');
53 | child_process.execSync('nyc' +
54 | ' --all' +
55 | ' --reporter=lcov' +
56 | ' --dir coverage' +
57 | ' -x "doc/**"' +
58 | ' -x "specs/**"' +
59 | ' -x "coverage/**"' +
60 | ' -x "gulpfile.js"' +
61 | ' -x "index.js"' +
62 | ' node_modules/jasmine/bin/jasmine.js' +
63 | ' JASMINE_CONFIG_PATH=specs/jasmine.json', {
64 | stdio: [process.stdin, process.stdout, process.stderr]
65 | });
66 | open('coverage/lcov-report/index.html');
67 | });
68 |
69 | gulp.task('jsDoc', function() {
70 | return new Promise(function(resolve, reject) {
71 | child_process.exec('jsdoc --configure tools/jsdoc/conf.json', function(error, stdout, stderr) {
72 | if (error) {
73 | console.log(stderr);
74 | return reject(error);
75 | }
76 | console.log(stdout);
77 | open('doc/index.html');
78 | resolve();
79 | });
80 | });
81 | });
82 |
83 | gulp.task('cloc', function() {
84 | var cmdLine;
85 | var clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
86 |
87 | //Run cloc on primary Source files only
88 | var source = new Promise(function(resolve, reject) {
89 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
90 | ' lib/ bin/';
91 |
92 | child_process.exec(cmdLine, function(error, stdout, stderr) {
93 | if (error) {
94 | console.log(stderr);
95 | return reject(error);
96 | }
97 | console.log('Source:');
98 | console.log(stdout);
99 | resolve();
100 | });
101 | });
102 |
103 | //If running cloc on source succeeded, also run it on the tests.
104 | return source.then(function() {
105 | return new Promise(function(resolve, reject) {
106 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
107 | ' specs/lib/';
108 | child_process.exec(cmdLine, function(error, stdout, stderr) {
109 | if (error) {
110 | console.log(stderr);
111 | return reject(error);
112 | }
113 | console.log('Specs:');
114 | console.log(stdout);
115 | resolve();
116 | });
117 | });
118 | });
119 | });
120 |
121 |
--------------------------------------------------------------------------------
/tools/index.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable global-require*/
2 | 'use strict';
3 | module.exports = {
4 | databaseToTileset : require('./lib/databaseToTileset'),
5 | extractB3dm : require('./lib/extractB3dm'),
6 | extractCmpt : require('./lib/extractCmpt'),
7 | extractI3dm : require('./lib/extractI3dm'),
8 | glbToB3dm : require('./lib/glbToB3dm'),
9 | glbToI3dm : require('./lib/glbToI3dm'),
10 | gzipTileset : require('./lib/gzipTileset'),
11 | runPipeline : require('./lib/runPipeline'),
12 | tilesetToDatabase : require('./lib/tilesetToDatabase')
13 | };
14 |
--------------------------------------------------------------------------------
/tools/lib/bufferToJson.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = bufferToJson;
3 |
4 | /**
5 | * @private
6 | */
7 | function bufferToJson(buffer) {
8 | if (buffer.length === 0) {
9 | return {};
10 | }
11 | return JSON.parse(buffer.toString());
12 | }
13 |
--------------------------------------------------------------------------------
/tools/lib/databaseToTileset.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var path = require('path');
5 | var Promise = require('bluebird');
6 | var sqlite3 = require('sqlite3');
7 | var zlib = require('zlib');
8 | var isGzipped = require('../lib/isGzipped');
9 |
10 | var defaultValue = Cesium.defaultValue;
11 | var defined = Cesium.defined;
12 | var DeveloperError = Cesium.DeveloperError;
13 |
14 | module.exports = databaseToTileset;
15 |
16 | /**
17 | * Unpacks a .3dtiles database to a tileset folder.
18 | *
19 | * @param {String} inputFile The input .3dtiles database file.
20 | * @param {String} [outputDirectory] The output directory of the tileset.
21 | * @returns {Promise} A promise that resolves when the tileset is written.
22 | */
23 | function databaseToTileset(inputFile, outputDirectory) {
24 | if (!defined(inputFile)) {
25 | throw new DeveloperError('inputFile is required.');
26 | }
27 |
28 | outputDirectory = defaultValue(outputDirectory, path.join(path.dirname(inputFile), path.basename(inputFile, path.extname(inputFile))));
29 |
30 | // Open the database.
31 | var db = new sqlite3.Database(inputFile, sqlite3.OPEN_READWRITE);
32 | var dbAll = Promise.promisify(db.all, {context : db});
33 |
34 | // Read a chunk of rows from the database at a time. Since the row contents contain tile blobs the limit should not be too high.
35 | var offset = 0;
36 | var limit = 100;
37 | var processChunk = function() {
38 | return dbAll('SELECT * FROM media LIMIT ? OFFSET ?', limit, offset)
39 | .then(function(rows) {
40 | if (rows.length === 0) {
41 | // No more rows left
42 | return Promise.resolve();
43 | }
44 | return Promise.map(rows, function(row) {
45 | ++offset;
46 | return writeFile(outputDirectory, row.key, row.content);
47 | })
48 | .then(function () {
49 | return processChunk();
50 | });
51 | });
52 | };
53 |
54 | return processChunk().finally(function() {
55 | db.close();
56 | });
57 | }
58 |
59 | function writeFile(outputDirectory, file, data) {
60 | var filePath = path.normalize(path.join(outputDirectory, file));
61 | if (isGzipped(data)) {
62 | data = zlib.gunzipSync(data);
63 | }
64 | return fsExtra.outputFile(filePath, data);
65 | }
66 |
--------------------------------------------------------------------------------
/tools/lib/directoryExists.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 |
4 | module.exports = directoryExists;
5 |
6 | /**
7 | * @private
8 | */
9 | function directoryExists(directory) {
10 | return fsExtra.stat(directory)
11 | .then(function(stats) {
12 | return stats.isDirectory();
13 | })
14 | .catch(function(err) {
15 | // If the directory doesn't exist the error code is ENOENT.
16 | // Otherwise something else went wrong - permission issues, etc.
17 | if (err.code !== 'ENOENT') {
18 | throw err;
19 | }
20 | return false;
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/tools/lib/extractB3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var bufferToJson = require('./bufferToJson');
4 | var getMagic = require('./getMagic');
5 |
6 | var defined = Cesium.defined;
7 | var DeveloperError = Cesium.DeveloperError;
8 |
9 | module.exports = extractB3dm;
10 |
11 | /**
12 | * Extracts information and sections from a b3dm buffer.
13 | *
14 | * @param {Buffer} b3dmBuffer A buffer containing a b3dm asset.
15 | * @returns {Object} An object containing the header and sections of the b3dm asset.
16 | */
17 | function extractB3dm(b3dmBuffer) {
18 | if (!defined(b3dmBuffer)) {
19 | throw new DeveloperError('b3dmBuffer is not defined.');
20 | }
21 | var magic = getMagic(b3dmBuffer);
22 | if (magic !== 'b3dm') {
23 | throw new DeveloperError('Invalid magic, expected "b3dm", got: "' + magic + '".');
24 | }
25 | var version = b3dmBuffer.readUInt32LE(4);
26 | if (version !== 1) {
27 | throw new DeveloperError('Invalid version, only "1" is valid, got: "' + version + '".');
28 | }
29 | var headerByteLength = 28;
30 | var byteLength = b3dmBuffer.readUInt32LE(8);
31 | var featureTableJsonByteLength = b3dmBuffer.readUInt32LE(12);
32 | var featureTableBinaryByteLength = b3dmBuffer.readUInt32LE(16);
33 | var batchTableJsonByteLength = b3dmBuffer.readUInt32LE(20);
34 | var batchTableBinaryByteLength = b3dmBuffer.readUInt32LE(24);
35 | var batchLength = 0;
36 |
37 | // Keep this legacy check in for now since a lot of tilesets are still using the old header.
38 | // Legacy header #1: [batchLength] [batchTableByteLength]
39 | // Legacy header #2: [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength]
40 | // Current header: [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength]
41 | // If the header is in the first legacy format 'batchTableJsonByteLength' will be the start of the JSON string (a quotation mark) or the glTF magic.
42 | // Accordingly its first byte will be either 0x22 or 0x67, and so the minimum uint32 expected is 0x22000000 = 570425344 = 570MB. It is unlikely that the feature table Json will exceed this length.
43 | // The check for the second legacy format is similar, except it checks 'batchTableBinaryByteLength' instead
44 | if (batchTableJsonByteLength >= 570425344) {
45 | // First legacy check
46 | headerByteLength = 20;
47 | batchLength = featureTableJsonByteLength;
48 | batchTableJsonByteLength = featureTableBinaryByteLength;
49 | batchTableBinaryByteLength = 0;
50 | featureTableJsonByteLength = 0;
51 | featureTableBinaryByteLength = 0;
52 | } else if (batchTableBinaryByteLength >= 570425344) {
53 | // Second legacy check
54 | headerByteLength = 24;
55 | batchLength = batchTableJsonByteLength;
56 | batchTableJsonByteLength = featureTableJsonByteLength;
57 | batchTableBinaryByteLength = featureTableBinaryByteLength;
58 | featureTableJsonByteLength = 0;
59 | featureTableBinaryByteLength = 0;
60 | }
61 |
62 | var featureTableJsonByteOffset = headerByteLength;
63 | var featureTableBinaryByteOffset = featureTableJsonByteOffset + featureTableJsonByteLength;
64 | var batchTableJsonByteOffset = featureTableBinaryByteOffset + featureTableBinaryByteLength;
65 | var batchTableBinaryByteOffset = batchTableJsonByteOffset + batchTableJsonByteLength;
66 | var glbByteOffset = batchTableBinaryByteOffset + batchTableBinaryByteLength;
67 |
68 | var featureTableJsonBuffer = b3dmBuffer.slice(featureTableJsonByteOffset, featureTableBinaryByteOffset);
69 | var featureTableBinary = b3dmBuffer.slice(featureTableBinaryByteOffset, batchTableJsonByteOffset);
70 | var batchTableJsonBuffer = b3dmBuffer.slice(batchTableJsonByteOffset, batchTableBinaryByteOffset);
71 | var batchTableBinary = b3dmBuffer.slice(batchTableBinaryByteOffset, glbByteOffset);
72 | var glbBuffer = b3dmBuffer.slice(glbByteOffset, byteLength);
73 | glbBuffer = alignGlb(glbBuffer, glbByteOffset);
74 |
75 | var featureTableJson = bufferToJson(featureTableJsonBuffer);
76 | var batchTableJson = bufferToJson(batchTableJsonBuffer);
77 |
78 | if (Object.keys(featureTableJson).length === 0) {
79 | featureTableJson = {
80 | BATCH_LENGTH : batchLength
81 | };
82 | }
83 |
84 | return {
85 | header : {
86 | magic : magic,
87 | version : version
88 | },
89 | featureTable : {
90 | json : featureTableJson,
91 | binary : featureTableBinary
92 | },
93 | batchTable : {
94 | json : batchTableJson,
95 | binary : batchTableBinary
96 | },
97 | glb : glbBuffer
98 | };
99 | }
100 |
101 | function alignGlb(buffer, byteOffset) {
102 | // The glb may not be aligned to an 8-byte boundary within the tile, causing gltf-pipeline operations to fail.
103 | // If unaligned, copy the glb to a new buffer.
104 | if (byteOffset % 8 === 0) {
105 | return buffer;
106 | }
107 | return Buffer.from(buffer);
108 | }
109 |
--------------------------------------------------------------------------------
/tools/lib/extractCmpt.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var getMagic = require('./getMagic');
5 |
6 | var defined = Cesium.defined;
7 | var DeveloperError = Cesium.DeveloperError;
8 |
9 | module.exports = extractCmpt;
10 |
11 | /**
12 | * Extracts interior tiles from a cmpt buffer. This operates recursively on interior cmpt tiles.
13 | *
14 | * @param {Buffer} buffer A buffer containing a cmpt asset.
15 | * @returns {Buffer[]} An array containing interior tiles.
16 | */
17 | function extractCmpt(buffer) {
18 | var results = [];
19 | extractCmptInner(buffer, results);
20 | return results;
21 | }
22 |
23 | function extractCmptInner(buffer, results) {
24 | if (!defined(buffer)) {
25 | throw new DeveloperError('buffer is not defined.');
26 | }
27 |
28 | var magic = getMagic(buffer);
29 | if (magic !== 'cmpt') {
30 | throw new DeveloperError('Invalid magic, expected "cmpt", got: "' + magic + '".');
31 | }
32 |
33 | var version = buffer.readUInt32LE(4);
34 | if (version !== 1) {
35 | throw new DeveloperError('Invalid version, only "1" is valid, got: "' + version + '".');
36 | }
37 |
38 | var tilesLength = buffer.readUInt32LE(12);
39 | var byteOffset = 16;
40 |
41 | for (var i = 0; i < tilesLength; ++i) {
42 | var innerMagic = getMagic(buffer, byteOffset);
43 | var innerByteLength = buffer.readUInt32LE(byteOffset + 8);
44 | var innerBuffer = buffer.slice(byteOffset, byteOffset + innerByteLength);
45 | byteOffset += innerByteLength;
46 |
47 | if (innerMagic === 'cmpt') {
48 | extractCmptInner(innerBuffer, results);
49 | } else {
50 | results.push(innerBuffer);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tools/lib/extractI3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 | var bufferToJson = require('./bufferToJson');
5 | var getMagic = require('./getMagic');
6 |
7 | var defined = Cesium.defined;
8 | var DeveloperError = Cesium.DeveloperError;
9 |
10 | module.exports = extractI3dm;
11 |
12 | /**
13 | * Extracts information and sections from an i3dm buffer.
14 | *
15 | * @param {Buffer} buffer A buffer containing an i3dm asset.
16 | * @returns {Object} An object containing the header and sections of the i3dm asset.
17 | */
18 | function extractI3dm(buffer) {
19 | if (!defined(buffer)) {
20 | throw new DeveloperError('buffer is not defined.');
21 | }
22 | var magic = getMagic(buffer);
23 | if (magic !== 'i3dm') {
24 | throw new DeveloperError('Invalid magic, expected "i3dm", got: "' + magic + '".');
25 | }
26 | var version = buffer.readUInt32LE(4);
27 | if (version !== 1) {
28 | throw new DeveloperError('Invalid version, only "1" is valid, got: "' + version + '".');
29 | }
30 |
31 | var byteLength = buffer.readUInt32LE(8);
32 | var featureTableJsonByteLength = buffer.readUInt32LE(12);
33 | var featureTableBinaryByteLength = buffer.readUInt32LE(16);
34 | var batchTableJsonByteLength = buffer.readUInt32LE(20);
35 | var batchTableBinaryByteLength = buffer.readUInt32LE(24);
36 | var gltfFormat = buffer.readUInt32LE(28);
37 |
38 | if (gltfFormat !== 1) {
39 | throw new DeveloperError('Only embedded binary glTF is supported.');
40 | }
41 |
42 | var headerByteLength = 32;
43 | var featureTableJsonByteOffset = headerByteLength;
44 | var featureTableBinaryByteOffset = featureTableJsonByteOffset + featureTableJsonByteLength;
45 | var batchTableJsonByteOffset = featureTableBinaryByteOffset + featureTableBinaryByteLength;
46 | var batchTableBinaryByteOffset = batchTableJsonByteOffset + batchTableJsonByteLength;
47 | var gltfByteOffset = batchTableBinaryByteOffset + batchTableBinaryByteLength;
48 |
49 | var gltfByteLength = byteLength - gltfByteOffset;
50 | if (gltfByteLength === 0) {
51 | throw new DeveloperError('glTF byte length is zero, i3dm must have a glTF to instance.');
52 | }
53 |
54 | var featureTableJsonBuffer = buffer.slice(featureTableJsonByteOffset, featureTableBinaryByteOffset);
55 | var featureTableBinaryBuffer = buffer.slice(featureTableBinaryByteOffset, batchTableJsonByteOffset);
56 | var batchTableJsonBuffer = buffer.slice(batchTableJsonByteOffset, batchTableBinaryByteOffset);
57 | var batchTableBinaryBuffer = buffer.slice(batchTableBinaryByteOffset, gltfByteOffset);
58 | var glbBuffer = buffer.slice(gltfByteOffset, byteLength);
59 | glbBuffer = alignGlb(glbBuffer, gltfByteOffset);
60 |
61 | var featureTableJson = bufferToJson(featureTableJsonBuffer);
62 | var batchTableJson = bufferToJson(batchTableJsonBuffer);
63 |
64 | return {
65 | header : {
66 | magic : magic,
67 | version : version,
68 | gltfFormat : gltfFormat
69 | },
70 | featureTable : {
71 | json : featureTableJson,
72 | binary : featureTableBinaryBuffer
73 | },
74 | batchTable : {
75 | json : batchTableJson,
76 | binary : batchTableBinaryBuffer
77 | },
78 | glb : glbBuffer
79 | };
80 | }
81 |
82 | function alignGlb(buffer, byteOffset) {
83 | if (byteOffset % 4 === 0) {
84 | return buffer;
85 | }
86 | return Buffer.from(buffer);
87 | }
88 |
--------------------------------------------------------------------------------
/tools/lib/fileExists.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 |
4 | module.exports = fileExists;
5 |
6 | /**
7 | * @private
8 | */
9 | function fileExists(filePath) {
10 | return fsExtra.stat(filePath)
11 | .then(function(stats) {
12 | return stats.isFile();
13 | })
14 | .catch(function(err) {
15 | // If the file doesn't exist the error code is ENOENT.
16 | // Otherwise something else went wrong - permission issues, etc.
17 | if (err.code !== 'ENOENT') {
18 | throw err;
19 | }
20 | return false;
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/tools/lib/getBufferPadded.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 | var defined = Cesium.defined;
6 |
7 | module.exports = getBufferPadded;
8 |
9 | /**
10 | * Pad the buffer to the next 8-byte boundary to ensure proper alignment for the section that follows.
11 | * Padding is not required by the 3D Tiles spec but is important when using Typed Arrays in JavaScript.
12 | *
13 | * @param {Buffer} buffer The buffer.
14 | * @param {Number} [byteOffset=0] The byte offset on which the buffer starts.
15 | * @returns {Buffer} The padded buffer.
16 | *
17 | * @private
18 | */
19 | function getBufferPadded(buffer, byteOffset) {
20 | if (!defined(buffer)) {
21 | return Buffer.alloc(0);
22 | }
23 |
24 | byteOffset = defaultValue(byteOffset, 0);
25 |
26 | var boundary = 8;
27 | var byteLength = buffer.length;
28 | var remainder = (byteOffset + byteLength) % boundary;
29 | var padding = (remainder === 0) ? 0 : boundary - remainder;
30 | var emptyBuffer = Buffer.alloc(padding);
31 | return Buffer.concat([buffer, emptyBuffer]);
32 | }
33 |
--------------------------------------------------------------------------------
/tools/lib/getDefaultWriteCallback.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var path = require('path');
4 |
5 | module.exports = getDefaultWriteCallback;
6 |
7 | /**
8 | * @private
9 | */
10 | function getDefaultWriteCallback(outputDirectory) {
11 | return function(file, data) {
12 | var outputFile = path.join(outputDirectory, file);
13 | return fsExtra.outputFile(outputFile, data);
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/tools/lib/getFilesInDirectory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var klaw = require('klaw');
3 | var Promise = require('bluebird');
4 |
5 | module.exports = getFilesInDirectory;
6 |
7 | /**
8 | * @private
9 | */
10 | function getFilesInDirectory(directory) {
11 | return new Promise(function (resolve, reject) {
12 | var files = [];
13 | klaw(directory)
14 | .on('data', function (item) {
15 | if (!item.stats.isDirectory()) {
16 | files.push(item.path);
17 | }
18 | })
19 | .on('end', function () {
20 | resolve(files);
21 | })
22 | .on('error', reject);
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/tools/lib/getJsonBufferPadded.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 | var defined = Cesium.defined;
6 |
7 | module.exports = getJsonBufferPadded;
8 |
9 | /**
10 | * Convert the JSON object to a padded buffer.
11 | *
12 | * Pad the JSON with extra whitespace to fit the next 8-byte boundary. This ensures proper alignment
13 | * for the section that follows (for example, batch table binary or feature table binary).
14 | * Padding is not required by the 3D Tiles spec but is important when using Typed Arrays in JavaScript.
15 | *
16 | * @param {Object} [json] The JSON object.
17 | * @param {Number} [byteOffset=0] The byte offset on which the buffer starts.
18 | * @returns {Buffer} The padded JSON buffer.
19 | *
20 | * @private
21 | */
22 | function getJsonBufferPadded(json, byteOffset) {
23 | // Check for undefined or empty
24 | if (!defined(json) || Object.keys(json).length === 0) {
25 | return Buffer.alloc(0);
26 | }
27 |
28 | byteOffset = defaultValue(byteOffset, 0);
29 | var string = JSON.stringify(json);
30 |
31 | var boundary = 8;
32 | var byteLength = Buffer.byteLength(string);
33 | var remainder = (byteOffset + byteLength) % boundary;
34 | var padding = (remainder === 0) ? 0 : boundary - remainder;
35 | var whitespace = '';
36 | for (var i = 0; i < padding; ++i) {
37 | whitespace += ' ';
38 | }
39 | string += whitespace;
40 |
41 | return Buffer.from(string);
42 | }
43 |
--------------------------------------------------------------------------------
/tools/lib/getMagic.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 |
4 | var defaultValue = Cesium.defaultValue;
5 |
6 | module.exports = getMagic;
7 |
8 | /**
9 | * @private
10 | */
11 | function getMagic(tileBuffer, byteOffset) {
12 | byteOffset = defaultValue(byteOffset, 0);
13 | return tileBuffer.toString('utf8', byteOffset, byteOffset + 4);
14 | }
15 |
--------------------------------------------------------------------------------
/tools/lib/getWorkingDirectory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require('path');
3 | var os = require('os');
4 | var uuid = require('uuid');
5 |
6 | module.exports = getWorkingDirectory;
7 |
8 | /**
9 | * @private
10 | */
11 | function getWorkingDirectory() {
12 | var tempDirectory = os.tmpdir();
13 | var randomId = uuid.v4();
14 | return path.join(tempDirectory, randomId);
15 | }
16 |
--------------------------------------------------------------------------------
/tools/lib/glbToB3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var getBufferPadded = require('./getBufferPadded');
4 | var getJsonBufferPadded = require('./getJsonBufferPadded');
5 |
6 | var defined = Cesium.defined;
7 | var DeveloperError = Cesium.DeveloperError;
8 |
9 | module.exports = glbToB3dm;
10 |
11 | /**
12 | * Generates a new Buffer representing a b3dm asset.
13 | *
14 | * @param {Buffer} glbBuffer A buffer containing a binary glTF asset.
15 | * @param {Object} [featureTableJson] The feature table JSON.
16 | * @param {Buffer} [featureTableBinary] The feature table binary.
17 | * @param {Object} [batchTableJson] The batch table JSON.
18 | * @param {Buffer} [batchTableBinary] The batch table binary.
19 | * @returns {Buffer} Buffer representing the b3dm asset.
20 | */
21 | function glbToB3dm(glbBuffer, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary) {
22 | if (!defined(glbBuffer)) {
23 | throw new DeveloperError('glbBuffer is not defined.');
24 | }
25 |
26 | var headerByteLength = 28;
27 | var featureTableJsonBuffer = getJsonBufferPadded(featureTableJson, headerByteLength);
28 | var featureTableBinaryBuffer = getBufferPadded(featureTableBinary);
29 | var batchTableJsonBuffer = getJsonBufferPadded(batchTableJson);
30 | var batchTableBinaryBuffer = getBufferPadded(batchTableBinary);
31 |
32 | var byteLength = headerByteLength + featureTableJsonBuffer.length + featureTableBinaryBuffer.length + batchTableJsonBuffer.length + batchTableBinaryBuffer.length + glbBuffer.length;
33 | var header = Buffer.alloc(headerByteLength);
34 | header.write('b3dm', 0); // magic
35 | header.writeUInt32LE(1, 4); // version
36 | header.writeUInt32LE(byteLength, 8); // byteLength - length of entire tile, including header, in bytes
37 | header.writeUInt32LE(featureTableJsonBuffer.length, 12); // featureTableJSONByteLength - length of feature table JSON section in bytes.
38 | header.writeUInt32LE(featureTableBinaryBuffer.length, 16); // featureTableBinaryByteLength - length of feature table binary section in bytes.
39 | header.writeUInt32LE(batchTableJsonBuffer.length, 20); // batchTableJSONByteLength - length of batch table JSON section in bytes. (0 for basic, no batches)
40 | header.writeUInt32LE(batchTableBinaryBuffer.length, 24); // batchTableBinaryByteLength - length of batch table binary section in bytes. (0 for basic, no batches)
41 |
42 | return Buffer.concat([header, featureTableJsonBuffer, featureTableBinaryBuffer, batchTableJsonBuffer, batchTableBinaryBuffer, glbBuffer]);
43 | }
44 |
--------------------------------------------------------------------------------
/tools/lib/glbToI3dm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var getBufferPadded = require('./getBufferPadded');
4 | var getJsonBufferPadded = require('./getJsonBufferPadded');
5 |
6 | var defined = Cesium.defined;
7 | var DeveloperError = Cesium.DeveloperError;
8 |
9 | module.exports = glbToI3dm;
10 |
11 | /**
12 | * Generates a new Buffer representing a i3dm asset.
13 | *
14 | * @param {Buffer} glbBuffer A buffer containing a binary glTF asset.
15 | * @param {Object} [featureTableJson] The feature table JSON.
16 | * @param {Buffer} [featureTableBinary] The feature table binary.
17 | * @param {Object} [batchTableJson] The batch table JSON.
18 | * @param {Buffer} [batchTableBinary] The batch table binary.
19 | * @returns {Buffer} Buffer representing the i3dm asset.
20 | */
21 | function glbToI3dm(glbBuffer, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary) {
22 | if (!defined(glbBuffer)) {
23 | throw new DeveloperError('glbBuffer is not defined.');
24 | }
25 |
26 | var featureTableJsonBuffer = getJsonBufferPadded(featureTableJson);
27 | var featureTableBinaryBuffer = getBufferPadded(featureTableBinary);
28 | var batchTableJsonBuffer = getJsonBufferPadded(batchTableJson);
29 | var batchTableBinaryBuffer = getBufferPadded(batchTableBinary);
30 |
31 | var headerByteLength = 32;
32 | var byteLength = headerByteLength + featureTableJsonBuffer.length + featureTableBinaryBuffer.length + batchTableJsonBuffer.length + batchTableBinaryBuffer.length + glbBuffer.length;
33 | var gltfFormat = 1;
34 |
35 | var header = Buffer.alloc(32);
36 | header.write('i3dm', 0); // magic
37 | header.writeUInt32LE(1, 4); // version
38 | header.writeUInt32LE(byteLength, 8); // byteLength - length of entire tile, including header, in bytes
39 | header.writeUInt32LE(featureTableJsonBuffer.length, 12); // featureTableJsonByteLength - length of feature table JSON section in bytes.
40 | header.writeUInt32LE(featureTableBinaryBuffer.length, 16); // featureTableBinaryByteLength - length of feature table binary section in bytes.
41 | header.writeUInt32LE(batchTableJsonBuffer.length, 20); // batchTableJsonByteLength - length of batch table JSON section in bytes.
42 | header.writeUInt32LE(batchTableBinaryBuffer.length, 24); // batchTableBinaryByteLength - length of batch table binary section in bytes.
43 | header.writeUInt32LE(gltfFormat, 28); // gltfFormat - format of the glTF body field (0 for URL, 1 for embedded binary)
44 |
45 | return Buffer.concat([header, featureTableJsonBuffer, featureTableBinaryBuffer, batchTableJsonBuffer, batchTableBinaryBuffer, glbBuffer]);
46 | }
47 |
--------------------------------------------------------------------------------
/tools/lib/gzipTileset.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var path = require('path');
5 | var zlib = require('zlib');
6 | var getDefaultWriteCallback = require('./getDefaultWriteCallback');
7 | var isGzipped = require('./isGzipped');
8 | var isTile = require('./isTile');
9 | var walkDirectory = require('./walkDirectory');
10 |
11 | var Check = Cesium.Check;
12 | var defaultValue = Cesium.defaultValue;
13 | var defined = Cesium.defined;
14 |
15 | module.exports = gzipTileset;
16 |
17 | /**
18 | * gzips or ungzips the input tileset.
19 | *
20 | * @param {Object} options Object with the following properties:
21 | * @param {String} options.inputDirectory Path to the input directory.
22 | * @param {Object} [options.outputDirectory] Path to the output directory.
23 | * @param {Boolean} [options.gzip=true] Whether to gzip or ungzip the tileset.
24 | * @param {Boolean} [options.tilesOnly=false] Only gzip tiles, does not gzip tileset.json or other files.
25 | * @param {WriteCallback} [options.writeCallback] A callback function that writes files after they have been processed.
26 | * @param {LogCallback} [options.logCallback] A callback function that logs messages.
27 | *
28 | * @returns {Promise} A promise that resolves when the operation completes.
29 | */
30 | function gzipTileset(options) {
31 | options = defaultValue(options, defaultValue.EMPTY_OBJECT);
32 | var inputDirectory = options.inputDirectory;
33 | var outputDirectory = options.outputDirectory;
34 | var gzip = defaultValue(options.gzip, true);
35 | var tilesOnly = defaultValue(options.tilesOnly, false);
36 |
37 | Check.typeOf.string('options.inputDirectory', inputDirectory);
38 |
39 | inputDirectory = path.normalize(inputDirectory);
40 | outputDirectory = path.normalize(defaultValue(outputDirectory,
41 | path.join(path.dirname(inputDirectory), path.basename(inputDirectory) + '-' + (gzip ? 'gzipped' : 'ungzipped'))));
42 |
43 | var writeCallback = defaultValue(options.writeCallback, getDefaultWriteCallback(outputDirectory));
44 | var logCallback = options.logCallback;
45 |
46 | if (defined(logCallback)) {
47 | logCallback((gzip ? 'Compressing' : 'Uncompressing') + ' files...');
48 | }
49 |
50 | var operation = gzip ? zlib.gzipSync : zlib.gunzipSync;
51 | return walkDirectory(inputDirectory, function(file) {
52 | return fsExtra.readFile(file)
53 | .then(function(data) {
54 | if (!(gzip && tilesOnly && !isTile(file)) && (isGzipped(data) !== gzip)) {
55 | data = operation(data);
56 | }
57 | var relativePath = path.relative(inputDirectory, file);
58 | return writeCallback(relativePath, data);
59 | });
60 | });
61 | }
62 |
--------------------------------------------------------------------------------
/tools/lib/isGzipped.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = isGzipped;
3 |
4 | /**
5 | * @private
6 | */
7 | function isGzipped(buffer) {
8 | return (buffer[0] === 0x1f) && (buffer[1] === 0x8b);
9 | }
10 |
--------------------------------------------------------------------------------
/tools/lib/isGzippedFile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var Promise = require('bluebird');
4 | var isGzipped = require('./isGzipped');
5 |
6 | module.exports = isGzippedFile;
7 |
8 | var readStreamOptions = {
9 | start : 0,
10 | end : 2
11 | };
12 |
13 | /**
14 | * @private
15 | */
16 | function isGzippedFile(file) {
17 | return new Promise(function (resolve, reject) {
18 | var readStream = fsExtra.createReadStream(file, readStreamOptions);
19 | readStream.on('error', reject);
20 | readStream.on('data', function(chunk) {
21 | resolve(isGzipped(chunk));
22 | readStream.destroy();
23 | });
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/tools/lib/isJson.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require('path');
3 |
4 | module.exports = isJson;
5 |
6 | /**
7 | * @private
8 | */
9 | function isJson(file) {
10 | return path.extname(file) === '.json';
11 | }
12 |
--------------------------------------------------------------------------------
/tools/lib/isTile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var path = require('path');
3 |
4 | module.exports = isTile;
5 |
6 | /**
7 | * @private
8 | */
9 | function isTile(file) {
10 | var extension = path.extname(file);
11 | return extension === '.b3dm' ||
12 | extension === '.i3dm' ||
13 | extension === '.pnts' ||
14 | extension === '.cmpt' ||
15 | extension === '.vctr';
16 | }
17 |
--------------------------------------------------------------------------------
/tools/lib/makeCompositeTile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var getBufferPadded = require('./getBufferPadded');
3 |
4 | module.exports = makeCompositeTile;
5 |
6 | /**
7 | * Combines an array of tile buffers into a single composite tile.
8 | *
9 | * @param {Buffer[]} tileBuffers An array of buffers holding tile data.
10 | * @returns {Buffer} A single buffer holding the composite tile.
11 | */
12 | function makeCompositeTile(tileBuffers) {
13 | var headerByteLength = 16;
14 | var buffers = [];
15 | var byteLength = headerByteLength;
16 | var tilesLength = tileBuffers.length;
17 | for (var i = 0; i < tilesLength; i++) {
18 | var tile = tileBuffers[i];
19 | tile = getBufferPadded(tile, byteLength);
20 | tile.writeUInt32LE(tile.length, 8); // Rewrite byte length
21 | buffers.push(tile);
22 | byteLength += tile.length;
23 | }
24 | var header = Buffer.alloc(16);
25 | header.write('cmpt', 0); // magic
26 | header.writeUInt32LE(1, 4); // version
27 | header.writeUInt32LE(byteLength, 8); // byteLength
28 | header.writeUInt32LE(tilesLength, 12); // tilesLength
29 |
30 | buffers.unshift(header);
31 | return Buffer.concat(buffers);
32 | }
33 |
--------------------------------------------------------------------------------
/tools/lib/optimizeGlb.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var GltfPipeline = require('gltf-pipeline');
4 |
5 | var Cartesian3 = Cesium.Cartesian3;
6 | var DeveloperError = Cesium.DeveloperError;
7 | var defaultValue = Cesium.defaultValue;
8 | var defined = Cesium.defined;
9 |
10 | var addCesiumRTC = GltfPipeline.addCesiumRTC;
11 | var getBinaryGltf = GltfPipeline.getBinaryGltf;
12 | var loadGltfUris = GltfPipeline.loadGltfUris;
13 | var parseBinaryGltf = GltfPipeline.parseBinaryGltf;
14 | var Pipeline = GltfPipeline.Pipeline;
15 |
16 | module.exports = optimizeGlb;
17 |
18 | /**
19 | * Given an input buffer containing a binary glTF asset, optimize it using gltf-pipeline with the provided options
20 | *
21 | * @param {Buffer} glbBuffer The buffer containing the binary glTF.
22 | * @param {Object} [options] Options specifying custom gltf-pipeline behavior.
23 | * @returns {Promise} A promise that resolves to the optimized binary glTF.
24 | * @private
25 | */
26 | function optimizeGlb(glbBuffer, options) {
27 | options = defaultValue(options, defaultValue.EMPTY_OBJECT);
28 | if (!defined(glbBuffer)) {
29 | throw new DeveloperError('glbBuffer is not defined.');
30 | }
31 | var rtcPosition;
32 | var gltf = parseBinaryGltf(glbBuffer);
33 | var extensions = gltf.extensions;
34 | if (defined(extensions)) {
35 | // If it is used, extract the CesiumRTC extension and add it back after processing
36 | var cesiumRTC = extensions.CESIUM_RTC;
37 | if (defined(cesiumRTC)) {
38 | rtcPosition = Cartesian3.unpack(cesiumRTC.center);
39 | }
40 | }
41 | fixBatchIdSemantic(gltf);
42 | return loadGltfUris(gltf, options)
43 | .then(function() {
44 | return Pipeline.processJSONWithExtras(gltf, options)
45 | .then(function(gltf) {
46 | if (defined(rtcPosition)) {
47 | addCesiumRTC(gltf, {
48 | position: rtcPosition
49 | });
50 | }
51 | var embed = defaultValue(options.embed, true);
52 | var embedImage = defaultValue(options.embedImage, true);
53 | return getBinaryGltf(gltf, embed, embedImage).glb;
54 | });
55 | });
56 | }
57 |
58 | function fixBatchIdSemantic(gltf) {
59 | var meshes = gltf.meshes;
60 | for (var meshId in meshes) {
61 | if (meshes.hasOwnProperty(meshId)) {
62 | var primitives = meshes[meshId].primitives;
63 | var primitivesLength = primitives.length;
64 | for (var i = 0; i < primitivesLength; ++i) {
65 | var attributes = primitives[i].attributes;
66 | if (defined(attributes.BATCHID)) {
67 | attributes._BATCHID = attributes.BATCHID;
68 | delete attributes.BATCHID;
69 | }
70 | }
71 | }
72 | }
73 |
74 | var techniques = gltf.techniques;
75 | for (var techniqueId in techniques) {
76 | if (techniques.hasOwnProperty(techniqueId)) {
77 | var parameters = techniques[techniqueId].parameters;
78 | for (var parameterId in parameters) {
79 | if (parameters.hasOwnProperty(parameterId)) {
80 | var parameter = parameters[parameterId];
81 | if (parameter.semantic === 'BATCHID') {
82 | parameter.semantic = '_BATCHID';
83 | }
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/tools/lib/readFile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var zlib = require('zlib');
5 | var isGzipped = require('./isGzipped');
6 |
7 | var defaultValue = Cesium.defaultValue;
8 |
9 | module.exports = readFile;
10 |
11 | /**
12 | * Reads the contents of a file.
13 | *
14 | * @param {String} filePath The file path to read from.
15 | * @param {String} [type=binary] Whether to read the file as 'binary', 'text', or 'json'.
16 | * @returns {Promise} A promise that resolves with the file contents as either a Buffer, String, or JSON object.
17 | */
18 | function readFile(filePath, type) {
19 | type = defaultValue(type, 'binary');
20 | return fsExtra.readFile(filePath)
21 | .then(function (data) {
22 | if (isGzipped(data)) {
23 | data = zlib.gunzipSync(data);
24 | }
25 | if (type === 'text') {
26 | return data.toString();
27 | } else if (type === 'json') {
28 | return JSON.parse(data.toString());
29 | }
30 | return data;
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/tools/lib/runPipeline.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var path = require('path');
5 | var Promise = require('bluebird');
6 | var combineTileset = require('./combineTileset');
7 | var getWorkingDirectory = require('./getWorkingDirectory');
8 | var gzipTileset = require('./gzipTileset');
9 | var upgradeTileset = require('./upgradeTileset');
10 |
11 | var defaultValue = Cesium.defaultValue;
12 | var defined = Cesium.defined;
13 | var DeveloperError = Cesium.DeveloperError;
14 |
15 | module.exports = runPipeline;
16 |
17 | /**
18 | * Run an input pipeline.
19 | *
20 | * @param {Object} pipeline A JSON object containing an input, output, and list of stages to run.
21 | * @param {String} pipeline.input Input tileset path.
22 | * @param {String} [pipeline.output] Output tileset path.
23 | * @param {Array} [pipeline.stages] The stages to run on the tileset.
24 | * @param {Object} [options] An object with the following properties:
25 | * @param {WriteCallback} [options.writeCallback] A callback function that writes files after they have been processed.
26 | * @param {LogCallback} [options.logCallback] A callback function that logs messages.
27 | */
28 | function runPipeline(pipeline, options) {
29 | pipeline = defaultValue(pipeline, defaultValue.EMPTY_OBJECT);
30 | var inputDirectory = pipeline.input;
31 | var outputDirectory = pipeline.output;
32 | var stages = pipeline.stages;
33 | if (!defined(inputDirectory)) {
34 | throw new DeveloperError('pipeline.input is required');
35 | }
36 |
37 | inputDirectory = path.normalize(inputDirectory);
38 | outputDirectory = path.normalize(defaultValue(outputDirectory,
39 | path.join(path.dirname(inputDirectory), path.basename(inputDirectory) + '-processed')));
40 |
41 | if (!defined(stages)) {
42 | return fsExtra.copy(inputDirectory, outputDirectory);
43 | }
44 |
45 | options = defaultValue(options, defaultValue.EMPTY_OBJECT);
46 |
47 | var writeCallback = options.writeCallback;
48 | var logCallback = options.logCallback;
49 |
50 | var workingDirectory1 = getWorkingDirectory();
51 | var workingDirectory2 = getWorkingDirectory();
52 |
53 | var stageObjects = [];
54 |
55 | var stagesLength = stages.length;
56 | for (var i = 0; i < stagesLength; ++i) {
57 | var stageName;
58 | var stageOptions;
59 | var stage = stages[i];
60 | if (typeof stage === 'string') {
61 | stageName = stage;
62 | stageOptions = {};
63 | } else {
64 | stageName = stage.name;
65 | if (!defined(stageName)) {
66 | throw new DeveloperError('Stage must have a "name" property');
67 | }
68 | stageOptions = stage;
69 | }
70 |
71 | // Ping-pong between the two working directories when multiple stages are run
72 | var stageInputDirectory = (i === 0) ? inputDirectory : ((i % 2 === 0) ? workingDirectory2 : workingDirectory1);
73 | var stageOutputDirectory = (i === stagesLength - 1) ? outputDirectory : ((i % 2 === 0) ? workingDirectory1 : workingDirectory2);
74 |
75 | stageOptions.inputDirectory = stageInputDirectory;
76 | stageOptions.outputDirectory = stageOutputDirectory;
77 | stageOptions.logCallback = logCallback;
78 |
79 | if (i === stagesLength - 1) {
80 | // TODO : Not sure if this is the right approach. Should the writeCallback also have control over the temp directories? How would that work?
81 | // Only allow the write callback to act on the last stage. The intermediary stages always write to temp directories.
82 | stageOptions.writeCallback = writeCallback;
83 | }
84 |
85 | var stageFunction = getStageFunction(stageName, stageOptions);
86 | if (!defined(stageFunction)) {
87 | throw new DeveloperError('Stage "' + stageName + '" does not exist');
88 | }
89 |
90 | stageObjects.push({
91 | options : stageOptions,
92 | stageFunction : stageFunction,
93 | name : stageName
94 | });
95 | }
96 |
97 | // Run the stages in sequence
98 | return Promise.each(stageObjects, function(stage) {
99 | return fsExtra.emptyDir(stage.options.outputDirectory)
100 | .then(function() {
101 | if (defined(logCallback)) {
102 | logCallback('Running ' + stage.name);
103 | }
104 | return stage.stageFunction(stage.options);
105 | });
106 | }).finally(function() {
107 | return Promise.all([
108 | fsExtra.remove(workingDirectory1),
109 | fsExtra.remove(workingDirectory2)
110 | ]);
111 | });
112 | }
113 |
114 | function getStageFunction(stageName, stageOptions) {
115 | switch (stageName) {
116 | case 'gzip':
117 | stageOptions.gzip = true;
118 | return gzipTileset;
119 | case 'ungzip':
120 | stageOptions.gzip = false;
121 | return gzipTileset;
122 | case 'combine':
123 | return combineTileset;
124 | case 'upgrade':
125 | return upgradeTileset;
126 | default:
127 | return undefined;
128 | }
129 | }
130 |
131 | /**
132 | * A callback function that writes files after they have been processed.
133 | * @callback WriteCallback
134 | *
135 | * @param {String} file Relative path of the file.
136 | * @param {Buffer} buffer A buffer storing the processed file's data.
137 | * @returns {Promise} A promise that resolves when the callback is complete.
138 | */
139 |
140 | /**
141 | * A callback function that logs messages.
142 | * @callback LogCallback
143 | *
144 | * @param {String} message A log message.
145 | */
146 |
--------------------------------------------------------------------------------
/tools/lib/tilesetToDatabase.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var klaw = require('klaw');
5 | var path = require('path');
6 | var Promise = require('bluebird');
7 | var sqlite3 = require('sqlite3');
8 | var zlib = require('zlib');
9 | var isGzipped = require('../lib/isGzipped');
10 | var isTile = require('../lib/isTile');
11 |
12 | var defaultValue = Cesium.defaultValue;
13 | var defined = Cesium.defined;
14 | var DeveloperError = Cesium.DeveloperError;
15 |
16 | module.exports = tilesetToDatabase;
17 |
18 | /**
19 | * Generates a sqlite database for a tileset, saved as a .3dtiles file.
20 | *
21 | * @param {String} inputDirectory The input directory of the tileset.
22 | * @param {String} [outputFile] The output .3dtiles database file.
23 | * @returns {Promise} A promise that resolves when the database is written.
24 | */
25 | function tilesetToDatabase(inputDirectory, outputFile) {
26 | if (!defined(inputDirectory)) {
27 | throw new DeveloperError('inputDirectory is required.');
28 | }
29 |
30 | outputFile = defaultValue(outputFile,
31 | path.join(path.dirname(inputDirectory), path.basename(inputDirectory) + '.3dtiles'));
32 |
33 | var db;
34 | var dbRun;
35 | // Delete the .3dtiles file if it already exists
36 | return Promise.resolve(fsExtra.remove(outputFile))
37 | .then(function () {
38 | // Create the database.
39 | db = new sqlite3.Database(outputFile, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);
40 | dbRun = Promise.promisify(db.run, {context: db});
41 |
42 | // Disable journaling and create the table.
43 | return dbRun('PRAGMA journal_mode=off;');
44 | })
45 | .then(function () {
46 | return dbRun('BEGIN');
47 | })
48 | .then(function () {
49 | return dbRun('CREATE TABLE media (key TEXT PRIMARY KEY, content BLOB)');
50 | })
51 | .then(function () {
52 | //Build the collection of file paths to be inserted.
53 | var filePaths = [];
54 | var stream = klaw(inputDirectory);
55 | stream.on('readable', function () {
56 | var filePath = stream.read();
57 | while (defined(filePath)) {
58 | if (filePath.stats.isFile()) {
59 | filePaths.push(filePath.path);
60 | }
61 | filePath = stream.read();
62 | }
63 | });
64 |
65 | return new Promise(function (resolve, reject) {
66 | stream.on('error', reject);
67 | stream.on('end', function () {
68 | resolve(filePaths);
69 | });
70 | });
71 | })
72 | .then(function (filePaths) {
73 | return Promise.map(filePaths, function (filePath) {
74 | return fsExtra.readFile(filePath)
75 | .then(function (data) {
76 | filePath = path.normalize(path.relative(inputDirectory, filePath)).replace(/\\/g, '/');
77 | // Only gzip tiles and json files. Other files like external textures should not be gzipped.
78 | var shouldGzip = isTile(filePath) || path.extname(filePath) === '.json';
79 | if (shouldGzip && !isGzipped(data)) {
80 | data = zlib.gzipSync(data);
81 | }
82 | return dbRun('INSERT INTO media VALUES (?, ?)', [filePath, data]);
83 | });
84 | }, {concurrency: 100});
85 | })
86 | .then(function () {
87 | return dbRun('COMMIT');
88 | })
89 | .finally(function () {
90 | if (defined(db)) {
91 | db.close();
92 | }
93 | });
94 | }
95 |
--------------------------------------------------------------------------------
/tools/lib/upgradeTileset.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var path = require('path');
4 | var Promise = require('bluebird');
5 | var zlib = require('zlib');
6 | var extractB3dm = require('./extractB3dm');
7 | var extractCmpt = require('./extractCmpt');
8 | var getDefaultWriteCallback = require('./getDefaultWriteCallback');
9 | var getMagic = require('./getMagic');
10 | var glbToB3dm = require('./glbToB3dm');
11 | var isGzippedFile = require('./isGzippedFile');
12 | var isJson = require('./isJson');
13 | var isTile = require('./isTile');
14 | var makeCompositeTile = require('./makeCompositeTile');
15 | var optimizeGlb = require('./optimizeGlb');
16 | var readFile = require('./readFile');
17 | var walkDirectory = require('./walkDirectory');
18 |
19 | var Check = Cesium.Check;
20 | var defaultValue = Cesium.defaultValue;
21 | var defined = Cesium.defined;
22 |
23 | module.exports = upgradeTileset;
24 |
25 | /**
26 | * Upgrades the input tileset to the latest version of the 3D Tiles spec. Embedded glTF models will be upgraded to glTF 2.0.
27 | *
28 | * @param {Object} options Object with the following properties:
29 | * @param {String} options.inputDirectory Path to the input directory.
30 | * @param {Object} [options.outputDirectory] Path to the output directory.
31 | * @param {WriteCallback} [options.writeCallback] A callback function that writes files after they have been processed.
32 | * @param {LogCallback} [options.logCallback] A callback function that logs messages.
33 | *
34 | * @returns {Promise} A promise that resolves when the operation completes.
35 | */
36 | function upgradeTileset(options) {
37 | options = defaultValue(options, defaultValue.EMPTY_OBJECT);
38 | var inputDirectory = options.inputDirectory;
39 | var outputDirectory = options.outputDirectory;
40 |
41 | Check.typeOf.string('options.inputDirectory', inputDirectory);
42 |
43 | inputDirectory = path.normalize(inputDirectory);
44 | outputDirectory = path.normalize(defaultValue(outputDirectory,
45 | path.join(path.dirname(inputDirectory), path.basename(inputDirectory) + '-upgrades')));
46 |
47 | var writeCallback = defaultValue(options.writeCallback, getDefaultWriteCallback(outputDirectory));
48 | var logCallback = options.logCallback;
49 |
50 | if (defined(logCallback)) {
51 | logCallback('Upgrading to 3D Tiles version 1.0');
52 | }
53 |
54 | return walkDirectory(inputDirectory, function(file) {
55 | return isGzippedFile(file)
56 | .then(function(gzipped) {
57 | return upgradeFile(file)
58 | .then(function(data) {
59 | if (gzipped) {
60 | data = zlib.gzipSync(data);
61 | }
62 | var relativePath = path.relative(inputDirectory, file);
63 | return writeCallback(relativePath, data);
64 | });
65 | });
66 | });
67 | }
68 |
69 | function upgradeFile(file) {
70 | if (isJson(file)) {
71 | return upgradeTilesetJson(file);
72 | } else if (isTile(file)) {
73 | return upgradeTile(file);
74 | }
75 | return readFile(file);
76 | }
77 |
78 | function upgradeTilesetJson(file) {
79 | return readFile(file, 'text')
80 | .then(function(contents) {
81 | contents = contents.replace(/"version": ".*"/g, '"version": "1.0"');
82 | contents = contents.replace(/"add"/g, '"ADD"');
83 | contents = contents.replace(/"replace"/g, '"REPLACE"');
84 | return Buffer.from(contents);
85 | });
86 | }
87 |
88 | var optimizeOptions = {
89 | preserve : true
90 | };
91 |
92 | function upgradeTile(file) {
93 | return readFile(file)
94 | .then(function(buffer) {
95 | return upgradeTileContent(buffer, path.dirname(file));
96 | });
97 | }
98 |
99 | function upgradeTileContent(buffer, basePath) {
100 | var magic = getMagic(buffer);
101 | if (magic === 'b3dm') {
102 | var b3dm = extractB3dm(buffer);
103 | return optimizeGlb(b3dm.glb, Object.assign({}, optimizeOptions, {basePath: basePath}))
104 | .then(function(glb) {
105 | return glbToB3dm(glb, b3dm.featureTable.json, b3dm.featureTable.binary, b3dm.batchTable.json, b3dm.batchTable.binary);
106 | });
107 | } else if (magic === 'cmpt') {
108 | var tiles = extractCmpt(buffer);
109 | return Promise.map(tiles, function(tile) {
110 | return upgradeTileContent(tile, basePath);
111 | }).then(function(upgradedTiles) {
112 | return makeCompositeTile(upgradedTiles);
113 | });
114 | }
115 | return buffer;
116 | }
117 |
--------------------------------------------------------------------------------
/tools/lib/walkDirectory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var klaw = require('klaw');
4 | var Promise = require('bluebird');
5 |
6 | var defined = Cesium.defined;
7 |
8 | module.exports = walkDirectory;
9 |
10 | /**
11 | * @private
12 | */
13 | function walkDirectory(directory, processFileCallback) {
14 | return new Promise(function(resolve, reject) {
15 | getNumberOfFilesInDirectory(directory)
16 | .then(function(numberOfFiles) {
17 | var numberComplete = 0;
18 | function complete() {
19 | ++numberComplete;
20 | if (numberComplete === numberOfFiles) {
21 | resolve();
22 | }
23 | }
24 | walk(directory, processFileCallback, complete, reject);
25 | })
26 | .catch(reject);
27 | });
28 | }
29 |
30 | function getNumberOfFilesInDirectory(directory) {
31 | return new Promise(function(resolve, reject) {
32 | var numberOfFiles = 0;
33 | klaw(directory)
34 | .on('data', function (item) {
35 | if (!item.stats.isDirectory()) {
36 | ++numberOfFiles;
37 | }
38 | })
39 | .on('end', function () {
40 | resolve(numberOfFiles);
41 | })
42 | .on('error', reject);
43 | });
44 | }
45 |
46 | function walk(directory, processFileCallback, resolve, reject) {
47 | klaw(directory)
48 | .on('data', function (item) {
49 | if (!item.stats.isDirectory()) {
50 | var promise = processFileCallback(item.path);
51 | if (defined(promise) && defined(promise.then)) {
52 | promise
53 | .then(resolve)
54 | .catch(reject);
55 | } else {
56 | resolve();
57 | }
58 | }
59 | })
60 | .on('error', reject);
61 | }
62 |
--------------------------------------------------------------------------------
/tools/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "3d-tiles-tools",
3 | "version": "0.1.3",
4 | "license": "Apache-2.0",
5 | "description": "Tools for debugging, analyzing, and validating 3D Tiles tilesets.",
6 | "author": {
7 | "name": "Analytical Graphics, Inc. and Contributors"
8 | },
9 | "keywords": [
10 | "3D Tiles"
11 | ],
12 | "homepage": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/issues"
19 | },
20 | "main": "index.js",
21 | "engines": {
22 | "node": ">=4.0.0"
23 | },
24 | "dependencies": {
25 | "bluebird": "^3.5.1",
26 | "cesium": "^1.39",
27 | "fs-extra": "^4.0.2",
28 | "gltf-bounding-box": "^0.2.2",
29 | "gltf-pipeline": "^1.0.2",
30 | "klaw": "^2.1.0",
31 | "recursive-readdir": "^2.2.2",
32 | "sqlite3": "file:mapbox-node-sqlite3-v4.0.6-2-ga9dc5a3.tar.gz",
33 | "uuid": "^3.1.0",
34 | "yargs": "^10.0.3"
35 | },
36 | "devDependencies": {
37 | "cloc": "^2.3.3",
38 | "eslint": "^4.10.0",
39 | "eslint-config-cesium": "^2.0.1",
40 | "gulp": "^3.9.1",
41 | "jasmine": "^2.8.0",
42 | "jasmine-spec-reporter": "^4.2.1",
43 | "jsdoc": "^3.5.5",
44 | "nyc": "^11.3.0",
45 | "open": "^0.0.5",
46 | "request": "^2.83.0",
47 | "requirejs": "^2.3.5"
48 | },
49 | "scripts": {
50 | "eslint": "eslint \"./**/*.js\" --cache --quiet",
51 | "test": "gulp test",
52 | "test-watch": "gulp test-watch",
53 | "coverage": "gulp coverage",
54 | "jsDoc": "gulp jsDoc",
55 | "cloc": "gulp cloc"
56 | },
57 | "bin": {
58 | "3d-tiles-tools": "./bin/3d-tiles-tools.js"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tools/specs/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.eslintrc.json",
3 | "env": {
4 | "jasmine": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/tools/specs/data/BatchedDeprecated1/batchedDeprecated1.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/BatchedDeprecated1/batchedDeprecated1.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/BatchedDeprecated1/tileset.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0"
4 | },
5 | "properties": {
6 | "id": {
7 | "minimum": 0,
8 | "maximum": 9
9 | },
10 | "Longitude": {
11 | "minimum": -1.3196972173766555,
12 | "maximum": -1.3196718547473905
13 | },
14 | "Latitude": {
15 | "minimum": 0.6988624606923348,
16 | "maximum": 0.6988888301460953
17 | },
18 | "Height": {
19 | "minimum": 6.2074098233133554,
20 | "maximum": 12.83180232718587
21 | }
22 | },
23 | "geometricError": 70,
24 | "root": {
25 | "refine": "ADD",
26 | "boundingVolume": {
27 | "region": [
28 | -1.3197004795898053,
29 | 0.6988582109,
30 | -1.3196595204101946,
31 | 0.6988897891,
32 | 0,
33 | 20
34 | ]
35 | },
36 | "geometricError": 0,
37 | "content": {
38 | "url": "batchedDeprecated1.b3dm"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tools/specs/data/BatchedDeprecated2/batchedDeprecated2.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/BatchedDeprecated2/batchedDeprecated2.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/BatchedDeprecated2/tileset.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0"
4 | },
5 | "properties": {
6 | "id": {
7 | "minimum": 0,
8 | "maximum": 9
9 | },
10 | "Longitude": {
11 | "minimum": -1.3196972173766555,
12 | "maximum": -1.3196718547473905
13 | },
14 | "Latitude": {
15 | "minimum": 0.6988624606923348,
16 | "maximum": 0.6988888301460953
17 | },
18 | "Height": {
19 | "minimum": 6.2074098233133554,
20 | "maximum": 12.83180232718587
21 | }
22 | },
23 | "geometricError": 70,
24 | "root": {
25 | "refine": "ADD",
26 | "boundingVolume": {
27 | "region": [
28 | -1.3197004795898053,
29 | 0.6988582109,
30 | -1.3196595204101946,
31 | 0.6988897891,
32 | 0,
33 | 20
34 | ]
35 | },
36 | "geometricError": 0,
37 | "content": {
38 | "url": "batchedDeprecated2.b3dm"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tools/specs/data/CesiumTexturedBox/CesiumTexturedBox.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/CesiumTexturedBox/CesiumTexturedBox.glb
--------------------------------------------------------------------------------
/tools/specs/data/Textured/batchedTextured.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/Textured/batchedTextured.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/Textured/instancedTextured.i3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/Textured/instancedTextured.i3dm
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/lr.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/TilesetOfTilesets/lr.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/parent.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/TilesetOfTilesets/parent.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/tileset.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0"
4 | },
5 | "properties": {
6 | "id": {
7 | "minimum": 0,
8 | "maximum": 9
9 | },
10 | "Longitude": {
11 | "minimum": -1.3197192952275933,
12 | "maximum": -1.319644104024109
13 | },
14 | "Latitude": {
15 | "minimum": 0.698848878034009,
16 | "maximum": 0.6989046192460953
17 | },
18 | "Height": {
19 | "minimum": 6.161747192963958,
20 | "maximum": 84.83180232718587
21 | }
22 | },
23 | "geometricError": 240,
24 | "root": {
25 | "boundingVolume": {
26 | "region": [
27 | -1.3197209591796106,
28 | 0.6988424218,
29 | -1.3196390408203893,
30 | 0.6989055782,
31 | 0,
32 | 88
33 | ]
34 | },
35 | "geometricError": 70,
36 | "refine": "ADD",
37 | "content": {
38 | "url": "tileset2.json"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/tileset2.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0"
4 | },
5 | "geometricError": 70,
6 | "root": {
7 | "boundingVolume": {
8 | "region": [
9 | -1.3197209591796106,
10 | 0.6988424218,
11 | -1.3196390408203893,
12 | 0.6989055782,
13 | 0,
14 | 88
15 | ]
16 | },
17 | "geometricError": 70,
18 | "refine": "ADD",
19 | "content": {
20 | "url": "parent.b3dm"
21 | },
22 | "children": [
23 | {
24 | "boundingVolume": {
25 | "region": [
26 | -1.3197209591796106,
27 | 0.6988424218,
28 | -1.31968,
29 | 0.698874,
30 | 0,
31 | 20
32 | ]
33 | },
34 | "geometricError": 0,
35 | "content": {
36 | "url": "tileset3/tileset3.json"
37 | }
38 | },
39 | {
40 | "boundingVolume": {
41 | "region": [
42 | -1.31968,
43 | 0.6988424218,
44 | -1.3196390408203893,
45 | 0.698874,
46 | 0,
47 | 20
48 | ]
49 | },
50 | "geometricError": 0,
51 | "content": {
52 | "url": "lr.b3dm"
53 | }
54 | },
55 | {
56 | "boundingVolume": {
57 | "region": [
58 | -1.31968,
59 | 0.698874,
60 | -1.3196390408203893,
61 | 0.6989055782,
62 | 0,
63 | 20
64 | ]
65 | },
66 | "geometricError": 0,
67 | "content": {
68 | "url": "ur.b3dm"
69 | }
70 | },
71 | {
72 | "boundingVolume": {
73 | "region": [
74 | -1.3197209591796106,
75 | 0.698874,
76 | -1.31968,
77 | 0.6989055782,
78 | 0,
79 | 20
80 | ]
81 | },
82 | "geometricError": 0,
83 | "content": {
84 | "url": "ul.b3dm"
85 | }
86 | }
87 | ]
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/tileset3/ll.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/TilesetOfTilesets/tileset3/ll.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/tileset3/tileset3.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0"
4 | },
5 | "geometricError": 0,
6 | "root": {
7 | "boundingVolume": {
8 | "region": [
9 | -1.3197209591796106,
10 | 0.6988424218,
11 | -1.31968,
12 | 0.698874,
13 | 0,
14 | 20
15 | ]
16 | },
17 | "geometricError": 0,
18 | "refine": "ADD",
19 | "content": {
20 | "url": "ll.b3dm"
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/ul.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/TilesetOfTilesets/ul.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/TilesetOfTilesets/ur.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/TilesetOfTilesets/ur.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/batchedWithBatchTableBinary.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/batchedWithBatchTableBinary.b3dm
--------------------------------------------------------------------------------
/tools/specs/data/composite.cmpt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/composite.cmpt
--------------------------------------------------------------------------------
/tools/specs/data/compositeOfComposite.cmpt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/compositeOfComposite.cmpt
--------------------------------------------------------------------------------
/tools/specs/data/instancedWithBatchTableBinary.i3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/instancedWithBatchTableBinary.i3dm
--------------------------------------------------------------------------------
/tools/specs/data/pipeline.json:
--------------------------------------------------------------------------------
1 | {
2 | "input": "TilesetOfTilesets/",
3 | "output": "TilesetOfTilesets-output/",
4 | "stages": [
5 | "combine",
6 | {
7 | "name": "gzip",
8 | "tilesOnly": true
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/tools/specs/data/tileset.3dtiles:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/tools/specs/data/tileset.3dtiles
--------------------------------------------------------------------------------
/tools/specs/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "specs",
3 | "spec_files": [
4 | "**/*Spec.js"
5 | ],
6 | "helpers": [
7 | "matchers/nodeHelper.js"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/tools/specs/lib/databaseToTilesetSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var databaseToTileset = require('../../lib/databaseToTileset');
4 | var fileExists = require('../../lib/fileExists');
5 | var isGzipped = require('../../lib/isGzipped');
6 |
7 | var inputFile = './specs/data/tileset.3dtiles';
8 | var outputDirectory = './specs/data/Tileset/';
9 | var tilesetJsonFile = './specs/data/TilesetOfTilesets/tileset.json';
10 |
11 | describe('databaseToTileset', function() {
12 | afterEach(function (done) {
13 | fsExtra.remove(outputDirectory)
14 | .then(function() {
15 | done();
16 | });
17 | });
18 |
19 | it('creates a tileset from an sqlite database', function(done) {
20 | expect(databaseToTileset(inputFile, outputDirectory)
21 | .then(function() {
22 | return fileExists(tilesetJsonFile)
23 | .then(function(exists) {
24 | expect(exists).toEqual(true);
25 | return fsExtra.readJson(tilesetJsonFile);
26 | }).then(function(data) {
27 | expect(isGzipped(data)).toBe(false);
28 | });
29 | }), done).toResolve();
30 | });
31 |
32 | it('throws an error if no input file is provided', function() {
33 | expect(function() {
34 | databaseToTileset(undefined, outputDirectory);
35 | }).toThrowError('inputFile is required.');
36 | });
37 |
38 | it('works when no output directory is provided', function(done) {
39 | expect(databaseToTileset(inputFile)
40 | .then(function() {
41 | return fileExists(tilesetJsonFile)
42 | .then(function(exists) {
43 | expect(exists).toBe(true);
44 | });
45 | }), done).toResolve();
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/tools/specs/lib/extractB3dmSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | var extractB3dm = require('../../lib/extractB3dm');
4 |
5 | var b3dmPath = './specs/data/batchedWithBatchTableBinary.b3dm';
6 |
7 | describe('extractB3dm', function() {
8 | var b3dmBuffer;
9 | beforeAll(function() {
10 | b3dmBuffer = fs.readFileSync(b3dmPath);
11 | });
12 |
13 | it('extracts a b3dm from buffer', function() {
14 | var b3dm = extractB3dm(b3dmBuffer);
15 | expect(b3dm.header.magic).toBe('b3dm');
16 | expect(b3dm.header.version).toBe(1);
17 | expect(b3dm.featureTable.json).toBeDefined();
18 | expect(b3dm.featureTable.json.BATCH_LENGTH).toBe(10);
19 | expect(b3dm.featureTable.binary.length).toBe(0);
20 | expect(b3dm.batchTable.json).toBeDefined();
21 | expect(b3dm.batchTable.json.Height).toBeDefined();
22 | expect(b3dm.batchTable.binary.length).toBe(256);
23 | expect(b3dm.glb.length).toBe(14141);
24 | });
25 |
26 | it('throws an error if no buffer is provided', function() {
27 | expect(function() {
28 | extractB3dm();
29 | }).toThrowError();
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/tools/specs/lib/extractCmptSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var Promise = require('bluebird');
4 | var extractCmpt = require('../../lib/extractCmpt');
5 |
6 | var compositePath = './specs/data/composite.cmpt';
7 | var compositeOfCompositePath = './specs/data/compositeOfComposite.cmpt';
8 |
9 | describe('extractCmpt', function() {
10 | var compositeBuffer;
11 | var compositeOfCompositeBuffer; //eslint-disable-line no-unused-vars
12 | beforeAll(function(done) {
13 | Promise.all([
14 | fsExtra.readFile(compositePath)
15 | .then(function(data) {
16 | compositeBuffer = data;
17 | }),
18 | fsExtra.readFile(compositeOfCompositePath)
19 | .then(function(data) {
20 | compositeOfCompositeBuffer = data;
21 | })
22 | ]).then(done);
23 | });
24 |
25 | it('extracts a b3dm and i3dm from composite buffer', function() {
26 | var innerTiles = extractCmpt(compositeBuffer);
27 | var b3dmMagic = innerTiles[0].toString('utf8', 0, 4);
28 | var i3dmMagic = innerTiles[1].toString('utf8', 0, 4);
29 | expect(innerTiles.length).toBe(2);
30 | expect(b3dmMagic).toBe('b3dm');
31 | expect(i3dmMagic).toBe('i3dm');
32 | });
33 |
34 | it('extracts a b3dm and i3dm from composite-of-composite buffer', function() {
35 | var innerTiles = extractCmpt(compositeBuffer);
36 | var b3dmMagic = innerTiles[0].toString('utf8', 0, 4);
37 | var i3dmMagic = innerTiles[1].toString('utf8', 0, 4);
38 | expect(innerTiles.length).toBe(2);
39 | expect(b3dmMagic).toBe('b3dm');
40 | expect(i3dmMagic).toBe('i3dm');
41 | });
42 |
43 | it('throws an error if no buffer is provided', function() {
44 | expect(function() {
45 | extractCmpt();
46 | }).toThrowError();
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/tools/specs/lib/extractI3dmSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | var extractI3dm = require('../../lib/extractI3dm');
4 |
5 | var i3dmPath = './specs/data/instancedWithBatchTableBinary.i3dm';
6 |
7 | describe('extractI3dm', function() {
8 | var i3dmBuffer;
9 |
10 | beforeAll(function() {
11 | i3dmBuffer = fs.readFileSync(i3dmPath);
12 | });
13 |
14 | it('extracts a i3dm from buffer', function() {
15 | var i3dm = extractI3dm(i3dmBuffer);
16 | expect(i3dm.header.magic).toBe('i3dm');
17 | expect(i3dm.header.version).toBe(1);
18 | expect(i3dm.featureTable.json).toBeDefined();
19 | expect(i3dm.featureTable.json.INSTANCES_LENGTH).toBe(25);
20 | expect(i3dm.featureTable.binary.length).toBe(304);
21 | expect(i3dm.batchTable.json).toBeDefined();
22 | expect(i3dm.batchTable.json.id).toBeDefined();
23 | expect(i3dm.batchTable.binary.length).toBe(104);
24 | expect(i3dm.glb.length).toBe(5352);
25 | });
26 |
27 | it('throws an error if no buffer is provided', function() {
28 | expect(function() {
29 | extractI3dm();
30 | }).toThrowError();
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/tools/specs/lib/glbToB3dmSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | var extractB3dm = require('../../lib/extractB3dm');
4 | var getBufferPadded = require('../../lib/getBufferPadded');
5 | var getJsonBufferPadded = require('../../lib/getJsonBufferPadded');
6 | var glbToB3dm = require('../../lib/glbToB3dm');
7 |
8 | var glbPath = './specs/data/CesiumTexturedBox/CesiumTexturedBox.glb';
9 | var b3dmPath = './specs/data/batchedWithBatchTableBinary.b3dm';
10 |
11 | describe('glbToB3dm', function() {
12 | var glbBuffer;
13 |
14 | beforeAll(function() {
15 | glbBuffer = fs.readFileSync(glbPath);
16 | });
17 |
18 | it('generates a basic b3dm header for a glb', function() {
19 | var headerByteLength = 28;
20 | var byteLength = headerByteLength + glbBuffer.length;
21 | var b3dmBuffer = glbToB3dm(glbBuffer);
22 | var header = b3dmBuffer.slice(0, headerByteLength);
23 | expect(header.toString('utf8', 0, 4)).toEqual('b3dm'); // magic
24 | expect(header.readUInt32LE(4)).toEqual(1); // version
25 | expect(header.readUInt32LE(8)).toEqual(byteLength); // byteLength
26 | expect(header.readUInt32LE(12)).toEqual(0); // featureTableJSONByteLength
27 | expect(header.readUInt32LE(16)).toEqual(0); // featureTableBinaryByteLength
28 | expect(header.readUInt32LE(20)).toEqual(0); // batchTableJSONByteLength
29 | expect(header.readUInt32LE(24)).toEqual(0); // batchTableBinaryByteLength
30 | expect(b3dmBuffer.length).toEqual(byteLength);
31 | });
32 |
33 | it('generates a b3dm with feature table and batch table', function() {
34 | var featureTableJson = {
35 | BATCH_LENGTH : 10
36 | };
37 | var batchTableJson = {
38 | height : {
39 | componentType : 'FLOAT',
40 | type : 'SCALAR',
41 | byteOffset : 0
42 | }
43 | };
44 |
45 | var headerByteLength = 28;
46 | var featureTableJsonBuffer = getJsonBufferPadded(featureTableJson, headerByteLength);
47 | var featureTableBinaryBuffer = getBufferPadded(Buffer.alloc(16)); // Contents don't matter
48 | var batchTableJsonBuffer = getJsonBufferPadded(batchTableJson);
49 | var batchTableBinaryBuffer = getBufferPadded(Buffer.alloc(32)); // Contents don't matter
50 |
51 | var byteLength = headerByteLength + featureTableJsonBuffer.length + featureTableBinaryBuffer.length + batchTableJsonBuffer.length + batchTableBinaryBuffer.length + glbBuffer.length;
52 |
53 | var b3dmBuffer = glbToB3dm(glbBuffer, featureTableJson, featureTableBinaryBuffer, batchTableJson, batchTableBinaryBuffer);
54 | var header = b3dmBuffer.slice(0, headerByteLength);
55 | expect(header.toString('utf8', 0, 4)).toEqual('b3dm'); // magic
56 | expect(header.readUInt32LE(4)).toEqual(1); // version
57 | expect(header.readUInt32LE(8)).toEqual(byteLength); // byteLength
58 | expect(header.readUInt32LE(12)).toEqual(featureTableJsonBuffer.length); // featureTableJSONByteLength
59 | expect(header.readUInt32LE(16)).toEqual(featureTableBinaryBuffer.length); // featureTableBinaryByteLength
60 | expect(header.readUInt32LE(20)).toEqual(batchTableJsonBuffer.length); // batchTableJSONByteLength
61 | expect(header.readUInt32LE(24)).toEqual(batchTableBinaryBuffer.length); // batchTableBinaryByteLength
62 | expect(b3dmBuffer.length).toEqual(byteLength);
63 | });
64 |
65 | it('convert b3dm to glb and back to b3dm', function() {
66 | var b3dmBuffer = fs.readFileSync(b3dmPath);
67 | var b3dm = extractB3dm(b3dmBuffer);
68 | var b3dmOut = glbToB3dm(b3dm.glb, b3dm.featureTable.json, b3dm.featureTable.binary, b3dm.batchTable.json, b3dm.batchTable.binary);
69 | expect(b3dm).toEqual(extractB3dm(b3dmOut));
70 | expect(b3dmOut).toEqual(b3dmBuffer);
71 | });
72 |
73 | it('throws an error if no glbBuffer is provided', function() {
74 | expect(function() {
75 | glbToB3dm();
76 | }).toThrowError('glbBuffer is not defined.');
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/tools/specs/lib/glbToI3dmSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | var extractI3dm = require('../../lib/extractI3dm');
4 | var getBufferPadded = require('../../lib/getBufferPadded');
5 | var getJsonBufferPadded = require('../../lib/getJsonBufferPadded');
6 | var glbToI3dm = require('../../lib/glbToI3dm');
7 |
8 | var glbPath = './specs/data/CesiumTexturedBox/CesiumTexturedBox.glb';
9 | var i3dmPath = './specs/data/instancedWithBatchTableBinary.i3dm';
10 |
11 | describe('glbToI3dm', function() {
12 | var glbBuffer;
13 |
14 | beforeAll(function() {
15 | glbBuffer = fs.readFileSync(glbPath);
16 | });
17 |
18 | it('generates a basic i3dm header for a glb', function() {
19 | var headerByteLength = 32;
20 | var byteLength = headerByteLength + glbBuffer.length;
21 | var i3dmBuffer = glbToI3dm(glbBuffer);
22 | var header = i3dmBuffer.slice(0, headerByteLength);
23 | expect(header.toString('utf8', 0, 4)).toEqual('i3dm'); // magic
24 | expect(header.readUInt32LE(4)).toEqual(1); // version
25 | expect(header.readUInt32LE(8)).toEqual(byteLength); // byteLength
26 | expect(header.readUInt32LE(12)).toEqual(0); // featureTableJSONByteLength
27 | expect(header.readUInt32LE(16)).toEqual(0); // featureTableBinaryByteLength
28 | expect(header.readUInt32LE(20)).toEqual(0); // batchTableJSONByteLength
29 | expect(header.readUInt32LE(24)).toEqual(0); // batchTableBinaryByteLength
30 | expect(header.readUInt32LE(28)).toEqual(1); // gltfFormat
31 | expect(i3dmBuffer.length).toEqual(byteLength);
32 | });
33 |
34 | it('generates an i3dm with feature table and batch table', function() {
35 | var featureTableJson = {
36 | INSTANCES_LENGTH : 1,
37 | POSITION : {
38 | byteOffset : 0
39 | }
40 | };
41 | var batchTableJson = {
42 | height : {
43 | componentType : 'FLOAT',
44 | type : 'SCALAR',
45 | byteOffset : 0
46 | }
47 | };
48 |
49 | var featureTableJsonBuffer = getJsonBufferPadded(featureTableJson);
50 | var featureTableBinaryBuffer = getBufferPadded(Buffer.alloc(16)); // Contents don't matter
51 | var batchTableJsonBuffer = getJsonBufferPadded(batchTableJson);
52 | var batchTableBinaryBuffer = getBufferPadded(Buffer.alloc(32)); // Contents don't matter
53 |
54 | var headerByteLength = 32;
55 | var byteLength = headerByteLength + featureTableJsonBuffer.length + featureTableBinaryBuffer.length + batchTableJsonBuffer.length + batchTableBinaryBuffer.length + glbBuffer.length;
56 |
57 | var i3dmBuffer = glbToI3dm(glbBuffer, featureTableJson, featureTableBinaryBuffer, batchTableJson, batchTableBinaryBuffer);
58 | var header = i3dmBuffer.slice(0, headerByteLength);
59 | expect(header.toString('utf8', 0, 4)).toEqual('i3dm'); // magic
60 | expect(header.readUInt32LE(4)).toEqual(1); // version
61 | expect(header.readUInt32LE(8)).toEqual(byteLength); // byteLength
62 | expect(header.readUInt32LE(12)).toEqual(featureTableJsonBuffer.length); // featureTableJSONByteLength
63 | expect(header.readUInt32LE(16)).toEqual(featureTableBinaryBuffer.length); // featureTableBinaryByteLength
64 | expect(header.readUInt32LE(20)).toEqual(batchTableJsonBuffer.length); // batchTableJSONByteLength
65 | expect(header.readUInt32LE(24)).toEqual(batchTableBinaryBuffer.length); // batchTableBinaryByteLength
66 | expect(header.readUInt32LE(28)).toEqual(1); // gltfFormat
67 | expect(i3dmBuffer.length).toEqual(byteLength);
68 | });
69 |
70 | it('convert i3dm to glb and back to i3dm', function() {
71 | var i3dmBuffer = fs.readFileSync(i3dmPath);
72 | var i3dm = extractI3dm(i3dmBuffer);
73 | var i3dmOut = glbToI3dm(i3dm.glb, i3dm.featureTable.json, i3dm.featureTable.binary, i3dm.batchTable.json, i3dm.batchTable.binary);
74 | expect(i3dm).toEqual(extractI3dm(i3dmOut));
75 | expect(i3dmOut).toEqual(i3dmBuffer);
76 | });
77 |
78 | it('throws an error if no glbBuffer is provided', function() {
79 | expect(function() {
80 | glbToI3dm();
81 | }).toThrowError('glbBuffer is not defined.');
82 | });
83 | });
84 |
--------------------------------------------------------------------------------
/tools/specs/lib/makeCompositeTileSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var getMagic = require('../../lib/getMagic');
4 | var makeCompositeTile = require('../../lib/makeCompositeTile');
5 |
6 | var b3dmPath = './specs/data/batchedWithBatchTableBinary.b3dm';
7 | var i3dmPath = './specs/data/instancedWithBatchTableBinary.i3dm';
8 |
9 | function getPaddedByteLength(byteLength) {
10 | var boundary = 8;
11 | var remainder = byteLength % boundary;
12 | var padding = (remainder === 0) ? 0 : boundary - remainder;
13 | return byteLength + padding;
14 | }
15 |
16 | describe('makeCompositeTile', function() {
17 | it('makes a composite tile', function() {
18 | var b3dm = fsExtra.readFileSync(b3dmPath);
19 | var i3dm = fsExtra.readFileSync(i3dmPath);
20 |
21 | var b3dmOriginalLength = b3dm.length;
22 | var i3dmOriginalLength = i3dm.length;
23 | expect(b3dmOriginalLength % 8 > 0).toBe(true); // initially not aligned
24 |
25 | var cmpt = makeCompositeTile([b3dm, i3dm]);
26 | var magic = getMagic(cmpt);
27 | var version = cmpt.readUInt32LE(4);
28 | var byteLength = cmpt.readUInt32LE(8);
29 | var tilesLength = cmpt.readUInt32LE(12);
30 |
31 | var headerByteLength = 16;
32 | var expectedByteLength = headerByteLength + getPaddedByteLength(b3dmOriginalLength) + getPaddedByteLength(i3dmOriginalLength);
33 |
34 | expect(magic).toBe('cmpt');
35 | expect(version).toBe(1);
36 | expect(byteLength).toBe(cmpt.length);
37 | expect(byteLength).toBe(expectedByteLength);
38 | expect(tilesLength).toBe(2);
39 |
40 | var b3dmMagic = getMagic(cmpt, headerByteLength);
41 | var b3dmByteLength = cmpt.readUInt32LE(headerByteLength + 8);
42 | expect(b3dmMagic).toBe('b3dm');
43 | expect(b3dmByteLength % 8 === 0).toBe(true); // b3dm is aligned
44 |
45 | var i3dmMagic = getMagic(cmpt, headerByteLength + b3dmByteLength);
46 | var i3dmByteLength = cmpt.readUInt32LE(headerByteLength + b3dmByteLength + 8);
47 | expect(i3dmMagic).toBe('i3dm');
48 | expect(i3dmByteLength % 8 === 0).toBe(true); // i3dm is aligned
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/tools/specs/lib/optimizeGlbSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fsExtra = require('fs-extra');
3 | var Promise = require('bluebird');
4 | var optimizeGlb = require('../../lib/optimizeGlb');
5 |
6 | var glbPath = './specs/data/CesiumTexturedBox/CesiumTexturedBox.glb';
7 |
8 | describe('optimizeGlb', function() {
9 | var buffer;
10 | beforeAll(function(done) {
11 | fsExtra.readFile(glbPath)
12 | .then(function(data) {
13 | buffer = data;
14 | done();
15 | });
16 | });
17 |
18 | it('optimizes a glb using the gltf-pipeline', function(done) {
19 | expect(optimizeGlb(buffer)
20 | .then(function(optimizedGlb) {
21 | expect(optimizedGlb).not.toEqual(buffer);
22 | }), done).toResolve();
23 | });
24 |
25 | it('compresses textures in a glb using the gltf-pipeline', function(done) {
26 | var compressionOptions = {
27 | textureCompressionOptions : {
28 | format: 'dxt1',
29 | quality: 10
30 | }
31 | };
32 |
33 | var promises = [];
34 | promises.push(optimizeGlb(buffer));
35 | promises.push(optimizeGlb(buffer, compressionOptions));
36 |
37 | expect(Promise.all(promises)
38 | .then(function(optimizedGlbs) {
39 | expect(optimizedGlbs.length).toEqual(2);
40 | expect(optimizedGlbs[0]).not.toEqual(optimizedGlbs[1]);
41 | }), done).toResolve();
42 | });
43 |
44 | it('throws an error if no buffer is provided', function() {
45 | expect(function() {
46 | optimizeGlb();
47 | }).toThrowError();
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/tools/specs/lib/tilesetToDatabseSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Cesium = require('cesium');
3 | var fsExtra = require('fs-extra');
4 | var Promise = require('bluebird');
5 | var sqlite3 = require('sqlite3');
6 | var zlib = require('zlib');
7 | var fileExists = require('../../lib/fileExists');
8 | var isGzipped = require('../../lib/isGzipped');
9 | var tilesetToDatabase = require('../../lib/tilesetToDatabase');
10 |
11 | var zlibGunzip = Promise.promisify(zlib.gunzip);
12 | var getStringFromTypedArray = Cesium.getStringFromTypedArray;
13 |
14 | var inputDirectory = './specs/data/TilesetOfTilesets/';
15 | var tilesetJsonFile = './specs/data/TilesetOfTilesets/tileset.json';
16 | var outputFile = './specs/data/TilesetOfTilesets.3dtiles';
17 |
18 | describe('tilesetToDatabase', function() {
19 | afterEach(function (done) {
20 | fsExtra.remove(outputFile)
21 | .then(done)
22 | .catch(done.fail);
23 | });
24 |
25 | it('creates a sqlite database from a tileset', function(done) {
26 | expect(tilesetToDatabase(inputDirectory, outputFile)
27 | .then(function() {
28 | var db;
29 | return Promise.resolve(fileExists(outputFile))
30 | .then(function(exists) {
31 | expect(exists).toEqual(true);
32 | }).then(function() {
33 | db = new sqlite3.Database(outputFile);
34 | var dbAll = Promise.promisify(db.all, {context : db});
35 | return dbAll("SELECT * FROM media WHERE key='tileset.json'");
36 | }).then(function(rows) {
37 | expect(rows.length).toEqual(1);
38 |
39 | var content = rows[0].content;
40 | expect(isGzipped(content)).toEqual(true);
41 |
42 | return Promise.all([
43 | zlibGunzip(content),
44 | fsExtra.readJson(tilesetJsonFile)
45 | ]).then(function(data) {
46 | var jsonStr = getStringFromTypedArray(data[0]);
47 | var dbTilesetJson = JSON.parse(jsonStr);
48 | var tilesetJson = data[1];
49 | expect(dbTilesetJson).toEqual(tilesetJson);
50 | });
51 | }).finally(function() {
52 | db.close();
53 | });
54 | }), done).toResolve();
55 | });
56 |
57 | it('throws an error if no input directory is provided', function() {
58 | expect(function() {
59 | tilesetToDatabase(undefined, outputFile);
60 | }).toThrowError('inputDirectory is required.');
61 | });
62 |
63 | it('works when no output file is provided', function(done) {
64 | expect(tilesetToDatabase(inputDirectory)
65 | .then(function() {
66 | return fileExists(outputFile)
67 | .then(function(exists) {
68 | expect(exists).toBe(true);
69 | });
70 | }), done).toResolve();
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/tools/specs/matchers/customizeJasmine.js:
--------------------------------------------------------------------------------
1 | /*eslint strict: ["error", "function"]*/
2 | /*eslint-env amd*/
3 | define([
4 | './addDefaultMatchers',
5 | './equalsMethodEqualityTester'
6 | ], function (addDefaultMatchers,
7 | equalsMethodEqualityTester) {
8 | 'use strict';
9 |
10 | return function (env) {
11 | env.beforeEach(function () {
12 | addDefaultMatchers(true).call(env);
13 | env.addCustomEqualityTester(equalsMethodEqualityTester);
14 | });
15 | };
16 | });
17 |
--------------------------------------------------------------------------------
/tools/specs/matchers/equals.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equals.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/FeatureDetection'
6 | ], function(
7 | FeatureDetection) {
8 | 'use strict';
9 | /*global CanvasPixelArray*/
10 |
11 | var typedArrayTypes = [];
12 |
13 | // Earlier versions of IE do not support typed arrays
14 | if (FeatureDetection.supportsTypedArrays()) {
15 | typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
16 |
17 | if (typeof Uint8ClampedArray !== 'undefined') {
18 | typedArrayTypes.push(Uint8ClampedArray);
19 | }
20 |
21 | if (typeof CanvasPixelArray !== 'undefined') {
22 | typedArrayTypes.push(CanvasPixelArray);
23 | }
24 | }
25 |
26 | function isTypedArray(o) {
27 | return typedArrayTypes.some(function(type) {
28 | return o instanceof type;
29 | });
30 | }
31 |
32 | function typedArrayToArray(array) {
33 | if (array !== null && typeof array === 'object' && isTypedArray(array)) {
34 | return Array.prototype.slice.call(array, 0);
35 | }
36 | return array;
37 | }
38 |
39 | function equals(util, customEqualiyTesters, a, b) {
40 | a = typedArrayToArray(a);
41 | b = typedArrayToArray(b);
42 | return util.equals(a, b, customEqualiyTesters);
43 | }
44 |
45 | return equals;
46 | });
47 |
--------------------------------------------------------------------------------
/tools/specs/matchers/equalsMethodEqualityTester.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equalsMethodEqualityTester.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/defined'
6 | ], function(
7 | defined) {
8 | 'use strict';
9 |
10 | return function(a, b) {
11 | var to_run;
12 | // if either a or b have an equals method, call it.
13 | if (a !== null && defined(a)) {
14 | if (typeof a.equals === 'function') {
15 | return a.equals(b);
16 | } else if(a instanceof Object) {
17 | // Check if the current object has a static function named 'equals'
18 | to_run = Object.getPrototypeOf(a).constructor.equals;
19 | if( typeof to_run === 'function') {
20 | return to_run(a, b);
21 | }
22 | }
23 | }
24 |
25 | if (b !== null && defined(b)) {
26 | if (typeof b.equals === 'function') {
27 | return b.equals(a);
28 | } else if(b instanceof Object) {
29 | // Check if the current object has a static function named 'equals'
30 | to_run = Object.getPrototypeOf(b).constructor.equals;
31 | if( typeof to_run === 'function') {
32 | return to_run(b, a);
33 | }
34 | }
35 | }
36 |
37 | // fall back to default equality checks.
38 | return undefined;
39 | };
40 | });
41 |
--------------------------------------------------------------------------------
/tools/specs/matchers/expectPromise.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 |
5 | var defined = Cesium.defined;
6 | var defaultValue = Cesium.defaultValue;
7 |
8 | module.exports = function expectPromise(promise, done) {
9 | return {
10 | toResolve: function toResolve() {
11 | return promise
12 | .then(done)
13 | .catch(function(err){
14 | done.fail('Expected promise to resolve' + err);
15 | });
16 | },
17 | toResolveWith: function toResolveWith(expectedValue) {
18 | return promise
19 | .then(function (result) {
20 | expect(result).toEqual(expectedValue);
21 | done();
22 | })
23 | .catch(function(err){
24 | done.fail('Expected promise to resolve' + err);
25 | });
26 | },
27 | toRejectWith: function toRejectWith(ErrorType, errorMessage) {
28 | var typeName = defaultValue(ErrorType.displayName, ErrorType.name);
29 |
30 | promise
31 | .then(function () {
32 | done.fail('expected promise to reject with ' + typeName);
33 | })
34 | .catch(function (error) {
35 | if (!(error instanceof ErrorType)) {
36 | done.fail(defaultValue(defaultValue(error.displayName, error.name), ErrorType) + ' to be instance of ' + typeName);
37 | console.log(error);
38 | }
39 |
40 | if (defined(errorMessage)) {
41 | expect(error.message).toEqual(errorMessage);
42 | }
43 | done();
44 | });
45 | }
46 | };
47 | };
48 |
--------------------------------------------------------------------------------
/tools/specs/matchers/nodeHelper.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var requirejs = require('requirejs');
5 |
6 | var expectPromise = require('./expectPromise');
7 |
8 | //Since Jasmine matchers are shared between client and server code
9 | //We need to use requirejs to bring them into node.
10 | requirejs.config({
11 | baseUrl: path.join(__dirname, '../..'),
12 | paths: {
13 | 'Cesium': 'node_modules/cesium/source'
14 | },
15 | nodeRequire: require
16 | });
17 |
18 | var customizeJasmine = requirejs('./specs/matchers/customizeJasmine');
19 |
20 | var env = jasmine.getEnv();
21 | customizeJasmine(env);
22 |
23 | var oldExpect = global.expect;
24 | global.expect = function (promise, done) {
25 | //We can't use instanceof Promise here because promise
26 | //may not be a bluebird-defined Promise
27 | if (promise && promise.then && done) {
28 | return expectPromise(promise, done);
29 | }
30 |
31 | //If it wasn't a promise, call original implementation
32 | return oldExpect.apply(global, arguments);
33 | };
34 |
--------------------------------------------------------------------------------
/tools/tools/jsdoc/conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags": {
3 | "allowUnknownTags": false
4 | },
5 | "source": {
6 | "include": ["lib"],
7 | "includePattern": ".+\\.js(doc)?$",
8 | "excludePattern": "(^|\\/|\\\\)_"
9 | },
10 | "templates": {
11 | "cleverLinks": true,
12 | "default": {
13 | "outputSourceFiles": false
14 | },
15 | "sourceUrl": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/{version}/lib/{filename}"
16 | },
17 | "opts": {
18 | "destination": "doc",
19 | "recurse": true
20 | }
21 | }
--------------------------------------------------------------------------------
/validator/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 | coverage/**
3 | doc/**
4 |
--------------------------------------------------------------------------------
/validator/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cesium/node"
3 | }
4 |
--------------------------------------------------------------------------------
/validator/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | package.json text eol=lf
--------------------------------------------------------------------------------
/validator/.gitignore:
--------------------------------------------------------------------------------
1 | # NPM
2 | node_modules
3 | npm-debug.log
4 | package-lock.json
5 |
6 | # WebStorm user-specific
7 | .idea/workspace.xml
8 | .idea/tasks.xml
9 |
10 | # Generated files
11 | .nyc_output
12 | .eslintcache
13 | doc
14 | coverage
15 | *.tgz
16 | *.zip
17 |
--------------------------------------------------------------------------------
/validator/.idea/3d-tiles-validator.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/validator/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/validator/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/validator/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/validator/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/validator/.idea/jsLinters/jshint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/validator/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/validator/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/validator/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/validator/.npmignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /doc
3 | /specs
4 | /tools
5 | /.idea
6 | .eslintrc.json
7 | .gitattributes
8 | .npmignore
9 | .travis.yml
10 | gulpfile.js
11 | *.tgz
12 | .eslintcache
13 | .nyc_output
14 |
--------------------------------------------------------------------------------
/validator/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/validator/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 8
4 | script:
5 | - npm run eslint
6 | - npm run test -- --failTaskOnError --suppressPassed
7 |
--------------------------------------------------------------------------------
/validator/CHANGES.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 |
--------------------------------------------------------------------------------
/validator/README.md:
--------------------------------------------------------------------------------
1 | # 3D Tiles Validator
2 |
3 | Node.js library and command-line tools for validating 3D Tiles tilesets.
4 |
5 | ## Instructions
6 |
7 | Clone this repo and install [Node.js](http://nodejs.org/). From the root directory of this repo, run:
8 | ```
9 | npm install
10 | ```
11 |
12 | ## Command line tools
13 |
14 | ### validate
15 |
16 | Validates the input tileset.
17 |
18 | ```
19 | node ./bin/3d-tiles-validator.js ./specs/data/Tileset/
20 | ```
21 | ```
22 | node ./bin/3d-tiles-validator.js -i ./specs/data/Tileset/
23 | ```
24 |
25 | |Flag|Description|Required|
26 | |----|-----------|--------|
27 | |`-i`, `--input`|Input directory of the tileset.| No. An input tileset is required but this flag may be omitted|
28 |
29 | ## Build Instructions
30 |
31 | Run the tests:
32 | ```
33 | npm run test
34 | ```
35 | To run ESLint on the entire codebase, run:
36 | ```
37 | npm run eslint
38 | ```
39 | To run ESLint automatically when a file is saved, run the following and leave it open in a console window:
40 | ```
41 | npm run eslint-watch
42 | ```
43 |
44 | ### Running Test Coverage
45 |
46 | Coverage uses [istanbul](https://github.com/gotwarlost/istanbul). Run:
47 | ```
48 | npm run coverage
49 | ```
50 | For complete coverage details, open `coverage/lcov-report/index.html`.
51 |
52 | The tests and coverage covers the Node.js module; it does not cover the command-line interface.
53 |
54 | ## Generating Documentation
55 |
56 | To generate the documentation:
57 | ```
58 | npm run jsDoc
59 | ```
60 |
61 | The documentation will be placed in the `doc` folder.
62 |
63 | ### Debugging
64 |
65 | * To debug the tests in Webstorm, open the Gulp tab, right click the `test` task, and click `Debug 'test'`.
66 | * To run a single test, change the test function from `it` to `fit`.
--------------------------------------------------------------------------------
/validator/bin/3d-tiles-validator.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
--------------------------------------------------------------------------------
/validator/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 | var child_process = require('child_process');
5 | var fsExtra = require('fs-extra');
6 | var gulp = require('gulp');
7 | var Jasmine = require('jasmine');
8 | var jasmineSpecReporter = require('jasmine-spec-reporter');
9 | var open = require('open');
10 | var path = require('path');
11 | var Promise = require('bluebird');
12 | var yargs = require('yargs');
13 |
14 | var defined = Cesium.defined;
15 | var argv = yargs.argv;
16 |
17 | // Add third-party node module binaries to the system path
18 | // since some tasks need to call them directly.
19 | var environmentSeparator = process.platform === 'win32' ? ';' : ':';
20 | var nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
21 | process.env.PATH += environmentSeparator + nodeBinaries;
22 |
23 | var specFiles = ['**/*.js', '!node_modules/**', '!coverage/**'];
24 |
25 | gulp.task('test', function (done) {
26 | var jasmine = new Jasmine();
27 | jasmine.loadConfigFile('specs/jasmine.json');
28 | jasmine.addReporter(new jasmineSpecReporter.SpecReporter({
29 | displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
30 | }));
31 | jasmine.execute();
32 | jasmine.onComplete(function (passed) {
33 | done(argv.failTaskOnError && !passed ? 1 : 0);
34 | });
35 | });
36 |
37 | gulp.task('test-watch', function () {
38 | gulp.watch(specFiles).on('change', function () {
39 | // We can't simply depend on the test task because Jasmine
40 | // does not like being run multiple times in the same process.
41 | try {
42 | child_process.execSync('jasmine JASMINE_CONFIG_PATH=specs/jasmine.json', {
43 | stdio: [process.stdin, process.stdout, process.stderr]
44 | });
45 | } catch (exception) {
46 | console.log('Tests failed to execute.');
47 | }
48 | });
49 | });
50 |
51 | gulp.task('coverage', function () {
52 | fsExtra.removeSync('coverage/server');
53 | child_process.execSync('nyc' +
54 | ' --all' +
55 | ' --reporter=lcov' +
56 | ' --dir coverage' +
57 | ' -x "bin/**"' +
58 | ' -x "doc/**"' +
59 | ' -x "specs/**"' +
60 | ' -x "coverage/**"' +
61 | ' -x index.js' +
62 | ' -x gulpfile.js"' +
63 | ' node_modules/jasmine/bin/jasmine.js' +
64 | ' JASMINE_CONFIG_PATH=specs/jasmine.json', {
65 | stdio: [process.stdin, process.stdout, process.stderr]
66 | });
67 | open('coverage/lcov-report/index.html');
68 | });
69 |
70 | gulp.task('jsDoc', function() {
71 | return new Promise(function(resolve, reject) {
72 | child_process.exec('jsdoc --configure tools/jsdoc/conf.json', function(error, stdout, stderr) {
73 | if (error) {
74 | console.log(stderr);
75 | return reject(error);
76 | }
77 | console.log(stdout);
78 | open('doc/index.html');
79 | resolve();
80 | });
81 | });
82 | });
83 |
84 | gulp.task('cloc', function() {
85 | var cmdLine;
86 | var clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
87 |
88 | //Run cloc on primary Source files only
89 | var source = new Promise(function(resolve, reject) {
90 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
91 | ' lib/ bin/';
92 |
93 | child_process.exec(cmdLine, function(error, stdout, stderr) {
94 | if (error) {
95 | console.log(stderr);
96 | return reject(error);
97 | }
98 | console.log('Source:');
99 | console.log(stdout);
100 | resolve();
101 | });
102 | });
103 |
104 | //If running cloc on source succeeded, also run it on the tests.
105 | return source.then(function() {
106 | return new Promise(function(resolve, reject) {
107 | cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
108 | ' specs/lib/';
109 | child_process.exec(cmdLine, function(error, stdout, stderr) {
110 | if (error) {
111 | console.log(stderr);
112 | return reject(error);
113 | }
114 | console.log('Specs:');
115 | console.log(stdout);
116 | resolve();
117 | });
118 | });
119 | });
120 | });
121 |
--------------------------------------------------------------------------------
/validator/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = {
3 | };
4 |
--------------------------------------------------------------------------------
/validator/lib/isGzipped.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = isGzipped;
3 |
4 | /**
5 | * Test if the provided data is gzipped.
6 | *
7 | * @param {Buffer} data A buffer containing the data to test.
8 | * @returns {Boolean} True if the data is gzipped, False if not.
9 | */
10 | function isGzipped(data) {
11 | return data[0] === 0x1f && data[1] === 0x8b;
12 | }
13 |
--------------------------------------------------------------------------------
/validator/lib/readTile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs-extra');
3 | var Promise = require('bluebird');
4 | var zlib = require('zlib');
5 | var isGzipped = require('./isGzipped');
6 |
7 | var fsReadFile = Promise.promisify(fs.readFile);
8 | var zlibGunzip = Promise.promisify(zlib.gunzip);
9 |
10 | module.exports = readTile;
11 |
12 | /**
13 | * Reads tile data from a file.
14 | *
15 | * @param {String} filePath The file path to read from.
16 | * @returns {Promise} A promise that resolves with the data when the read operation completes.
17 | */
18 | function readTile(filePath) {
19 | return fsReadFile(filePath)
20 | .then(function(buffer) {
21 | if (isGzipped(buffer)) {
22 | return zlibGunzip(buffer);
23 | }
24 | return buffer;
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/validator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "3d-tiles-validator",
3 | "version": "0.1.0",
4 | "license": "Apache-2.0",
5 | "description": "Tools for validating 3D Tiles tilesets.",
6 | "author": {
7 | "name": "Analytical Graphics, Inc. and Contributors"
8 | },
9 | "keywords": [
10 | "3D Tiles"
11 | ],
12 | "homepage": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/issues"
19 | },
20 | "main": "index.js",
21 | "engines": {
22 | "node": ">=4.0.0"
23 | },
24 | "dependencies": {
25 | "bluebird": "^3.5.1",
26 | "cesium": "^1.39",
27 | "fs-extra": "^4.0.2",
28 | "yargs": "^10.0.3"
29 | },
30 | "devDependencies": {
31 | "cloc": "^2.3.3",
32 | "eslint": "^4.10.0",
33 | "eslint-config-cesium": "^2.0.1",
34 | "gulp": "^3.9.1",
35 | "jasmine": "^2.8.0",
36 | "jasmine-spec-reporter": "^4.2.1",
37 | "jsdoc": "^3.5.5",
38 | "nyc": "^11.3.0",
39 | "open": "^0.0.5",
40 | "requirejs": "^2.3.5"
41 | },
42 | "scripts": {
43 | "eslint": "eslint \"./**/*.js\" --cache --quiet",
44 | "test": "gulp test",
45 | "test-watch": "gulp test-watch",
46 | "coverage": "gulp coverage",
47 | "jsDoc": "gulp jsDoc",
48 | "cloc": "gulp cloc"
49 | },
50 | "bin": {
51 | "3d-tiles-validator": "./bin/3d-tiles-validator.js"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/validator/specs/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.eslintrc.json",
3 | "env": {
4 | "jasmine": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/ll.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/validator/specs/data/Tileset/ll.b3dm
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/lr.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/validator/specs/data/Tileset/lr.b3dm
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/parent.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/validator/specs/data/Tileset/parent.b3dm
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/tileset.json:
--------------------------------------------------------------------------------
1 | {
2 | "asset": {
3 | "version": "1.0",
4 | "tilesetVersion": "1.2.3"
5 | },
6 | "properties": {
7 | "id": {
8 | "minimum": 0,
9 | "maximum": 9
10 | },
11 | "Longitude": {
12 | "minimum": -1.3197190069941716,
13 | "maximum": -1.3196399825465384
14 | },
15 | "Latitude": {
16 | "minimum": 0.6988468038519597,
17 | "maximum": 0.6989046685398855
18 | },
19 | "Height": {
20 | "minimum": 6,
21 | "maximum": 84
22 | }
23 | },
24 | "geometricError": 240,
25 | "root": {
26 | "boundingVolume": {
27 | "region": [
28 | -1.3197209591796106,
29 | 0.6988424218,
30 | -1.3196390408203893,
31 | 0.6989055782,
32 | 0,
33 | 88
34 | ]
35 | },
36 | "geometricError": 70,
37 | "refine": "ADD",
38 | "content": {
39 | "url": "parent.b3dm",
40 | "boundingVolume": {
41 | "region": [
42 | -1.3197004795898053,
43 | 0.6988582109,
44 | -1.3196595204101946,
45 | 0.6988897891,
46 | 0,
47 | 88
48 | ]
49 | }
50 | },
51 | "children": [
52 | {
53 | "boundingVolume": {
54 | "region": [
55 | -1.3197209591796106,
56 | 0.6988424218,
57 | -1.31968,
58 | 0.698874,
59 | 0,
60 | 20
61 | ]
62 | },
63 | "geometricError": 0,
64 | "content": {
65 | "url": "ll.b3dm"
66 | }
67 | },
68 | {
69 | "boundingVolume": {
70 | "region": [
71 | -1.31968,
72 | 0.6988424218,
73 | -1.3196390408203893,
74 | 0.698874,
75 | 0,
76 | 20
77 | ]
78 | },
79 | "geometricError": 0,
80 | "content": {
81 | "url": "lr.b3dm"
82 | }
83 | },
84 | {
85 | "boundingVolume": {
86 | "region": [
87 | -1.31968,
88 | 0.698874,
89 | -1.3196390408203893,
90 | 0.6989055782,
91 | 0,
92 | 20
93 | ]
94 | },
95 | "geometricError": 0,
96 | "content": {
97 | "url": "ur.b3dm"
98 | }
99 | },
100 | {
101 | "boundingVolume": {
102 | "region": [
103 | -1.3197209591796106,
104 | 0.698874,
105 | -1.31968,
106 | 0.6989055782,
107 | 0,
108 | 20
109 | ]
110 | },
111 | "geometricError": 0,
112 | "content": {
113 | "url": "ul.b3dm"
114 | }
115 | }
116 | ]
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/ul.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/validator/specs/data/Tileset/ul.b3dm
--------------------------------------------------------------------------------
/validator/specs/data/Tileset/ur.b3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nxddsnc/3d-tiles-tools/591b35885803a42b3d6436f33031437b282c0e0e/validator/specs/data/Tileset/ur.b3dm
--------------------------------------------------------------------------------
/validator/specs/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "specs",
3 | "spec_files": [
4 | "**/*Spec.js"
5 | ],
6 | "helpers": [
7 | "matchers/nodeHelper.js"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/validator/specs/lib/isGzippedSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Promise = require('bluebird');
3 | var zlib = require('zlib');
4 | var isGzipped = require('../../lib/isGzipped');
5 |
6 | var zlibGzip = Promise.promisify(zlib.gzip);
7 |
8 | describe('isGzipped', function() {
9 | it('detects when data is gzipped', function(done) {
10 | var data = Buffer.alloc(40);
11 | expect(isGzipped(data)).toBe(false);
12 | expect(zlibGzip(data)
13 | .then(function(zippedData) {
14 | expect(isGzipped(zippedData)).toBe(true);
15 | }), done).toResolve();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/validator/specs/lib/readTileSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var readTile = require('../../lib/readTile');
3 |
4 | describe('readTile', function() {
5 | it('reads a tile', function(done) {
6 | expect(readTile('./specs/data/Tileset/parent.b3dm')
7 | .then(function(tileData) {
8 | var magic = tileData.toString('utf8', 0, 4);
9 | expect(magic).toEqual('b3dm');
10 | }), done).toResolve();
11 | });
12 |
13 | it('reads a gzipped tile', function(done) {
14 | expect(readTile('./specs/data/Tileset/parent.b3dm')
15 | .then(function(tileData) {
16 | var magic = tileData.toString('utf8', 0, 4);
17 | expect(magic).toEqual('b3dm');
18 | }), done).toResolve();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/validator/specs/matchers/customizeJasmine.js:
--------------------------------------------------------------------------------
1 | /*eslint strict: ["error", "function"]*/
2 | /*eslint-env amd*/
3 | define([
4 | './addDefaultMatchers',
5 | './equalsMethodEqualityTester'
6 | ], function (addDefaultMatchers,
7 | equalsMethodEqualityTester) {
8 | 'use strict';
9 |
10 | return function (env) {
11 | env.beforeEach(function () {
12 | addDefaultMatchers(true).call(env);
13 | env.addCustomEqualityTester(equalsMethodEqualityTester);
14 | });
15 | };
16 | });
17 |
--------------------------------------------------------------------------------
/validator/specs/matchers/equals.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equals.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/FeatureDetection'
6 | ], function(
7 | FeatureDetection) {
8 | 'use strict';
9 | /*global CanvasPixelArray*/
10 |
11 | var typedArrayTypes = [];
12 |
13 | // Earlier versions of IE do not support typed arrays
14 | if (FeatureDetection.supportsTypedArrays()) {
15 | typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
16 |
17 | if (typeof Uint8ClampedArray !== 'undefined') {
18 | typedArrayTypes.push(Uint8ClampedArray);
19 | }
20 |
21 | if (typeof CanvasPixelArray !== 'undefined') {
22 | typedArrayTypes.push(CanvasPixelArray);
23 | }
24 | }
25 |
26 | function isTypedArray(o) {
27 | return typedArrayTypes.some(function(type) {
28 | return o instanceof type;
29 | });
30 | }
31 |
32 | function typedArrayToArray(array) {
33 | if (array !== null && typeof array === 'object' && isTypedArray(array)) {
34 | return Array.prototype.slice.call(array, 0);
35 | }
36 | return array;
37 | }
38 |
39 | function equals(util, customEqualiyTesters, a, b) {
40 | a = typedArrayToArray(a);
41 | b = typedArrayToArray(b);
42 | return util.equals(a, b, customEqualiyTesters);
43 | }
44 |
45 | return equals;
46 | });
47 |
--------------------------------------------------------------------------------
/validator/specs/matchers/equalsMethodEqualityTester.js:
--------------------------------------------------------------------------------
1 | //This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equalsMethodEqualityTester.js
2 | /*eslint strict: ["error", "function"]*/
3 | /*eslint-env amd*/
4 | define([
5 | 'Cesium/Core/defined'
6 | ], function(
7 | defined) {
8 | 'use strict';
9 |
10 | return function(a, b) {
11 | var to_run;
12 | // if either a or b have an equals method, call it.
13 | if (a !== null && defined(a)) {
14 | if (typeof a.equals === 'function') {
15 | return a.equals(b);
16 | } else if(a instanceof Object) {
17 | // Check if the current object has a static function named 'equals'
18 | to_run = Object.getPrototypeOf(a).constructor.equals;
19 | if( typeof to_run === 'function') {
20 | return to_run(a, b);
21 | }
22 | }
23 | }
24 |
25 | if (b !== null && defined(b)) {
26 | if (typeof b.equals === 'function') {
27 | return b.equals(a);
28 | } else if(b instanceof Object) {
29 | // Check if the current object has a static function named 'equals'
30 | to_run = Object.getPrototypeOf(b).constructor.equals;
31 | if( typeof to_run === 'function') {
32 | return to_run(b, a);
33 | }
34 | }
35 | }
36 |
37 | // fall back to default equality checks.
38 | return undefined;
39 | };
40 | });
41 |
--------------------------------------------------------------------------------
/validator/specs/matchers/expectPromise.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cesium = require('cesium');
4 |
5 | var defined = Cesium.defined;
6 | var defaultValue = Cesium.defaultValue;
7 |
8 | module.exports = function expectPromise(promise, done) {
9 | return {
10 | toResolve: function toResolve() {
11 | return promise
12 | .then(done)
13 | .catch(function(err){
14 | done.fail('Expected promise to resolve' + err);
15 | });
16 | },
17 | toResolveWith: function toResolveWith(expectedValue) {
18 | return promise
19 | .then(function (result) {
20 | expect(result).toEqual(expectedValue);
21 | done();
22 | })
23 | .catch(function(err){
24 | done.fail('Expected promise to resolve' + err);
25 | });
26 | },
27 | toRejectWith: function toRejectWith(ErrorType, errorMessage) {
28 | var typeName = defaultValue(ErrorType.displayName, ErrorType.name);
29 |
30 | promise
31 | .then(function () {
32 | done.fail('expected promise to reject with ' + typeName);
33 | })
34 | .catch(function (error) {
35 | if (!(error instanceof ErrorType)) {
36 | done.fail(defaultValue(defaultValue(error.displayName, error.name), ErrorType) + ' to be instance of ' + typeName);
37 | console.log(error);
38 | }
39 |
40 | if (defined(errorMessage)) {
41 | expect(error.message).toEqual(errorMessage);
42 | }
43 | done();
44 | });
45 | }
46 | };
47 | };
48 |
--------------------------------------------------------------------------------
/validator/specs/matchers/nodeHelper.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var requirejs = require('requirejs');
5 |
6 | var expectPromise = require('./expectPromise');
7 |
8 | //Since Jasmine matchers are shared between client and server code
9 | //We need to use requirejs to bring them into node.
10 | requirejs.config({
11 | baseUrl: path.join(__dirname, '../..'),
12 | paths: {
13 | 'Cesium': 'node_modules/cesium/source'
14 | },
15 | nodeRequire: require
16 | });
17 |
18 | var customizeJasmine = requirejs('./specs/matchers/customizeJasmine');
19 |
20 | var env = jasmine.getEnv();
21 | customizeJasmine(env);
22 |
23 | var oldExpect = global.expect;
24 | global.expect = function (promise, done) {
25 | //We can't use instanceof Promise here because promise
26 | //may not be a bluebird-defined Promise
27 | if (promise && promise.then && done) {
28 | return expectPromise(promise, done);
29 | }
30 |
31 | //If it wasn't a promise, call original implementation
32 | return oldExpect.apply(global, arguments);
33 | };
34 |
--------------------------------------------------------------------------------
/validator/tools/jsdoc/conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags": {
3 | "allowUnknownTags": false
4 | },
5 | "source": {
6 | "include": ["lib"],
7 | "includePattern": ".+\\.js(doc)?$",
8 | "excludePattern": "(^|\\/|\\\\)_"
9 | },
10 | "templates": {
11 | "cleverLinks": true,
12 | "default": {
13 | "outputSourceFiles": false
14 | },
15 | "sourceUrl": "https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/{version}/lib/{filename}"
16 | },
17 | "opts": {
18 | "destination": "doc",
19 | "recurse": true
20 | }
21 | }
--------------------------------------------------------------------------------