protected void initializeTexture(DrawContext dc) { Texture iconTexture = dc.getTextureCache().getTexture(this.getIconFilePath()); if (iconTexture != null) return; try { InputStream iconStream = this.getClass().getResourceAsStream("/" + this.getIconFilePath()); if (iconStream == null) { File iconFile = new File(this.iconFilePath); if (iconFile.exists()) { iconStream = new FileInputStream(iconFile); } } iconTexture = TextureIO.newTexture(iconStream, false, null); iconTexture.bind(); this.iconWidth = iconTexture.getWidth(); this.iconHeight = iconTexture.getHeight(); dc.getTextureCache().put(this.getIconFilePath(), iconTexture); } catch (IOException e) { String msg = Logging.getMessage("layers.IOExceptionDuringInitialization"); Logging.logger().severe(msg); throw new WWRuntimeException(msg, e); } GL gl = dc.getGL(); gl.glTexParameteri( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); // _MIPMAP_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); // Enable texture anisotropy, improves "tilted" world map quality. int[] maxAnisotropy = new int[1]; gl.glGetIntegerv(GL.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy, 0); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy[0]); }
private void loadAllTopLevelTextures(DrawContext dc) { for (MercatorTextureTile tile : this.topLevels) { if (!tile.isTextureInMemory(dc.getTextureCache())) this.forceTextureLoad(tile); } this.levelZeroLoaded = true; }
private void addTile(DrawContext dc, MercatorTextureTile tile) { tile.setFallbackTile(null); if (tile.isTextureInMemory(dc.getTextureCache())) { // System.out.printf("Sector %s, min = %f, max = %f\n", tile.getSector(), // dc.getGlobe().getMinElevation(tile.getSector()), // dc.getGlobe().getMaxElevation(tile.getSector())); this.addTileToCurrent(tile); return; } // Level 0 loads may be forced if (tile.getLevelNumber() == 0 && this.forceLevelZeroLoads && !tile.isTextureInMemory(dc.getTextureCache())) { this.forceTextureLoad(tile); if (tile.isTextureInMemory(dc.getTextureCache())) { this.addTileToCurrent(tile); return; } } // Tile's texture isn't available, so request it if (tile.getLevelNumber() < this.levels.getNumLevels()) { // Request only tiles with data associated at this level if (!this.levels.isResourceAbsent(tile)) this.requestTexture(dc, tile); } // Set up to use the currentResource tile's texture if (this.currentResourceTile != null) { if (this.currentResourceTile.getLevelNumber() == 0 && this.forceLevelZeroLoads && !this.currentResourceTile.isTextureInMemory(dc.getTextureCache()) && !this.currentResourceTile.isTextureInMemory(dc.getTextureCache())) this.forceTextureLoad(this.currentResourceTile); if (this.currentResourceTile.isTextureInMemory(dc.getTextureCache())) { tile.setFallbackTile(currentResourceTile); this.addTileToCurrent(tile); } } }
private void addTileOrDescendants(DrawContext dc, MercatorTextureTile tile) { if (this.meetsRenderCriteria(dc, tile)) { this.addTile(dc, tile); return; } // The incoming tile does not meet the rendering criteria, so it must be subdivided and those // subdivisions tested against the criteria. // All tiles that meet the selection criteria are drawn, but some of those tiles will not have // textures associated with them either because their texture isn't loaded yet or because they // are finer grain than the layer has textures for. In these cases the tiles use the texture of // the closest ancestor that has a texture loaded. This ancestor is called the // currentResourceTile. // A texture transform is applied during rendering to align the sector's texture coordinates // with the // appropriate region of the ancestor's texture. MercatorTextureTile ancestorResource = null; try { // TODO: Revise this to reflect that the parent layer is only requested while the algorithm // continues // to search for the layer matching the criteria. // At this point the tile does not meet the render criteria but it may have its texture in // memory. // If so, register this tile as the resource tile. If not, then this tile will be the next // level // below a tile with texture in memory. So to provide progressive resolution increase, add // this tile // to the draw list. That will cause the tile to be drawn using its parent tile's texture, and // it will // cause it's texture to be requested. At some future call to this method the tile's texture // will be in // memory, it will not meet the render criteria, but will serve as the parent to a tile that // goes // through this same process as this method recurses. The result of all this is that a tile // isn't rendered // with its own texture unless all its parents have their textures loaded. In addition to // causing // progressive resolution increase, this ensures that the parents are available as the user // zooms out, and // therefore the layer remains visible until the user is zoomed out to the point the layer is // no longer // active. if (tile.isTextureInMemory(dc.getTextureCache()) || tile.getLevelNumber() == 0) { ancestorResource = this.currentResourceTile; this.currentResourceTile = tile; } else if (!tile.getLevel().isEmpty()) { // this.addTile(dc, tile); // return; // Issue a request for the parent before descending to the children. if (tile.getLevelNumber() < this.levels.getNumLevels()) { // Request only tiles with data associated at this level if (!this.levels.isResourceAbsent(tile)) this.requestTexture(dc, tile); } } MercatorTextureTile[] subTiles = tile.createSubTiles(this.levels.getLevel(tile.getLevelNumber() + 1)); for (MercatorTextureTile child : subTiles) { if (this.isTileVisible(dc, child)) this.addTileOrDescendants(dc, child); } } finally { if (ancestorResource != null) // Pop this tile as the currentResource ancestor this.currentResourceTile = ancestorResource; } }
protected void drawIcon(DrawContext dc) { if (this.getIconFilePath() == null) return; GL gl = dc.getGL(); OGLStackHandler ogsh = new OGLStackHandler(); try { // Initialize texture if necessary Texture iconTexture = dc.getTextureCache().getTexture(this.getIconFilePath()); if (iconTexture == null) { this.initializeTexture(dc); iconTexture = dc.getTextureCache().getTexture(this.getIconFilePath()); if (iconTexture == null) { String msg = Logging.getMessage("generic.ImageReadFailed"); Logging.logger().finer(msg); return; } } gl.glDisable(GL.GL_DEPTH_TEST); double width = this.getScaledIconWidth(); double height = this.getScaledIconHeight(); // Load a parallel projection with xy dimensions (viewportWidth, viewportHeight) // into the GL projection matrix. java.awt.Rectangle viewport = dc.getView().getViewport(); ogsh.pushProjectionIdentity(gl); double maxwh = width > height ? width : height; gl.glOrtho(0d, viewport.width, 0d, viewport.height, -0.6 * maxwh, 0.6 * maxwh); // Translate and scale ogsh.pushModelviewIdentity(gl); double scale = this.computeScale(viewport); Vec4 locationSW = this.computeLocation(viewport, scale); gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z()); // Scale to 0..1 space gl.glScaled(scale, scale, 1); gl.glScaled(width, height, 1d); if (!dc.isPickingMode()) { gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Draw background color behind the map gl.glColor4ub( (byte) this.backColor.getRed(), (byte) this.backColor.getGreen(), (byte) this.backColor.getBlue(), (byte) (this.backColor.getAlpha() * this.getOpacity())); dc.drawUnitQuad(); // Draw world map icon gl.glColor4d(1d, 1d, 1d, this.getOpacity()); gl.glEnable(GL.GL_TEXTURE_2D); iconTexture.bind(); TextureCoords texCoords = iconTexture.getImageTexCoords(); dc.drawUnitQuad(texCoords); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); gl.glDisable(GL.GL_TEXTURE_2D); // Draw crosshair for current location gl.glLoadIdentity(); gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z()); // Scale to width x height space gl.glScaled(scale, scale, 1); // Set color float[] colorRGB = this.color.getRGBColorComponents(null); gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity()); // Draw crosshair Position groundPos = this.computeGroundPosition(dc, dc.getView()); if (groundPos != null) { int x = (int) (width * (groundPos.getLongitude().degrees + 180) / 360); int y = (int) (height * (groundPos.getLatitude().degrees + 90) / 180); int w = 10; // cross branch length // Draw gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x - w, y, 0); gl.glVertex3d(x + w + 1, y, 0); gl.glEnd(); gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x, y - w, 0); gl.glVertex3d(x, y + w + 1, 0); gl.glEnd(); } // Draw view footprint in map icon space if (this.showFootprint) { this.footPrintPositions = this.computeViewFootPrint(dc, 32); if (this.footPrintPositions != null) { gl.glBegin(GL.GL_LINE_STRIP); LatLon p1 = this.footPrintPositions.get(0); for (LatLon p2 : this.footPrintPositions) { int x = (int) (width * (p2.getLongitude().degrees + 180) / 360); int y = (int) (height * (p2.getLatitude().degrees + 90) / 180); // Draw if (LatLon.locationsCrossDateline(p1, p2)) { int y1 = (int) (height * (p1.getLatitude().degrees + 90) / 180); gl.glVertex3d(x < width / 2 ? width : 0, (y1 + y) / 2, 0); gl.glEnd(); gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x < width / 2 ? 0 : width, (y1 + y) / 2, 0); } gl.glVertex3d(x, y, 0); p1 = p2; } gl.glEnd(); } } // Draw 1px border around and inside the map gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(0, 0, 0); gl.glVertex3d(width, 0, 0); gl.glVertex3d(width, height - 1, 0); gl.glVertex3d(0, height - 1, 0); gl.glVertex3d(0, 0, 0); gl.glEnd(); } else { // Picking this.pickSupport.clearPickList(); this.pickSupport.beginPicking(dc); // Where in the world are we picking ? Position pickPosition = computePickPosition( dc, locationSW, new Dimension((int) (width * scale), (int) (height * scale))); Color color = dc.getUniquePickColor(); int colorCode = color.getRGB(); this.pickSupport.addPickableObject(colorCode, this, pickPosition, false); gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); dc.drawUnitQuad(); this.pickSupport.endPicking(dc); this.pickSupport.resolvePick(dc, dc.getPickPoint(), this); } } finally { dc.restoreDefaultDepthTesting(); dc.restoreDefaultCurrentColor(); if (dc.isPickingMode()) dc.restoreDefaultBlending(); ogsh.pop(gl); } }