protected static boolean isTileVisible( DrawContext dc, Tile tile, double minDistanceSquared, double maxDistanceSquared) { if (!tile.getSector().intersects(dc.getVisibleSector())) return false; View view = dc.getView(); Position eyePos = view.getEyePosition(); if (eyePos == null) return false; Angle lat = clampAngle( eyePos.getLatitude(), tile.getSector().getMinLatitude(), tile.getSector().getMaxLatitude()); Angle lon = clampAngle( eyePos.getLongitude(), tile.getSector().getMinLongitude(), tile.getSector().getMaxLongitude()); Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d); double distSquared = dc.getView().getEyePoint().distanceToSquared3(p); //noinspection RedundantIfStatement if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false; return true; }
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]); }
protected static boolean isServiceVisible(DrawContext dc, PlaceNameService placeNameService) { //noinspection SimplifiableIfStatement if (!placeNameService.isEnabled()) return false; return (dc.getVisibleSector() != null) && placeNameService.getMaskingSector().intersects(dc.getVisibleSector()); // // return // placeNameService.getExtent(dc).intersects(dc.getView().getFrustumInModelCoordinates()); }
protected static boolean isNameVisible( DrawContext dc, PlaceNameService service, Position namePosition) { double elevation = dc.getVerticalExaggeration() * namePosition.getElevation(); Vec4 namePoint = dc.getGlobe() .computePointFromPosition( namePosition.getLatitude(), namePosition.getLongitude(), elevation); Vec4 eyeVec = dc.getView().getEyePoint(); double dist = eyeVec.distanceTo3(namePoint); return dist >= service.getMinDisplayDistance() && dist <= service.getMaxDisplayDistance(); }
@Override protected void doRender(DrawContext dc) { if (this.frameTimestamp != dc.getFrameTimeStamp()) { this.assembleControlPoints(dc); this.frameTimestamp = dc.getFrameTimeStamp(); } this.markerRenderer.render(dc, this.controlPoints); if (this.annotation != null && isShowAnnotation()) { this.annotation.render(dc); } }
/** * Compute the lat/lon position of the view center * * @param dc the current DrawContext * @param view the current View * @return the ground position of the view center or null */ protected Position computeGroundPosition(DrawContext dc, View view) { if (view == null) return null; Position groundPos = view.computePositionFromScreenPoint( view.getViewport().getWidth() / 2, view.getViewport().getHeight() / 2); if (groundPos == null) return null; double elevation = dc.getGlobe().getElevation(groundPos.getLatitude(), groundPos.getLongitude()); return new Position( groundPos.getLatitude(), groundPos.getLongitude(), elevation * dc.getVerticalExaggeration()); }
protected void assembleControlPoints(DrawContext dc) { // Control points are re-computed each frame this.controlPoints = new ArrayList<Marker>(); this.assembleVertexControlPoints(dc); if (!dc.is2DGlobe()) this.assembleHeightControlPoints(); }
protected void requestTile(DrawContext dc, Tile tile) { Vec4 centroid = dc.getGlobe().computePointFromPosition(tile.getSector().getCentroid(), 0); if (this.getReferencePoint() != null) tile.setPriority(centroid.distanceTo3(this.getReferencePoint())); RequestTask task = new RequestTask(tile, this); this.getRequestQ().add(task); }
protected void assembleVertexControlPoints(DrawContext dc) { Terrain terrain = dc.getTerrain(); ExtrudedPolygon polygon = this.getPolygon(); Position refPos = polygon.getReferencePosition(); Vec4 refPoint = terrain.getSurfacePoint(refPos.getLatitude(), refPos.getLongitude(), 0); int altitudeMode = polygon.getAltitudeMode(); double height = polygon.getHeight(); Vec4 vaa = null; double vaaLength = 0; // used to compute independent length of each cap vertex double vaLength = 0; int i = 0; for (LatLon location : polygon.getOuterBoundary()) { Vec4 vert; // Compute the top/cap point. if (altitudeMode == WorldWind.CONSTANT || !(location instanceof Position)) { if (vaa == null) { // Compute the vector lengths of the top and bottom points at the reference position. vaa = refPoint.multiply3(height / refPoint.getLength3()); vaaLength = vaa.getLength3(); vaLength = refPoint.getLength3(); } // Compute the bottom point, which is on the terrain. vert = terrain.getSurfacePoint(location.getLatitude(), location.getLongitude(), 0); double delta = vaLength - vert.dot3(refPoint) / vaLength; vert = vert.add3(vaa.multiply3(1d + delta / vaaLength)); } else if (altitudeMode == WorldWind.RELATIVE_TO_GROUND) { vert = terrain.getSurfacePoint( location.getLatitude(), location.getLongitude(), ((Position) location).getAltitude()); } else // WorldWind.ABSOLUTE { vert = terrain .getGlobe() .computePointFromPosition( location.getLatitude(), location.getLongitude(), ((Position) location).getAltitude() * terrain.getVerticalExaggeration()); } Position vertexPosition = this.wwd.getModel().getGlobe().computePositionFromPoint(vert); this.controlPoints.add( new ControlPointMarker( MOVE_VERTEX_ACTION, vertexPosition, vert, this.vertexControlAttributes, i)); i++; } }
/** * Compute the view range footprint on the globe. * * @param dc the current <code>DrawContext</code> * @param steps the number of steps. * @return an array list of <code>LatLon</code> forming a closed shape. */ protected ArrayList<LatLon> computeViewFootPrint(DrawContext dc, int steps) { ArrayList<LatLon> positions = new ArrayList<LatLon>(); Position eyePos = dc.getView().getEyePosition(); Angle distance = Angle.fromRadians( Math.asin( dc.getView().getFarClipDistance() / (dc.getGlobe().getRadius() + eyePos.getElevation()))); if (distance.degrees > 10) { double headStep = 360d / steps; Angle heading = Angle.ZERO; for (int i = 0; i <= steps; i++) { LatLon p = LatLon.greatCircleEndPosition(eyePos, heading, distance); positions.add(p); heading = heading.addDegrees(headStep); } return positions; } else return null; }
/** * Computes the lat/lon of the pickPoint over the world map * * @param dc the current <code>DrawContext</code> * @param locationSW the screen location of the bottom left corner of the map * @param mapSize the world map screen dimension in pixels * @return the picked Position */ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimension mapSize) { Position pickPosition = null; Point pickPoint = dc.getPickPoint(); if (pickPoint != null) { Rectangle viewport = dc.getView().getViewport(); // Check if pickpoint is inside the map if (pickPoint.getX() >= locationSW.getX() && pickPoint.getX() < locationSW.getX() + mapSize.width && viewport.height - pickPoint.getY() >= locationSW.getY() && viewport.height - pickPoint.getY() < locationSW.getY() + mapSize.height) { double lon = (pickPoint.getX() - locationSW.getX()) / mapSize.width * 360 - 180; double lat = (viewport.height - pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90; double pickAltitude = 1000e3; pickPosition = new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), pickAltitude); } } return pickPosition; }
protected void doPick( DrawContext dc, Iterable<? extends Renderable> renderables, java.awt.Point pickPoint) { this.pickSupport.clearPickList(); this.pickSupport.beginPicking(dc); try { for (Renderable renderable : renderables) { // If the caller has specified their own Iterable, // then we cannot make any guarantees about its contents. if (renderable != null) { float[] inColor = new float[4]; dc.getGL().glGetFloatv(GL.GL_CURRENT_COLOR, inColor, 0); java.awt.Color color = dc.getUniquePickColor(); dc.getGL() .glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); try { renderable.render(dc); } catch (Exception e) { String msg = Logging.getMessage("generic.ExceptionWhilePickingRenderable"); Logging.logger().severe(msg); continue; // go on to next renderable } dc.getGL().glColor4fv(inColor, 0); if (renderable instanceof Locatable) { this.pickSupport.addPickableObject( color.getRGB(), renderable, ((Locatable) renderable).getPosition(), false); } else { this.pickSupport.addPickableObject(color.getRGB(), renderable); } } } this.pickSupport.resolvePick(dc, pickPoint, this); } finally { this.pickSupport.endPicking(dc); } }
@Override public void render(DrawContext dc) { if (dc.isPickingMode() && this.isResizeable()) return; // This is called twice: once during normal rendering, then again during ordered surface // rendering. During // normal renering we render both the interior and border shapes. During ordered surface // rendering, both // shapes are already added to the DrawContext and both will be individually processed. // Therefore we just // call our superclass behavior if (dc.isOrderedRenderingMode()) { super.render(dc); return; } if (!this.isResizeable()) { if (this.hasSelection()) { this.doRender(dc); } return; } PickedObjectList pos = dc.getPickedObjects(); PickedObject terrainObject = pos != null ? pos.getTerrainObject() : null; if (terrainObject == null) return; if (this.getStartPosition() != null) { Position end = terrainObject.getPosition(); if (!this.getStartPosition().equals(end)) { this.setEndPosition(end); this.setSector(Sector.boundingSector(this.getStartPosition(), this.getEndPosition())); this.doRender(dc); } } else { this.setStartPosition(pos.getTerrainObject().getPosition()); } }
protected boolean isNavSectorVisible( DrawContext dc, double minDistanceSquared, double maxDistanceSquared) { if (!navSector.intersects(dc.getVisibleSector())) return false; View view = dc.getView(); Position eyePos = view.getEyePosition(); if (eyePos == null) return false; // check for eyePos over globe if (Double.isNaN(eyePos.getLatitude().getDegrees()) || Double.isNaN(eyePos.getLongitude().getDegrees())) return false; Angle lat = clampAngle(eyePos.getLatitude(), navSector.getMinLatitude(), navSector.getMaxLatitude()); Angle lon = clampAngle( eyePos.getLongitude(), navSector.getMinLongitude(), navSector.getMaxLongitude()); Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d); double distSquared = dc.getView().getEyePoint().distanceToSquared3(p); //noinspection RedundantIfStatement if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false; return true; }
public void preRender(DrawContext dc) { // This is called twice: once during normal rendering, then again during ordered surface // rendering. During // normal renering we pre-render both the interior and border shapes. During ordered surface // rendering, both // shapes are already added to the DrawContext and both will be individually processed. // Therefore we just // call our superclass behavior if (dc.isOrderedRenderingMode()) { super.preRender(dc); return; } this.doPreRender(dc); }
protected Vec4 computeReferencePoint(DrawContext dc) { if (dc.getViewportCenterPosition() != null) return dc.getGlobe().computePointFromPosition(dc.getViewportCenterPosition()); java.awt.geom.Rectangle2D viewport = dc.getView().getViewport(); int x = (int) viewport.getWidth() / 2; for (int y = (int) (0.5 * viewport.getHeight()); y >= 0; y--) { Position pos = dc.getView().computePositionFromScreenPoint(x, y); if (pos == null) continue; return dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), 0d); } return null; }
@Override public void doRender(DrawContext dc) { // Delegate drawing to the ordered renderable list dc.addOrderedRenderable(this.orderedImage); }
@Override public void doPick(DrawContext dc, Point pickPoint) { // Delegate drawing to the ordered renderable list dc.addOrderedRenderable(this.orderedImage); }
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); } }