Closed ahuarte47 closed 6 years ago
Seems very good so far during my tests, well done.
Performance of Cesium took a leap forward compared to heightmap terrain tiles.
There is one problem, when I tried to play with --mesh-qfactor option, ctb-tile segfaulted.
Thanks @kvuorine. About --mesh-qfactor error, may I have your settings or data to try fix it?
With commands below you can get some of the data I am working with, I tested that this dataset produces --mesh-qfactor error too
wget http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141E.tif http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141G.tif http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141F.tif http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141H.tif
gdalbuildvrt merged.vrt L4141?.tif
mkdir terrain
ctb-tile -o terrain -f Mesh -g 1.1 merged.vrt
ok, I'll review this as soon as possible
Hi @kvuorine, I have fixed this option. Thanks for your notice!
Hello @ahuarte47 ! I tried to use this code to generate quantized mesh for Cesium and it works very well. Thank you! :+1: :1st_place_medal:
I had only an issue when i tried to generate tiles from two different adjacent tiff images (from SRTM dataset) : on the seam between these tiles there is a "canyon", a crack. I am sure that the tiffs data are correct, they are perfectly adjacent.
I launched "ctb-tile" 2 times, each with a tile and on the seam this is the result...
do you have some advice? should be the two tiles concatenated before launch ctb-tile?
The result...
Hi, I think you need an unique MDT that covers all area in order to execute the ctb-tile only once. You could create a virtual raster with "gdalbuildvrt" to virtually create an unique source from many individual files.
You can see a previous comment to how to use or read about "gdalbuildvrt" tool:
gdalbuildvrt merged.vrt L4141?.tif
mkdir terrain
ctb-tile -o terrain -f Mesh -g 1.1 merged.vrt
Ok thank you very much, i will try this command! (Probably this is the solution, but i am asking the need of memory for the entire world tileset!)
Looking at the image is interesting to note that the first generated tileset on the right is "cutted", the second on the left is "seamed" to globe. Futhermore looking far where the tiles are loaded with minor zoom level the canyon appers to be larger. These can be clues to uderstand. I am wondering if "ctb-tile" has an option not to seam to the ground level the tileset border.
About the generation of the "layout.json" file, also this works very well, but again in my case with two tiles generated it is not very usefull. Could be interesting a tool that analize the directory tree and from this generate the layout.json.
All this things let me understand that my approach is not correct. :)
Ok, as not said. :)
"gdalbuildvrt" solves perfectly the problems, also the "layer.json" one. Thank you a lot! :)
Is there a technical reason as to why the new "-l" option is separate from the actual terrain generation? For large datasets, generating the layer.json file still takes quite a while.
Hi @ediebold, there is none technical reason. But I thought it seems better two separate tasks, I can be wrong but it looks more versatile. You could create the layer.json of existing old terrain sets, or update only a specific level without overwriting an existing json file (You could have edited it with your own settings). If you update a level, only the limits of it are calculated.
How about creating layer.json if there is none when generating tiles, but update layer.json only with command line option selected?
I have been testing --mesh-qfactor option which now doesn't crash the program, but I don't quite get the purpose of this option because tileset size on disk doesn't seem to vary at all when testing different values. @ahuarte47 could you explain it a bit?
Thanks everybody for your advices, I will try to integrate the -l option as complementary to -f option, but it will require me to do many changes in the original base code, but indeed it seems more logic.
About --mesh-qfactor option, it is supposed larger values should mean minor amount of triangles with minor quality. As my little tutorial said, the process takes care of an input geometric error to safely merge each pair of triangles with its parent one if there is not a visible loss of quality. The factor multiplies the default error value, larger values should mean minor quality.
Did not you notice any change? You can set "wireframe" rendering mode in Cesium to compare between different factors
Hi @kvuorine, I changed the code, now CTB creates the layer.json if there is none when generating tiles. Thanks everybody!
@ahuarte47 Thanks for your support.
I did notice difference in terrain. I just thought simplified mesh would take less space on disk and be quicker to serve over net. I guess simple mesh still reduces rendering workload.
I tried to read your docs/tutorials earlier but that registration barrier was just too much for me.
How to serve the generated tiles? @ahuarte47 I guess storing them on a simple apache directory is not an option, right? I tried to copy some tiles here temp-tiles (they are using the same files used by @kvuorine ) sand-castle example returns:
An error occurred in "CesiumTerrainProvider": An error occurred while accessing https://epinux.com/epinux_data/shared/data/terrain2/layer.json.
Set as URL the root directory: https://epinux.com/epinux_data/shared/data/terrain2/
without the json file.
Also, You have clone the missing level-0 folder from the other existing one (You can google about it, you will find this trick).
https://github.com/geo-data/cesium-terrain-builder/issues/1 or https://github.com/geo-data/cesium-terrain-builder/issues/2
UPDATE: You could read this, it notices some steps to take care (Search... "So I got 65 000 terrain tiles").
@epifanio , I also have following apache directives for the directory
AddType application/octet-stream terrain
AddEncoding gzip terrain
Not sure if quantized-mesh requires them, but I had problems serving heightmap tiles without those.
Hi, I finally rendered our first city-level quantized-mesh terrain with help of Alvaro's CTB. Thanks for all kind of useful information.
Hi, I'm still having troubles with the missing tiles issue.
I tried several time to debug the issue but I can't figure it uout ...
I still have the missing 0.terrain
isue. In my last attmpt I'm serving the tiles directly from the /root/Apps/
Cesium forlder using nodejs server.js
this is exactly what I did:
cesium.js
src code:mkdir Cesium
wget -O Cesium/Cesium-1.43.zip https://github.com/AnalyticalGraphicsInc/cesium/releases/download/1.43/Cesium-1.43.zip
cd Cesium
unzip Cesium-1.43.zip
install Cesium
npm install
cd
into cesium/Apps
cd Apps
add a new HTML
file with the following code in it (add your BingMapsApi
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Hello World!</title>
<script src="../Build/Cesium/Cesium.js"></script>
<style>
@import url(../Build/Cesium/Widgets/widgets.css);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
Cesium.BingMapsApi.defaultKey = '------------------------'
var viewer = new Cesium.Viewer('cesiumContainer');
var terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'tiles/'
});
viewer.terrainProvider = terrainProvider;
viewer.scene.globe.enableLighting = true;
</script>
</body>
</html>
Download and merge the terrain sample GeoTiff
in a gdal VRT
file:
wget http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141E.tif \
http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141G.tif \
http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141F.tif \
http://kartat.kapsi.fi/files/korkeusmalli/hila_2m/etrs-tm35fin-n2000/L4/L41/L4141H.tif
gdalbuildvrt merged.vrt L4141?.tif
Generate the terrain tiles using ctb-tile
:
mkdir tiles
ctb-tile -o tiles -f Mesh -g 1.1 merged.vrt
Download the blank terrain tile"
wget -O 0.terrain https://raw.github.com/geo-data/cesium-terrain-builder/master/data/smallterrain-blank.terrain
Add the blank tile where needed (here I maybe do something wrong)
mkdir -p tiles/0/0/
cp 0.terrain tiles/0/0/
Serve the app using nodejs
:
cd ..
nodejs server.js --port 8000 --public true
On OSX, using safari as the browser, I got the following in the JS console:
[Log] An error occurred in "w": Failed to obtain terrain tile X: 0 Y: 0 Level: 0. (Cesium.js, line 477)
[Log] An error occurred in "w": Failed to obtain terrain tile X: 1 Y: 0 Level: 0. (Cesium.js, line 477)
Can you help me to understand what I'm missing/doing wrong?
I think you need the other root terrain tile: https://epinux.com/epinux_data/shared/data/terrain/0/1/0.terrain
You should have both: https://epinux.com/epinux_data/shared/data/terrain/0/0/0.terrain https://epinux.com/epinux_data/shared/data/terrain/0/1/0.terrain
@ahuarte47 I moved the tiles inside the cesium app so to make them "available" to cesium without using apache (I thought it was a correct way to avoid apache .htaccess (which I also tried)). I do have my app running on 8000 same host at the moment. I'll try again with apache as well.
I made the tiles i'm using [zip -r tiles.zip Apps/tiles/
] avaialble at tiles.zip
I don't have this "...Apps\tiles\0\0\1.terrain"
I see, I manually added it thinking that's was a missing tiles , my several attempts to debug..
removing it this is the log I have:
in the html I point to the tiles directory (no apache):
var terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'tiles/'
});
Log:
[Log] An error occurred in "w": Failed to obtain terrain tile X: 0 Y: 0 Level: 0. (Cesium.js, line 477)
[Log] An error occurred in "w": Failed to obtain terrain tile X: 1 Y: 0 Level: 0. (Cesium.js, line 477)
Using apache dir I have a cross origin problem (I'm googling about it):
html code:
var terrainProvider = new Cesium.CesiumTerrainProvider({
url: 'https://epinux.com/epinux_data/shared/data/tiles/'
});
viewer.terrai
Log:
[Error] Origin http://epinux.com:8000 is not allowed by Access-Control-Allow-Origin.
[Error] Failed to load resource: Origin http://epinux.com:8000 is not allowed by Access-Control-Allow-Origin. (layer.json, line 0)
[Error] XMLHttpRequest cannot load https://epinux.com/epinux_data/shared/data/tiles/layer.json due to access control checks.
[Log] An error occurred in "w": An error occurred while accessing https://epinux.com/epinux_data/shared/data/tiles/layer.json. (Cesium.js, line 477)
I tried to change https://epinux.com:8000
with http://localhost:8000
but then the log says:
[Log] An error occurred in "w": An error occurred while accessing https://localhost/epinux_data/shared/data/tiles/layer.json. (Cesium.js, line 477)
[Error] Failed to load resource: An SSL error has occurred and a secure connection to the server cannot be made. (layer.json, line 0)
finally removing https
and using http
, the log is:
[Error] Failed to load resource: Could not connect to the server. (layer.json, line 0)
I can leave the process running if usual to debug
Sorry, these errors are related with Cesium deployment. I only can say a last try, edit your "web.config" in Cesium root folder adding this:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="origin, x-requested-with, content-type" />
<add name="Content-Encoding" value="gzip" />
</customHeaders>
</httpProtocol>
That's a bit frustrating, I started from scratch on my laptop (before was on a remote server) I can run Cesium with its own server.js or just storing the Cesium directory under the apache root dir. I can run all the examples. In having Cesium served via apache I do not have the control origin error (both "tiles" and "cesium app" are served by apache on localhost on my laptop) but the tiles are giving me the same error:
[Log] An error occurred in "w": Failed to obtain terrain tile X: 0 Y: 0 Level: 0. (Cesium.js, line 477)
[Log] An error occurred in "w": Failed to obtain terrain tile X: 1 Y: 0 Level: 0. (Cesium.js, line 477)
btw ... this log is not very useful.
the only thing left to try is to add the .htaccess
inside the root /tiles/
directory.
I'm gonna try with this .htaccess
:
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with,
content-type"
<IfModule mod_headers.c>
<FilesMatch "\.(png|jpeg)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env= IS_CORS
</FilesMatch>
</IfModule>
AddType application/octet-stream terrain
AddEncoding gzip terrain
no luck, actually trying to load the page with chrome instead of safari, the cesium widget doesn't load at all with a nice message:
webgl works because the src examples (e.g.: HelloWorld) works fine.
I'm gonna write on the mailing list to seek help, I already bloated the whole thread here :) Huge thanks for the help!
did something change here recently? I was able to build fine a week ago, but now I am encountering issues. I'm using GDAL 2.1.3
Huh, didn't realise the original repo was even still active. Okay, I'll go upgrade my GDAL
Hi @ediebold, I did a minor change, do you can build now?
I upgraded my GDAL to 2.2.2 - but have hit a new issue (with and without that minor change, so definitely a 2.2 issue).
Compiler message is:
../src/libctb.so: undefined reference to `GDALCreateOverviewDataset(GDALDataset*, int, int)' collect2: error: ld returned 1 exit status tools/CMakeFiles/ctb-tile.dir/build.make:98: recipe for target 'tools/ctb-tile' failed make[2]: [tools/ctb-tile] Error 1 CMakeFiles/Makefile2:202: recipe for target 'tools/CMakeFiles/ctb-tile.dir/all' failed make[1]: [tools/CMakeFiles/ctb-tile.dir/all] Error 2 Makefile:127: recipe for target 'all' failed make: *** [all] Error 2
Yeah, my understanding is that that method is no longer even being exported in GDAL 2.2. The signature was also changed, but it's not being exported, so you can't link to it. (This discussion should probably be moved over to #15 .)
I am testing the quantized mesh output now- but just to confirm, do we still need to add any missing base tiles ourselves? Is this something we could make ctb-tile do automatically? This is really the only thing preventing the automatic hosting of ctb-tile output.
Also, I've done some tests, and this branch works fantastic for me.
Yeah, my initial tests with a couple different source terrain datasets show it seems to be working well.
I'm actually hoping to write up a blog post after I've had a chance to generate a complete dataset.
Okay, I've found one problem.
It seems that the layer.json's available array isn't being filled out for all the layers. I am processing a dataset that goes down to zoom level 16. However, when viewed with the generated layer.json file, I can't get past zoom level 12. This is true for both quantized mesh and heightmap. When I build a heightmap tileset and delete the entire available entry from the json, I can see all the levels of detail.
Edit: I added the missing layer's availabiltiy to the json file manually, and it fixed the problem. Of my 17 zoom levels (0 included), only 13 had entries in the available list initially.
Edit 2: Just to confirm, running with the -l flag doesn't help.
Okay, I've hit another issue. Not 100% sure this belongs here, but this place seems to be where problems get fixed.
I've made a VRT which is a combination of two SRTM 30m files, and a DEM we collected ourselves. I used gdalwarp and gdal_translate to make sure all three files had the same projection and band type.
Everything goes fine for the first 10 levels of depth (level 16 till 7), but then I get this error message:
ERROR 1: Integer overflow : nSrcXSize=22062, nSrcYSize=30960
ERROR 1: IReadBlock failed at X offset 0, Y offset 0
ERROR 1: GetBlockRef failed at X block offset 0, Y block offset 0
Error: Could not read heights from raster
ERROR 1: Integer overflow : nSrcXSize=22268, nSrcYSize=31465
ERROR 1: IReadBlock failed at X offset 0, Y offset 0
ERROR 1: GetBlockRef failed at X block offset 0, Y block offset 0
Error: Could not read heights from raster
This leaves me with no tiles at a zoom level lower than 7 (i.e. I have tiles from 16 to 7). The folder structure for zoom level 6 exists, but is empty. I know this is a VRT issue since the individual files all work fine
Edit: Interestingly, I made another VRT out of the files, but set the resolution to "lowest", rather than "highest", as it was before. This seems to prevent the issue, but obviously isn't a solution since I'm after the higher resolution of the other DEM. Setting the resolution to "average" also fixes the problem, but also isn't what I'm after.
Edit 2: Even though the process fails out early, it still produces a layer.json file. Everything seems fine, except for the available list, which is obviously missing the early zoom levels. Interestingly, it has the details for level 6, the level it is failing out on:
"available": [
[ ]
,[ ]
,[ ]
,[ ]
,[ ]
,[ ]
,[ { "startX": 114, "startY": 29, "endX": 114, "endY": 29 } ]
,[ { "startX": 228, "startY": 59, "endX": 229, "endY": 60 } ]
,[ { "startX": 457, "startY": 118, "endX": 459, "endY": 120 } ]
,[ { "startX": 915, "startY": 236, "endX": 918, "endY": 241 } ]
,[ { "startX": 1831, "startY": 472, "endX": 1837, "endY": 483 } ]
,[ { "startX": 3663, "startY": 944, "endX": 3675, "endY": 967 } ]
,[ { "startX": 7327, "startY": 1888, "endX": 7350, "endY": 1934 } ]
]
Without being familiar with the code, this suggests to me that the issue is separate from the layers.json construction at least.
@ediebold : the "Integer Overflow" issue appears to be the same thing as #28 and https://github.com/geo-data/cesium-terrain-builder/issues/37#issuecomment-252857173 .
Another option besides building multiple VRT levels may be using gdaladdo
to add overviews for your dataset.
I just came here to say I'd found the answer, but you beat me to it.
I've done the fix from #37 , but it's worth noting that doing so breaks the layer.json creation- since layer.json is only created if one doesn't already exist. To get around this, you need to re-call ctb-tile with the "-l" flag. Of course, at the moment, this still runs into my first issue - I don't get all the zoom levels in the layers.json file.
Both issues (Missing root tile for CesiumJS, and "Integer Overflow" error) are old known issues but not related with Quantized-mesh output.
I could fix some of them (first one looks easy to develop), but I have the doubt if it is better to create specific pull requests in order to do not mix features. Any thoughts?
@ahuarte47 I think that Missing root tile issue is not a bug in ctb-tile but Cesium should be fixed to handle this.
I see no sense in generating empty tiles for terrain or imagery.
I opened an issue https://github.com/AnalyticalGraphicsInc/cesium/issues/6301 for this while ago but closed it when I found that "missing" root tile was causing my problem with only half of the globe rendered when no terrain tile for the other half. I'm thinking of reopening it and explaining myself better.
Edit: Cesium already handles this for imagery tiles.
@ahuarte47 - I agree about the scope of this pull request. However, this main repo has been effectively dead for years. Would it be better if we just began raising issues in your fork?
Also, what about the issue with layers.json? That would almost certainly be an issue for this pull request?
Hi @kvuorine
I think that Missing root tile issue is not a bug in ctb-tile but Cesium should be fixed to handle this.
I agree, but does it have sense add a new option to workaround this issue now?
I opened an issue AnalyticalGraphicsInc/cesium#6301 for this while ago but closed it when I found that "missing" root tile was causing my problem with only half of the globe rendered when no terrain tile for the other half. I'm thinking of reopening it and explaining myself better.
+1
Hi @ediebold
I agree about the scope of this pull request. However, this main repo has been effectively dead for years. Would it be better if we just began raising issues in your fork?
I am going to do my best, but I can not offer official support for this.
Also, what about the issue with layers.json? That would almost certainly be an issue for this pull request?
I think the best option is to do not create the layer.json if any error occurs and no all scales are specified when executing the tool. it seems congruent me.
@ahuarte47
I think you misunderstood which issue I’m talking about. I meant this comment:
https://github.com/geo-data/cesium-terrain-builder/pull/55#comment-376384683
It seems that the layer.json’s availability list is required for quantized mesh terrains, so I can’t not include it. Based on the fact that only a few zoom levels are missing, I’m hoping it’s just a typo somewhere.
Sorry, I am going to try explain my point, only the json file will be created if -l option or all levels are specified (from 0 to....).
ctb-tile -s 16 -e 5 -p geodetic -f Terrain -o C:\folder raster.tif
No create the json file although it does not exist.
ctb-tile -s 16 -e 0 -p geodetic -f Terrain -o C:\folder raster.tif
Create the json file if it does not exist.
ctb-tile -l -s 16 -e 5 -p geodetic -f Terrain -o C:\folder raster.tif
ctb-tile -l -s 16 -e 0 -p geodetic -f Terrain -o C:\folder raster.tif
Always trying to create the json file.
-l option does not open any input raster file, only travels by all tiles to count them. You can always execute it with all levels.
If you get some "Integer Overflow" error, you would have to execute, by example:
ctb-tile -s 16 -e 7 -p geodetic -f Terrain -o C:\folder raster_05m_resolution.tif
ctb-tile -s 6 -e 0 -p geodetic -f Terrain -o C:\folder raster_10m_resolution.tif
ctb-tile -s 16 -e 0 -p geodetic -f Terrain -o C:\folder raster_5m_resolution.tif -l
Edit: In order to avoid confusion, I think it is better to create the json file only when -l option is specified. "Integer overflow" error will not create more corrupt json files. And also, this step will be more fast than previous versions because of it take advantage of available CPU/Threads. ok?
I added a new "cesium-friendly" option to force the creation of the missing root tile when the 0-level is included in the command settings. It copies the existing file to the missing location. If everybody think that is bad option, I rollback this commit.
Provides some new features:
Details: https://www.linkedin.com/pulse/fast-cesium-terrain-rendering-new-quantized-mesh-output-alvaro-huarte/