2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.layers
;
9 import com
.sun
.opengl
.util
.texture
.*;
10 import gov
.nasa
.worldwind
.WorldWind
;
11 import gov
.nasa
.worldwind
.cache
.TextureCache
;
12 import gov
.nasa
.worldwind
.geom
.*;
13 import gov
.nasa
.worldwind
.globes
.Globe
;
14 import gov
.nasa
.worldwind
.render
.*;
15 import gov
.nasa
.worldwind
.util
.*;
17 import javax
.media
.opengl
.*;
21 * @version $Id: TextureTile.java 2533 2007-08-13 05:59:08Z tgaskins $
23 public class TextureTile
extends Tile
implements SurfaceTile
25 private volatile TextureData textureData
;
26 private TextureTile fallbackTile
= null; // holds texture to use if own texture not available
27 private Vec4 centroid
; // Cartesian coordinate of lat/lon center
28 private Vec4
[] corners
; // Cartesian coordinate of lat/lon corners
29 private Extent extent
= null; // bounding volume
30 private double extentVerticalExaggertion
= Double
.MIN_VALUE
; // VE used to calculate the extent
31 private double minDistanceToEye
= Double
.MAX_VALUE
;
33 public TextureTile(Sector sector
, TileKey tileKey
)
35 super(sector
, tileKey
);
38 public TextureTile(Sector sector
, Level level
, int row
, int col
)
40 super(sector
, level
, row
, col
);
44 public final long getSizeInBytes()
46 long size
= super.getSizeInBytes();
48 if (this.textureData
!= null)
49 size
+= this.textureData
.getEstimatedMemorySize();
54 public TextureTile
getFallbackTile()
56 return this.fallbackTile
;
59 public void setFallbackTile(TextureTile fallbackTile
)
61 this.fallbackTile
= fallbackTile
;
64 public TextureData
getTextureData()
66 return this.textureData
;
69 public void setTextureData(TextureData textureData
)
71 this.textureData
= textureData
;
74 public Texture
getTexture(TextureCache tc
)
78 String message
= Logging
.getMessage("nullValue.TextureCacheIsNull");
79 Logging
.logger().severe(message
);
80 throw new IllegalStateException(message
);
83 return tc
.get(this.getTileKey());
86 public boolean isTextureInMemory(TextureCache tc
)
90 String message
= Logging
.getMessage("nullValue.TextureCacheIsNull");
91 Logging
.logger().severe(message
);
92 throw new IllegalStateException(message
);
95 return this.getTexture(tc
) != null || this.getTextureData() != null;
98 public void setTexture(TextureCache tc
, Texture texture
)
102 String message
= Logging
.getMessage("nullValue.TextureCacheIsNull");
103 Logging
.logger().severe(message
);
104 throw new IllegalStateException(message
);
107 tc
.put(this.getTileKey(), texture
);
109 // No more need for texture data; allow garbage collector and memory cache to reclaim it.
110 this.textureData
= null;
111 this.updateMemoryCache();
114 public Vec4
getCentroidPoint(Globe globe
)
118 String msg
= Logging
.getMessage("nullValue.GlobeIsNull");
119 Logging
.logger().severe(msg
);
120 throw new IllegalArgumentException(msg
);
123 if (this.centroid
== null)
125 LatLon c
= this.getSector().getCentroid();
126 this.centroid
= globe
.computePointFromPosition(c
.getLatitude(), c
.getLongitude(), 0);
129 return this.centroid
;
132 public Vec4
[] getCornerPoints(Globe globe
)
136 String msg
= Logging
.getMessage("nullValue.GlobeIsNull");
137 Logging
.logger().severe(msg
);
138 throw new IllegalArgumentException(msg
);
141 if (this.corners
== null)
143 Sector s
= this.getSector();
144 this.corners
= new Vec4
[4];
145 this.corners
[0] = globe
.computePointFromPosition(s
.getMinLatitude(), s
.getMinLongitude(), 0); // sw
146 this.corners
[1] = globe
.computePointFromPosition(s
.getMinLatitude(), s
.getMaxLongitude(), 0); // se
147 this.corners
[2] = globe
.computePointFromPosition(s
.getMaxLatitude(), s
.getMaxLongitude(), 0); // nw
148 this.corners
[3] = globe
.computePointFromPosition(s
.getMaxLatitude(), s
.getMinLongitude(), 0); // ne
154 public double getWidth()
156 double sLow
= this.corners
[0].distanceTo3(this.corners
[1]);
157 double sHigh
= this.corners
[2].distanceTo3(this.corners
[3]);
159 return sLow
> sHigh ? sLow
: sHigh
;
162 public double getHeight()
164 double tLow
= this.corners
[0].distanceTo3(this.corners
[2]);
165 double tHigh
= this.corners
[1].distanceTo3(this.corners
[3]);
167 return tLow
> tHigh ? tLow
: tHigh
;
170 public double getMinDistanceToEye()
172 return this.minDistanceToEye
;
175 public void setMinDistanceToEye(double minDistanceToEye
)
177 if (minDistanceToEye
< 0)
179 String msg
= Logging
.getMessage("layers.TextureTile.MinDistanceToEyeNegative");
180 Logging
.logger().severe(msg
);
181 throw new IllegalArgumentException(msg
);
183 this.minDistanceToEye
= minDistanceToEye
;
186 public Extent
getExtent(DrawContext dc
)
190 String msg
= Logging
.getMessage("nullValue.DrawContextIsNull");
191 Logging
.logger().severe(msg
);
192 throw new IllegalArgumentException(msg
);
195 if (this.extent
== null || this.extentVerticalExaggertion
!= dc
.getVerticalExaggeration())
197 this.extent
= Sector
.computeBoundingCylinder(dc
.getGlobe(), dc
.getVerticalExaggeration(), this.getSector());
198 this.extentVerticalExaggertion
= dc
.getVerticalExaggeration();
204 public TextureTile
[] createSubTiles(Level nextLevel
)
206 if (nextLevel
== null)
208 String msg
= Logging
.getMessage("nullValue.LevelIsNull");
209 Logging
.logger().severe(msg
);
210 throw new IllegalArgumentException(msg
);
212 Angle p0
= this.getSector().getMinLatitude();
213 Angle p2
= this.getSector().getMaxLatitude();
214 Angle p1
= Angle
.midAngle(p0
, p2
);
216 Angle t0
= this.getSector().getMinLongitude();
217 Angle t2
= this.getSector().getMaxLongitude();
218 Angle t1
= Angle
.midAngle(t0
, t2
);
220 String nextLevelCacheName
= nextLevel
.getCacheName();
221 int nextLevelNum
= nextLevel
.getLevelNumber();
222 int row
= this.getRow();
223 int col
= this.getColumn();
225 TextureTile
[] subTiles
= new TextureTile
[4];
227 TileKey key
= new TileKey(nextLevelNum
, 2 * row
, 2 * col
, nextLevelCacheName
);
228 TextureTile subTile
= this.getTileFromMemoryCache(key
);
230 subTiles
[0] = subTile
;
232 subTiles
[0] = new TextureTile(new Sector(p0
, p1
, t0
, t1
), nextLevel
, 2 * row
, 2 * col
);
234 key
= new TileKey(nextLevelNum
, 2 * row
, 2 * col
+ 1, nextLevelCacheName
);
235 subTile
= this.getTileFromMemoryCache(key
);
237 subTiles
[1] = subTile
;
239 subTiles
[1] = new TextureTile(new Sector(p0
, p1
, t1
, t2
), nextLevel
, 2 * row
, 2 * col
+ 1);
241 key
= new TileKey(nextLevelNum
, 2 * row
+ 1, 2 * col
, nextLevelCacheName
);
242 subTile
= this.getTileFromMemoryCache(key
);
244 subTiles
[2] = subTile
;
246 subTiles
[2] = new TextureTile(new Sector(p1
, p2
, t0
, t1
), nextLevel
, 2 * row
+ 1, 2 * col
);
248 key
= new TileKey(nextLevelNum
, 2 * row
+ 1, 2 * col
+ 1, nextLevelCacheName
);
249 subTile
= this.getTileFromMemoryCache(key
);
251 subTiles
[3] = subTile
;
253 subTiles
[3] = new TextureTile(new Sector(p1
, p2
, t1
, t2
), nextLevel
, 2 * row
+ 1, 2 * col
+ 1);
258 private TextureTile
getTileFromMemoryCache(TileKey tileKey
)
260 return (TextureTile
) WorldWind
.getMemoryCache(TextureTile
.class.getName()).getObject(tileKey
);
263 private void updateMemoryCache()
265 if (this.getTileFromMemoryCache(this.getTileKey()) != null)
266 WorldWind
.getMemoryCache(TextureTile
.class.getName()).add(this.getTileKey(), this);
269 public Texture
initializeTexture(DrawContext dc
)
273 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
274 Logging
.logger().severe(message
);
275 throw new IllegalStateException(message
);
278 Texture t
= this.getTexture(dc
.getTextureCache());
282 if (this.getTextureData() == null)
284 String msg
= Logging
.getMessage("nullValue.TextureDataIsNull");
285 Logging
.logger().severe(msg
);
286 throw new IllegalStateException(msg
);
291 t
= TextureIO
.newTexture(this.getTextureData());
295 Logging
.logger().log(
296 java
.util
.logging
.Level
.SEVERE
, "layers.TextureLayer.ExceptionAttemptingToReadTextureFile", e
);
300 this.setTexture(dc
.getTextureCache(), t
);
304 gl
.glTexParameteri(GL
.GL_TEXTURE_2D
, GL
.GL_TEXTURE_MIN_FILTER
, GL
.GL_LINEAR
);
305 gl
.glTexParameteri(GL
.GL_TEXTURE_2D
, GL
.GL_TEXTURE_MAG_FILTER
, GL
.GL_LINEAR
);
306 gl
.glTexParameteri(GL
.GL_TEXTURE_2D
, GL
.GL_TEXTURE_WRAP_S
, GL
.GL_CLAMP_TO_EDGE
);
307 gl
.glTexParameteri(GL
.GL_TEXTURE_2D
, GL
.GL_TEXTURE_WRAP_T
, GL
.GL_CLAMP_TO_EDGE
);
312 public boolean bind(DrawContext dc
)
316 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
317 Logging
.logger().severe(message
);
318 throw new IllegalStateException(message
);
321 Texture t
= this.getTexture(dc
.getTextureCache());
322 if (t
== null && this.getTextureData() != null)
324 t
= this.initializeTexture(dc
);
326 return true; // texture was bound during initialization.
329 if (t
== null && this.getFallbackTile() != null)
331 TextureTile resourceTile
= this.getFallbackTile();
332 t
= resourceTile
.getTexture(dc
.getTextureCache());
335 t
= resourceTile
.initializeTexture(dc
);
337 return true; // texture was bound during initialization.
347 public void applyInternalTransform(DrawContext dc
)
351 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
352 Logging
.logger().severe(message
);
353 throw new IllegalStateException(message
);
356 // Use the tile's texture if available.
357 Texture t
= this.getTexture(dc
.getTextureCache());
358 if (t
== null && this.getTextureData() != null)
359 t
= this.initializeTexture(dc
);
363 if (t
.getMustFlipVertically())
365 GL gl
= GLContext
.getCurrent().getGL();
366 gl
.glMatrixMode(GL
.GL_TEXTURE
);
368 gl
.glScaled(1, -1, 1);
369 gl
.glTranslated(0, -1, 0);
374 // Use the tile's fallback texture if its primary texture is not available.
375 TextureTile resourceTile
= this.getFallbackTile();
376 if (resourceTile
== null) // no fallback specified
379 t
= resourceTile
.getTexture(dc
.getTextureCache());
380 if (t
== null && resourceTile
.getTextureData() != null)
381 t
= resourceTile
.initializeTexture(dc
);
383 if (t
== null) // was not able to initialize the fallback texture
386 // Apply necessary transforms to the fallback texture.
387 GL gl
= GLContext
.getCurrent().getGL();
388 gl
.glMatrixMode(GL
.GL_TEXTURE
);
391 if (t
.getMustFlipVertically())
393 gl
.glScaled(1, -1, 1);
394 gl
.glTranslated(0, -1, 0);
397 this.applyResourceTextureTransform(dc
);
400 private void applyResourceTextureTransform(DrawContext dc
)
404 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
405 Logging
.logger().severe(message
);
406 throw new IllegalStateException(message
);
409 if (this.getLevel() == null)
412 int levelDelta
= this.getLevelNumber() - this.getFallbackTile().getLevelNumber();
416 double twoToTheN
= Math
.pow(2, levelDelta
);
417 double oneOverTwoToTheN
= 1 / twoToTheN
;
419 double sShift
= oneOverTwoToTheN
* (this.getColumn() % twoToTheN
);
420 double tShift
= oneOverTwoToTheN
* (this.getRow() % twoToTheN
);
422 dc
.getGL().glTranslated(sShift
, tShift
, 0);
423 dc
.getGL().glScaled(oneOverTwoToTheN
, oneOverTwoToTheN
, 1);
427 public boolean equals(Object o
)
431 if (o
== null || getClass() != o
.getClass())
434 final TextureTile tile
= (TextureTile
) o
;
436 return !(this.getTileKey() != null ?
!this.getTileKey().equals(tile
.getTileKey()) : tile
.getTileKey() != null);
440 public int hashCode()
442 return (this.getTileKey() != null ?
this.getTileKey().hashCode() : 0);
446 public String
toString()
448 return this.getSector().toString();