001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wpvs/j3d/OffScreenWPVSRenderer.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.ogcwebservices.wpvs.j3d; 038 039 import java.awt.Color; 040 import java.awt.image.BufferedImage; 041 import java.awt.image.RenderedImage; 042 043 import javax.media.j3d.Appearance; 044 import javax.media.j3d.BranchGroup; 045 import javax.media.j3d.Canvas3D; 046 import javax.media.j3d.ImageComponent; 047 import javax.media.j3d.ImageComponent2D; 048 import javax.media.j3d.Light; 049 import javax.media.j3d.Locale; 050 import javax.media.j3d.Material; 051 import javax.media.j3d.OrderedGroup; 052 import javax.media.j3d.RenderingAttributes; 053 import javax.media.j3d.Transform3D; 054 import javax.media.j3d.TransformGroup; 055 import javax.media.j3d.View; 056 import javax.vecmath.Color3f; 057 import javax.vecmath.Vector3d; 058 059 import org.deegree.framework.log.ILogger; 060 import org.deegree.framework.log.LoggerFactory; 061 import org.deegree.framework.util.MapUtils; 062 import org.deegree.i18n.Messages; 063 064 import com.sun.j3d.utils.geometry.Sphere; 065 import com.sun.j3d.utils.universe.MultiTransformGroup; 066 import com.sun.j3d.utils.universe.SimpleUniverse; 067 import com.sun.j3d.utils.universe.ViewingPlatform; 068 069 /** 070 * The class provides the capabilitiy for rendering a <code>WPVSScene</code> to an offscreen graphic context that is 071 * represent by a <code>BufferedImage</code>. That is, the returned BufferedImage of this class's renderScene method is 072 * the response Object of a GetView request. 073 * 074 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 075 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 076 * 077 * @version $Revision: 19665 $ $Date: 2009-09-16 10:11:29 +0200 (Mi, 16 Sep 2009) $ 078 */ 079 public class OffScreenWPVSRenderer extends Abstract3DRenderingEngine { 080 081 private static ILogger LOG = LoggerFactory.getLogger( OffScreenWPVSRenderer.class ); 082 083 private Canvas3D offScreenCanvas3D; 084 085 private SimpleUniverse universe; 086 087 private final boolean renderAntialiased; 088 089 /** 090 * Initializes the render class with a default width and height (800x600) and a nearclipping plane of 2 091 * 092 * @param canvas 093 * to render upon 094 * 095 * @param scene 096 * to render 097 */ 098 public OffScreenWPVSRenderer( Canvas3D canvas, WPVSScene scene ) { 099 this( canvas, 2, scene, 800, 600, true ); 100 } 101 102 /** 103 * Initializes the renderer class with the submitted width and height and a nearclipping plane of 2 104 * 105 * @param canvas 106 * to render upon 107 * 108 * @param scene 109 * to render 110 * @param width 111 * of the resulting image 112 * @param height 113 * of the resulting image 114 * @param antialiased 115 * true if the scene should be rendered antialiased 116 */ 117 public OffScreenWPVSRenderer( Canvas3D canvas, WPVSScene scene, int width, int height, boolean antialiased ) { 118 this( canvas, 2, scene, width, height, antialiased ); 119 } 120 121 /** 122 * Initializes the renderer class with the submitted width and height 123 * 124 * @param canvas 125 * to render upon 126 * @param nearClippingPlane 127 * of the scene's viewport. 128 * 129 * @param scene 130 * to render 131 * @param width 132 * of the resulting image 133 * @param height 134 * of the resulting image 135 * @param antialiased 136 * true if the scene should be rendered antialiased 137 */ 138 public OffScreenWPVSRenderer( Canvas3D canvas, double nearClippingPlane, WPVSScene scene, int width, int height, 139 boolean antialiased ) { 140 super( scene, nearClippingPlane ); 141 142 // offScreenCanvas3D = WPVSConfiguration.getCanvas3D(); 143 offScreenCanvas3D = canvas; 144 if ( offScreenCanvas3D == null ) { 145 throw new IllegalArgumentException( "Did not retrieve a Canvas3D from the Configuraion, cannot proceed" ); 146 } 147 offScreenCanvas3D.getScreen3D().setPhysicalScreenHeight( MapUtils.DEFAULT_PIXEL_SIZE * height ); 148 offScreenCanvas3D.getScreen3D().setPhysicalScreenWidth( MapUtils.DEFAULT_PIXEL_SIZE * width ); 149 150 offScreenCanvas3D.getScreen3D().setSize( width, height ); 151 BufferedImage renderedImage = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 152 153 ImageComponent2D imageComponent = new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 154 // new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 155 156 imageComponent.setCapability( ImageComponent.ALLOW_IMAGE_READ ); 157 158 offScreenCanvas3D.setOffScreenBuffer( imageComponent ); 159 160 universe = new SimpleUniverse( offScreenCanvas3D ); 161 162 OrderedGroup theScene = scene.getScene(); 163 BranchGroup sceneGroup = new BranchGroup(); 164 sceneGroup.addChild( theScene ); 165 166 addBackground( scene.getViewPoint(), sceneGroup, scene.getBackground() ); 167 168 sceneGroup.compile(); 169 BranchGroup lightGroup = new BranchGroup(); 170 Light[] lights = scene.getLights(); 171 for ( Light light : lights ) { 172 lightGroup.addChild( light.cloneTree() ); 173 } 174 lightGroup.compile(); 175 176 universe.addBranchGraph( sceneGroup ); 177 universe.addBranchGraph( lightGroup ); 178 this.renderAntialiased = antialiased; 179 } 180 181 /** 182 * @param scene 183 * the Scene to render 184 */ 185 public void setScene( WPVSScene scene ) { 186 this.scene = scene; 187 } 188 189 /** 190 * Renders the scene to a <code>BufferedImage</code>. This Method uses the viewmatrix of the the ViewPoint class, 191 * which the defines the necessary viewing rotations and translations for the j3d scene. 192 * 193 * @return a <code>BufferedImage</code> where the scene has been rendered to 194 */ 195 public BufferedImage renderScene() { 196 197 // setting up the transformation of the viewingplatform according to the requested 198 // (calculated) values. 199 ViewingPlatform vp = universe.getViewingPlatform(); 200 View view = universe.getViewer().getView(); 201 202 // view parameters 203 view.setBackClipDistance( farClippingPlane ); 204 view.setFrontClipDistance( nearClippingPlane ); 205 view.setWindowEyepointPolicy( View.RELATIVE_TO_FIELD_OF_VIEW ); 206 view.setFieldOfView( scene.getViewPoint().getAngleOfView() ); 207 view.setSceneAntialiasingEnable( renderAntialiased ); 208 // view.setTransparencySortingPolicy( View.TRANSPARENCY_SORT_GEOMETRY ); 209 // view.setDepthBufferFreezeTransparent( false ); 210 211 MultiTransformGroup mtg = vp.getMultiTransformGroup(); 212 int transforms = mtg.getNumTransforms(); 213 TransformGroup transGroup = null; 214 // if one or more transformgroups are present take the first one will be set to the 215 // viewmatrix of the ViewPoint 216 if ( transforms > 0 ) { 217 transGroup = mtg.getTransformGroup( 0 ); 218 } 219 if ( transGroup == null ) { 220 LOG.logError( Messages.getMessage( "WPVS_NO_TRANSFORMS_ERROR" ) ); 221 return null; 222 } 223 Transform3D viewMatrix = scene.getViewPoint().getViewMatrix(); 224 transGroup.setTransform( viewMatrix ); 225 226 // draw the poi as a sphere if the Debug level is on. 227 BranchGroup sphere = new BranchGroup(); 228 sphere.setCapability( BranchGroup.ALLOW_DETACH ); 229 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 230 Appearance app = new Appearance(); 231 RenderingAttributes ra = new RenderingAttributes(); 232 ra.setDepthBufferEnable( true ); 233 app.setRenderingAttributes( ra ); 234 Material material = new Material(); 235 material.setAmbientColor( new Color3f( Color.WHITE ) ); 236 material.setDiffuseColor( new Color3f( Color.WHITE ) ); 237 app.setMaterial( material ); 238 Sphere s = new Sphere( 20, app ); 239 Transform3D t3d = new Transform3D(); 240 t3d.setTranslation( new Vector3d( scene.getViewPoint().getPointOfInterest() ) ); 241 TransformGroup tg = new TransformGroup(); 242 tg.setTransform( t3d ); 243 tg.addChild( s ); 244 sphere.addChild( tg ); 245 universe.addBranchGraph( sphere ); 246 } 247 248 // Finally draw the scene 249 view.startView(); 250 offScreenCanvas3D.renderOffScreenBuffer(); 251 offScreenCanvas3D.waitForOffScreenRendering(); 252 view.stopView(); 253 // removing the sphere out of the universe 254 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 255 Locale l = universe.getLocale(); 256 l.removeBranchGraph( sphere ); 257 } 258 259 ImageComponent2D imageComponent = offScreenCanvas3D.getOffScreenBuffer(); 260 if ( imageComponent == null ) { 261 LOG.logError( Messages.getMessage( "WPVS_NO_IMAGE_COMPONENT_ERROR" ) ); 262 return null; 263 } 264 /** 265 * If using the TestWPVS class option NO_NEW_REQUEST, make sure to comment following two lines as well as the 266 * WPVSConfiguration.releaseCanvas3D( canvas ); line in the DefaultGetViewHandler#handleRequest. 267 */ 268 // and cleaning the universe and all of its used memory. 269 universe.cleanup(); 270 view.removeAllCanvas3Ds(); 271 return imageComponent.getImage(); 272 } 273 274 /** 275 * Called to render the scene into the offscreen Canvas3D 276 * 277 * @param offScreenCanvas3D 278 * to be rendered into 279 * @return a buffered image as a result of the Rendering. 280 */ 281 protected RenderedImage getImage( Canvas3D offScreenCanvas3D ) { 282 283 offScreenCanvas3D.renderOffScreenBuffer(); 284 offScreenCanvas3D.waitForOffScreenRendering(); 285 286 ImageComponent2D imageComponent = offScreenCanvas3D.getOffScreenBuffer(); 287 288 return imageComponent.getImage(); 289 } 290 }