Height Fields in Povray (Ray Tracing Elevation Data, Part II)
This is Part II of a four-part article on ray tracing digital elevation model (DEM) data. (Actually, it's looking like there may be five or more parts in the end.)
The goal: render a ray-traced image of mountains from a digital elevation model (DEM).
- Part I, Get and Understand the Data: Working with Digital Elevation Models in Python
- Part II, Understand Povray: Height Fields in Povray (this article)
- Part III, Povray on real DEM data: Ray-Tracing Digital Elevation Data in 3D with Povray
- Part IV, Make a 3D Panorama: Making a Panorama from Raytraced DEM Images
My goal for that DEM data was to use ray tracing to show the elevations of mountain peaks as if you're inside the image looking out at those peaks.
I'd seen the open source ray tracer povray used for that purpose in the book Mapping Hacks: Tips & Tools for Electronic Cartography: Hack 20, "Make 3-D Raytraced Terrain Models", discusses how to use it for DEM data.
Unfortunately, the book is a decade out of date now, and lots of things have changed. When I tried following the instructions in Hack 20, no matter what DEM file I used as input I got the same distorted grey rectangle. Figuring out what was wrong meant understanding how povray works, which involved a lot of testing and poking since the documentation isn't clear.
Convert to PNG
Before you can do anything, convert the DEM file to a 16-bit greyscale PNG, the only format povray accepts for what it calls height fields:
gdal_translate -ot UInt16 -of PNG demfile.tif demfile.png
If your data is in some format like ArcGIS that has multiple files, rather than a single GeoTIFF file, try using the name of the directory containing the files in place of a filename.
Set up the .pov file
Now create a .pov file, which will look something like this:
camera { location <.5, .5, 2> look_at <.5, .6, 0> } light_source { <0, 2, 1> color <1,1,1> } height_field { png "YOUR_DEM_FILE.png" smooth pigment { gradient y color_map { [ 0 color <.5 .5 .5> ] [ 1 color <1 1 1> ] } } scale <1, 1, 1> }
The trick is setting up the right values for the camera and light source. Coordinates like the camera location and look_at, are specified by three numbers that represent <rightward, upward, forward> as a fraction of the image size.
Imagine your DEM tilting forward to lie flat in front of you: the bottom (southern) edge of your DEM image corresponds to 0 forward, whereas the top (northern) edge is 1 forward. 0 in the first coordinate is the western edge, 1 is the eastern. So, for instance, if you want to put the virtual camera at the middle of the bottom (south) edge of your DEM and look straight north and horizontally, neither up nor down, you'd want:
location <.5, HEIGHT, 0> look_at <.5, HEIGHT, 1>(I'll talk about HEIGHT in a minute.)
It's okay to go negative, or to use numbers bigger than zero; that just means a coordinate that's outside the height map. For instance, a camera location of
location <-1, HEIGHT, 2>would be off the west and north edges of the area you're mapping.
look_at, as you might guess, is the point the camera is looking at. Rather than specify an angle, you specify a point in three dimensions which defines the camera's angle.
What about HEIGHT?
If you make it too high, you won't see anything
because the relief in your DEM will be too far below you and will disappear.
That's what happened with the code from the book: it specified
location <0, .25, 0>
, which, in current DEM files,
means the camera is about 16,000 feet up in the sky, so high that the
mountains shrink to invisibility.
If you make the height too low, then everything disappears because ... well, actually I don't know why. If it's 0, then you're most likely underground and I understand why you can't see anything, but you have to make it significantly higher than ground level, and I'm not sure why. Seems to be a povray quirk.
Once you have a .pov file with the right camera and light source, you can run povray like this:
povray +A +W800 +H600 +Idemfile.pov +Orendered.pngthen take a look at rendered.png in your favorite image viewer.
Simple Sample Data
There's not much documentation for any of this. There's povray: Placing the Camera, but it doesn't explain details like which number controls which dimension or why it doesn't work if you're too high or too low. To figure out how it worked, I made a silly little test image in GIMP consisting of some circles with fuzzy edges. Those correspond to very tall pillars with steep sides: in these height maps, white means the highest point possible, black means the lowest.
Then I tried lots of different values for location and look_at until I understood what was going on.
For my bowling-pin image, it turned out looking northward (upward) from the south (the bottom of the image) didn't work, because the pillar at the point of the triangle blocked everything else. It turned out to be more useful to put the camera beyond the top (north side) of the image and look southward, back toward the image.
location <.5, HEIGHT, 2> look_at <.5, HEIGHT, 0>
The position of the light_source is also important.
For instance, for my circles, the light source given in the original hack,
<0, 3000, 0>
,
is so high that the pillars aren't visible at all,
because the light is shining only on their tops and not on their sides.
(That was also true for most DEM data I tried to view.)
I had to move the light source much lower, so it illuminated the sides
of the pillars and cast some shadows, and that was true for DEM data
as well.
The .pov file above, with the camera halfway up the field (.5) and situated in the center of the north end of the field, looking southward and just slightly up from horizontal (.6), rendered like this. I can't explain the two artifacts in the middle. The artifacts at the tops and bottoms of the pillars are presumably rounding errors and don't worry me.
Finally, I felt like I was getting a handle on povray camera positioning.
The next step was to apply it to real Digital Elevation Maps files.
I'll cover that in Part III, Povray on real DEM data:
Ray-Tracing Digital Elevation Data in 3D with Povray
[ 18:02 Jul 12, 2019 More mapping | permalink to this entry | ]