robhawkes / horizonator

Terrain renderer based on SRTM DEMs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Horizonator!

Overview

This tool renders terrain data, and can be used to simulate views captured by a camera. This is most useful in areas with significant topographic relief.

There are a number of other, more polished tools to do this

Although less polished, the implementation in the horizonator is freely licensed (under any version of the LGPL), and is a good base for experimentation. The horizonator is mostly intended as a building block for other tools, so the user-facing UI tool is somewhat feature-sparse.

The horizonator consists of a C library, a Python library and two user-facing tools:

  • The horizonator tool: an interactive FLTK application that displays an overhead map and a render, allowing the user to interactively move around in both those views, and to relate the views to each other
  • The standalone tool: a one-render application. Can produce either a static GLUT window or a .png image on disk

Building the horizonator

This isn’t “released”, so I’m not providing packages, and building from source is required. This probably can work on any recent UNIXy platform, but I’ve only tested on Debian and CentOS.

On Debian, you need the following packages (I believe that’s it; may be missing one or two):

  • libfltk1.3-dev
  • libboost-filesystem-dev
  • libboost-system-dev
  • libboost-thread-dev
  • libcurl4-gnutls-dev
  • libgl1-mesa-dev
  • libepoxy-dev
  • libglu-dev
  • libpng12-dev
  • libfreeimage-dev
  • libtinyxml-dev
  • libpython3-dev

Once you have those, run make. You also need wget at runtime to download the tiles.

Using the horizonator

Before running the tool, you need data to render. The horizonator uses 3sec SRTM DEMs. Raw SRTM data contains gaps, so I usually use the gap-filled SRTM data from

http://viewfinderpanoramas.org/dem3.html

You need to download the archive for your area (for North America, you can pick from a map). Then extract the .hgt files to

~/.horizonator/DEMs_SRTM3

Any missing DEM files are assumed to describe an area at elevation = 0 (such as an area of open ocean). After the DEMs are downloaded, the tool can be run (OpenStreetMap tiles are required too, but those are downloaded automatically at runtime).

There’s an interactive tool for humans to mess around with, and a standalone tool to just make single renders (useful for scripting)

Interactive

The interactive tool is invoked by running the ./horizonator executable. ./horizonator --help has basic usage instructions. The only required arguments are the latitude and longitude of the viewer. Example: standing on top of Iron Mt, looking N and E towards Mount Baden-Powell and Baldy:

./horizonator --zfar-color 8000 34.2884 -117.7134 45 80

example-interactive.png

This brings up a window where the top half shows an OpenStreetMap slippy map. OSM tiles are downloaded (and cached locally to ~/.horizonator/tiles/) as required. The extents of the current view are shown as lines in the render. The currently-loaded data is also shown, as a rectangle. The data is loaded at the beginning, centered on the latitude,longitude given on the commandline. To load a different set of data, re-launch the application.

The bottom half shows the render. By default, the shade of red encodes the distance to the viewer. It is possible instead to texture the render using the map; pass --texture to select this mode. Currently this uses the same OpenStreetMap tiles that are used in the slippy-map, which isn’t terribly useful. Eventually topography or aerial imagery should be hooked in here.

The initial render is made from the latitude,longitude position given on the commandline (the altitude is sampled from the DEM). The user may change the viewpoint at runtime, but new data is loaded only at the start.

UI

  • Mousewheel up/down in the slippy map: zoom in/out
  • Left click/drag in the slippy map: pan
  • Right click in the slippy map: re-render the currently-loaded data from that location
  • Mousewheel up/down in the render: zoom in/out. Changes the azimuth extents. Does not change the pitch or roll or yaw. The viewer always look out parallel to the ground plane: pitch, roll are always 0.
  • Mousewheel left/right in the render: pan left/right. Changes the yaw only.
  • Left click/drag in the render: pan by moving the azimuth extents and/or the yaw. Exactly what the mousewheel does.
  • Right click in the render: display the rendered point on the slippy map. Useful for identifying peaks.
  • Keyboard w: cycle between filled triangles, wireframe and point renders
  • Keyboard r: cycle between the two winding directions; this is only useful for debugging.
  • Keyboard q: quit

Commandline

If all we want is a single render from a known position, with known azimuth bounds, run the ./standalone tool. Example:

./standalone --width 800 --image example-standalone.png  --zfar-color 8000 34.2884 -117.7134 -35 125

example-standalone.png

This can either run a static GLUT application, or it can render to a .png image on disk and/or a binary range image. Run with --help for details. Note that the azimuth extents are currently specified differently than they are in the interactive tool.

C API

The tool can be invoked from C. The header comments and its usages in the commandline tool should be clear.

Python API

A Python interface is provided, and is built as part of the normal invocation of make. The Python library consists of

This works similarly to the other components: the constructor loads the data, and we can then render it in different ways by calling render() repeatedly.

Render details

The tool uses an equirectangular projection. The x coordinate of the rendered image represents the azimuth: the viewing direction. The y coordinate represents the elevation: the angle above/below the horizontal. The same angular resolution is used in both directions. As elevation increases, this projection acquires more and more distortion, but with small elevation angles (the usual case) things works well.

The view straight ahead (elevation = 0) is at the center of the render.

This tool operates in the tangent plane to the viewer, so it assumes that locally, the Earth is flat. This produces small inaccuracies, but unless we care about small pixel-level errors, this is a good approximation. I will eventually fix this.

Nice-to-have improvements

In no particular order:

  • Texturing with aerial imagery
  • Being more efficient about data loading: the DEM and texture resolution needs to be high close-in, but can be dramatically lower further out.
  • Higher-res DEMs are available (1sec SRTM instead of 3sec). It would be nice to use them, if we can do so efficiently
  • Nicer handling of the mesh immediately near the viewer.
  • Intelligently loading faraway data. Currently we load data a constant number of cells away from the viewer
  • Peak-labelling the render
  • More UI stuff
    • text showing the current lat, lon, az bounds
    • text inputs to change the current lat, lon, az bounds
    • controls to re-center the data, to get more data in some particular direction
    • controls to change the texturing, shading configuration, etc
    • controls to save renders to disk
  • Auto-downloading DEMs

License and copyright

Horizonator (everything except florb/)

Copyright 2012-2021 Dima Kogan <dima@secretsauce.net> Released under the terms of the GNU LGPL (any version)

florb/

Copyright (c) 2010, Björn Rehm (bjoern@shugaa.de) Released under the terms of the MIT license

About

Terrain renderer based on SRTM DEMs

License:Other


Languages

Language:C 45.4%Language:C++ 43.1%Language:Makefile 11.5%