World Wind Forums

Go Back   World Wind Forums > WorldWind JAVA forums > Development Help

Development Help Help for building applications or diagnosing problems with WWJ

Reply
 
Thread Tools Display Modes
Old 08-01-2012, 12:50 PM   #1
wakenney
Junior Member
 
Join Date: Oct 2010
Posts: 3
wakenney is on a distinguished road
Default Level of detail for RenderableLayer

I am developing an application that mimics a camera in flight. The camera "zooms" in by reducing the field of view as opposed tot he WW standard method of reducing the altitude. For terrain images this was relatively easy. Change the FoV and the .setDetailHint value to get the map images to increase or decrease resolution without changing the altitude of the camera eye.

I have a number of surfacecircles on the map as well as a surfaceicon or two that do NOT rerender at higher resolution as I zoom in. There doesn't seem to be a method of setting a detail hint for 2-D surface objects, at least not there is for 3-D objects.

Am I missing something? I need the surface shapes to increase resultion just as the map images do.

How do I set the detail hint for surface shapes on a renderable layer?

Thanks.
wakenney is offline   Reply With Quote
Old 08-02-2012, 09:26 PM   #2
brujito
Member
 
Join Date: May 2009
Posts: 58
brujito is on a distinguished road
Default

Some time ago I've implemented tiled rendering to capture high resolution screenshot of WWJ scene. I had to set detail hints to TiledImageLayers and SurfaceObjectTileBuilder as following:

Code:
package com.transas.tvmap.ui.worldwind.tools;

import gov.nasa.worldwind.BasicSceneController;
import gov.nasa.worldwind.View;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.layers.LayerList;
import gov.nasa.worldwind.layers.TiledImageLayer;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.SurfaceObjectTileBuilder;
import gov.nasa.worldwind.view.AdvOrbitView;

import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.media.opengl.GL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.opengl.util.TileRenderer;
import com.transas.tvmap.ui.worldwind.tools.ExportImageTool.CaptureResult;

public class ExportImageSceneController extends BasicSceneController {
	
	private static final Log LOG = LogFactory.getLog(ExportImageSceneController.class);
	
	private final ExportImageTool tool;
	private final Rectangle imageSize;
	
	private TileRenderer tileRenderer = null;
	private List<File> tileFiles = new LinkedList<File>();	
	private int currentTile = 0;
	private int framesPerTile = 0;
	
	private CaptureResult captureResult = null;
	
	ExportImageSceneController(ExportImageTool tool, Rectangle imageSize) {
		this.tool = tool;
		this.imageSize = imageSize;
	}
	
	public void doRepaint(DrawContext dc)
    {
		if (captureResult != null) {
			super.doRepaint(dc);
			return ;
		}
		 
		
		this.initializeFrame(dc);
		
		if (tileRenderer == null) {
			this.applyView(dc);
			tileRenderer = createTileRenderer(dc);
		}
		
		try {
			GL gl = dc.getGL();

			AdvOrbitView aView = null;
	        if (view instanceof AdvOrbitView) {
	        	aView = (AdvOrbitView)view;
	        }
	        
	        if (aView == null) {
	        	LOG.error("Invalid View instance: " + aView);
	        	tool.capturingCancelled();
	        	return ;
	        }
	        
	        gl.glMatrixMode(GL.GL_PROJECTION);
            gl.glPushMatrix();	        
	        tileRenderer.beginTile(gl);
	        // now we need to read matrix and apply it to the view
	        aView.readProjection(gl);
	        gl.glPopMatrix();
	        
	        this.applyView(dc);
			
	        Angle savedFov = aView.getFieldOfView();
	        aView.setFieldOfView(tileFov);
	        Map<TiledImageLayer, Double> savedDetailHints = setupTiledImageLayers(dc, tileRenderer);
	        try {
				this.createTerrain(dc);
				this.preRender(dc);
				this.clearFrame(dc);
				this.draw(dc);
	        } finally {
	        	cleanupTiledImageLayers(dc, savedDetailHints);
	        	aView.setFieldOfView(savedFov);
	        }
			
			
			framesPerTile++;
			
			boolean hasMore = true;
			
			if (framesPerTile > 40) {
				gl.glMatrixMode(GL.GL_PROJECTION);
	            gl.glPushMatrix();	
				hasMore = tileRenderer.endTile(gl);
				gl.glPopMatrix();
				
				
				framesPerTile = 0;			
				
				if (captureResult == null) {
					saveTile(gl);
				}
	            currentTile++;
			}
			
            
			if (hasMore) {
				dc.setRedrawRequested(100);
			} else {
				if (captureResult == null) {
					int cols = tileRenderer.getParam(TileRenderer.TR_COLUMNS);
					int rows = tileRenderer.getParam(TileRenderer.TR_ROWS);
					captureResult = new CaptureResult(cols, rows, tileFiles);
					
					tool.capturingDone(captureResult);
				}
			}
			
		} finally {
			this.finalizeFrame(dc);
		}
    }
	
	private void cleanupTiledImageLayers(DrawContext dc,
			Map<TiledImageLayer, Double> savedDetailHints) {
		for (TiledImageLayer til : savedDetailHints.keySet()) {
			Double hint = savedDetailHints.get(til);
			til.setDetailHint(hint);
		}
	}

	/**
	 * Increase detail hint for TiledImageLayers
	 * @param dc
	 * @param tileRenderer
	 */
	private Map<TiledImageLayer, Double> setupTiledImageLayers(DrawContext dc,
			TileRenderer tileRenderer) {
		Map<TiledImageLayer, Double> saved = new HashMap<TiledImageLayer, Double>();
		
        double zoom = (double)tileRenderer.getParam(TileRenderer.TR_IMAGE_WIDTH)
        		/(double)tileRenderer.getParam(TileRenderer.TR_TILE_WIDTH);
        double scaleLog = Math.log10(zoom);
        
        LayerList layers = dc.getModel().getLayers();
        for (Layer l : layers) {
        	if (l instanceof TiledImageLayer) {
        		// XXX
        		TiledImageLayer til = (TiledImageLayer)l;
        		saved.put(til, til.getDetailHint());
        		til.setDetailHint(scaleLog);        		
        	}
        }
        
        return saved;
	}

	private void saveTile(GL gl) {
		int[] viewport = new int[4];
		gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
		try {
			
			String dirName = System.getProperty("java.io.tmpdir");
			File screenFolder = new File(dirName, "TransasGlobe");
			if (!screenFolder.exists()) {
				screenFolder.mkdirs();
			}
			
			File tileFile = 
					new File(screenFolder, "screen_" + currentTile + ".png");
			if (tileFile.exists()) {
				tileFile.delete();
			}
			
			com.sun.opengl.util.Screenshot.writeToFile(
				tileFile, 
				viewport[2], viewport[3], false);
			
			tileFiles.add(tileFile);			
		} catch (IOException e) {
			LOG.error("Failed ", e);
		}
	}

	private Angle tileFov = null;
	
	private TileRenderer createTileRenderer(DrawContext dc) {
		Rectangle viewport = dc.getView().getViewport();
		
        tileRenderer = new TileRenderer();
        tileRenderer.setTileSize(viewport.width, viewport.height, 0);
//        tileRenderer.setTileSize(512, 512, 0);
        tileRenderer.setImageSize(imageSize.width, imageSize.height);
        tileRenderer.setRowOrder(TileRenderer.TR_TOP_TO_BOTTOM);
        
        View view = dc.getView();        
        Angle fov = view.getFieldOfView(); // horizontal fov
        
        // XXX fov is different for each tile, should compute it from frustum 
        double scale = (double)tileRenderer.getParam(TileRenderer.TR_TILE_WIDTH) 
        		/ (double)tileRenderer.getParam(TileRenderer.TR_IMAGE_WIDTH);
        tileFov = fov.multiply(scale);
        
        double near = view.getNearClipDistance();
        double far = view.getFarClipDistance();
        
        int w = viewport.width;
        int h = viewport.height;        
        double fovy = (fov.degrees * h) / w;
        
        tileRenderer.trPerspective(
        		fovy, 
        		(float) imageSize.width / (float) imageSize.height, 
        		near, 
        		far);
        
        return tileRenderer;
	}
	
	

	@Override
    protected SurfaceObjectTileBuilder createSurfaceObjectTileBuilder()
    {
		SurfaceObjectTileBuilder tileBuilder = super.createSurfaceObjectTileBuilder();
        double zoom = (double)tileRenderer.getParam(TileRenderer.TR_IMAGE_WIDTH)
        		/(double)tileRenderer.getParam(TileRenderer.TR_TILE_WIDTH);
        double scaleLog = Math.log10(zoom);
        
        tileBuilder.setSplitScale(tileBuilder.getSplitScale() + scaleLog);
		return tileBuilder;
    }
}
brujito is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may post new threads
You may post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to adjust terrain detail layer zoom thresholds? Noriym Development Help 0 09-12-2011 06:52 PM
WMS memory run up to 1 GB jason_liu Server Discussion 8 03-23-2011 08:32 PM
set zoom in level for wms layer in wwj jalwan Development Help 1 04-01-2010 02:54 PM
Level of detail jonnyboy Technical Support 5 09-25-2005 10:46 PM
when do i get 100% of data? ethnic1 WorldWind General 12 12-19-2004 12:25 AM


All times are GMT +1. The time now is 07:00 AM.


Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.