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 }