Thursday, December 5, 2013

WhirlyGlobe 2.2

I'm pleased to announce the release of WhirlyGlobe 2.2.

WhirlyGlobe is a 3D globe rendering toolkit for iPad and iPhone based on OpenGL ES 2.0.  It lets you put labels, markers, vectors, and shapes on top of a 3D interactive globe with one or more base layers of pageable image data.

Check out the video for a quick tour.



WhirlyGlobe presents a nice, simple Objective-C interface and uses standard MVC constructs such as view controllers and delegates.  It's very easy to integrate into your own app.

Where To Get It

The github repository is the best place.  The master branch is on 2.2.  You'll want to check out the readme, but basically it goes like this.

  • git clone https://github.com/mousebird/WhirlyGlobe.git WhirlyGlobe-Maply
  • cd WhirlyGlobe-Maply
  • git submodule init
  • git submodule update
  • Open the WhirlyGlobeComponentTester in Xcode
All the example data is in one of the submodules, so it takes a while.

There's also a binary distribution.  Download it and open the WhirlyGlobeComponentTester example.


Using The Framework - GitHub

It's pretty easy to use WhirlyGlobe in your own project.  If you're using WhirlyGlobe as a submodule, it's like so:

  • Set up a brand new project for your app with git enabled.
  • cd to the root directory of the project
  • mkdir libs
  • git submodule add https://github.com/mousebird/WhirlyGlobe.git libs/WhirlyGlobe-Maply
  • git submodule init
  • git submodule update
  • cd libs/WhirlyGlobe-Maply
  • git submodule init
  • git submodule update
One of WhirlyGlobe's submodules contains all the source data, so that'll take a while.  You only have to do it once.

Then in your Xcode project, do the following:
  • Go to Build Phases and open "Link Binary With Libraries".
  • Hit +
  • Select "Add Other"
  • Navigate to libs/WhirlyGlobeSrc/WhirlyGlobe-MaplyComponent/
  • Select WhirlyGlobe-MaplyComponent.xcodeproj
  • Hit + again
  • Select libWhirlyGlobe-MaplyComponent.a
  • Add a few other libraries you'll need
    • libc++
    • CoreLocation
    • libz
    • libxml2
    • libsqlite3
  • In Build Settings find "Header Search Paths"
  • Add the path "$(SRCROOT)/libs/WhirlyGlobe-Maply/WhirlyGlobeSrc/WhirlyGlobe-MaplyComponent/include/"
You should now be able to pull in WhirlyGlobeComponent.h and compile.

Using The Framework - Binary Distribution


If you're using the binary distribution instead of github, there are even fewer steps.
  • Set up a brand new project for your app.
  • Go to Build Phases and open "Link Binary With Libraries".
  • Hit +
  • Select Add Other
  • Navigate to WhirlyGlobeMaplyComponent.framework in the binary distribution and select it.
  • Hit + again
  • Select libWhirlyGlobe-MaplyComponent.a
  • Add a few other libraries you'll need
    • libc++
    • CoreLocation
    • libz
    • libxml2
    • libsqlite3
  • In Build Settings find "Header Search Paths"
  • Add the path to "$(binary dist path)/WhirlyGlobeMaplyComponent.framework/Headers".  You fill in the binary dist path.
You should now be able to pull in WhirlyGlobeComponent.h and compile.

Documentation

The full set of reference documentation is now available.  That's documentation for each of the Objective-C classes.  The crazy C++ internals are not documented there, so think twice before using them.

To see what's possible, consult the WhirlyGlobeComponentTester app which is included both in git and the binary distribution.  TestViewController.m is the best place to start.  Getting a simple globe up and running is surprisingly easy.

Wednesday, November 13, 2013

WhirlyGlobe-Maply 2.2 Beta4

Busy, busy, busy.  So here's the next WhirlyGlobe-Maply 2.2 beta.

That's animating, trust me.

I probably should have shipped the last one and moved on to version 2.3.  But I didn't.  I was busy integrating with a few client projects and that shook out a lot of bugs.  The user community was pretty active as well, finding bugs and minor gaps in functionality.  The result is beta4, which I quite like.

Updates to Beta4


There were many, many bug fixes.  We shook out a lot of problems and I added a whole bunch of new functionality.

  • 2D Maps
    • These work more smoothly in general.
    • When displaying a tile source that's in the same coordinate system as the viewer, we skip all the complicated screen space calculation logic.  This makes the loading look better.
    • For that case (simple flat map, basically) you can now ask "what zoom level are we at?"  That question only makes sense for a flat map.
    • The display supports coordinate systems other than spherical mercator.  Only one other is available, but in the future... more.
    • Rotation is now working thanks to a pull request.
  • Quad Image Paging Layer
    • Image paging now lives in its own thread and synchronizes with the frame draw boundaries.  This is very fast.
    • More knobs for controlling animation.
    • Many bug fixes to animation.  This deserves its own blog post.
    • Handles empty tiles better.  Now you can have a tile source that only provides levels 10-12, say, and it'll work.
    • Better error reporting including feedback at the tile source for failed loads.
    • Support for asynchronous loading if that's how you swing.
  • WhirlyGlobeViewController / MaplyViewController
    • You can now ask the control how high you should be to see a given bounding box.  This is nice for centering on data.
    • There are delegate methods for didStartMoving and didStopMoving.  These are useful for reacting to where the user is looking.  Be careful, they're on the main thread.
    • I support images on various high level objects, like stickers or markers.  The toolkit reference counted those when converting to OpenGL ES textures.  Now you can nail those down in the format you want with the settings you want and avoid creation/deletion thrashing.
    • Stickers support multiple images which they will happily pass to custom shaders.
    • Filled vectors now support textures.  [You should be saying "Oooooo" right now.]
    • Shader support has been there for a while, but now it tracks updates and forces redraws more consistently.
    • You can pass an image to a shader where it'll use it to do... whatever you write your shader to do.
    • Billboards are... hard to explain.  Useful if you know what they're for.


Distribution


You've got a couple different options for getting WhirlyGlobe-Maply 2.2 (beta4):
Don't forget about the documentation.  It took long enough to write, so read it.

The Future


This is more or less it for 2.2, I think.  Maybe a few bug fixes if anything heinous turns up.

I've absorbed 2.3 into the last beta, so next up is probably 3.0.  That'll be a while.

Friday, October 4, 2013

WhirlyGlobe-Maply 2.2 Beta3

The WhirlyGlobe-Maply 2.2 beta #3 is live on the master branch on github.  You can work with the precompiled distribution as well.

Yeah, I'm repeating myself.

What's New

Mostly bug fixes, but there is some new functionality of note.

  • Elevation Support - It's in there, hooked up at the Component level so go wild.  The test app also has a nice data set.  Look in the Washington state area.  Upper left in the U! S! A! for those of you overseas.
  • Basemap animation - I'm still messing with it.  Be warned.  Sure looks cool.
  • Multi-texture support - In at a low level.  Not much to see here yet, but hints of things to come.
  • Image paging layers changed quite a lot.
    • Each one gets its own thread.  This lets them be incredibly anti-social.
    • They work in a metered mode where they're tracking frame boundaries.  This reduces latency to the renderer.  Think: render, switch, render, switch, and so on.
    • Reload will now appear to switch instantly if all the tiles are local and it doesn't take too long.  This is nice for things like weather layers.
    • There's a mode to wait for all outstanding loads before switching to new geometry.  This looks great for local tile sets when loading is fast.  I'm ambivalent about how it looks for remote tile sets.  You've go the knobs, go twiddle.
  • QuadImageTilesLayer - I've consolidated all the image paging functionality at the top level in a single layer.  You can now mess with fairly advanced settings to your hearts' content.  The defaults are fine for most uses.
  • Xcode5 / iOS7 Support - It was mostly there before.  Now it's all pretty much there.  If it doesn't work then maybe it's you.  Ever consider that?
  • The death of -all_load - The Objective-C categories used to cause no end of trouble linking.  Now they don't.
  • Maply Fixes - Flat map 2D mode is working better and a user was kind enough to add rotation.
  • Documentation.  Lots and lots and lots of documentation.  Boy am I ever sick of writing documentation.
The image paging caused a bit of heartburn and I considered holding off to 2.3.  But damn, it's sweet, so I went ahead anyway.  The elevation support seems solid, but there are some obvious things it could do.  Animation is still a bit wonky.

The Future

This is it for big changes in the beta.  I've got a few more bugs I'm eyeballing.  I'm sure others will turn up, but I think beta3 is pretty stable.

Next up is 2.3, which should be fairly minor.  I'm thinking vector map updates, more on the animation, and whatever else I get paid for.  The big architectural changes are on hold until 3.0.

Wednesday, September 18, 2013

Contributions and Copyright

I've had clients for WhirlyGlobe-Maply for a couple years now.  Recently I've been getting contributors.  As an open source project, that's very exciting and I'm happy to see them!

They do add a bit of complexity, though, because of the way my project works.

Who Owns The Code?


That's easy, I own the code.  Every line of WhirlyGlobe-Maply is MINE!  But don't worry, you can use it for free.

Copyright is separate from license (I can hear my lawyer frowning).  I hold the copyright on the code, but I release it under an Apache 2.0 license so you can use it.  That license is incredibly friendly to commercial interests so you can make apps, modify the source, and generally go wild while abiding by its pleasant terms.

Sometimes I put WhirlyGlobe-Maply under another license for a client.  Why?  Money, that's why.  This doesn't effect the Apache 2.0 version and you needn't worry about it.  But it does mean I must own every line of WhirlyGlobe-Maply.

This is Open Source?


It is, yes, one of the variants.  It's not GPL, it's not even one of those big techno-hippie projects we all love.  But it is a well known, well tested, well understood variety of open source.

Okay, so if I own it, can I take it away?  I cannot.  Even if I decide to start charging for WhirlyGlobe-Maply 3.0 you still have the 2.2 version released under the Apache 2.0 license.  That can never go away.  [I have no plans to do this, by the way.]

Git Pull and Contributed Source


Now we get to the point of this post.  When contributors send me a pull request, what's the copyright on it?  Legally, it's "All Rights Reserved".

This won't do for either the open source version or for my own.  It could potentially taint the apps of anyone who uses the toolkit.  I can't have that.

If you're sending me a pull request, I need you to resolve the copyright and ownership.

Copyright Options


If you've modified the source, those modifications are yours (or your employer's).  If you write something new, that source is yours (or your employer's).  It's up to you (or your employer) to assign the copyright.  I'll explain some options.

All Rights Reserved

If you reserve copyright I can't touch it.  You can do what you like with it, including putting it up on github, but I'd ask you to put an explicit copyright on it so no one gets confused.

If you modified my source code in the process, you can't change my Apache 2.0 license and the copyright is now ambiguous, in my mind at least.  It would be great if you put a notice to that effect at the top of the files you've changed.  That way no one will accidentally get into trouble.

In any case, I won't be putting any of this code in my github repo.

Retain Ownership & Assign an Open Source License

If you write brand new code, you could retain ownership for yourself, of course.  If you then put an open source license on it, I will be delighted to put it in the Contributed directory.  Please pick a really, really permissive license, if you would.

I don't own source code in the Contributed area of WhirlyGlobe-Maply.  I may maintain it, from time to time, but I make no guarantees.

If you want to modify code in Contributed, feel free.  Just respect the license that's on it.

Transfer Ownership

The last option is transferring ownership to mousebird consulting inc (e.g. me).  In this case I'll pull it back into the toolkit, slap the Apache 2.0 license on it and treat it as my own, because it now is my own.

I'm only going to ask this for small amounts of code and bug fixes.  I know, it seems stupid to ask for bug fixes, but I legally have to.

Let me emphasize: YOU DO NOT HAVE TO DO THIS.  Sending me a pull request does not imply anything.  When I ask you, you can then make your choice and I will respect it.

Working For The Man


If you're an employee or doing work for hire, you must get your employer's permission to assign ownership.  I cannot accept the assignment if I think you can't give it, so I may ask some probing questions.

I know no one does this and I'm sorry to be difficult.  Look, I've been in silicon valley a long time now and I've seen a lot of stupid go by.  Much as I love github, and I really do, there is a lot of stupid around it and copyright.  I won't have it on my project.

"But hey", you may be thinking, "don't you work for The Man as well!"  I do, random interlocutor, but I have a Lawyer and a Contract.  It's a big nasty contract that spells out what I own and what The Man owns.  I trust it works because it's killed a few potential deals.

Standard work for hire contracts or employment agreements do not look like mine.  I very much doubt you have the same rights I do unless you specifically negotiated for them.

Conclusion


If I've sent you here for a pull request, let me just say:  Thank You!  Even if I can't accept it, it's helpful for a few reasons:

  • I can see what developers are interested in
  • If it's a bug fix, I can see what the problem is
  • It gets my stats up on github (don't laugh)
  • It was probably useful in your own app

So again, thank you!

Please take a look at your copyright options and pick the one most appropriate.  Picking nothing defaults to "All Rights Reserved".  That's fine too.

Friday, September 13, 2013

Vectors, OpenStreetMap, and Maply

A few months ago I gave a talk at the OpenStreetMap conference in San Francisco.  It was all about using vector tiles for map display on iOS.

Not San Francisco
This was based on new functionality in Maply, the 2D part of WhirlyGlobe-Maply.  Since then I've improved things.

Vector Support in Maply


I've had support for vector data in WhirlyGlobe since 1.0.  With version 2.2 it's gotten much better, specifically for map display.  The important bit was the MaplyQuadPagingLayer and the MaplyPagingDelegate protocol.

It works like this.  You provide an object that supports the MaplyPagingDelegate protocol, start up a MaplyQuadPagingLayer and wait for the callbacks.  When it's time to load a tile, you load your data, convert it to a displayable form and then hand it over.  The system cleans it up for you when it's no longer needed.

Now we can treat vector data like we do image tiles.  If only we had a good data source...

OSM Vectors


A few months ago OpenStreetMap began providing vector data tiles experimentally.  Mike Migurski was the driving force behind it, and he explains it better than I.

Tasteful buildings
The short of it is, we've got vector data chopped up into individual tiles, with some basic cartographic choices made at the various levels.  The server responds much like an image tile server, but it returns GeoJSON.

That's great, but how well does it all work?

Base Map + Vector Overlay


There are two sorts of vector maps we might want to display with Maply.  The first is comprised of vector data overlaid on an image base map.


That's the easier case.  It's a subset of the full vector features, including roads, labels, and buildings.  More importantly, the polygons are fairly simple.  Which leads to the next question:  How about everything?

Pure Vector Map


An entirely vector based map is the goal, at least from a technical standpoint.  With pure vector on one end and pure image on the other, we'd like to dial in the appropriate mix for a given app.  The OSM data is there, so how well does it work?


It works well.  Quite well indeed.  That's the big innovation from a few months ago:  WhirlyGlobe-Maply 2.2 can handle the weird polygons it gets from the server.  The tessellation is working well even for complex polygons with holes.

Room For Improvement


Nothing's perfect, of course; that would be creepy.  There are a few areas that could be better, in no particular order, they are:

  • Parsing GeoJSON is just slow.  It needs to be faster.
  • A binary vector data cache would make things appear much faster.  For some cases it would be a big improvement.
  • The vector data is coming in tiny little chunks.  This is messing with the drawing optimization.  There are ways to fix this.
  • Place names are dominating the display in cities.  For a real app, I'd suggest making some cartographic choices.
  • It needs more styles.  I've broken out a few of the feature types, but more is better.

Even so, this is usable as is.  Go check out the code, all open source, and give it a try.

What's Next


I build out serious toolkit functionality with serious apps.  On the WhirlyGlobe side I've had some great clients who did some really ambitious things.  There's been some interest on the Maply side, but so far nothing really big.  The toolkit is ready (more than ready) so as soon as I reel those clients in, we should have some interesting results.

In the mean time Maply vectors are pretty stable.  Go give the OSM example a look and feel free to use it in your own apps.

Thursday, September 12, 2013

WhirlyGlobe-Maply Feature: Elevation

Terrain support has been a very popular request in WhirlyGlobe-Maply.  Here you go.



Works pretty well, actually.  The data set I'm using there is in Spherical Mercator to match the map tiles coming from MapBox.  There's one 32x32 sample tile for each image and the data is stored locally in an sqlite database.  More about the tools later.

Component Support


If the elevation data is stored in a sqlite database, we obviously have to get it out.  We use a MaplyElevationDatabase to do that.  That object implements the MaplyElevationSourceDelegate protocol, which you can use to query individual tiles.



You can also implement your own elevation database, perhaps one which fetches data remotely.  Just implement the MaplyElevationSourceDelegate protocol.  Don't worry, you're called in another thread so go ahead and block on the network calls.

We hand the elevation database over to a MaplyBaseViewController, which is the parent of both globe and map view controllers.  Though that object doesn't use it, it does pass it on to layers that care about elevation.  At present, that's just the MaplyQuadImageTilesLayer, which now handles all of the local and remote image tile paging.

Here's what that all looks like, from the WhirlyGlobeComponentTester app.




And all that will get you this.

How active could that volcano be?


Elevation Pyramid Generator


Getting terrain support in the toolkit wasn't actually all that difficult.  I know kind of a lot about this stuff.  No, the real problem is how to generate the data.

From past experience I knew I couldn't just throw this functionality out there and expect users to pick it up.  I needed to provide a tool.

This one's just gratuitious
That tool is elev_tile_pyramid and you can find it on github in the develop branch.  It deserves its own blog post, but for now you can look in the README file.  That explains how to compile it and how to run off the Pacific Northwest example.  You can also just download that database.

The Fine Print


It's cool and it works!  But there are some caveats.

Elevation data adds complexity.  We can no longer predict where the surface of the earth is at any given point and, even worse, it moves between levels of detail.  That means features are hard to place.

The settings panel.  Titillating!
That's the settings panel from the WhirlyGlobeComponentTester app.  The base layers are all there, but you might notice all the overlays are missing, as are the vectors.

You can do vectors, labels, markers, and all that good stuff in this mode, but they won't work well.  Markers and labels might, actually, but vectors certainly won't.  Why not?  Because topology.

We've got a different version of the surface for each level of detail, and there are 14 levels in the example.  That means whatever you stick on top of the earth needs to move around as those levels of detail swap in and out.  It's not impossible, but it does require some work.  Work that, frankly, a client can pay for.

The Conclusion


It works pretty well and it's in the develop branch on github.   Go have fun.  I'm sure more features will be forthcoming, but I'm going to see what clients want to do.

Wednesday, September 4, 2013

WhirlyGlobe-Maply 2.2 Beta

As promised, the WhirlyGlobe-Maply beta is up for version 2.2.  You can get it on github from the master branch.  That's the preferred location.

Gratuitous Image
If you want a binary distribution, I've got one of those up now too.  This includes the framework, now stripped of its debug info, as well as a the sample app and all dependent libraries.