Wednesday, November 30, 2011

App Store Mention: Santa's Big Helper

The whole point of doing WhirlyGlobe is for developers to use it.  I had in my mind a couple of types of developers who might find it useful:  People who just want to toss some info up on the globe and hard core globe centric app developers.

They're both really interesting groups, but for very different reasons.

Hard Core Interactive Globes

I wasn't expecting to attract this group right off the bat.  I have, though, and that's both good and bad.  On the good side, they push really hard for new features.  On the bad side, they push really hard for new features.  It's great to see that WhirlyGlobe is useful to them, but I'm not as responsive as I'd like to be.

Mobile development is an interesting place full of really excited people trying out lots of great ideas.  Which is to say, the failure rate is pretty high.  I've worked with a number of projects that have collapsed under the weight of their own ambitions.  Others have just slowed considerably after the initial burst of excitement.  In software engineering parlance that's called "normal".

One of the big issues that confounds these projects is data collection and manipulation.

GIS Is Harder Than You Think

Getting the right data for your project is much more difficult than people realize.  Any number of projects I'm involved with have tripped over these issues.  I warn, but I'm not doing a great job at it.

Most developers are vaguely aware of the Blue Marble imagery data set so I don't have to point it out.   The next place I'll send them is to the Natural Earth web site for vector data.  After that it gets tricky.  If you want something specific you really have to do some data processing.

You can't really do that data processing on OSX.  There are some open source tools, but they're not all that user friendly.  The major tools vendor hasn't ported to the mac and why on earth would they?  That means I can't even reliably get a client to look at their own data.  They really need a PC or they need to be pretty savvy to use the open source stuff.  Even then they're going to have to outsource the data processing.

A lot of projects bog down here.  That's why it's nice to work with simpler projects too.  These are developers who just want to bring up a globe and toss a few geolocated objects on top of it.  One of them recently shipped.

Santa's Big Helper

That's just what the developer is doing in Santa's Big Helper.  He's bringing up a globe with one of the Blue Marble composites overlaid and then dropping a few Markers on top.

These projects are a great test of how usable WhirlyGlobe is on the less complex end of things.  Obviously Santa's Big Helper is not a simple app, but the globe is a relatively straightforward application of my toolkit.

I could use more documentation, I think, but these projects are able to proceed and that makes me happy.

There are a number of interesting things they did here, actually.  There are views underlaid and overlaid, including transparency.  They look really good.

Surprisingly, the frame rate is still quite good.  I obsess about performance because that's my thing so semi-transparent overlays are something I avoid.  I may be overthinking it.

That's cool and it's great to see that WhirlyGlobe is working on the simpler end of things.  That's what it was designed to do and there are a few features in the pipeline that'll help with this sort of project.

WhirlyGlobe Version 1.2

As for the actual 1.2 release, I'm still a few weeks away.  Here's how things are going.

  • Particle systems are working and scaled correctly.  
  • Markers are working, but I'm still scaling them.  If you just need a handful, you're good.  If you want to toss 2000 of them up there, wait a bit.
  • The Texture Atlas Builder is up and running, as is texture ID translation.  I'm pretty happy with this one as it solves a lot of problems.
  • The new Selection layer is up and running.  It really simplifies label and marker selection logic.
  • There's a new test app I'm using for tracking down memory and resource problems.  It needs to test a few more features before it's complete.
  • Lofted polygons haven't been integrated yet.  These are what WhirlyGraph uses.
  • Render Data Caching is working, but not complete.  It's also a bit slower than I'd like.
  • Bitmap font support for labels has not started.  I'm wavering on this one.  It's really the last unnecessary resource hog in WhirlyGlobe 1.1, but I would like to release soon.
  • Gridlines may get postponed.  No one seems to be bugging me for them.


The source tree is actually in pretty good shape right now.  If you need one of the new features, just ping me to see how well it's working.

Tuesday, November 8, 2011

Image Pyramid Support: MapBox Tiles

I've been planning to add support for multi-resolution images, or image pyramids, for a while.  I'm still planning on it.

Image Pyramid

An image pyramid is pretty much what it sounds like.  You take a giant image, make a version at about half the resolution, put that somewhere, made another version at half that resolution and keep going.  You stop when you either get to 1 pixel or it just gets stupid, usually the latter.

Rather than storing a big image at each level, you tend to chop these suckers up into manageable pieces.  The definition of manageable changes depending on what you're up to.  For interactive 3D the chunks tend to be less than 1M pixels in a format conducive to fast drawing.  That size might be 256 x 256 pixels and the format is PVRTC for our purposes.

Another way of looking at an image pyramid is as a quad tree.  Each node would store a single image, ideally in your optimized format, ready to be loaded.  Or, and this where it gets fun, a node might be empty.  This lets you build a sparse image pyramid and save a lot of space.

Image pyramids are easy enough to build, but you have to do something with them.

Paging Image Data

There are different ways to page an image pyramid or similar structure.  If you're displaying the image in 2D, you tend to want everything in your window at one resolution.  When the user zooms in or out, you switch resolutions.  For 3D display, you tend to use the higher resolutions close up and lower resolutions in the distance.

For a globe, it gets weirder.  You want lower resolutions when you're farther away and higher resolutions when zoomed in.  And if the user spins the damn thing really fast... well you need to not go on a paging binge.  It's similar enough to 2D and 3D display, though, that you can borrow from those approaches.  The main question is where you're pulling the data from.

There are as many tiled multi-resolution image formats as their are clever idiots to make them.  I developed one myself back in the day.  There are many, many others.  To pick one, you really have to look at the technology you're targeting and think a little about marketing.

MapBox Tiles

For WhirlyGlobe, I'm planning to implement the MapBox Tiles (MBTiles) spec.  It's got a few things going for it.

MBTiles is being actively developed.  That means an ecosystem of applications producing it and users interested in plugging things together.  The folks behind it have a pretty good open source vibe too.

It's based on currently hot technology.  You store tiles in a sqlite3 database, which is pretty much ubiquitous these days.  It can also be streamed from a remote site.  2004 here we come!

MBTiles are stored pretty flexibly, so I can mess with them.  I need to stick PVRTC image data in there, rather than PNG or JPEG.  The difference in memory is pretty big and that's what we really care about.

MapBox makes user level tools to produce MBTiles, including an iPad app (TileMill).  Data production for GIS is a bitch, so this is promising.  The dots may not all connect, but it's a start.  [Edit:  Too lazy here in my description.  The iPad app displays maps produced by TileMill, which runs on the mac, among other places.  Getting all the tools together on one platform is a problem I have with clients all the time, so this is promising.]

WhirlyGlobe Issues & Schedule

Of course, there's always work to do.  Paging imagery also means paging terrain, or in my case, making it up on the fly.  I'm already doing that in the Spherical Earth Layer, but now I'm going to have to do it differently.

Multiple resolutions of terrain means multiple resolutions of data sitting on top of the terrain... possibly.  So it gets complicated.  What fun.

MapBox Tile support will be after WhirlyGlobe 1.2.  My guess at this point is early 2012.

Thursday, October 27, 2011

Markers and Particle Systems - First Look

Let's start with Markers.  You'll recall that these are just stamps we place at locations on the globe.  Pretty basic stuff.

Marker placed right over Paris.  Woo.

So that's working.  It can also display a series of images, you just give it a list of textures and a period over which to switch them and off it goes.

And it's smoooth.  Why so smooth?  Because I do the switching on the rendering thread.  And that makes it complex.  For me, anyway, not you.

Marker Code

Here's the example code.

// Utility routine to add a texture to the scene
- (SimpleIdentity)makeTexture:(NSString *)name
{
    UIImage *image = [UIImage imageNamed:name];
    if (!image)
        return EmptyIdentity;
    Texture *theTexture = new Texture(image);
    scene->addChangeRequest(new AddTextureReq(theTexture));

    return theTexture->getId();
}

// Add a Marker over Paris
- (void)addMarkers
{
    // Description of the marker
    NSDictionary *markerDesc =
    [NSDictionary dictionaryWithObjectsAndKeys:
     [UIColor whiteColor],@"color",
     nil];
    
    // Set up a texture for the marker
    SimpleIdentity parisArmsTexId = [self makeTexture:@"200px-Grandes_Armes_de_Paris"];
    SimpleIdentity parisFlagTexID = [self makeTexture:@"200px-Flag_of_Paris"];
    SimpleIdentity frenchArmsTexID = [self makeTexture:@"175px-Armoiries_republique_francaise"];
    SimpleIdentity frenchFlagTexID = [self makeTexture:@"320px-Flag_of_France"];

    // Set up the marker
    WGMarker *parisMarker = [[[WGMarker alloc] init] autorelease];
    
    // Stick it right on top of Paris
    GeoCoord paris = GeoCoord::CoordFromDegrees(2.350833, 48.856667);
    [parisMarker setLoc:paris];

    // We're going to give it four different textures that rotate over a period of 10s
    [parisMarker addTexID:parisArmsTexId];
    [parisMarker addTexID:parisFlagTexID];
    [parisMarker addTexID:frenchArmsTexID];
    [parisMarker addTexID:frenchFlagTexID];
    parisMarker.period = 10.0;

    // These values are relative to the globe, which has a radius of 1.0
    parisMarker.width = 0.01;    parisMarker.height = 0.01;
    
    // And add the marker
    [self.markerLayer addMarker:parisMarker desc:markerDesc];
}

That's totally self explanatory.  Definitely.

The only thing I don't like about this is how the textures work.  That's one texture per image, which means one Drawable per state and that kinda sucks.  I may need to expand the TextureAtlas support a bit to help out with this case.

But this is pretty much how it'll work for the WhirlyGlobe 1.2 release.

Particle Systems

These are never going to be full desktop graphics particle systems or non-real time animation particle systems.  They'll be pretty simple.

A couple of fountains
Okay, they won't be quite that simple, but you get the basic idea.  These are fountains with a single color.  A proof of concept, as you might say.

Particle System Code

Here's what the code looks like.

// Add a particle system
- (void)addParticleSystems
{
    NSDictionary *partDesc =
    [NSDictionary dictionaryWithObjectsAndKeys:
     [NSNumber numberWithFloat:0.02],@"minLength",
     [NSNumber numberWithFloat:0.03],@"maxLength",
     [NSNumber numberWithInt:500],@"minNumPerSec",
     [NSNumber numberWithInt:600],@"maxNumPerSec",
     [NSNumber numberWithFloat:1.0],@"minLifetime",
     [NSNumber numberWithFloat:5.0],@"maxLifetime",
     nil];
    
    // Add a single particle system
    ParticleSystem *particleSystem = [[[ParticleSystem alloc] init] autorelease];
    GeoCoord washDc = GeoCoord::CoordFromDegrees(-77.036667,38.895111);
    [particleSystem setLoc:washDc];
    [particleSystem setNorm:PointFromGeo(washDc)];
    
    [self.particleSystemLayer addParticleSystem:particleSystem desc:partDesc];
}

Okay, I'm skipping a step, like where I create the particle system layer.  Trust me, you'll just copy my example for that anyway.  It's easy.  This is the interesting bit.

Again, pretty standard stuff.  You give it some parameters to control its size, some functions of the particles, a location, and you're off.  I'll add a few more parameters to control the distribution and color and maybe another type or two if I'm feeling saucy.  Otherwise, that's about how it'll look for 1.2.

Thursday, October 20, 2011

WhirlyGlobe 1.2 feature - Markers

The paperwork's still being shuffled on this one, but it looks like it'll happen.  I have a client who needs Markers and Selection.

That'll be two new layers that find their way into WhirlyGlobe 1.2.

Markers

Markers are pretty simple, really.  You give the toolkit a location, a size, and an image and it sticks that sucker right where you tell it.  Kind of obvious, really.  I'd say it was an oversight in 1.1, but I just chose to work on vectors instead.

In true WhirlyGlobe fashion, you'll be able to specify a whole NSArray of Markers (and I recommend that you do) for speed.

You'll also be able to specify a whole array of UIImages to iterate over, in much the same way as UIImageView.  I'll be tossing these in to a Texture Atlas, because that's just how I roll.  Should be pretty fast.

The switching will be controlled by a render-side Generator, which I'm not ready to talk about yet.  We'll see more Generators in 1.2.

Selection

This one is more infrastructure-y.  The Selection layer will let you pick features based on a 2D screen location.

Selecting vector features is pretty easy already.  All you need is a geographic location and a big pile of features to look through.  With the MBR (bounding box) cache on top of a shapefile, we can do most of the checking without looking at the actual features.  It's fast and reasonably easy.

Selecting labels is harder.  To do it properly you'd really like to tap within a label or near one and that nearness test makes it tricky.  What coordinate system is it "near" the tap in?  Well, from the user's perspective, it's the screen and that means you need to do it in screen space.

What the Selection layer will do is keep track of objects, such as labels, in 3-space and project them back to the screen on demand for testing.  You'll hand the Selection layer a point, distance, and a callback delegate.  Everything that falls within the given range will be handed to the delegate.

Toolkit Support & WhirlyGlobe 1.2

The Marker and Label layers will automatically pass their data to the Selection layer if given the right parameters.  There's a bit of overhead in keeping the outlines of features available for selection so this will be optional.  In fact, it will probably cost more memory to make a given label available for selection than to render it.  Weird, eh?

Geographic features, such as points, linears, and areals will still be selectable by geographic test.  For now, that makes more sense.

The 1.2 release is being shuffled a bit.  Markers are new and Selection was something I was contemplating for later.  Caching is still in, as are particle systems, since I have those largely implemented.  We'll have to see what else makes the cut.

Tuesday, October 4, 2011

WhirlyGlobe 1.2 - What's Coming

I'm working on WhirlyGlobe 1.2 at the moment.  Well, I'm working on things and those things will wind up in 1.2.  Here's a list of some of those things.

Caching

Here's what I mean by caching.  WhirlyGlobe reads fairly generic data sets: geodetic shape files.  These are relatively unstructured lists of points, linears, and areal features with matching attribution.  All the coordinates are in (latitude,longitude).  Turning these into what you see on the screen involves a bit of processing.

What I'm doing internally is batching all that data into a small set of Drawables and tossing those over to the renderer.  To cache, I save that data out in a form compatible with OpenGL and load it back in on startup.

The caching is mostly finished.  I had a client who wanted to load all the Natural Earth 10m country vectors at once.  Turns out it's possible, even on the iPad1.

Bitmap Fonts

When you add text to the label layer in WhirlyGlobe it's rendering it to a UIImage and turning that into a texture.  That's not deeply efficient.  If you add a whole bunch of labels together, it is stitching those images together into Texture Atlases, so that's not as bad as it could be.  Still, it uses more memory than it should.

The obvious next step is to use a giant texture made up of all the various characters you might want to use.  There are standards for this sort of thing and tools to generate the textures, such as BMFont.  It's just a matter of actually doing the work.

Grid Layer

This one's pretty simple.  It's just a layer that drops down lines at the lat/lon boundaries.  It's in there now, it just doesn't work all that well.

Lofting Layer

The lofting layer is part of WhirlyGraph.  That's the thing that creates transparent geometry for country outlines.  In that sense, this isn't all that new.

What is new is integrating it into the regular toolkit.  I was doing an early version of caching to make it fast enough to use for the bigger countries.  Now caching is worked out, I'll switch the lofting layer over and integrate with the main toolkit.

Particle Generator

I've had requests for simple particle generation, much like in the Smule apps.  It's easy enough, but making it fast requires some design.

You'll most likely be restricted to a fairly simple set of parameters: particle color, speed, and various randomizers.  I think I'll avoid fireworks for the first go and we'll stick to fairly basic fountains.

The Farther Future

That's all for 1.2, I think.  Of course, some of this might slip and anything a client needs gets priority.

There are already some interesting things in store for 1.3.  In particular, discussions with other groups related to doing data fetching over the network.  We'll see how those go.

Monday, September 26, 2011

WhirlyGlobe 1.1

Version 1.1 was released around August 27th.  I'm still catching up, obviously.

Mainly, this was a bug fix release.  There was a bit of new functionality like so:

  • Support for label selection.  Not actual label selection, mind you, just support for getting size and location info projected in to 2D.
  • Added pre, post frame and lighting callbacks.  You can now override how WhirlyGlobe does the lighting, if you so desire.
  • WhirlyGraph was integrated in to the Contributed tree.  That's one of the prettier demos.
There was a bit of stuff under the hood not worth discussing.

Framework & Starter Pack

The most useful pieces were these.  I hacked together a framework building shell script from a useful blog post and started distributing a framework.  Now you can just drag and drop WhirlyGlobe into your project.

Of course you still need all the dependencies and that was causing people problems.  To that end I put together a distribution with all the various dependencies.  You can get the download off the WhirlyGlobe project page.

Tuesday, September 20, 2011

WhirlyGlobe

So I didn't keep the blog up, but oddly enough I did finish the project: WhirlyGlobe.



What WhirlyGlobe does is handle the 3D interaction and rendering for a globe with vector data.  The vectors can be from a remote source or Shape files that you bring along with your app.

There are a couple of apps available on iTunes to look at.

  • The WhirlyGlobe demo app lets you tap around countries and states as well as oceans (my personal favorite).
  • WhirlyGraph shows comparative statistics for countries around the world.  And it's candy colored.


Earth Data

WhirlyGlobe is meant to display a set of earth imagery with vector data overlaid.  Basically, that means it takes a collection of images in the proper format with an index file.  It comes with a utility to prepare that data from a regular image file if you want to use your own.

Vector data can come from a couple of different sources.  The first is you.  Just create points, linears, or areal features and, optionally, labels.  The second source is Shape files.  These are a standard for geographic data and can be found on the web, often for free, or created with standard industry tools.

Audience

As you might have guessed, this is for app developers.  You need to know Objective-C, Cocoa Touch, and a smattering of C++ to use it effectively.  There are a couple of decent examples, including the source code for the WhirlyGlobe app.

Source Code

WhirlyGlobe is an open source toolkit distributed under the Apache License (2.0).  That should allow you to use it in just about any configuration for free, commercial, or any sort of app.  mousebird consulting owns the source code entirely so if you need some other license, we can discuss it.

Motivation

Obviously no one does this sort of work for free.  Unless they do.  If they do, they probably have a reason.  Here are our reasons.

  • The WhirlyGlobe toolkit is free to use in most ways, as constrained by the Apache License (2.0).  If you would like additional functionality, you can hire us to add it.
  • I've benefited from quite a few open source toolkits for ios.  WhirlyGlobe is a way of giving something back.
  • Data visualization on mobile devices is interesting and difficult.  I like those sorts of problems.
0r maybe I just like showing off.

In any case, if you need a 3D interactive globe component for ios, give WhirlyGlobe a look.

Thursday, February 17, 2011

First Post!

Here's a little blog associated with mousebird consulting.  This won't be high traffic.

I'm contemplating a series of posts on an open source project I'm working.  The project's interesting enough to attract some attention, but needs a little marketing.  When the project releases, I'm planning to sign up for one of those guest blogger spots on a developer site.

For now, I think I'll post on a few random topics related to computational geometry and ios development, just to provide a little background reading.