001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }