Tuesday, August 27, 2013

Geospatial Data Display using OpenGL ES (for iOS)

A few weeks ago I gave this talk at the local NSMeetup.  That's a nice venue, primarily for iOS development, with a very strict technical bent.  Most iOS related meetups around here (San Francisco) devolve into meet markets for "technical cofounders".

Anyway, I asked to give a talk and after a bit of back and forth I made it more general than my usual WhirlyGlobe-Maply pitch.  Here it is in its full glory.


Overview


I had about an hour so I couldn't do a full OpenGL ES tutorial.  I tried to distill a few lessons from geodata display, things that you run into when you have more data than you can easily draw.  And of course, how to draw it fast.

There was code!  I honed a few examples related to my favorite problems.  Hit the links below to jump to the code examples in the video.


I tend to think of these as really big problems I throw a lot of code at to fix.  It was interesting to boil them down to their essence in a little code and show the solutions.

The Code


You can get the NSMeetup app source on github.  It has the code examples, as well as links to the code in github gists.

Cubes are like spheres, only less so.
The github gists were an experiment.  I've watched any number of talks with the speaker struggling to use Xcode in less pixels than Xcode would prefer.  And anyway, I do my talks on an iPad because my demos are on an iPad.  So why not show the code on the iPad?

Using gists and a UIWebView let me keep the flow going.  I went back and forth between code and the working example without leaving the app.  I'd definitely do that again.


More Tutorials?


I may do a few more, but just related to WhirlyGlobe-Maply.  This was very interesting, but time consuming and I'm not in the OpenGL ES training business.  If you are in that business, feel free to link to the video if you find it useful.

Tuesday, August 20, 2013

WhirlyGlobe-Maply 2.2

I've been working on 2.2 for a few months now, ever since 2.1 was released.  There's a lot of new stuff in this version.  So much that I've been actively delaying writing it up.

Let's get on with it!  Here's what's in WhirlyGlobe-Maply 2.2.


Base Map Display


The quad paging layers changed radically in this version.  I talk a bit about the underlying technology elsewhere, suffice it to say that they draw fast.  Real fast.

In addition to that (which is big), I've also exposed a lot more functionality at the Component level.  Now you can do tricky stuff like this.


That's three base maps stacked on top of each other:

  • My variant of Geography Class, paged locally.
  • USGS Ortho photos coming from their WMS server
  • Transparent weather data from the OpenWeatherMap server

Each of those layers is independent, with its own coordinate system, level range and protocol.  You can now stack these things up to your heart's content and control their order.  And it's fast.

In addition to my own low level layers, you can also make your own.   Just create a MaplyQuadEarthTilesLayer and hand it an object implementing the MaplyTileSource protocol.  Have that object return an image for a given tile and off you go.  It even uses dispatch queues.

Vector Paging Layer


Though vector display hasn't changed all that much in 2.2, I have added high level support for paging your own data sets.  We organize base image maps as tiles and we can do the same with vector tiles.

OpenStreetMap vector data

In this example we're paging vector data from the US OpenStreetMap server.  That's an experimental setup where they're serving up GeoJSON tiles, sort of like what we used for images.

You don't have to have GeoJSON or anything specific.  Just create a MaplyQuadPagingLayer and fill in the MaplyPagingDelegate protocol.  You create the visible objects associated with your tile and the Component handles everything else, including cleanup.  It's also multi-threaded.

ZBuffer Control / Draw Priority


This one's a bit low level, but really useful.  You can now control which features respect the zBuffer (or ignore it) and which write to it.  That's incredibly useful for features you want to stick right to the globe.

  

From the picture, here's how the standard defaults play out.

  • Geography class is the base layer at priority 100.  It writes to the zbuffer, but doesn't read.
  • The USGS Ortho layer is next around priority 101.  Also writes to the zbuffer, but doesn't read.
  • Next, we draw the stickers (priority 30,000) which neither read from nor write to the zbuffer.
  • Grid lines (in blue) are drawn next (priority 50,000).  They ignore the zbuffer entirely and have a tricky little shader program to deal with the lines behind the globe.
  • Lastly, we throw on the shapes, including those spheres and the great circles (with altitude) at about priority 80,000.  They read from the z buffer, but don't write to it.
There's also a little book keeping for skirts.  What are skirts?  Do you see any obvious lines between levels in the base map?  That's what skirts do.

That's all without the dreaded drawOffset; drawPriority now rules the day.

Anyway, that's all with the defaults.  Odds are you'll never need to set any of this yourself, but it's there if you do.


Text Fonts & Layout


We've now got a font glyph manager.  It's not too tricky, but it speeds things up and (potentially) saves a lot of memory.



We used to render each label in Quartz, which worked great, but was kind of slow and a memory hog.  Now when you ask for a label, it renders the appropriate glyphs, saves them to a giant texture atlas and makes up the polygons for your string.

When you delete the string, it may delete the glyphs as well.  So feel free to use weird fonts with impunity.


Labels now support a wider range of features, including an outline color and size.  That's nice for maps with cluttered backgrounds.

The layout engine is a bit more sophisticated as well.  It can handle rotation and does a better job with justification.

Vectors & Lofted Polygons


The toolkit can now tesselate large, weird polygons.  Why?  Because sometimes you get large, weird polygons.

Oh goodie, lakes.

This is useful in a couple of places.  First, the kMaplyFilled attribute works a hole (pun intended) lot better on vectors.  Second, the lofted poly layer is a lot faster.  Tapping Russia is now interactive.

Ha ha.  Red.  I get it.

Thread Control & Active Objects


Now for the obscure stuff.  You can add things on the main thread!  Gasp!  Wait.  What?

That little sphere is moving.  Just keep staring.
WhirlyGlobe-Maply likes its threads, it uses a bunch of them.  We try to do everything on either the layer thread or in custom dispatch queues.

Well great, but what if you want to change something RIGHT NOW.  You know, if you're editing it.  Or maybe animating it.  Now you can.

All the usual add calls (i.e. addScreenLabels:) take a mode: parameter.  Right now the mode is either MaplyThreadAny (the old way) or MaplyThreadCurrent.  For the latter we do the deed right now on the thread we're currently in.

There's also a new MaplyActiveObject, which is wrapper around a callback you get right before the next frame draws.  This is how you animate if you're so inclined.  Use it wisely.

Screen Space Calculation & Tilt


The toolkit spends a lot of its time trying to figure out what to load and when to load it.  It does this by deciding how big things are on the screen.  That works fine if you're staring straight down, it gets trickier if you're not.

Crazy!  Who knew?  Well I knew, I was just avoiding it.


And now I'm not avoiding it.  We can display the sampled curved surface of a globe when looking outward.  That was fun.

You can mess with the tilt in a WhirlyGlobeViewController.  This can get tricky, so check out the setTiltMinHeight:maxHeight:minTilt:maxTilt: method.  That'll muck with the tilt as you get close to the ground in a somewhat intuitive fashion.

Maply (2D) Changes


Support for the 2D/3D map mode is fleshed out a bit more.  I think you can actually use it for apps now, because... well... I have.

Like a Globe, only Flat.

There's a true 2D map mode now, where you can turn off lighting and even tie the map to a UIScrollView.  It's a bit... tricky yet.

The gestures could use a bit of work and I'm getting a better idea of what users might want (hint: looks like MapKit).  There will probably more of this in 2.3.

Component vs. WhirlyGlobe-Maply API


I used to stress the difference between the low level WhirlyGlobe-Maply API and the high level Component.  The API uses a combination of C++, STL, Boost, and apparently MADNESS.  I'm just pushing the WhirlyGlobe-Maply Component these days.

In fact, most of my clients are using the Component, so all the good stuff gets exposed there.  Point being, just use the Component.

Other Stuff


There's a lot of new functionality in WhirlyGlobe-Maply 2.2.  Did I mention custom shaders?  I did not.  The low level rework that'll make Android porting easier?  Didn't really go into that.  How about elevation data?  Yeah, it's there, but you need your own data.  Don't have that... let's wait until 2.3.

And, oh yeah, the WhirlyGlobe-Maply Component Tester app has been heavily reworked to show all this off.  Check that out for examples.

The Future


I'm putting 2.2 into Beta shortly.  It'll go active on the main branch on github, then we'll update the pod specs, the documentation, and the binary distribution.

After 2.2 I'm looking more toward map related features.  The globe is fun, but maps (vector and image) are a bigger user base.  Rather than crazy high end stuff (which my clients like), I need to put some time into making things easier to use.  Annotations are an obvious problem, as is area based update.

Of course, clients pay the bills, so expect more high end craziness as well.

Tuesday, August 6, 2013

Geospatial data display using OpenGL ES

I'm doing a talk tomorrow night on geospatial display and OpenGL ES for iOS.  Down in SOMA in good old San Francisco.

There's a few examples, a bit of code, and a whole lot of slides.  Should be fun.

Along with the talk is a tutorial illustrating some of the problems you run into doing geospatial data display.  You can find the code on github.

Thursday, July 25, 2013

Web Map Service (WMS) Support

The Web Map Service protocol has been around a while.  A long while.  I just got around to implementing it in WhirlyGlobe-Maply.

Add witty caption
Of course the toolkit has been able to do this sort of thing since 1.0, but with a variant of TMS.  I think.  You know, what OpenStreetMap and Google publish.  Bing does something weirder.

Anyway, you can do WMS now in your WhirlyGlobe or Maply app.

The Code


All this is in WhirlyGlobe-Maply 2.2, a rather massive update to the toolkit I'll be publishing shortly.  It's in the develop branch if you're feeling frisky.

Here's how you'd add the NAIP ortho quads to your globe (or map).

Pretty simple, actually.  Here's all we're doing.

  • Create a coordinate system that describes good old WGS84 lat/lon.
  • Setting up a tile source to point to the WMS end point.
  • Starting a new layer which uses that tile source.

Incidentally, you can write your own tile sources now.  The code for MaplyWMSTileSource is pretty simple and it lives at the Component level.  That means it's entirely Objective-C.

Oh, and I don't think you should do this for WMS sources you don't own.  WMS is much more general and I'm using it for tiles, which is... yeah.  Anyway, be sure you know what services you're hitting and how they feel about it.

Thursday, July 18, 2013

COM.Geo Talk - Monday July 22

I'm giving a short talk on WhirlyGlobe-Maply at the COM.Geo conference in San Jose on Monday.

It's a 10 minute overview of the toolkit, who uses it, what it's for and such.

Here are the slides.

Sunday, July 7, 2013

StrataLogica 2.0

This is a beast of an app based on WhirlyGlobe.

Woo!  Topical!
They've got a free mode, so I suggest checking it out.

The 2.0 version just came out and it's a lot of new functionality and a whole new interface.  You can draw on the globe.  I kid you not.

They're going for schools here.  Teachers, students, geography, history, that sort of thing.

WhirlyGlobe


Of course it's all about me, so yes it's using WhirlyGlobe-Maply.  More WhirlyGlobe than Maply, for sure.  StrataLogic 1.0 was using WhirlyGlobe, but I never got around to posting about it.  Er, duh.

Anyway, without going into too much (any) detail on the inner workings, there are a lot of moving parts here.  The interface is entirely the product of a talented team at RoundArch Isobar.  The data sets are shared with the desktop version, which is based on Google Earth and owned by HerffJones-Nystrom.

I did the globe portion, as you might guess.  That may look like the big piece, but trust me, it ain't.  That interface is pretty deep.

WrapUp


These guys have been a client for the better part of a year and it's nice working with a team.  They've been willing to experiment and bring the necessary resources to bear.  I think the result speaks for itself.

Friday, June 21, 2013

Android Port: Begging for Money

I'm getting a lot of queries about an Android port.  Just to recap, I make the WhirlyGlobe-Maply toolkit, an open source 3D interactive globe and map display toolkit for iPad and iPhone.

Globe                            3D Map                         2D Map
Most of the development I do is incremental.  If I add, say, font based text rendering it doesn't cost all that much and one client can pay for it.  Everyone else gets the benefit and that's how open source works.

The Money


Some things are just too big for that model.  An Android port isn't like a feature request, it's big.  How big?  About $50k (USD).

Normally I'd approach this one of two ways:

  1. Do it myself.  I absorb the cost of lots of features no one really wants to pay for.
  2. Wait until a big client needs it.  Pretty likely, but could take a while.
This is just too big for the former.  Remember, I give this stuff away.  The latter will probably happen... eventually.

What if I could speed that up?

The Engineering


I've bid an Android port on several projects now and worked out the details.  Here's how it would go.

The core rendering modules of WhirlyGlobe-Maply are largely C++. We would be making heavy use of the NDK on Android to port the rendering engine.  

The first step would be to move more of the rendering modules into pure C++ on iOS. This has the virtue of being easily testable with the current toolkit.

The next step would be a direct port of the rendering engine modules to the Android NDK.  After that we would rewrite the threading and messaging logic in Java for Android as well as the various interface logic to go between Java and the rendering engine.

Lastly, we would rewrite the high level interface in Java. This would correspond to the Component level on iOS. These objects need to be native Java and function in ways Android developers expect, just as the Component on iOS is native Objective-C. 


The Appeal


A lot of companies are interested in an Android port of WhirlyGlobe-Maply.  Some are using the globe, but most want to do custom map display on both platforms.  Mine is probably the best open source toolkit for that and superior to a lot of the commercial solutions.

So, I'm talking to you guys here:
How much would you kick in for an Android port?

Drop me an email and let me know.  If I hit a certain threshold, I'll come back to you for details.