I’m working on a script to read srtm data and use it to build terrains in 3dsMax. I’m using .hgt files which are readily available online. A sample can be downloaded here. Documentation is here.
It works great, but it’s a bit slow. One of the reasons is the fact that the data consists of 16 bit integers. This means I’ve got to read two bytes from the file and turn those into a 16 bit integer to get to my data. Also, the data is provided in big-endian while I need to read it little-endian by reversing the order of the bytes.
So here’s what I’ve got.
function fn_getHgtDataSample hgtFilePath dataCount:160000 = ( local hgtBinStream = (dotNetClass "System.io.file").open hgtFilePath (dotnetClass "system.io.filemode").open --open the hgt file as a filestream local hgtReadMethod = (hgtBinStream.GetType()).GetMethod "Read" --using the normal .read method didn't work: http://forums.cgsociety.org/showthread.php?f=98&t=1108923 local theBuffer = dotnetobject "System.Byte" (dataCount * 2) --set up a buffer to get the requested amount of data. Each data-item consists of 2 bytes local isLittleEndian = (dotNetClass "System.BitConverter").IsLittleEndian --the hgt data is big-endian. We need to reverse the byte order to get good data local toInt16 = (dotNetClass "System.BitConverter").ToInt16 --this method will convert two bytes (8 bit each) to a 16 bit signed integer hgtReadMethod.invoke hgtBinStream #(theBuffer, 0, theBuffer.Length) --get an entire row of data if isLittleEndian do theBuffer.Reverse theBuffer --going from big-endian to little-endian local arrData = for i = 0 to theBuffer.Length-1 by 2 collect ToInt16 theBuffer i --loop over the streamed bytes and collect int16's hgtBinStream.close() arrData ) ( clearListener() gc() local st = timeStamp() local mem = heapFree local hgtPath = @"some\path o he\file\here\N34W119.hgt" local theData = fn_getHgtDataSample hgtPath dataCount:160000 format "%" (msg as string) format "Time: % ms, memory: % " (timestamp()-st) (mem-heapfree) )
Now I’m streaming the data. An alternative I’ve found is to use a binaryreader. It has a method to read int16 directly from the data, but it only works if the data is little-endian, which it is not.
The above sample will get 160k points of data which means a grid of 400 by 400. Other methods will arrange the data in an actual grid and build the meshes. Getting the data takes a little over 1 second on my machine. I’d like to make it faster.