// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/j3d/com/bbn/openmap/tools/j3d/MapContent.java,v $
// $RCSfile: MapContent.java,v $
// $Revision: 1.5.2.2 $
// $Date: 2005/08/11 21:03:15 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.tools.j3d;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Iterator;
import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Point2f;
import javax.vecmath.Point3f;
import com.bbn.openmap.Layer;
import com.bbn.openmap.LayerHandler;
import com.bbn.openmap.MapBean;
import com.bbn.openmap.MapHandler;
import com.bbn.openmap.image.AcmeGifFormatter;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGrid;
import com.bbn.openmap.proj.Proj;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;
import com.sun.j3d.utils.image.TextureLoader;
/**
* A more complex MapContent. The regular layers get drawn into a base
* image that is overlaid upon the earth geometry which can have
* shape, if elevation data is available. The other layers, that
* provide objects that should be rendered in 3D space, get entered
* into the scene as specific objects.
*
* @author dietrick
*/
public class MapContent extends BranchGroup implements OM3DConstants {
protected MapBean map;
protected Proj proj;
protected LayerHandler layerHandler;
protected HashSet graphicHandlers;
protected MapHandler mapHandler;
public MapContent(MapHandler mapHandler, int contentMask) {
super();
init(mapHandler);
if ((contentMask & CONTENT_MASK_OM3DGRAPHICHANDLERS) != 0) {
createMapObjects();
}
if ((contentMask & CONTENT_MASK_IMAGEMAP) != 0) {
createMapImage();
}
if ((contentMask & CONTENT_MASK_ELEVATIONMAP) != 0) {
createMapElevations();
}
}
protected void init(MapHandler mapHandler) {
if (mapHandler == null) {
return;
}
map = (MapBean) mapHandler.get("com.bbn.openmap.MapBean");
proj = null;
if (map != null) {
proj = (Proj) map.getProjection();
}
this.mapHandler = mapHandler;
}
protected HashSet getGraphicHandlers(MapHandler mapHandler) {
Debug.message("3d", "LayerMapContent: looking for OM3DGraphicHandlers.");
HashSet ret = new HashSet();
Iterator iterator = mapHandler.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
if (obj instanceof OM3DGraphicHandler) {
Debug.message("3d", "LayerMapContent: found one, adding " + obj);
ret.add(obj);
}
}
// Have to do layers separately because they may not be
// exposed to the MapHandler.
layerHandler = (LayerHandler) mapHandler.get("com.bbn.openmap.LayerHandler");
if (layerHandler != null) {
Layer[] layers = layerHandler.getLayers();
int size = layers.length;
for (int i = size - 1; i >= 0; i--) {
Layer layer = layers[i];
if (layer.isVisible() && (layer instanceof OM3DGraphicHandler)) {
Debug.message("3d",
"LayerMapContent: found layer version, adding "
+ layer.getName());
ret.add(layer);
}
}
}
return ret;
}
/**
* May be used for OM3DGraphicHandlers to get an idea of what the
* map looks like.
*
* @return The projection value
*/
public Projection getProjection() {
return proj;
}
/**
* Goes through the MapHandler, and sets this object in any
* OM3DGraphicHandler, so they can call back to load in Shape3D or
* OMGraphic objects.
*/
protected void createMapObjects() {
if (mapHandler == null) {
Debug.error("MapContent: MapHandler not set!");
return;
}
graphicHandlers = getGraphicHandlers(mapHandler);
Iterator iterator = graphicHandlers.iterator();
while (iterator.hasNext()) {
((OM3DGraphicHandler) iterator.next()).addGraphicsToScene(this);
}
}
/**
* Callback method for OM3DGraphicHandlers, to add an OMGrid
* object to the scene. For now, the values of the OMGrid
* correspond to the height of the values in the grid. The heights
* should be relative to the 3D scene, in relation to the OpenMap
* projection (screen X/Y coordinates of the OpenMap projection
* have a direct relationship with the X/Z axis of the 3D scene).
*
* @param grid Description of the Parameter
*/
public void add(OMGrid grid) {
add(OMGraphicUtil.createShape3D(grid, 0, proj));
}
/**
* Callback method for OM3DGraphicHandlers, to add an OMGraphics
* to the scene.
*
* @param omgraphic an OMGraphic.
* @param height the height of the object. All points of the
* object are at this height. The height should be relative
* to the 3D scene, in relation to the OpenMap projection
* (screen X/Y coordinates of the OpenMap projection have a
* direct relationship with the X/Z axis of the 3D scene).
* If you have an object with varying height, create an
* Shape3D object instead and use the other add() method.
*/
public void add(OMGraphic omgraphic, double height) {
add(OMGraphicUtil.createShape3D(omgraphic, height));
}
/**
* Callback method for OM3DGraphicHandlers, to add a Shape3D
* object to the scene.
*
* @param shape Description of the Parameter
*/
public void add(Shape3D shape) {
addChild(shape);
}
/**
* Add the Shape3D objects from an iterator.
*
* @param shapeIterator Iterator containing Shape3D objects.
*/
protected void add(Iterator shapeIterator) {
while (shapeIterator.hasNext()) {
try {
Shape3D shape = (Shape3D) shapeIterator.next();
if (shape != null) {
add(shape);
}
} catch (ClassCastException cce) {
continue;
}
}
}
/**
* Add a TransformGroup from a OM3DGraphicHandler. This will
* provide an object to the scene that can be controlled by an
* outside source.
*
* @param transformGroup any transform group containing Shape3D
* objects.
*/
protected void add(TransformGroup transformGroup) {
addChild(transformGroup);
}
protected void createMapElevations() {
Debug.error("MapContent.createMapElevations not implemented.");
}
protected void createMapImage() {
if (proj == null || mapHandler == null) {
Debug.error("MapContent: MapHandler not set!");
return;
}
int pwidth = 512;
int pheight = 512;
AcmeGifFormatter formatter = new AcmeGifFormatter();
Graphics graphics = formatter.getGraphics(pwidth, pheight);
Paint background;
if (map == null) {
background = MapBean.DEFAULT_BACKGROUND_COLOR;
} else {
background = map.getBckgrnd();
}
proj.drawBackground((Graphics2D) graphics, background);
layerHandler = (LayerHandler) mapHandler.get("com.bbn.openmap.LayerHandler");
if (layerHandler != null) {
Debug.message("3d",
"LayerMapContent: putting layer graphics on the map.");
Layer[] layers = layerHandler.getLayers();
int size = layers.length;
for (int i = size - 1; i >= 0; i--) {
Layer layer = layers[i];
if (layer.isVisible() && !(layer instanceof OM3DGraphicHandler)) {
layer.renderDataForProjection(proj, graphics);
}
}
}
BufferedImage bimage = formatter.getBufferedImage();
// Now we have our textured image.
QuadArray plane = new QuadArray(4, GeometryArray.COORDINATES
| GeometryArray.TEXTURE_COORDINATE_2);
float height = (float) pheight;
float width = (float) pwidth;
Point3f p = new Point3f(0f, 0f, 0f);//-1.0f, 1.0f, 0.0f);
plane.setCoordinate(0, p);
p.set(0f, 0f, height);//-1.0f, -1.0f, 0.0f);
plane.setCoordinate(1, p);
p.set(width, 0f, height);//1.0f, -1.0f, 0.0f);
plane.setCoordinate(2, p);
p.set(0f, 0f, height);//1.0f, 1.0f, 0.0f);
plane.setCoordinate(3, p);
Point2f q = new Point2f(0.0f, 1.0f);
plane.setTextureCoordinate(0, q);
q.set(0.0f, 0.0f);
plane.setTextureCoordinate(1, q);
q.set(1.0f, 0.0f);
plane.setTextureCoordinate(2, q);
q.set(1.0f, 1.0f);
plane.setTextureCoordinate(3, q);
Appearance appear = new Appearance();
TextureLoader loader = new TextureLoader(bimage);
ImageComponent2D image = loader.getImage();
if (Debug.debugging("3d")) {
Debug.output("MapContent: image height: " + image.getHeight()
+ ", width: " + image.getWidth());
}
// can't use parameterless constuctor
Texture2D texture = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, image.getWidth(), image.getHeight());
texture.setImage(0, image);
//texture.setEnable(false);
appear.setTexture(texture);
appear.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.FASTEST, 0.1f));
Shape3D planeObj = new Shape3D(plane, appear);
addChild(planeObj);
}
}