Monday, December 24, 2007

WWJ Annotated Icons

Suppose you have icons around the globe representing some type of events (traffic, rain, fire, ...) and you want to see more information when click on them with the mouse.

Well, I have created the so called AnnotatedIcons with this idea in mind. Note, as suggested here byt Pat, there is another approach to achieve similar effect based only in annotations (one annotation with two or more annotation attribute styles). Unfortunately :( I had done the major part of code when I known the alternative, and anyway I like AnnotatedIcons :)

As you can see in the image (I have no time to make a video), some icons are rendered and when the mouse is over one its associated annotation is shown with more extended information.

You can take the source code from here.

WWJ Rotable Icons

Reading this thread other developer talk about how useful will be have icons that can be rotated.
I don't know if these contribution success with all expectation but if you can compute the heading desired for your icons then these can be useful for you.
The RotableUserFacingIcon implementation allows to specify the heading rotation of your icons (like the compass).

You can get the source code from here.

Note, this contribution adds a peace of code into the IconRenderer class to allows icon rotation take effect, and also take into account the icon is slightly displaced when it is a rotable icon.

Saturday, December 08, 2007

The new balloon...

I'm glad to present a screenshot about the new balloon application.

For the moment I'm working very hard on the user interface, but it allows to work with the default WWJ BlueMarble and Lansat layers, load images (local or remote) with re-loading option ;) and animate with a temporality associated.

Tuesday, November 27, 2007

WWJ SurfaceImage reloaded

Don't worry this isn't Matrix ;) (I hope it)

I have made a little update on the previous update of SurfaceImage to allow reload of data.
Suppose you have an image file that can be modified by an external process and you want reload it at regular intervals of time to see its changes.
Now you can have it with SurfaceImage reloaded :)

You can get the source code here.

I have added a new reload(boolean useCache) method. Note, it has one boolean parameter to specify if the image must be reloaded from cache (if it is there, I think this option isn't very useful) or reloading it from the original source of data.

Monday, November 26, 2007

A note on LayerSet

Unfortunately I must recognize I am a newbie with my own code :P
Using LayerSet in the Balloon project I get a little headache I want to comment here.
LayerSet extends LayerList class and also implements the Layer interface (in the same way as AbstractLayer).
Take very into account, that if you create a LayerSet an adds a LayerList object, all contained layers in LayerList are copied into the LayerSet, and that's all. If later you modify the LayerList, adding or removing layers, the changes are not propagated to the LayerSet.

Friday, November 23, 2007

WWJ renderable objects

Although it seems a very big change, here I present a WWJ hack to convert more object into Renderable object, that is, objects that implements the Renderable interface.
I have made only three things to achieve this:

  1. Add the next methods to the Renderable interface:

    public boolean isEnabled();
    public void setEnabled(boolean enabled);
    public String getName();
    public void setName(String name);
    public double getOpacity();
    public void setOpacity(double opacity);

    The idea is that a any Renderable object can has a enable/disable state, an opacity value and optionally a name.

  2. Add a default implementation for this method in all affected classes and interfaces. The default implementation doesn't alter the normal behavior of this elements.

    * Default Renderable implementation.
    public boolean isEnabled()
    return true;

    public void setEnabled(boolean enabled)
    // Do nothing.

    public String getName()
    return null;

    public void setName(String name)
    // Do nothing.

    public double getOpacity()
    return 1;

    public void setOpacity(double opacity)
    // Do nothing.

  3. Added a new class RenderableListLayer, similar to LayerList that can contain any "new" Renderable object, that is, Layers, Icons, Images, etc.
    Here are a peace of code using this class:

    LayerList ll = new LayerList();
    RenderableListLayer main = new RenderableListLayer();

    main.add(new BMNGSurfaceLayer());
    main.add(new LandsatI3());
    main.add(new ScalebarLayer());

    RenderableListLayer rll = new RenderableListLayer();
    rll.add(new CompassLayer());
    rll.add(new WorldMapLayer());



Source code can be found here.

Finally it must be necessary to implement the appropriate mechanism to render images, nodes and other Renderable object taking into account its opacity and enable values.

Wednesday, November 21, 2007

WWJ Movable SurfaceImage

Finally I have modified the SurfaceImage class to implement the Movable interface too.
The source code can be found here.

Sunday, November 18, 2007

WWJ remote SurfaceImage updated

Well, after a couple of days improving some things finally here is the until now best version of SurfaceImage ;)

The new features are:
* Local and remote images (except BufferedImage's) are loaded in a separate thread.
* Remote images are cached on disk, to avoid network overhead.
* Added a 'setSector' method to change the image sector position.

You can find the source code here.

JOGL mipmap problem

Working on WWJ SurfaceImage class I get an strange phenomenon with the mipmap option. Here are the differences between using:

textureData = TextureIO.newTextureData(iconStream, false, null);
(mipmap option set to 'false')

textureData = TextureIO.newTextureData(iconStream, true, null);
(mipmap option set to 'true')

All three are PNG images.

Following Ken answer I report it as a possible JOGL bug.

Wednesday, November 14, 2007

WWJ and remote SurfaceImage

Yesterday and today afternoon I was working on the SurfaceImage class. I was modify a bit to allow load remote HTTP images on a Retriever thread. Now you can make things like:

SurfaceImage img = new SurfaceImage("", Sector.fromDegrees(40, 43, 0, 5));

You can found the code here.

Sunday, November 11, 2007

WWJ The needle of the compass

Here are a modified version of CompassLayer to allow compass with needle.
You can choose between the classic compass or a compass with a needle inside it. Also you can make the compass fixed and see how only rolls the needle.

As you can imagine you can set the images for the compass and the needle.

Saturday, November 10, 2007

WWJ LayerSet updated

I put here the link to the updated version.

Basically I have added a couple of useful methods to query if an object or a class is contained by the LayerSet or some other contained Layer.

public boolean contains(Object o) {

if (super.contains(o)) {
return true;

for (Iterator it = this.iterator(); it.hasNext();) {
Layer layer =;
if (layer instanceof LayerList) {
if (((LayerList) layer).contains(o)) {
return true;

return false;

Finally, I have added the mothod 'indexOf' that given a class returns the first instance ocurrence in the list (the search is not recursively).

Tuesday, November 06, 2007

WWJ Temporality updated

Today I have modified a bit the Temporality related classes. The TemporalityAdaptar has changed to TemporalityRenderableAdaptar and also I have created a TemporalityLayerAdapter to work with layers.
You can find the changes here.

Saturday, November 03, 2007

As farewell of Core API...

As I say in a previous post, I continue working on the Balloon Project but instead of build, improve and maintain my own 3D API, so called Balloon Core API, I change to use WWJ as 3D API.

It would not be fair for my lovely Balloon Core API not shown some videos with the latest improvements achieved.
I upload three videos to YouTube but also I upload them to my personal page with better quality. I only have 100mb of personal space and I don't know until when I store them, because this I have uploaded them to YouTube.
As usual, remember the animation in my laptop (with only 64mb graphics card) is very good although the captured screens seems poor.

The quality videos are cutted by my blog CSS, you can see completely HERE.

The first video shows three improvements: (1) the camera object can return the camera position and mouse coordinates (as you can see in the status bar). (2) Rotation was improved to move the world in a WWJ way. (3) Every layer informs the user with an "Uploading..." message in the status bar.

The second and third videos show the improvements in drag and drop object. Any object (images, points, polygons, ...) can be moved trough the globe, change its dimensions or change its elevation.

The low quality youtube videos are:

Sunday, October 28, 2007

WWJ Layers opacity

This post describes the changes needed to allow modifiable opacity in some
layers, those that use the SurfaceTileRenderer class to render its tiles.

I published it some time ago, but here is a more clear summary of changes.

The class SurfaceTileRenderer is responsible to render tiles of any tiled layer,
the problem is it doesn't take in account the layer opacity.
The methods responsiblesto render tiles are 'renderTile' and 'renderTiles'.
The idea is to add a reference on these methods to the layer that contains the
tiles to be drawn and add the code to set the opacity in the tile rendering

Changes from original WWJ 0.3.0:

I have attached the modified files, but here are a brief description of changes
respect WWJ 0.3.0. Note that almost all changes are in SurfaceTileRenderer class.

  • ''. On 'rederTiles' method, added a reference to the layer that contains the tiles. Then every tile can be rendered with the opacity specified in the layer:

public void renderTiles(DrawContext dc, Iterable tiles) ...
public void renderTiles(DrawContext dc, Iterable tiles, AbstractLayer layer)...

After next code:

if (!dc.isPickingMode()) {
} else {

add the next code to set the opacity:

// Set opacity
if (layer != null) {
gl.glColor4f(1, 1, 1, (float) layer.getOpacity());

Also modify the 'renderTile' method adding a new parameter that reference the
owner layer. Change:
public void renderTile(DrawContext dc, SurfaceTile tile) ...
public void renderTile(DrawContext dc, SurfaceTile tile, AbstractLayer layer) ...

and modify the line:
this.renderTiles(dc, al);
this.renderTiles(dc, al, layer);

Finally, you need to overload both methods 'renderTiles' and 'renderTile':

public void renderTile(DrawContext dc, SurfaceTile tile) {
this.renderTile(dc, tile, null);

public void renderTiles(DrawContext dc, Iterable tiles) {
this.renderTiles(dc, tiles, null);

* Finally, you must change the invokation to the above methods in two clases,
TileImageLayer and RPFLayer.

In TileImageLayer's 'draw' method you must change the call:

dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.currentTiles);
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.currentTiles, this);

And in RPFLayer change lines:

dc.getGeographicSurfaceTileRenderer().renderTile(dc, tile);
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, rpfTextureTiles);


dc.getGeographicSurfaceTileRenderer().renderTile(dc, tile, this);
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, rpfTextureTiles, this);

Note these changes not alter the opacity in some Renderable objects, like SurfaceImage or SurfaceShape. These classes use SurfaceTileRenderer to render itself but there is no easy way to pass a reference to the owner layer without modifying the Renderable interface and many code.

Monday, October 22, 2007

WWJ Temporality

Finally I finish changes in WWJ (very few) to allow time animation.

The idea is to allow associate a period of validity to a renderable object. This period
can be represented with the Temporality class, which has an initial and a final Calendar to indicate the valid range where an object must be rendered.

View interface (and AbstractView) acts as camera and also can have associated a period of time,
for example: from October 1951 to October 1952.

When the "camera" has a temporality associated, we can step up or down into these period incrementally.
This step size is so called the "cursor". In the previous example we can define a cursor of
size "one month", "two days" or "20 minutes" to step up or down. The cursor can be moved within
the views temporality with the "go to" method.

Also, when the "camera" has a temporality associated it only renders objects that conforms with:
  1. If the object has an associated temporality, then it is only rendered if his temporality is inside the View's cursor.
  2. If the object hasn't a temporality, then it is always rendered.
Finally I have created a Timeline layer to show the current view temporality and cursor position.

Source code here.

WWJ LayerSet

Since the beginning I was surprised in the way some virtual globes handles layers and WWJ is not an exception.

I imagine a layer as an object that contains more objects, some of ones can be rendered. Render a layer implies render all its objects. Following this, an object in a layer, maybe a layer itself and can contain more objects (including layers).

With this idea I created my amzaing RenderableGroup object (in my deprecated Balloon Core API :( ).
The good thing is I could do the same in WWJ in a few days :)

LayerSet allows create like tree of layers. It is a subclass of LayerList and also implements
the Layer interface, so you can create composite LayerSets. Example:

|-- GroupA
| |-- IconLayer
| |-- RenderableLayer
|-- GroupB
|-- ScalebarLayer
|-- WorldmapLayer

Because it is a LayerList you can pass to any Model class.

The operation setOpacity, setEnable, render and so on, makes changes iteratively in all contained elements.

Source code here.

Sunday, October 21, 2007

The final decision

The decision are taken.
After some days (well weeks) thinking on the dilemma, finally I have changed to WWJ API.
My own Balloon Core API remains in a stand by state and more probably it will become a mere hobby on creating a 3D scene graph than other thing.
The WWJ is populated by more people than me alone. WWJ evolution is quickly than Balloon Core API and more powerful :( than it.
As a result and in addition to use WWJ in my project, I have started to create contribution. Now I am finishing testing two:
  • LayerSet: Insted of have a layer list (in the model) it allow to have a tree of layers.
  • Temporality: I have created a couple of classes and hacked a bit the WWJ to allow associate time properties to renderable object. Also I have created a simple timeline layer (based on the ScaleLayer) to show the time position.

Saturday, October 13, 2007

Icon screenshot

Here I want to show some things commented in my last post.

You can see an icon marking the Catalonia position. As other image type, you can change its coordinates position, elevation, size and transparency.

Also note the bottom status bar containing camer'as: altitude, distance and latitude/longitude mouse position.

I am preparing more videos to show Balloon in action.

Wednesday, October 10, 2007

Last improvements

Well, after four weeks without internet connection I want to communicate my last advances on Balloon Core API.
  • Finally (this was my big headache from the beginning) we can get the latitude and longitude position of the mouse in the canvas.
  • Improved globe rotation. You can rotate (respect the imaginaries global X,Y,Z axis) the globe in any amount of degrees. Also, I have added tilt, like WWJ ;)
  • Added support for so called icons. Icons are images that serves as markers: pins like GE, balloons like GMaps, ... any image you want like WWJ.
  • Added picking selection support. You can associate "handlers" to the objects and control its size, movement, etc when they are selected (depending on the handler).
Not all are good news, from now I have a very big problem: when two canvas are created there exists some threads problem that block the application. Home works :(

Saturday, September 15, 2007

The dilemma

Looking at the WWJ source code, I feel very happy. Honestly, my work in the Balloon's project core API is not as complete as the WWJ API:
  • not use any geode to calculate lat/lon,
  • not use the concept of LevelSet,
  • and more important, I don't implement any elevation model, my world is flat :(
Take in account nothing is perfect. Currently WWJ has a big problem with rendering vector data (polygons and points) in the surface (using elevation model).

The good things
On the other hand. Balloon is a one person project, and I think my work is enough good:
  • Balloon speed is similar to WWJ, inclusive when data are loading (remotely and locally at the same time).
  • Although my core API (my SDK) is simpler than WWJ, Balloon is a desktop application not only a SDK, it has a GUI module.
  • All objects allow change its features like: color, transparency, etc, without any distinction. This is not possible in WWJ with many layers.
  • All renderable objects are, optionally, timestamped and those Balloon can animate information.
  • Recently I was finishing the pick selection process of objects, and I want to improve GUI calculating the lat/lon position of the cursor in the screen.
The sentence that resumes my spirit and is enough for me to continue working is:
I want to improve the core API for the simple reason to learn and develop more and better.

The bad things
The problem is that for one person, develop the core API and GUI is too much job, and then the dilemma comes to me:
Why spend time in the core API if there exists a good API that makes something similar and, in more areas, better? Why doesn't use WWJ as the core API in the Balloon project?

I think I stop my project for a while, start learning more in WWJ API and trying to implement my existent layers and animation time concepts with the WWJ.
I think the real prolem is I don't know how to focus Balloon project Create another virtual globe? Focus it as another GIS application?

Finally I am thinking Why don't make a fork of the project: one using my core API and one using the WWJ API?

Sunday, September 09, 2007

Picking objects

After some days of work I have finally added the picking mechanism to the project. Now the objects can react when mouse is moving, button is clicked, pressed or released.
It is based on picking and selection mechanism of OpenGL and doesn't affect the performance in a visible way.
I'm happy :)

Tuesday, September 04, 2007

My first hack on WWJ

It is not any amazing thing but I want to show my first hack on WWJ code. Really this is the second hack, the first is my LayerSet class that allows create set of layers.

I have modified a bit the WWJ source code (in the SurfaceTileRenderer class) to allow some layers make use of the, until now not used, property opacity.
For example you can put a BMNGSurfaceLayer but you can change its opacity, or better said, you can invoke the setOpacity method but the opacity value is never used in the render process and thus the layer never changes its opacity.

Take a look at this two screenshots. The first is a normal set of layers:

The second shows the CountryBoundariesLayer and the landsat layer with opacity changed:

Which is the secret?
You know some layers like BMNGSurfaceLayer, CountryBoundariesLayer and USGS* are based on BasicTiledImageLayer that extends the TiledImageLayer class. The later class uses the SurfaceTileRenderer to render the tiles.

TiledImageLayer.draw() method change:
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.currentTiles);
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.currentTiles, this);

In SurfaceTileRenderer change:
public void renderTiles(DrawContext dc, Iterable tiles) {
public void renderTiles(DrawContext dc, Iterable tiles, AbstractLayer layer) {

and put this code (only the later 'if):
if (!dc.isPickingMode()) {
} else {

// Set transparency
gl.glColor4f(1, 1, 1, (float)layer.getOpacity());

Finally, create overload the method (to not affect other calls):
public void renderTiles(DrawContext dc, Iterable tiles) {
this.renderTiles(dc, tiles, null);

And thats all.

Thursday, August 30, 2007


Well, holidays are finished and we come back to the work. I didn't spend much time on the project but in my free time I did:
  • improved the WMS wizard,
  • added tilt rotation to the camera (similar to the WWJ), and also
  • I have started to play the WWJ source code.

As a result of this third point I show you a screenshot:

In there is no direct way to group layers, because this I have create a LayerSet class that can group layers.

The image shows the layers: BMNG, compass, landsat and finally country boundaries.

Thursday, August 02, 2007

More improvements

Finally I'm on holidays. Also I have finished refactoring the core API to work with listeners (take a look at previous post).

Today I want to post about a couple of new user interface improvements I have made thanks to the previous work.
Now, when the user loads some data (image, shapefile or WMS layer) a progress bar is shown:

And once the data is loaded, depending if the data can or can't be loaded, the label in the layer explorer change its color to show the final state:

Monday, July 23, 2007

Improving the model

Later I had worked on the logical model. Among other things Balloon has classes responsible to render graphic object and classes responsible to load data. I have just improved this using an event/listener mechanism.
Also I turn many java classes on JavaBeans, firing property change events and so on that helps to improve the client programming.

Finally I have divided the load process between synchronous (working in the update thread) and asynchronous process (working in a new thread). For example, to load WMS images the load process starts as a synchronous process, checks if the images is cached in the local disk and if so loads it, otherwise changes it to an asynchronous mode and loads data from the network server.

Probably it must be better to write some docs to help the future programmers of Balloon ;)

Tuesday, July 10, 2007

WMS and cached images

This is a little demo which works with WMS layers with some cached images.

Other time, sorry by poor quality but (1) my video card is not so good and it is very dificult to execute and capture at the same time, and (2) youtube takes a lot of quality.

Saturday, July 07, 2007

Working with WMS server

Here is a demo video working with WMS server.
The first step in the wizard is to select the WMS server and the second step is to select the layer (or layers) you want to load.
The load speed depends both on the server and your network speed. As you can see in the vieo, my network speed is poor.
Also I want to note my computer is not so good to work with balloon at the same time we are recording screen. In addition YouTube lows the qualitit of the movie.

Wednesday, July 04, 2007

A couple of demo videos

Here are the first demo videos of the balloon in action.
Unfortunately I captured it only at 10 FPS to save space and also YouTube reduce it much more, making the false ilusion it is slow.

Here are a basic work with georeferenced images and the GUI layout:

Here you can see how easy is to work with shapefiles (with lat/lon data):

Sunday, June 03, 2007

Time animation

Too much time without write any post, but we continue working on the project (step by step).

Since the designed conceptual model allows associate periods of temporary validity to the objects, I was working on some kind of graphic interface to show the time information.

The idea is to allow every camera (or view window) to animate a period of time, for example, from 12:00 to 22:00. This period is animated step by step (being able to choose the step size: 60min, 3 sec, ...) showing those objects that are visible within the step, also called cursor.

Once we define the period of time to be animated by the camera and set the temporary validity for every interesting object, we can animate them. The information shown to the user is:
  • The period of time the camera is animating.
  • The cursor initial and final time.
  • A progress bar shown the position of the cursor within the camera animation period.
I am preparing more beautiful screenshots and possibly a demo vide :), but until then here is an example image:

Wednesday, May 02, 2007

A bunch of screenshots

Every day the project needs more time, but every day I have less time to dedicate to it.
Anyway here present the latest screenshots.

This image shows a one camera view: earth with one WMS layer (Blue Marble).

This one shows the first step to import a shapefile. The second step ask you for the attribute to be use as the name of the shapes. The file used here contains the limits of the world.

Next, you can see the earth with the imported shapefile data and how you can select and change on the fly the color and size of the points and polygons:

When you have WMS layers the tile's color brings you information about which tiles are loaded (no border), which are actually loading (green border) and which get some type of error while retrieving data (red border).

Next image shows a two diferent views (cameras) of the world. First camera shows the transport lines of the Barcelona city.

Second camera shows the transports for all Catalonia (Catalunya).

Here, we are going to import and geo-reference an image:

The transparency of the image has changed to see the underlaying Blue Marble layer:

Finally, here is a more complex combination of layers. At bottom the Blue Marble opaque layer. Over it a semi-transparent transport layer and on top of them the semi-transparent radar image.

Monday, April 02, 2007

Repeatable read and direct HTTP images request

It seems I'm talking about DB with the Repeatable Read isolation problem but really it is more simple thing. Finally The Balloon Project is able to make repeatable reads from a source. For example you can:
Read every ten minutes an image from the web (i.e. from a meteorological service), or
You can read every five minutes the same image from your local disc (because it is changed by another proces).
In summar you can configure every load process to be executed at regular (online configurable) intervals.
From now, Ballon have loaders for: local images, WMS servers, shapefiles and now there is an HTTP loader to read remote images ;)

All these are very wonderful but I need to improve the GUI (my wizards and the properties window) to bring the user the possibility to work in an easy way with all the concepts.

Sunday, March 25, 2007

Radar screenshots

Lately I have no time to work on the project. Recently I had improved the Camera class and now I want to work on the GUI.
Here are a couple of screenshots with a radar image taken from

Saturday, March 10, 2007

Near a pre-alpha release of the Balloon

Lately I have working improving the Camera class and finally the rotations are much more intuitive and powerful.
The program is able to read simple images (indicating the user its lat/lon position), shapefiles (always expresed in lat/lon coordinates) and images from any WMS server.
For all this I'm currently thinking in releasing a pre-alpha version and get feedbacks of the users.

Thursday, February 01, 2007

A pool of thread

It is not a great and visually spectacular feature, but I think it is very important for performance questions.
I have added a thread pool to manage the execution of threads.

When working with WMS layers, every data request works in a new thread. This can derive (if too many request are made) on a great number of threads working at the same time and with its own resource consumption.
A thread's pool solves this situations limiting the number of threads that can be working in a given moment, and avoiding the massive consumption of resources.

Saturday, January 27, 2007

Earth halo

Among other things, tonight I had worked to make a simple halo around the earth.
Here is the result:

Next steps I am centering on are:
  • Create an editor to easily modify the initial and final time stamps associated to the renderable objects.
  • Represent a time line in the editor window.

Friday, January 26, 2007

Tile improved

Tonight I am very tired, but very happy because I think the project does what I had hoped from its beginning.
Today I have modified the classes responsible to render WMS layers. Now the variable used to request more precise images depends on two factor:
  • The distance of the camera to the earth surface, and
  • the longitude of the diagonal arc of the tile.
v = altitude / arclong

It seems that a proportion until 0.5 is good, then when the value is less than 0.5 it is time to request more little tiles

Wednesday, January 24, 2007

Working on...

Silently the project is growing. Recently some important changes are added to the core classes.

First, I add some support to the core objects to emit signals, for example when an object are added or removed from a group, or when some property (like color or line width) are changed. That brings more independency between the core and the UI. The later can react when receive a signal and, in the case of folders, new objects are added automatically.

Second, I have modified some presentation elements: defining the items of the menus and toolbars and finding appropriate icons for the explored. Also I modified the windows to definitively work in SDI (Single Document Interface) mode.

Finally, and this is a very important concept, I have added time support to the core objects. Now it is possible to set a time of validity to an object, including the camera itself. Given a period to be shown by the camera and a set of object (with or without periord of validity, independently) the camera's actual time advances step by step showing the object that are valids in the specified time position.
Now, I am working of the way to show the time line to the user: show the current visualization time (the cursor), indicate which objects are visible at the cursor position, and so on.