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
process.

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.

  • 'SurfaceTileRenderer.java'. 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:

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

After next code:

...
if (!dc.isPickingMode()) {
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
} else {
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_COMBINE);
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_SRC0_RGB, GL.GL_PREVIOUS);
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_COMBINE_RGB, GL.GL_REPLACE);
}

add the next code to set the opacity:

// Set opacity
if (layer != null) {
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
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) ...
by:
public void renderTile(DrawContext dc, SurfaceTile tile, AbstractLayer layer) ...

and modify the line:
this.renderTiles(dc, al);
by:
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);
by:
dc.getGeographicSurfaceTileRenderer().renderTiles(dc, this.currentTiles, this);

And in RPFLayer change lines:

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

by:

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:


MainLayer
|
|-- 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 :(