📄 tiledsurfaceobjectrenderer.java
字号:
{ return tile; } } return null; } @SuppressWarnings({"UnusedDeclaration"}) protected boolean needToSubdivide(DrawContext dc, Sector sector, int width, int height) { // Compute a point in the sector that is nearest to the eye point. This point will be used to estimate the // distance from the eye to the sector. Vec4 nearestPoint = this.getNearestPointInSector(dc, sector); // Compute the size in meters of a texel on the surface sector given the data dimensions (width, height). double texelSize = nearestPoint.getLength3() * sector.getDeltaLatRadians() / height; // Compute the size in meters that a screen pixel would cover on the surface. double eyeToSurfaceDistance = dc.getView().getEyePoint().distanceTo3(nearestPoint); double pixelSize = dc.getView().computePixelSizeAtDistance(eyeToSurfaceDistance); // Compute the the ratio of surface texels to screen pixels. // * If ratio is 1, then a surface texel will be about the same size as a screen pixel. // * If ratio is less than 1, then a surface texel will be smaller than a screen pixel. // * If ratio is greater than 1, then a surface texel will be larger than a screen pixel. double ratio = texelSize / pixelSize; // Subdivide when the ratio of surface texels to screen pixels to is greater than the desired ratio. // Subdividing will create sub tiles with a smaller ratio; the the texel size will decrease while the pixel // size stays constant. return ratio > this.texelToPixelRatio; } protected Vec4 getNearestPointInSector(DrawContext dc, Sector sector) { Position eyePos = dc.getView().getEyePosition(); if (sector.contains(eyePos)) { Vec4 point = dc.getPointOnGlobe(eyePos.getLatitude(), eyePos.getLongitude()); if (point == null) { double elev = dc.getGlobe().getElevation(eyePos.getLatitude(), eyePos.getLongitude()) * dc.getVerticalExaggeration(); return dc.getGlobe().computePointFromPosition(eyePos.getLatitude(), eyePos.getLongitude(), elev); } return point; } LatLon nearestCorner = null; Angle nearestDistance = Angle.fromDegrees(Double.MAX_VALUE); for (LatLon ll : sector) { Angle d = LatLon.greatCircleDistance(ll, eyePos); if (d.compareTo(nearestDistance) < 0) { nearestCorner = ll; nearestDistance = d; } } if (nearestCorner == null) return null; Vec4 point = dc.getPointOnGlobe(nearestCorner.getLatitude(), nearestCorner.getLongitude()); if (point != null) return point; double elev = dc.getGlobe().getElevation(nearestCorner.getLatitude(), nearestCorner.getLongitude()) * dc.getVerticalExaggeration(); return dc.getGlobe().computePointFromPosition(nearestCorner.getLatitude(), nearestCorner.getLongitude(), elev); } protected TextureTile[] assembleTopLevelTiles(LevelSet levelSet, Sector sector) { Level level = levelSet.getFirstLevel(); Angle dLat = level.getTileDelta().getLatitude(); Angle dLon = level.getTileDelta().getLongitude(); Angle latOrigin = levelSet.getTileOrigin().getLatitude(); Angle lonOrigin = levelSet.getTileOrigin().getLongitude(); // Determine the row and column offset from the common World Wind global tiling origin. int firstRow = Tile.computeRow(dLat, sector.getMinLatitude(), latOrigin); int firstCol = Tile.computeColumn(dLon, sector.getMinLongitude(), lonOrigin); int lastRow = Tile.computeRow(dLat, sector.getMaxLatitude(), latOrigin); int lastCol = Tile.computeColumn(dLon, sector.getMaxLongitude(), lonOrigin); int nLatTiles = lastRow - firstRow + 1; int nLonTiles = lastCol - firstCol + 1; int tileIndex = 0; TextureTile[] tiles = new TextureTile[nLatTiles * nLonTiles]; Angle p1 = Tile.computeRowLatitude(firstRow, dLat, latOrigin); for (int row = firstRow; row <= lastRow; row++) { Angle p2; p2 = p1.add(dLat); Angle t1 = Tile.computeColumnLongitude(firstCol, dLon, lonOrigin); for (int col = firstCol; col <= lastCol; col++) { Angle t2; t2 = t1.add(dLon); TileKey tileKey = new TileKey(level.getLevelNumber(), row, col, level.getCacheName()); TextureTile tile = this.getTileFromMemoryCache(tileKey); if (tile == null) { tile = new TextureTile(new Sector(p1, p2, t1, t2), level, row, col); TextureTile.getMemoryCache().add(tileKey, tile); } tiles[tileIndex++] = tile; t1 = t2; } p1 = p2; } return tiles; } protected TextureTile getTileFromMemoryCache(TileKey tileKey) { return (TextureTile) TextureTile.getMemoryCache().getObject(tileKey); } //**************************************************************// //******************** Tile Rasterization ********************// //**************************************************************// protected void updateTiles(DrawContext dc) { if (this.currentTiles.isEmpty()) return; OGLStackHandler stackHandler = new OGLStackHandler(); this.beginUpdateTiles(dc, stackHandler, this.currentTileViewport); try { for (TextureTile tile : this.currentTiles) { this.updateTile(dc, tile); } // Must update the pick tile data every frame. if (this.pickEnabled && this.havePickTile) { this.updatePickTile(dc, this.pickTile); } } finally { this.endUpdateTiles(dc, stackHandler); } } protected void beginUpdateTiles(DrawContext dc, OGLStackHandler stackHandler, java.awt.Rectangle viewport) { GL gl = dc.getGL(); this.renderToTextureSupport.beginRendering(gl, viewport.x, viewport.y, viewport.width, viewport.height); // Setup GL to use blending with non premultiplied alpha colors. The values actually written to the framebuffer // will have their color components multiplied by alpha. However, to use GL line or polygon blending, GL is // expecting to work with non premultiplied colors. OGLStateSupport stateSupport = new OGLStateSupport(); stateSupport.setEnableAlphaTest(true); stateSupport.setEnableBlending(true); stateSupport.setColorMode(OGLStateSupport.COLOR_NO_PREMULTIPLIED_ALPHA); stackHandler.pushAttrib(gl, stateSupport.getAttributeBits() | GL.GL_DEPTH_BUFFER_BIT); // For depth test. stateSupport.apply(gl); gl.glDisable(GL.GL_DEPTH_TEST); } protected void endUpdateTiles(DrawContext dc, OGLStackHandler stackHandler) { GL gl = dc.getGL(); stackHandler.pop(gl); this.renderToTextureSupport.endRendering(gl); } protected void updateTile(DrawContext dc, TextureTile tile) { SurfaceObjectState currentTileState = this.getCurrentStateFor(tile.getSector()); if (this.isTileCurrent(dc, tile, currentTileState)) { return; } this.updateTileData(dc, tile, currentTileState); currentTileState.setLastModifiedTime(System.currentTimeMillis()); this.setTileState(tile, currentTileState); } protected void updatePickTile(DrawContext dc, PickTile tile) { this.updatePickTileData(dc, tile); } protected boolean isTileCurrent(DrawContext dc, TextureTile tile, SurfaceObjectState state) { SurfaceObjectState currentState = this.getTileState(tile); //noinspection SimplifiableIfStatement if (currentState == null || currentState.isStateNewerOrModified(state)) { return false; } return tile.getTexture(dc.getTextureCache()) != null; } protected SurfaceObjectState getTileState(TextureTile tile) { return this.tileStateMap.get(tile.getTileKey()); } protected void setTileState(TextureTile tile, SurfaceObjectState state) { this.tileStateMap.put(tile.getTileKey(), state); } protected void clearAllTileState() { this.tileStateMap.clear(); } protected void updateTileData(DrawContext dc, TextureTile tile, SurfaceObjectState state) { GL gl = dc.getGL(); java.awt.Rectangle viewport = this.renderToTextureSupport.getViewport(); // Clear the current framebuffer contents. this.renderToTextureSupport.clear(gl, this.tileBackgroundColor); // Render each intersecting object into the framebuffer. for (SurfaceObject surfaceObject : state.getSurfaceObjects()) { surfaceObject.renderToRegion(dc, tile.getSector(), viewport.x, viewport.y, viewport.width, viewport.height); } // Copy the framebuffer contents to the tile. this.copyFramebufferContentsToTile(dc, tile, viewport.x, viewport.y, viewport.width, viewport.height, this.useMipmaps); } protected void updatePickTileData(DrawContext dc, PickTile tile) { GL gl = dc.getGL(); java.awt.Rectangle viewport = this.renderToTextureSupport.getViewport(); // Temporarily force the DrawContext into picking mode while the surface objects are rendered into the pick // tile. boolean isPicking = dc.isPickingMode(); if (!isPicking) { dc.enablePickingMode(); } this.pickSupport.beginPicking(dc); // Clear the current framebuffer contents. this.renderToTextureSupport.clear(gl, new java.awt.Color(0, 0, 0, 0)); // Render each intersecting object into the framebuffer with a unique pick color. for (SurfaceObjectInfo objectInfo : this.currentSurfaceObjects) { if (objectInfo.intersects(tile.getSector())) { this.bindPickableObject(dc, objectInfo.getSurfaceObject(), null); objectInfo.getSurfaceObject().renderToRegion(dc, tile.getSector(), viewport.x, viewport.y, viewport.width, viewport.height); } } // Copy the framebuffer contents to the tile. this.copyFramebufferContentsToTile(dc, tile.getDelegate(), viewport.x, viewport.y, viewport.width, viewport.height, false); this.pickSupport.endPicking(dc); // Restore the DrawContext's previous picking mode state. if (!isPicking) { dc.disablePickingMode(); } } protected void copyFramebufferContentsToTile(DrawContext dc, TextureTile tile, int x, int y, int width, int height, boolean useMipmaps) { // Update the tile texture with the current framebuffer contents. If the tile's dimensions do not match the // framebuffer viewport's dimensions, or if the tile does not have a texture, then new texture data with the // appropriate dimensions. Texture texture = tile.getTexture(dc.getTextureCache()); boolean hasTexture = (texture != null) && (texture.getWidth() == width) && (texture.getHeight() == height); if (!hasTexture) { // TODO: work with texture tile to refresh the texture data dc.getTextureCache().remove(tile.getTileKey()); tile.setTextureData(this.createTileTextureData(width, height, useMipmaps)); } // Bind the tile. If necessary this will transfer any in-memory texture data to OpenGL, or create the texture // object. Then this will make this tile's texture the current active texture object. tile.bind(dc); texture = tile.getTexture(dc.getTextureCache()); if (texture == null) { String message = Logging.getMessage("nullValue.TextureIsNull"); Logging.logger().warning(message); return; } if (hasTexture) { dc.getGL().glCopyTexSubImage2D( texture.getTarget(), // target 0, // level 0, 0, // xoffset, yoffset x, y, // x, y width, height); // width, height } else { dc.getGL().glCopyTexImage2D( texture.getTarget(), // target 0, // level GL.GL_RGBA, // internal format x, y, // x, y width, height, // width, height 0); // border } } protected TextureData createTileTextureData(int width, int height, boolean useMipmaps) { return new TextureData( GL.GL_RGBA, // internal format width, height, // width, height 0, // border GL.GL_RGBA, // pixel format GL.GL_UNSIGNED_BYTE, // pixel type useMipmaps, // mipmap false, false, // dataIsCompressed, mustFlipVertically null, null); // buffer, flusher } //**************************************************************// //******************** Pick Tile *****************************// //**************************************************************// protected static class PickTile implements SurfaceTile { protected Sector sector; protected int preferredWidth; protected int preferredHeight; protected TextureTile delegate; private Extent extent = null; // bounding volume private Object globeStateKey; public PickTile(Sector sector) { this.sector = sector; this.delegate = new TextureTile(sector); } public Sector getSector() { return this.sector; } public void setSector(Sector sector) { this.sector = sector; this.extent = null; } public int getPreferredWidth() { return this.preferredWidth; } public void setPreferredWidth(int preferredWidth) { this.preferredWidth = preferredWidth; } public int getPreferredHeight() { return this.preferredHeight; } public void setPreferredHeight(int preferredHeight) { this.preferredHeight = preferredHeight; } public TextureTile getDelegate() { return this.delegate; } public boolean bind(DrawContext dc) { return this.delegate.bind(dc); } public void applyInternalTransform(DrawContext dc) { this.delegate.applyInternalTransform(dc); } public java.util.List<? extends LatLon> getCorners() { return this.sector.asList(); } public Extent getExtent(DrawContext dc) { if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (this.extent == null || !this.isExtentValid(dc)) { this.extent = dc.getGlobe().computeBoundingCylinder(dc.getVerticalExaggeration(), this.getSector()); this.globeStateKey = dc.getGlobe().getStateKey(dc); } return this.extent; } protected boolean isExtentValid(DrawContext dc) { return !(dc.getGlobe() == null || this.globeStateKey == null) && this.globeStateKey.equals(dc.getGlobe().getStateKey(dc)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -