001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wpvs/j3d/OffScreenWPVSRenderer.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2006 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.RenderingAttributes; 059 import javax.media.j3d.Transform3D; 060 import javax.media.j3d.TransformGroup; 061 import javax.media.j3d.View; 062 import javax.vecmath.Color3f; 063 import javax.vecmath.Vector3d; 064 065 import org.deegree.framework.log.ILogger; 066 import org.deegree.framework.log.LoggerFactory; 067 import org.deegree.framework.util.MapUtils; 068 import org.deegree.i18n.Messages; 069 070 import com.sun.j3d.utils.geometry.Sphere; 071 import com.sun.j3d.utils.universe.MultiTransformGroup; 072 import com.sun.j3d.utils.universe.SimpleUniverse; 073 import com.sun.j3d.utils.universe.ViewingPlatform; 074 075 /** 076 * The class provides the capabilitiy for rendering a <code>WPVSScene</code> to an offscreen graphic context that is 077 * represent by a <code>BufferedImage</code>. That is, the returned BufferedImage of this class's renderScene method 078 * is the response Object of a GetView request. 079 * 080 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 081 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 082 * 083 * @version $Revision: 7957 $ $Date: 2007-08-09 11:59:39 +0200 (Do, 09 Aug 2007) $ 084 */ 085 public class OffScreenWPVSRenderer extends Abstract3DRenderingEngine { 086 087 private static ILogger LOG = LoggerFactory.getLogger( OffScreenWPVSRenderer.class ); 088 089 private int width = 800; 090 091 private int height = 600; 092 093 private Canvas3D offScreenCanvas3D; 094 095 private SimpleUniverse universe; 096 097 /** 098 * Initialzies the render class with a default width and height (800x600) and a nearclipping plane of 2 099 * 100 * @param scene 101 * to render 102 */ 103 public OffScreenWPVSRenderer( WPVSScene scene ) { 104 this( 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 scene 111 * to render 112 * @param width 113 * of the resulting image 114 * @param height 115 * of the resulting image 116 */ 117 public OffScreenWPVSRenderer( WPVSScene scene, int width, int height ) { 118 this( 2, scene, width, height ); 119 } 120 121 /** 122 * Initialzies the renderer class with the submitted width and height 123 * @param nearClippingPlane of the scene's viewport. 124 * @param scene 125 * to render 126 * @param width 127 * of the resulting image 128 * @param height 129 * of the resulting image 130 */ 131 public OffScreenWPVSRenderer( double nearClippingPlane, WPVSScene scene, int width, int height ) { 132 super( scene, nearClippingPlane ); 133 this.width = width; 134 this.height = height; 135 136 offScreenCanvas3D = createOffscreenCanvas3D(); 137 universe = new SimpleUniverse( offScreenCanvas3D ); 138 139 BranchGroup sceneGroup = scene.getScene(); 140 141 addBackground( scene.getViewPoint(), sceneGroup, scene.getBackground() ); 142 143 sceneGroup.compile(); 144 BranchGroup lightGroup = new BranchGroup(); 145 Light[] lights = scene.getLights(); 146 for ( Light light : lights ) { 147 lightGroup.addChild( light.cloneTree() ); 148 } 149 lightGroup.compile(); 150 151 universe.addBranchGraph( sceneGroup ); 152 universe.addBranchGraph( lightGroup ); 153 } 154 155 /** 156 * @param scene 157 * the Scene to render 158 */ 159 public void setScene( WPVSScene scene ) { 160 this.scene = scene; 161 } 162 163 /** 164 * Renders the scene to a <code>BufferedImage</code>. This Method uses the viewmatrix of the the ViewPoint class, 165 * which the defines the necessary viewing rotations and translations for the j3d scene. 166 * 167 * @return a <code>BufferedImage</code> where the scene has been rendered to 168 */ 169 public BufferedImage renderScene() { 170 171 // setting up the transformation of the viewingplatform according to the requested 172 // (calculated) values. 173 ViewingPlatform vp = universe.getViewingPlatform(); 174 View view = universe.getViewer().getView(); 175 176 // view parameters 177 view.setBackClipDistance( farClippingPlane ); 178 view.setFrontClipDistance( nearClippingPlane ); 179 view.setWindowEyepointPolicy( View.RELATIVE_TO_FIELD_OF_VIEW ); 180 view.setFieldOfView( scene.getViewPoint().getAngleOfView() ); 181 view.setSceneAntialiasingEnable( true ); 182 //view.setTransparencySortingPolicy( View.TRANSPARENCY_SORT_GEOMETRY ); 183 //view.setDepthBufferFreezeTransparent( false ); 184 185 MultiTransformGroup mtg = vp.getMultiTransformGroup(); 186 int transforms = mtg.getNumTransforms(); 187 TransformGroup transGroup = null; 188 // if one or more transformgroups are present take the first one will be set to the 189 // viewmatrix of the ViewPoint 190 if ( transforms > 0 ) { 191 transGroup = mtg.getTransformGroup( 0 ); 192 } 193 if ( transGroup == null ) { 194 LOG.logError( Messages.getMessage( "WPVS_NO_TRANSFORMS_ERROR" ) ); 195 return null; 196 } 197 Transform3D viewMatrix = scene.getViewPoint().getViewMatrix(); 198 transGroup.setTransform( viewMatrix ); 199 200 // draw the poi as a sphere if the Debug level is on. 201 BranchGroup sphere = new BranchGroup(); 202 sphere.setCapability( BranchGroup.ALLOW_DETACH ); 203 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 204 Appearance app = new Appearance(); 205 RenderingAttributes ra = new RenderingAttributes(); 206 ra.setDepthBufferEnable( true ); 207 app.setRenderingAttributes( ra ); 208 Material material = new Material(); 209 material.setAmbientColor( new Color3f( Color.WHITE ) ); 210 material.setDiffuseColor( new Color3f( Color.WHITE ) ); 211 app.setMaterial( material ); 212 Sphere s = new Sphere( 20, app ); 213 Transform3D t3d = new Transform3D(); 214 t3d.setTranslation( new Vector3d( scene.getViewPoint().getPointOfInterest() ) ); 215 TransformGroup tg = new TransformGroup(); 216 tg.setTransform( t3d ); 217 tg.addChild( s ); 218 sphere.addChild( tg ); 219 universe.addBranchGraph( sphere ); 220 } 221 222 // Finally draw the scene 223 view.startView(); 224 offScreenCanvas3D.renderOffScreenBuffer(); 225 offScreenCanvas3D.waitForOffScreenRendering(); 226 view.stopView(); 227 228 // removing the sphere out of the universe 229 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 230 Locale l = universe.getLocale(); 231 l.removeBranchGraph( sphere ); 232 } 233 234 ImageComponent2D imageComponent = offScreenCanvas3D.getOffScreenBuffer(); 235 if ( imageComponent == null ) { 236 LOG.logError( Messages.getMessage( "WPVS_NO_IMAGE_COMPONENT_ERROR" ) ); 237 return null; 238 } 239 // BufferedImage img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 240 // Graphics2D g2d = (Graphics2D) img.getGraphics(); 241 // g2d.drawImage( imageComponent.getImage(), new AffineTransformOp( AffineTransform.getScaleInstance( 0.5, 0.5 ), 242 // AffineTransformOp.TYPE_BICUBIC ), 0, 0 ); 243 // and cleaning the universe and all of its used memory. 244 universe.cleanup(); 245 return imageComponent.getImage(); 246 } 247 248 /** 249 * creates and returns a canvas for offscreen rendering 250 * 251 * @return a offscreen Canvas3D on which the the scene will be rendered. 252 */ 253 protected Canvas3D createOffscreenCanvas3D() { 254 Canvas3D offScreenCanvas3D = createCanvas( true ); 255 256 offScreenCanvas3D.getScreen3D().setPhysicalScreenHeight( MapUtils.DEFAULT_PIXEL_SIZE * height ); 257 offScreenCanvas3D.getScreen3D().setPhysicalScreenWidth( MapUtils.DEFAULT_PIXEL_SIZE * width); 258 259 260 offScreenCanvas3D.getScreen3D().setSize( width, height ); 261 BufferedImage renderedImage = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 262 263 ImageComponent2D imageComponent = new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 264 // new ImageComponent2D( ImageComponent.FORMAT_RGB, renderedImage ); 265 266 imageComponent.setCapability( ImageComponent.ALLOW_IMAGE_READ ); 267 268 offScreenCanvas3D.setOffScreenBuffer( imageComponent ); 269 270 return offScreenCanvas3D; 271 } 272 273 /** 274 * Called to render the scene into the offscreen Canvas3D 275 * 276 * @param offScreenCanvas3D 277 * to be rendered into 278 * @return a buffered image as a result of the Rendering. 279 */ 280 protected RenderedImage getImage( Canvas3D offScreenCanvas3D ) { 281 282 offScreenCanvas3D.renderOffScreenBuffer(); 283 offScreenCanvas3D.waitForOffScreenRendering(); 284 285 ImageComponent2D imageComponent = offScreenCanvas3D.getOffScreenBuffer(); 286 287 return imageComponent.getImage(); 288 } 289 }