akka facebook webgl demo hack
Switch branches/tags
Nothing to show
Latest commit 0be5a9f Feb 7, 2011 @buka buka thumbnail
Failed to load latest commit information.
project sbt files with rename... Feb 6, 2011
src/main updated readme; make sure apple lic travels with all their bits Feb 7, 2011
README readme Feb 7, 2011
fbgl1.png thumbnail Feb 7, 2011


fbgl1 - Hacking Akka, Facebook Graph API, WebGL and other things...

Quick Intro
A little while back, I posted a gist showing how to perform a server-side OAuth 
validation using Akka Mist, Leeloo and the Facebook Graph API. This is an 
iteration of that experiment that also mixes in some WebGL and web workers.
Anyway, it's posted as a simple sample for looking at some of these pieces
in an introductory way.  
Obviously what's going on here is that your Facebook account is allowing the 
app to access your friends list and in particular their current location and
hometown.  The former is preferred but the latter is used in its absence.  
If neither is available, that friend is ignored.  This happens frequently
which is why you'll find that the total loaded is almost always fewer than
you, in fact, have. Friends are aggregated together into common locations.

Each location is then thrown against the Google Maps API to acquire it's 
latitude & longitude.  Locations are queued for query by a web worker 
and should appear as they are loaded.  Locations will be updated 
(if applicable) as more friends are found (on the server) and added 
to the location's payload.

When a location node is loaded/updated, cubemaps are composed of all the
profile pictures.  The total number of nodes that may be drawn at a single
location is friends/6 + 1.  Locations with more than 1 node will 'fountain'
them over time.  The number of fountain nodes is initally capped at 5. This
can be adjusted using the slider.  Selecting 'max nodes' will discard the
slider value and add all friend nodes to the fountain.  The fountain isn't
exactly physically correct as it ensures the node falls back into the origin
rather than continuing along its motion vector.  There is a "co-location" 
tolerance as well.  This is added for cleanliness.  It is used to determine
if locations are too close to each other and, if so, to treat them as a 
fountain.  So... an example - you've got friends in San Francisco, CA
as well as Berkeley - these will fall within the same tolerance and the
Berekely node will be 'fountained' even if there are less than 6 friends.
Basically this is just so you can see pictures.  

Why bother with a server component? This is a fair question. Basically
as already noted, this started as a server-side OAuth example.  Nothing
prevents all of that logic from running in the client.  That said, the
server is used to do work in anticipation of being called again by the 
client, reduces the number of connections the client would otherwise
have to make and, if nothing else, illustrates some more akka-ness:
http & load balancing actors

Why is the "subnets" checkbox disabled? Just because it's useless unless
your friend's friends also grant access to your app. I thought it might
be cool to show but never really had the time to connect it all up fully.

Building, etc
Use SBT 0.7.5.RC0 and build the project.
Create an Akka deployment.
Copy the fbgl1.jar to the deploy/ folder 
Copy the oauth jars (2) from the lib_managed/ folder to deploy/
Copy the contents of src/main/resources/ to the config/ folder 
Copy the contents of src/main/html/ to a new folder called root/ (at the same level as deploy/)


where user_id is your Facebook user ID (not your account name).

Issues & Caveats
Almost inevitably, regardless of your deployment, the first time you hit the site 
it will appear to hang. This is a combination of a couple things first of which 
is the texture images, the rest is a function of your core count and bandwidth.  
I decided to add all 12 months to the globe texturing mostly for completeness 
and it looks nicer IMO.  Given this is just sample code, it hardly seemed to much matter, 
and besides they will end up (mostly) cached.  
Nevertheless, until they are, your world will be black or very dark.

There is a little indication of what's going on otherwise: 
"Loading user..." indicates a request was made to the server to get the geo-position of the user.
"Loading friends..." indicates a request was made to the server to get a list of all friend locations.
"Loading x from y" appears and will be updated as new locations appear or are updated with additional data.

I always had the location querying timer set to fire 4 or 5 times per second
which is fine on a good network and multi-core box but when I deployed the
server on an EC2 instance and tried it on a wireless mac mini it the experience
was annoying at best.  After that, I changed the interval to 1 second.  So it could
take a while, depending on how quickly everything gets organized on the backend,
to eventually cycle through every location and get all available geo-located friends.

This is a WebGL app afterall, it needs a GPU and it does do alot of background processing
so the more cores the better.

The server is balancing requests to Google Maps with two locator actors.  This makes it slower
than _possible_ but in practice their servers were bouncing too many requests back when flooded.

Other stuff
The shaders are pretty simple. In the vertex shader, there is a quaternion rotation
example.  In the fragment shader, earth textures are being blended together month-to-month 
to do that passing seasons effect.

The network polyarcs are computed in javascript when the friend location 
is first loaded. I added code on the server to do this later and never
had the time to update the protocol... which would have only served as a
trivial example of more direct VBO injection from XHR.  The trig is simple
so it shouldn't really impact things that much.

FPS - it's not the friends it's the locations.  I've tested over 600 friends
at 60+ locations with a framerate in the mid 20s... which is pretty bad I'll admit.

The basic structure and functionality of the WebGL stuff started from a Webkit demo; and
those bits fall under Apple's copyright notice found in the git.
The CRC-32 javascript was snipped from a useful blog post.

Given I barely had the spare midnight hour to scratch this together, it's not being
maintained in anyway. Everything herein that is mine, is hereby made available without
restriction in the public domain.