001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wpvs/j3d/TexturedSurface.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     Aennchenstr. 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    package org.deegree.ogcwebservices.wpvs.j3d;
044    
045    import java.awt.image.BufferedImage;
046    import java.io.IOException;
047    import java.net.URL;
048    
049    import javax.media.j3d.Appearance;
050    import javax.media.j3d.Material;
051    import javax.media.j3d.TexCoordGeneration;
052    import javax.media.j3d.Texture;
053    import javax.vecmath.Vector4f;
054    
055    import org.deegree.framework.util.ImageUtils;
056    import org.deegree.model.spatialschema.Position;
057    import org.deegree.model.spatialschema.Ring;
058    import org.deegree.model.spatialschema.Surface;
059    import org.deegree.ogcwebservices.wpvs.configuration.RenderingConfiguration;
060    
061    import com.sun.j3d.utils.geometry.GeometryInfo;
062    import com.sun.j3d.utils.geometry.NormalGenerator;
063    import com.sun.j3d.utils.image.TextureLoader;
064    
065    /**
066     * 
067     * 
068     * 
069     * @version $Revision: 6259 $
070     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
071     * @author last edited by: $Author: bezema $
072     * 
073     * @version 1.0. $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
074     * 
075     * @since 2.0
076     */
077    public class TexturedSurface extends ColoredSurface {
078    
079        private Texture texture = null;
080    
081        private BufferedImage textureImg = null;
082    
083        private float[][] textureCoords = null;
084        
085        /**
086         * creates a TexturedSurface from a geometry, color informations and a texture image. Since a
087         * texture image be somehow transparent it is useful to be able to define a surfaces color. This
088         * constructor will use default coordinates to adjust a texture onto a surface.
089         * 
090         * @param objectID
091         *            an Id for this Surface, for example a db primary key
092         * @param parentID
093         *            an Id for the parent of this Surface, for example if this is a wall the parent is
094         *            the building.
095         * @param surface
096         *            the ogc:geometry surface which holds the point references of a polygon, not to be
097         *            confused with a j3d Object which this class represents.
098         * @param red
099         * @param green
100         * @param blue
101         * @param transparency
102         * @param textureImg
103         */
104        public TexturedSurface( String objectID, String parentID, Surface surface, float red,
105                               float green, float blue, float transparency, BufferedImage textureImg ) {
106            super( objectID, parentID, surface, red, green, blue, transparency );
107            this.textureImg = textureImg;
108            createTexture( textureImg );
109            setAppearance( createAppearance() );
110        }
111    
112        /**
113         * creates a TexturedSurface from a geometry, Material and a texture image. Since a texture
114         * image be somehow transparent it is useful to be able to define a surfaces color. This
115         * constructor will use default coordinates to adjust a texture onto a surface.
116         * 
117         * @param objectID
118         *            an Id for this Surface, for example a db primary key
119         * @param parentID
120         *            an Id for the parent of this Surface, for example if this is a wall the parent is
121         *            the building.
122         * @param surface
123         *            the ogc:geometry surface which holds the point references of a polygon, not to be
124         *            confused with a j3d Object which this class represents.
125         * @param material
126         * @param transparency
127         * @param textureImg
128         */
129        public TexturedSurface( String objectID, String parentID, Surface surface, Material material,
130                               float transparency, BufferedImage textureImg ) {
131            super( objectID, parentID, surface, material, transparency );
132            this.textureImg = textureImg;
133            createTexture( textureImg );
134            setAppearance( createAppearance() );
135        }
136    
137        /**
138         * creates a TexturedSurface from a geometry, color informations and a reference to a texture
139         * image. Since a texture image be somehow transparent it is useful to be able to define a
140         * surfaces color. This constructor will use default coordinates to adjust a texture onto a
141         * surface.
142         * 
143         * @param objectID
144         *            an Id for this Surface, for example a db primary key
145         * @param parentID
146         *            an Id for the parent of this Surface, for example if this is a wall the parent is
147         *            the building.
148         * @param surface
149         *            the ogc:geometry surface which holds the point references of a polygon, not to be
150         *            confused with a j3d Object which this class represents.
151         * @param red
152         * @param green
153         * @param blue
154         * @param transparency
155         * @param textureImg
156         * @throws IOException
157         */
158        public TexturedSurface( String objectID, String parentID, Surface surface, float red,
159                               float green, float blue, float transparency, URL textureImg )
160                                throws IOException {
161            super( objectID, parentID, surface, red, green, blue, transparency );
162            this.textureImg = ImageUtils.loadImage( textureImg );
163            createTexture( this.textureImg );
164            setAppearance( createAppearance() );
165        }
166    
167        /**
168         * creates a TexturedSurface from a geometry, Material and a reference to a texture image. Since
169         * a texture image be somehow transparent it is useful to be able to define a surfaces color.
170         * This constructor will use default coordinates to adjust a texture onto a surface.
171         * 
172         * @param objectID
173         *            an Id for this Surface, for example a db primary key
174         * @param parentID
175         *            an Id for the parent of this Surface, for example if this is a wall the parent is
176         *            the building.
177         * @param surface
178         *            the ogc:geometry surface which holds the point references of a polygon, not to be
179         *            confused with a j3d Object which this class represents.
180         * @param material
181         * @param transparency
182         * @param textureImg
183         * @throws IOException
184         */
185        public TexturedSurface( String objectID, String parentID, Surface surface, Material material,
186                               float transparency, URL textureImg ) throws IOException {
187            super( objectID, parentID, surface, material, transparency );
188    
189            this.textureImg = ImageUtils.loadImage( textureImg );
190            createTexture( this.textureImg );
191            setAppearance( createAppearance() );
192        }
193    
194        /**
195         * creates a TexturedSurface from a geometry, color informations and a texture image. Since a
196         * texture image be somehow transparent it is useful to be able to define a surfaces color.
197         * 
198         * @param objectID
199         *            an Id for this Surface, for example a db primary key
200         * @param parentID
201         *            an Id for the parent of this Surface, for example if this is a wall the parent is
202         *            the building.
203         * @param surface
204         *            the ogc:geometry surface which holds the point references of a polygon, not to be
205         *            confused with a j3d Object which this class represents.
206         * @param red
207         * @param green
208         * @param blue
209         * @param transparency
210         * @param textureImg
211         * @param textureCoords
212         */
213        public TexturedSurface( String objectID, String parentID, Surface surface, float red,
214                               float green, float blue, float transparency, BufferedImage textureImg,
215                               float[][] textureCoords ) {
216            super( objectID, parentID, surface, red, green, blue, transparency );
217    
218            this.textureImg = textureImg;
219            this.textureCoords = textureCoords;
220            createTexture( textureImg );
221            setAppearance( createAppearance() );
222    
223        }
224    
225        /**
226         * creates a TexturedSurface from a geometry, Material and a texture image. Since a texture
227         * image be somehow transparent it is useful to be able to define a surfaces color.
228         * 
229         * @param objectID
230         *            an Id for this Surface, for example a db primary key
231         * @param parentID
232         *            an Id for the parent of this Surface, for example if this is a wall the parent is
233         *            the building.
234         * @param surface
235         *            the ogc:geometry surface which holds the point references of a polygon, not to be
236         *            confused with a j3d Object which this class represents.
237         * @param material
238         * @param transparency
239         * @param textureImg
240         * @param textureCoords
241         */
242        public TexturedSurface( String objectID, String parentID, Surface surface, Material material,
243                               float transparency, BufferedImage textureImg, float[][] textureCoords ) {
244            super( objectID, parentID, surface, material, transparency );
245    
246            this.textureImg = textureImg;
247            this.textureCoords = textureCoords;
248            createTexture( textureImg );
249            setAppearance( createAppearance() );
250        }
251    
252        /**
253         * creates a TexturedSurface from a geometry, color informations and a reference to a texture
254         * image. Since a texture image be somehow transparent it is useful to be able to define a
255         * surfaces color.
256         * 
257         * @param objectID
258         *            an Id for this Surface, for example a db primary key
259         * @param parentID
260         *            an Id for the parent of this Surface, for example if this is a wall the parent is
261         *            the building.
262         * @param surface
263         *            the ogc:geometry surface which holds the point references of a polygon, not to be
264         *            confused with a j3d Object which this class represents.
265         * @param red
266         * @param green
267         * @param blue
268         * @param transparency
269         * @param textureImg
270         * @param textureCoords
271         * @throws IOException
272         */
273        public TexturedSurface( String objectID, String parentID, Surface surface, float red,
274                               float green, float blue, float transparency, URL textureImg,
275                               float[][] textureCoords ) throws IOException {
276            super( objectID, parentID, surface, red, green, blue, transparency );
277    
278            this.textureImg = ImageUtils.loadImage( textureImg );
279            this.textureCoords = textureCoords;
280            createTexture( this.textureImg );
281            setAppearance( createAppearance() );
282        }
283    
284        /**
285         * creates a TexturedSurface from a geometry, Material and a reference to a texture image. Since
286         * a texture image be somehow transparent it is useful to be able to define a surfaces color.
287         * 
288         * @param objectID
289         *            an Id for this Surface, for example a db primary key
290         * @param parentID
291         *            an Id for the parent of this Surface, for example if this is a wall the parent is
292         *            the building.
293         * @param surface
294         *            the ogc:geometry surface which holds the point references of a polygon, not to be
295         *            confused with a j3d Object which this class represents.
296         * @param material
297         * @param transparency
298         * @param textureImg
299         * @param textureCoords
300         * @throws IOException
301         */
302        public TexturedSurface( String objectID, String parentID, Surface surface, Material material,
303                               float transparency, URL textureImg, float[][] textureCoords )
304                                throws IOException {
305            super( objectID, parentID, surface, material, transparency );
306            this.textureImg = ImageUtils.loadImage( textureImg );
307            this.textureCoords = textureCoords;
308            createTexture( this.textureImg );
309            setAppearance( createAppearance() );
310        }
311    
312        private void createTexture( BufferedImage textureImg ) {
313            try {
314                texture = new TextureLoader( textureImg ).getTexture();
315                texture.setEnable( true );
316                texture.setCapability( Texture.ALLOW_ENABLE_WRITE );
317            } catch ( Exception e ) {
318                e.printStackTrace();
319            }
320        }
321    
322        /**
323         * @return the texture of this surface.
324         */
325        public BufferedImage getTexture() {
326            return textureImg;
327        }
328    
329        /**
330         * this method must be called before addin the surface to a Group
331         */
332        @Override
333        public void compile() {
334    
335            GeometryInfo geometryInfo = new GeometryInfo( GeometryInfo.POLYGON_ARRAY );
336    
337            Position[] pos = surface.getSurfaceBoundary().getExteriorRing().getPositions();
338            Ring[] innerRings = surface.getSurfaceBoundary().getInteriorRings();
339            int k = 1;
340            int l = 3 * ( pos.length   );
341            if ( innerRings != null ) {
342                for ( int i = 0; i < innerRings.length; i++ ) {
343                    k++;
344                    l += ( 3 * innerRings[i].getPositions().length );
345                }
346            }
347    
348            float[] coords = new float[l];
349            int contourCounts[] = { k };
350            int[] stripCounts = new int[k];
351            k = 0;
352            stripCounts[k++] = pos.length;
353    
354            int z = 0;
355            for ( int i = 0; i < pos.length; i++ ) {
356                coords[z++] = (float) pos[i].getX();
357                coords[z++] = (float) pos[i].getY();
358                coords[z++] = (float) pos[i].getZ();
359            }
360    
361            if ( innerRings != null ) {
362                for ( int j = 0; j < innerRings.length; j++ ) {
363                    pos = innerRings[j].getPositions();
364                    stripCounts[k++] = pos.length;
365                    for ( int i = 0; i < pos.length; i++ ) {
366                        coords[z++] = (float) pos[i].getX();
367                        coords[z++] = (float) pos[i].getY();
368                        coords[z++] = (float) pos[i].getZ();
369                    }
370                }
371            }
372    
373            geometryInfo.setCoordinates( coords );
374            geometryInfo.setStripCounts( stripCounts );
375            geometryInfo.setContourCounts( contourCounts );
376    
377            // manually set texture coordinates must be done befor
378            // normals all calculated
379            if ( textureCoords != null ) {
380                geometryInfo.setTextureCoordinateParams( textureCoords.length, 2 );
381                for ( int i = 0; i < textureCoords.length; i++ ) {
382                    geometryInfo.setTextureCoordinates( i, textureCoords[i] );
383                }
384            }
385    
386            NormalGenerator ng = new NormalGenerator();
387            ng.generateNormals( geometryInfo );
388    
389            setGeometry( geometryInfo.getGeometryArray() );
390    
391            setAppearanceOverrideEnable( true );
392        }
393    
394        private Appearance createAppearance() {
395            Appearance ap = getAppearance();
396            if ( texture != null ) {
397                ap.setTexture( texture );
398                ap.setTextureAttributes( RenderingConfiguration.getInstance().getTextureAttributes() );
399    
400                if ( textureCoords == null ) {
401                    // automatic creation of texture coordinates is behavior of
402                    // the appearance
403                    TexCoordGeneration tcg = new TexCoordGeneration(
404                                                                     TexCoordGeneration.OBJECT_LINEAR,
405                                                                     TexCoordGeneration.TEXTURE_COORDINATE_2 );
406                    tcg.setPlaneS( new Vector4f( 1, 1, 0, 0 ) );
407                    tcg.setPlaneT( new Vector4f( 0, 0, 1, 0 ) );
408                    ap.setTexCoordGeneration( tcg );
409                }
410            }
411            return ap;
412        }
413    
414    }
415