001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wpvs/j3d/OffScreenWPVSRenderer.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstraße 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 044 package org.deegree.ogcwebservices.wpvs.j3d; 045 046 import java.awt.Color; 047 import java.awt.image.BufferedImage; 048 import java.awt.image.RenderedImage; 049 050 import javax.media.j3d.Appearance; 051 import javax.media.j3d.BranchGroup; 052 import javax.media.j3d.Canvas3D; 053 import javax.media.j3d.ImageComponent; 054 import javax.media.j3d.ImageComponent2D; 055 import javax.media.j3d.Light; 056 import javax.media.j3d.Locale; 057 import javax.media.j3d.Material; 058 import javax.media.j3d.OrderedGroup; 059 import javax.media.j3d.RenderingAttributes; 060 import javax.media.j3d.Transform3D; 061 import javax.media.j3d.TransformGroup; 062 import javax.media.j3d.View; 063 import javax.vecmath.Color3f; 064 import javax.vecmath.Vector3d; 065 066 import org.deegree.framework.log.ILogger; 067 import org.deegree.framework.log.LoggerFactory; 068 import org.deegree.framework.util.MapUtils; 069 import org.deegree.i18n.Messages; 070 071 import com.sun.j3d.utils.geometry.Sphere; 072 import com.sun.j3d.utils.universe.MultiTransformGroup; 073 import com.sun.j3d.utils.universe.SimpleUniverse; 074 import com.sun.j3d.utils.universe.ViewingPlatform; 075 076 /** 077 * The class provides the capabilitiy for rendering a <code>WPVSScene</code> to an offscreen graphic context that is 078 * represent by a <code>BufferedImage</code>. That is, the returned BufferedImage of this class's renderScene method 079 * is the response Object of a GetView request. 080 * 081 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 082 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 083 * 084 * @version $Revision: 9345 $ $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 085 */ 086 public class OffScreenWPVSRenderer extends Abstract3DRenderingEngine { 087 088 private static ILogger LOG = LoggerFactory.getLogger( OffScreenWPVSRenderer.class ); 089 090 private Canvas3D offScreenCanvas3D; 091 092 private SimpleUniverse universe; 093 094 /** 095 * Initialzies the render class with a default width and height (800x600) and a nearclipping plane of 2 096 * 097 * @param canvas 098 * to render upon 099 * 100 * @param scene 101 * to render 102 */ 103 public OffScreenWPVSRenderer( Canvas3D canvas, WPVSScene scene ) { 104 this( canvas, 2, scene, 800, 600 ); 105 } 106 107 /** 108 * Initialzies the renderer class with the submitted width and height and a nearclipping plane of 2 109 * 110 * @param canvas 111 * to render upon 112 * 113 * @param scene 114 * to render 115 * @param width 116 * of the resulting image 117 * @param height 118 * of the resulting image 119 */ 120 public OffScreenWPVSRenderer( Canvas3D canvas, WPVSScene scene, int width, int height ) { 121 this( canvas, 2, scene, width, height ); 122 } 123 124 /** 125 * Initialzies the renderer class with the submitted width and height 126 * 127 * @param canvas 128 * to render upon 129 * @param nearClippingPlane 130 * of the scene's viewport. 131 * 132 * @param scene 133 * to render 134 * @param width 135 * of the resulting image 136 * @param height 137 * of the resulting image 138 */ 139 public OffScreenWPVSRenderer( Canvas3D canvas, double nearClippingPlane, WPVSScene scene, int width, int height ) { 140 super( scene, nearClippingPlane ); 141 142 // offScreenCanvas3D = WPVSConfiguration.getCanvas3D(); 143 offScreenCanvas3D = canvas; 144 if ( offScreenCanvas3D == null ) { 145 LOG.logError( "Did not retrieve a Canvas3D from the Configuraion, cannot proceed" ); 146 return; 147 } 148 offScreenCanvas3D.getScreen3D().setPhysicalScreenHeight( MapUtils.DEFAULT_PIXEL_SIZE * height ); 149 offScreenCanvas3D.getScreen3D().setPhysicalScreenWidth( MapUtils.DEFAULT_PIXEL_SIZE * width ); 150 151 offScreenCanvas3D.getScreen3D().setSize( width, height ); 152 BufferedImage renderedImage = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 153 154 ImageComponent2D imageComponent = new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 155 // new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 156 157 imageComponent.setCapability( ImageComponent.ALLOW_IMAGE_READ ); 158 159 offScreenCanvas3D.setOffScreenBuffer( imageComponent ); 160 161 universe = new SimpleUniverse( offScreenCanvas3D ); 162 163 OrderedGroup theScene = scene.getScene(); 164 BranchGroup sceneGroup = new BranchGroup(); 165 sceneGroup.addChild( theScene ); 166 167 addBackground( scene.getViewPoint(), sceneGroup, scene.getBackground() ); 168 169 sceneGroup.compile(); 170 BranchGroup lightGroup = new BranchGroup(); 171 Light[] lights = scene.getLights(); 172 for ( Light light : lights ) { 173 lightGroup.addChild( light.cloneTree() ); 174 } 175 lightGroup.compile(); 176 177 universe.addBranchGraph( sceneGroup ); 178 universe.addBranchGraph( lightGroup ); 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( true ); 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 }