getRenderingExceptions()
{
return this.renderingExceptions;
}
+ @Override
public ScreenCreditController getScreenCreditController()
{
return screenCreditController;
}
+ @Override
public void setScreenCreditController(ScreenCreditController screenCreditController)
{
this.screenCreditController = screenCreditController;
}
/** {@inheritDoc} */
+ @Override
public GLRuntimeCapabilities getGLRuntimeCapabilities()
{
return this.glRuntimeCaps;
}
/** {@inheritDoc} */
+ @Override
public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
{
if (capabilities == null)
@@ -411,6 +440,7 @@ public void setDeferOrderedRendering(boolean deferOrderedRendering)
this.deferOrderedRendering = deferOrderedRendering;
}
+ @Override
public int repaint()
{
this.frameTime = System.currentTimeMillis();
@@ -635,8 +665,8 @@ protected void preRender(DrawContext dc)
protected void pickTerrain(DrawContext dc)
{
- if (dc.isPickingMode() && dc.getVisibleSector() != null && dc.getSurfaceGeometry() != null &&
- dc.getSurfaceGeometry().size() > 0)
+ if (dc.isPickingMode() && dc.getVisibleSector() != null && dc.getSurfaceGeometry() != null
+ && dc.getSurfaceGeometry().size() > 0)
{
this.pickPoints.clear();
if (dc.getPickPoint() != null)
@@ -757,7 +787,10 @@ else if (pol != null && pol.size() > 1)
// used to cull the number of colors that the draw context must consider with identifying the unique
// pick colors in the specified screen rectangle.
if (minAndMaxColorCodes == null)
- minAndMaxColorCodes = new int[] {colorCode, colorCode};
+ minAndMaxColorCodes = new int[]
+ {
+ colorCode, colorCode
+ };
else
{
if (minAndMaxColorCodes[0] > colorCode)
@@ -809,8 +842,8 @@ protected void pick(DrawContext dc)
this.lastPickedObjects = new PickedObjectList(dc.getPickedObjects());
this.lastObjectsInPickRect = new PickedObjectList(dc.getObjectsInPickRectangle());
- if (this.isDeepPickEnabled() &&
- (this.lastPickedObjects.hasNonTerrainObjects() || this.lastObjectsInPickRect.hasNonTerrainObjects()))
+ if (this.isDeepPickEnabled()
+ && (this.lastPickedObjects.hasNonTerrainObjects() || this.lastObjectsInPickRect.hasNonTerrainObjects()))
{
this.doDeepPick(dc);
}
@@ -957,8 +990,8 @@ protected void draw(DrawContext dc)
dc.setOrderedRenderingMode(false);
// Draw the diagnostic displays.
- if (dc.getSurfaceGeometry() != null && dc.getModel() != null && (dc.getModel().isShowWireframeExterior() ||
- dc.getModel().isShowWireframeInterior() || dc.getModel().isShowTessellationBoundingVolumes()))
+ if (dc.getSurfaceGeometry() != null && dc.getModel() != null && (dc.getModel().isShowWireframeExterior()
+ || dc.getModel().isShowWireframeInterior() || dc.getModel().isShowTessellationBoundingVolumes()))
{
Model model = dc.getModel();
@@ -994,7 +1027,6 @@ protected void draw(DrawContext dc)
*
* @param dc the relevant DrawContext
*/
- @SuppressWarnings({"UNUSED_SYMBOL", "UnusedDeclaration"})
protected void checkGLErrors(DrawContext dc)
{
GL gl = dc.getGL();
@@ -1010,7 +1042,6 @@ protected void checkGLErrors(DrawContext dc)
//**************************************************************//
//******************** Ordered Surface Renderable ************//
//**************************************************************//
-
protected void preRenderOrderedSurfaceRenderables(DrawContext dc)
{
if (dc.getOrderedSurfaceRenderables().isEmpty())
@@ -1125,9 +1156,9 @@ protected void drawCompositeSurfaceObjects(DrawContext dc)
if (tileCount == 0)
return;
- int attributeMask =
- GL2.GL_COLOR_BUFFER_BIT // For alpha test enable, blend enable, alpha func, blend func, blend ref.
- | GL2.GL_POLYGON_BIT; // For cull face enable, cull face, polygon mode.
+ int attributeMask
+ = GL2.GL_COLOR_BUFFER_BIT // For alpha test enable, blend enable, alpha func, blend func, blend ref.
+ | GL2.GL_POLYGON_BIT; // For cull face enable, cull face, polygon mode.
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
OGLStackHandler ogsh = new OGLStackHandler();
diff --git a/src/gov/nasa/worldwind/SceneController.java b/src/gov/nasa/worldwind/SceneController.java
index 2cbf20ee7b..7b93ad2664 100644
--- a/src/gov/nasa/worldwind/SceneController.java
+++ b/src/gov/nasa/worldwind/SceneController.java
@@ -128,7 +128,7 @@ public interface SceneController extends WWObject, Disposable
double getFrameTime();
/**
- * Specifies the current pick point in AWT screen coordinates, or null
to indicate that there is no
+ * Specifies the current pick point in GL surface screen coordinates, or null
to indicate that there is no
* pick point. Each frame, this scene controller determines which objects are drawn at the pick point and places
* them in a PickedObjectList. This list can be accessed by calling {@link #getPickedObjectList()}.
*
@@ -140,7 +140,7 @@ public interface SceneController extends WWObject, Disposable
void setPickPoint(Point pickPoint);
/**
- * Returns the current pick point in AWT screen coordinates.
+ * Returns the current pick point in GL surface coordinates.
*
* @return the current pick point, or null
if no pick point is current.
*
@@ -149,7 +149,7 @@ public interface SceneController extends WWObject, Disposable
Point getPickPoint();
/**
- * Specifies the current pick rectangle in AWT screen coordinates, or null
to indicate that there is no
+ * Specifies the current pick rectangle in GL surface coordinates, or null
to indicate that there is no
* pick rectangle. Each frame, this scene controller determines which objects intersect the pick rectangle and
* places them in a PickedObjectList. This list can be accessed by calling {@link #getObjectsInPickRectangle()}.
*
@@ -161,7 +161,7 @@ public interface SceneController extends WWObject, Disposable
void setPickRectangle(Rectangle pickRect);
/**
- * Returns the current pick rectangle in AWT screen coordinates.
+ * Returns the current pick rectangle in GL surface coordinates.
*
* @return the current pick rectangle, or null
if no pick rectangle is current.
*
diff --git a/src/gov/nasa/worldwind/WorldWindowImpl.java b/src/gov/nasa/worldwind/WorldWindowImpl.java
index 51da668096..d375bcba25 100644
--- a/src/gov/nasa/worldwind/WorldWindowImpl.java
+++ b/src/gov/nasa/worldwind/WorldWindowImpl.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -28,7 +28,6 @@
package gov.nasa.worldwind;
-import com.jogamp.nativewindow.ScalableSurface;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.cache.*;
import gov.nasa.worldwind.event.*;
@@ -68,6 +67,7 @@ public WorldWindowImpl()
* Causes resources used by the WorldWindow to be freed. The WorldWindow cannot be used once this method is
* called. An OpenGL context for the window must be current.
*/
+ @Override
public void shutdown()
{
WorldWind.getDataFileStore().removePropertyChangeListener(this);
@@ -104,6 +104,7 @@ public void shutdown()
sc.dispose();
}
+ @Override
public GpuResourceCache getGpuResourceCache()
{
return this.gpuResourceCache;
@@ -115,6 +116,7 @@ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
this.sceneController.setGpuResourceCache(this.gpuResourceCache);
}
+ @Override
public void setModel(Model model)
{
// model can be null, that's ok - it indicates no model.
@@ -122,11 +124,13 @@ public void setModel(Model model)
this.sceneController.setModel(model);
}
+ @Override
public Model getModel()
{
return this.sceneController != null ? this.sceneController.getModel() : null;
}
+ @Override
public void setView(View view)
{
// view can be null, that's ok - it indicates no view.
@@ -134,22 +138,26 @@ public void setView(View view)
this.sceneController.setView(view);
}
+ @Override
public View getView()
{
return this.sceneController != null ? this.sceneController.getView() : null;
}
+ @Override
public void setModelAndView(Model model, View view)
{
this.setModel(model);
this.setView(view);
}
+ @Override
public SceneController getSceneController()
{
return this.sceneController;
}
+ @Override
public void setSceneController(SceneController sc)
{
if (sc != null && this.getSceneController() != null)
@@ -160,30 +168,36 @@ public void setSceneController(SceneController sc)
this.sceneController = sc;
}
+ @Override
public InputHandler getInputHandler()
{
return this.inputHandler;
}
+ @Override
public void setInputHandler(InputHandler inputHandler)
{
this.inputHandler = inputHandler;
}
+ @Override
public void redraw()
{
}
+ @Override
public void redrawNow()
{
}
+ @Override
public void setPerFrameStatisticsKeys(Set keys)
{
if (this.sceneController != null)
this.sceneController.setPerFrameStatisticsKeys(keys);
}
+ @Override
public Collection getPerFrameStatistics()
{
if (this.sceneController == null || this.sceneController.getPerFrameStatistics() == null)
@@ -192,16 +206,19 @@ public Collection getPerFrameStatistics()
return this.sceneController.getPerFrameStatistics();
}
+ @Override
public PickedObjectList getObjectsAtCurrentPosition()
{
return null;
}
+ @Override
public PickedObjectList getObjectsInSelectionBox()
{
return null;
}
+ @Override
public Position getCurrentPosition()
{
if (this.sceneController == null)
@@ -243,11 +260,13 @@ protected PickedObjectList getCurrentBoxSelection()
return pol != null && pol.size() > 0 ? pol : null;
}
+ @Override
public void addRenderingListener(RenderingListener listener)
{
this.eventListeners.add(RenderingListener.class, listener);
}
+ @Override
public void removeRenderingListener(RenderingListener listener)
{
this.eventListeners.remove(RenderingListener.class, listener);
@@ -261,11 +280,13 @@ protected void callRenderingListeners(RenderingEvent event)
}
}
+ @Override
public void addPositionListener(PositionListener listener)
{
this.eventListeners.add(PositionListener.class, listener);
}
+ @Override
public void removePositionListener(PositionListener listener)
{
this.eventListeners.remove(PositionListener.class, listener);
@@ -275,6 +296,7 @@ protected void callPositionListeners(final PositionEvent event)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (PositionListener listener : eventListeners.getListeners(PositionListener.class))
@@ -285,11 +307,13 @@ public void run()
});
}
+ @Override
public void addSelectListener(SelectListener listener)
{
this.eventListeners.add(SelectListener.class, listener);
}
+ @Override
public void removeSelectListener(SelectListener listener)
{
this.eventListeners.remove(SelectListener.class, listener);
@@ -299,6 +323,7 @@ protected void callSelectListeners(final SelectEvent event)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (SelectListener listener : eventListeners.getListeners(SelectListener.class))
@@ -309,11 +334,13 @@ public void run()
});
}
+ @Override
public void addRenderingExceptionListener(RenderingExceptionListener listener)
{
this.eventListeners.add(RenderingExceptionListener.class, listener);
}
+ @Override
public void removeRenderingExceptionListener(RenderingExceptionListener listener)
{
this.eventListeners.remove(RenderingExceptionListener.class, listener);
@@ -323,6 +350,7 @@ protected void callRenderingExceptionListeners(final Throwable exception)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (RenderingExceptionListener listener : eventListeners.getListeners(
@@ -341,32 +369,4 @@ public static GpuResourceCache createGpuResourceCache()
long cacheSize = Configuration.getLongValue(AVKey.TEXTURE_CACHE_SIZE, FALLBACK_TEXTURE_CACHE_SIZE);
return new BasicGpuResourceCache((long) (0.8 * cacheSize), cacheSize);
}
-
- /**
- * Configures JOGL's surface pixel scaling on the specified
- * ScalableSurface
to ensure backward compatibility with
- * WorldWind applications developed prior to JOGL pixel scaling's
- * introduction.This method is used by GLCanvas
and
- * GLJPanel
to effectively disable JOGL's surface pixel scaling
- * by requesting a 1:1 scale.
- * Since v2.2.0, JOGL defaults to using high-dpi pixel scales where
- * possible. This causes WorldWind screen elements such as placemarks, the
- * compass, the world map, the view controls, and the scale bar (plus many
- * more) to appear smaller than they are intended to on screen. The high-dpi
- * default also has the effect of degrading WorldWind rendering performance.
- *
- * @param surface The surface to configure.
- */
- public static void configureIdentityPixelScale(ScalableSurface surface)
- {
- if (surface == null)
- {
- String message = Logging.getMessage("nullValue.SurfaceIsNull");
- Logging.logger().severe(message);
- throw new IllegalArgumentException(message);
- }
-
- float[] identityScale = new float[] {ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE};
- surface.setSurfaceScale(identityScale);
- }
}
diff --git a/src/gov/nasa/worldwind/awt/AWTInputHandler.java b/src/gov/nasa/worldwind/awt/AWTInputHandler.java
index 3697849cdc..4915cd6d77 100644
--- a/src/gov/nasa/worldwind/awt/AWTInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/AWTInputHandler.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -57,6 +57,7 @@ public class AWTInputHandler extends WWObjectImpl
protected boolean forceRedrawOnMousePressed = Configuration.getBooleanValue(AVKey.REDRAW_ON_MOUSE_PRESSED, false);
protected javax.swing.Timer hoverTimer = new javax.swing.Timer(600, new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent actionEvent)
{
if (AWTInputHandler.this.pickMatches(AWTInputHandler.this.hoverObjects))
@@ -75,6 +76,7 @@ public AWTInputHandler()
{
}
+ @Override
public void dispose()
{
this.hoverTimer.stop();
@@ -91,6 +93,7 @@ public void dispose()
this.objectsAtButtonPress = null;
}
+ @Override
public void setEventSource(WorldWindow newWorldWindow)
{
if (newWorldWindow != null && !(newWorldWindow instanceof Component))
@@ -139,6 +142,7 @@ public void setEventSource(WorldWindow newWorldWindow)
this.selectListener = new SelectListener()
{
+ @Override
public void selected(SelectEvent event)
{
if (event.getEventAction().equals(SelectEvent.ROLLOVER))
@@ -160,16 +164,19 @@ public void removeHoverSelectListener()
this.wwd.removeSelectListener(selectListener);
}
+ @Override
public WorldWindow getEventSource()
{
return this.wwd;
}
+ @Override
public void setHoverDelay(int delay)
{
this.hoverTimer.setDelay(delay);
}
+ @Override
public int getHoverDelay()
{
return this.hoverTimer.getDelay();
@@ -250,22 +257,25 @@ protected void setObjectsAtButtonPress(PickedObjectList objectsAtButtonPress)
this.objectsAtButtonPress = objectsAtButtonPress;
}
+ @Override
public boolean isForceRedrawOnMousePressed()
{
return forceRedrawOnMousePressed;
}
+ @Override
public void setForceRedrawOnMousePressed(boolean forceRedrawOnMousePressed)
{
this.forceRedrawOnMousePressed = forceRedrawOnMousePressed;
}
-/*
+
+ /*
public ViewInputHandler getViewInputHandler()
{
return viewInputHandler;
}
- */
-
+ */
+ @Override
public void keyTyped(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -286,6 +296,7 @@ public void keyTyped(KeyEvent keyEvent)
}
}
+ @Override
public void keyPressed(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -306,6 +317,7 @@ public void keyPressed(KeyEvent keyEvent)
}
}
+ @Override
public void keyReleased(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -326,7 +338,48 @@ public void keyReleased(KeyEvent keyEvent)
}
}
- public void mouseClicked(final MouseEvent mouseEvent)
+ /**
+ * Construct a mouse event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseEvent glMouseEvent(MouseEvent awtMouseEvent)
+ {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtMouseEvent.getPoint());
+ MouseEvent e = new MouseEvent(awtMouseEvent.getComponent(), awtMouseEvent.getID(),
+ awtMouseEvent.getWhen(), awtMouseEvent.getModifiersEx(),
+ GLmousePt[0], GLmousePt[1], awtMouseEvent.getClickCount(), awtMouseEvent.isPopupTrigger(),
+ awtMouseEvent.getButton());
+
+ if (awtMouseEvent.isConsumed()) // needed in case this method is overridden by a subclass
+ e.consume();
+
+ return e;
+ }
+
+ /**
+ * Construct a mouse wheel event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseWheelEvent glMouseWheelEvent(MouseWheelEvent awtEv)
+ {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtEv.getPoint());
+ MouseWheelEvent e = new MouseWheelEvent(awtEv.getComponent(), awtEv.getID(),
+ awtEv.getWhen(), awtEv.getModifiersEx(),
+ GLmousePt[0], GLmousePt[1], awtEv.getXOnScreen(), awtEv.getYOnScreen(),
+ awtEv.getClickCount(), awtEv.isPopupTrigger(),
+ awtEv.getScrollType(), awtEv.getScrollAmount(),
+ awtEv.getWheelRotation(), awtEv.getPreciseWheelRotation());
+
+ if (awtEv.isConsumed()) // needed in case this method is overridden by a subclass
+ e.consume();
+
+ return e;
+ }
+
+ @Override
+ public void mouseClicked(final MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
@@ -338,10 +391,11 @@ public void mouseClicked(final MouseEvent mouseEvent)
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
PickedObjectList pickedObjects = this.wwd.getObjectsAtCurrentPosition();
@@ -350,24 +404,26 @@ public void mouseClicked(final MouseEvent mouseEvent)
if (pickedObjects != null && pickedObjects.getTopPickedObject() != null
&& !pickedObjects.getTopPickedObject().isTerrain())
{
- // Something is under the cursor, so it's deemed "selected".
+ Point awtPt = awtMouseEvent.getPoint(); // AWT screen coordinates
+
+ // Something is under the cursor, so it's deemed "selected".
if (MouseEvent.BUTTON1 == mouseEvent.getButton())
{
if (mouseEvent.getClickCount() <= 1)
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
else
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_DOUBLE_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
}
else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.RIGHT_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
this.wwd.getView().firePropertyChange(AVKey.VIEW, null, this.wwd.getView());
@@ -381,20 +437,22 @@ else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
}
}
- public void mousePressed(MouseEvent mouseEvent)
+ @Override
+ public void mousePressed(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
// Determine if the mouse point has changed since the last mouse move event. This can happen if user switches to
// another window, moves the mouse, and then switches back to the WorldWind window.
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
boolean mousePointChanged = !mouseEvent.getPoint().equals(this.mousePoint);
this.mousePoint = mouseEvent.getPoint();
@@ -416,16 +474,18 @@ public void mousePressed(MouseEvent mouseEvent)
if (this.objectsAtButtonPress != null && objectsAtButtonPress.getTopPickedObject() != null
&& !this.objectsAtButtonPress.getTopPickedObject().isTerrain())
{
+ Point awtPt = awtMouseEvent.getPoint(); // AWT screen coordinates
+
// Something is under the cursor, so it's deemed "selected".
if (MouseEvent.BUTTON1 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_PRESS,
- mouseEvent, this.objectsAtButtonPress));
+ awtPt, mouseEvent, this.objectsAtButtonPress));
}
else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.RIGHT_PRESS,
- mouseEvent, this.objectsAtButtonPress));
+ awtPt, mouseEvent, this.objectsAtButtonPress));
}
// Initiate a repaint.
@@ -448,18 +508,20 @@ else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
}
}
- public void mouseReleased(MouseEvent mouseEvent)
+ @Override
+ public void mouseReleased(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.mousePoint = mouseEvent.getPoint();
this.callMouseReleasedListeners(mouseEvent);
if (!mouseEvent.isConsumed())
@@ -470,36 +532,40 @@ public void mouseReleased(MouseEvent mouseEvent)
this.cancelDrag();
}
- public void mouseEntered(MouseEvent mouseEvent)
+ @Override
+ public void mouseEntered(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.callMouseEnteredListeners(mouseEvent);
this.wwd.getView().getViewInputHandler().mouseEntered(mouseEvent);
this.cancelHover();
this.cancelDrag();
}
- public void mouseExited(MouseEvent mouseEvent)
+ @Override
+ public void mouseExited(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.callMouseExitedListeners(mouseEvent);
this.wwd.getView().getViewInputHandler().mouseExited(mouseEvent);
@@ -514,16 +580,18 @@ public void mouseExited(MouseEvent mouseEvent)
this.cancelDrag();
}
- public void mouseDragged(MouseEvent mouseEvent)
+ @Override
+ public void mouseDragged(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
return;
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
Point prevMousePoint = this.mousePoint;
this.mousePoint = mouseEvent.getPoint();
this.callMouseDraggedListeners(mouseEvent);
@@ -536,8 +604,9 @@ public void mouseDragged(MouseEvent mouseEvent)
&& !pickedObjects.getTopPickedObject().isTerrain()))
{
this.isDragging = true;
- DragSelectEvent selectEvent = new DragSelectEvent(this.wwd, SelectEvent.DRAG, mouseEvent, pickedObjects,
- prevMousePoint);
+ DragSelectEvent selectEvent = new DragSelectEvent(this.wwd, SelectEvent.DRAG,
+ awtMouseEvent.getPoint(), mouseEvent,
+ pickedObjects, prevMousePoint);
this.callSelectListeners(selectEvent);
// If no listener consumed the event, then cancel the drag.
@@ -562,18 +631,20 @@ public void mouseDragged(MouseEvent mouseEvent)
}
}
- public void mouseMoved(MouseEvent mouseEvent)
+ @Override
+ public void mouseMoved(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.mousePoint = mouseEvent.getPoint();
this.callMouseMovedListeners(mouseEvent);
@@ -590,24 +661,27 @@ public void mouseMoved(MouseEvent mouseEvent)
}
}
- public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent)
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent awtMouseWheelEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseWheelEvent == null)
+ if (awtMouseWheelEvent == null)
{
return;
}
+ MouseWheelEvent mouseWheelEvent = glMouseWheelEvent(awtMouseWheelEvent);
this.callMouseWheelMovedListeners(mouseWheelEvent);
if (!mouseWheelEvent.isConsumed())
this.wwd.getView().getViewInputHandler().mouseWheelMoved(mouseWheelEvent);
}
+ @Override
public void focusGained(FocusEvent focusEvent)
{
if (this.wwd == null)
@@ -623,6 +697,7 @@ public void focusGained(FocusEvent focusEvent)
this.wwd.getView().getViewInputHandler().focusGained(focusEvent);
}
+ @Override
public void focusLost(FocusEvent focusEvent)
{
if (this.wwd == null)
@@ -651,10 +726,10 @@ protected void doHover(boolean reset)
PickedObject hover = this.hoverObjects.getTopPickedObject();
PickedObject last = pickedObjects.getTopPickedObject();
- Object oh = hover == null ? null : hover.getObject() != null ? hover.getObject() :
- hover.getParentLayer() != null ? hover.getParentLayer() : null;
- Object ol = last == null ? null : last.getObject() != null ? last.getObject() :
- last.getParentLayer() != null ? last.getParentLayer() : null;
+ Object oh = hover == null ? null : hover.getObject() != null ? hover.getObject()
+ : hover.getParentLayer() != null ? hover.getParentLayer() : null;
+ Object ol = last == null ? null : last.getObject() != null ? last.getObject()
+ : last.getParentLayer() != null ? last.getParentLayer() : null;
if (oh != null && ol != null && oh.equals(ol))
{
return; // object picked is the hover object. don't do anything but wait for the timer to expire.
@@ -720,17 +795,19 @@ protected void cancelDrag()
if (this.isDragging)
{
this.callSelectListeners(new DragSelectEvent(this.wwd, SelectEvent.DRAG_END, null,
- this.objectsAtButtonPress, this.mousePoint));
+ null, this.objectsAtButtonPress, this.mousePoint));
}
this.isDragging = false;
}
+ @Override
public void addSelectListener(SelectListener listener)
{
this.eventListeners.add(SelectListener.class, listener);
}
+ @Override
public void removeSelectListener(SelectListener listener)
{
this.eventListeners.remove(SelectListener.class, listener);
@@ -744,41 +821,49 @@ protected void callSelectListeners(SelectEvent event)
}
}
+ @Override
public void addKeyListener(KeyListener listener)
{
this.eventListeners.add(KeyListener.class, listener);
}
+ @Override
public void removeKeyListener(KeyListener listener)
{
this.eventListeners.remove(KeyListener.class, listener);
}
+ @Override
public void addMouseListener(MouseListener listener)
{
this.eventListeners.add(MouseListener.class, listener);
}
+ @Override
public void removeMouseListener(MouseListener listener)
{
this.eventListeners.remove(MouseListener.class, listener);
}
+ @Override
public void addMouseMotionListener(MouseMotionListener listener)
{
this.eventListeners.add(MouseMotionListener.class, listener);
}
+ @Override
public void removeMouseMotionListener(MouseMotionListener listener)
{
this.eventListeners.remove(MouseMotionListener.class, listener);
}
+ @Override
public void addMouseWheelListener(MouseWheelListener listener)
{
this.eventListeners.add(MouseWheelListener.class, listener);
}
+ @Override
public void removeMouseWheelListener(MouseWheelListener listener)
{
this.eventListeners.remove(MouseWheelListener.class, listener);
@@ -872,6 +957,7 @@ protected void callMouseExitedListeners(MouseEvent event)
}
}
+ @Override
public void propertyChange(PropertyChangeEvent event)
{
if (this.wwd == null)
@@ -889,8 +975,8 @@ public void propertyChange(PropertyChangeEvent event)
return;
}
- if (event.getPropertyName().equals(AVKey.VIEW) &&
- (event.getSource() == this.getWorldWindow().getSceneController()))
+ if (event.getPropertyName().equals(AVKey.VIEW)
+ && (event.getSource() == this.getWorldWindow().getSceneController()))
{
this.wwd.getView().getViewInputHandler().setWorldWindow(this.wwd);
}
diff --git a/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java b/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
index b0783cd1f4..012457796b 100644
--- a/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
@@ -954,7 +954,7 @@ public double computeDragSlope(Point point1, Point point2, Vec4 vec1, Vec4 vec2)
return slope - 1.0;
}
- protected static Point constrainToSourceBounds(Point point, Object source)
+ protected static Point constrainToSourceBounds(Point point, WorldWindow source)
{
if (point == null)
return null;
@@ -962,19 +962,24 @@ protected static Point constrainToSourceBounds(Point point, Object source)
if (!(source instanceof Component))
return point;
- Component c = (Component) source;
+ // source.getHeight(), source.getWidth() are AWT coords height,
+ // but the 'point' is MouseEvent GL surface coords.
+ // Clamp to GL viewport size.
+ int glWidth = source.getView().getViewport().width;
+ int glHeight = source.getView().getViewport().height;
int x = (int) point.getX();
if (x < 0)
x = 0;
- if (x > c.getWidth())
- x = c.getWidth();
+ if (x >= glWidth)
+ x = glWidth - 1;
int y = (int) point.getY();
if (y < 0)
y = 0;
- if (y > c.getHeight())
- y = c.getHeight();
+
+ if (y >= glHeight)
+ y = glHeight - 1;
return new Point(x, y);
}
diff --git a/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java b/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
index e7af6f0ca6..2008517ca6 100644
--- a/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
@@ -219,10 +219,10 @@ public boolean inputActionPerformed(KeyEventState keys, String target,
Point movement = ViewUtil.subtract(point, lastPoint);
int headingInput = movement.x;
- int pitchInput = movement.y;
+ int pitchInput = -movement.y;
Point totalMovement = ViewUtil.subtract(point, mouseDownPoint);
int totalHeadingInput = totalMovement.x;
- int totalPitchInput = totalMovement.y;
+ int totalPitchInput = -totalMovement.y;
ViewInputAttributes.DeviceAttributes deviceAttributes =
getAttributes().getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE);
@@ -258,16 +258,16 @@ public boolean inputActionPerformed(AbstractViewInputHandler inputHandler,
return false;
}
+ // 'mouseEvent' is in GL surface coords, (0,0) in lower left of canvas
+ // Make down mouse movement increase the pitch.
Point movement = ViewUtil.subtract(point, lastPoint);
int headingInput = movement.x;
- int pitchInput = movement.y;
+ int pitchInput = -movement.y;
if (mouseDownPoint == null)
mouseDownPoint = lastPoint;
Point totalMovement = ViewUtil.subtract(point, mouseDownPoint);
int totalHeadingInput = totalMovement.x;
- int totalPitchInput = totalMovement.y;
-
-
+ int totalPitchInput = -totalMovement.y;
ViewInputAttributes.DeviceAttributes deviceAttributes =
getAttributes().getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE);
diff --git a/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java b/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
index 8a9942751b..3fb63c14ba 100644
--- a/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
+++ b/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
@@ -94,7 +94,6 @@ public WorldWindowGLCanvas()
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -132,7 +131,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith)
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -172,7 +170,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -216,7 +213,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -227,7 +223,8 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
}
}
- public void propertyChange(PropertyChangeEvent evt)
+ @Override
+ public void propertyChange(PropertyChangeEvent evt)
{
if(this.wwd == evt.getSource())
this.firePropertyChange(evt);
@@ -237,7 +234,8 @@ public void propertyChange(PropertyChangeEvent evt)
this.shutdown();
}
- public void shutdown()
+ @Override
+ public void shutdown()
{
WorldWind.removePropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
this.wwd.shutdown();
@@ -267,12 +265,14 @@ protected void createDefaultInputHandler()
this.setInputHandler((InputHandler) WorldWind.createConfigurationComponent(AVKey.INPUT_HANDLER_CLASS_NAME));
}
- public InputHandler getInputHandler()
+ @Override
+ public InputHandler getInputHandler()
{
return this.wwd.getInputHandler();
}
- public void setInputHandler(InputHandler inputHandler)
+ @Override
+ public void setInputHandler(InputHandler inputHandler)
{
if (this.wwd.getInputHandler() != null)
this.wwd.getInputHandler().setEventSource(null); // remove this window as a source of events
@@ -282,153 +282,182 @@ public void setInputHandler(InputHandler inputHandler)
inputHandler.setEventSource(this);
}
- public SceneController getSceneController()
+ @Override
+ public SceneController getSceneController()
{
return this.wwd.getSceneController();
}
- public void setSceneController(SceneController sceneController)
+ @Override
+ public void setSceneController(SceneController sceneController)
{
this.wwd.setSceneController(sceneController);
}
- public GpuResourceCache getGpuResourceCache()
+ @Override
+ public GpuResourceCache getGpuResourceCache()
{
return this.wwd.getGpuResourceCache();
}
- public void redraw()
+ @Override
+ public void redraw()
{
this.repaint();
}
- public void redrawNow()
+ @Override
+ public void redrawNow()
{
this.wwd.redrawNow();
}
- public void setModel(Model model)
+ @Override
+ public void setModel(Model model)
{
// null models are permissible
this.wwd.setModel(model);
}
- public Model getModel()
+ @Override
+ public Model getModel()
{
return this.wwd.getModel();
}
- public void setView(View view)
+ @Override
+ public void setView(View view)
{
// null views are permissible
if (view != null)
this.wwd.setView(view);
}
- public View getView()
+ @Override
+ public View getView()
{
return this.wwd.getView();
}
- public void setModelAndView(Model model, View view)
+ @Override
+ public void setModelAndView(Model model, View view)
{ // null models/views are permissible
this.setModel(model);
this.setView(view);
}
- public void addRenderingListener(RenderingListener listener)
+ @Override
+ public void addRenderingListener(RenderingListener listener)
{
this.wwd.addRenderingListener(listener);
}
- public void removeRenderingListener(RenderingListener listener)
+ @Override
+ public void removeRenderingListener(RenderingListener listener)
{
this.wwd.removeRenderingListener(listener);
}
- public void addSelectListener(SelectListener listener)
+ @Override
+ public void addSelectListener(SelectListener listener)
{
this.wwd.getInputHandler().addSelectListener(listener);
this.wwd.addSelectListener(listener);
}
- public void removeSelectListener(SelectListener listener)
+ @Override
+ public void removeSelectListener(SelectListener listener)
{
this.wwd.getInputHandler().removeSelectListener(listener);
this.wwd.removeSelectListener(listener);
}
- public void addPositionListener(PositionListener listener)
+ @Override
+ public void addPositionListener(PositionListener listener)
{
this.wwd.addPositionListener(listener);
}
- public void removePositionListener(PositionListener listener)
+ @Override
+ public void removePositionListener(PositionListener listener)
{
this.wwd.removePositionListener(listener);
}
- public void addRenderingExceptionListener(RenderingExceptionListener listener)
+ @Override
+ public void addRenderingExceptionListener(RenderingExceptionListener listener)
{
this.wwd.addRenderingExceptionListener(listener);
}
- public void removeRenderingExceptionListener(RenderingExceptionListener listener)
+ @Override
+ public void removeRenderingExceptionListener(RenderingExceptionListener listener)
{
this.wwd.removeRenderingExceptionListener(listener);
}
- public Position getCurrentPosition()
+ @Override
+ public Position getCurrentPosition()
{
return this.wwd.getCurrentPosition();
}
- public PickedObjectList getObjectsAtCurrentPosition()
+ @Override
+ public PickedObjectList getObjectsAtCurrentPosition()
{
return this.wwd.getSceneController() != null ? this.wwd.getSceneController().getPickedObjectList() : null;
}
- public PickedObjectList getObjectsInSelectionBox()
+ @Override
+ public PickedObjectList getObjectsInSelectionBox()
{
return this.wwd.getSceneController() != null ? this.wwd.getSceneController().getObjectsInPickRectangle() : null;
}
- public Object setValue(String key, Object value)
+ @Override
+ public Object setValue(String key, Object value)
{
return this.wwd.setValue(key, value);
}
- public AVList setValues(AVList avList)
+ @Override
+ public AVList setValues(AVList avList)
{
return this.wwd.setValues(avList);
}
- public Object getValue(String key)
+ @Override
+ public Object getValue(String key)
{
return this.wwd.getValue(key);
}
- public Collection getValues()
+ @Override
+ public Collection getValues()
{
return this.wwd.getValues();
}
- public Set> getEntries()
+ @Override
+ public Set> getEntries()
{
return this.wwd.getEntries();
}
- public String getStringValue(String key)
+ @Override
+ public String getStringValue(String key)
{
return this.wwd.getStringValue(key);
}
- public boolean hasKey(String key)
+ @Override
+ public boolean hasKey(String key)
{
return this.wwd.hasKey(key);
}
- public Object removeKey(String key)
+ @Override
+ public Object removeKey(String key)
{
return this.wwd.removeKey(key);
}
@@ -463,28 +492,53 @@ public void firePropertyChange(String propertyName, Object oldValue, Object newV
super.firePropertyChange(propertyName, oldValue, newValue);
}
- public void firePropertyChange(PropertyChangeEvent propertyChangeEvent)
+ @Override
+ public void firePropertyChange(PropertyChangeEvent propertyChangeEvent)
{
this.wwd.firePropertyChange(propertyChangeEvent);
}
- public AVList copy()
+ @Override
+ public AVList copy()
{
return this.wwd.copy();
}
- public AVList clearList()
+ @Override
+ public AVList clearList()
{
return this.wwd.clearList();
}
- public void setPerFrameStatisticsKeys(Set keys)
+ @Override
+ public void setPerFrameStatisticsKeys(Set keys)
{
this.wwd.setPerFrameStatisticsKeys(keys);
}
- public Collection getPerFrameStatistics()
+ @Override
+ public Collection getPerFrameStatistics()
{
return this.wwd.getPerFrameStatistics();
}
+
+ /**
+ * @return current mouse pointer position in GL surface screen coordinates.
+ */
+ @Override
+ public Point getMousePosition() throws HeadlessException {
+ Point mpos = super.getMousePosition();
+ int [] awtPt = { mpos.x, mpos.y };
+
+ if (wwd.getContext() == null) return mpos;
+
+ GLDrawable drawable = wwd.getContext().getGLDrawable();
+ if (drawable == null) return mpos;
+
+ // Convert to GL surface coordinates
+ int [] glSurfacePt = drawable.getNativeSurface().convertToPixelUnits(awtPt);
+ int glSurfaceHeight = drawable.getSurfaceHeight();
+ glSurfacePt[1] = glSurfaceHeight - glSurfacePt[1] - 1;
+ return new Point(glSurfacePt[0], glSurfacePt[1]);
+ }
}
diff --git a/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java b/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
index 5630b5b874..0b2a37322c 100644
--- a/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
+++ b/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
@@ -93,7 +93,6 @@ public WorldWindowGLJPanel()
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -131,7 +130,6 @@ public WorldWindowGLJPanel(WorldWindow shareWith)
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -175,7 +173,6 @@ public WorldWindowGLJPanel(WorldWindow shareWith, GLCapabilities capabilities,
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
diff --git a/src/gov/nasa/worldwind/drag/DragContext.java b/src/gov/nasa/worldwind/drag/DragContext.java
index 6623902e88..935f2c31b4 100644
--- a/src/gov/nasa/worldwind/drag/DragContext.java
+++ b/src/gov/nasa/worldwind/drag/DragContext.java
@@ -41,16 +41,16 @@
public class DragContext
{
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin.
+ * In accordance with the GL surface coordinates the top left point of the window is the origin.
*/
protected Point point;
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin. This point is the
+ * In accordance with the GL surface coordinates the top left point of the window is the origin. This point is the
* previous screen point.
*/
protected Point previousPoint;
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin. This point refers
+ * In accordance with the GL surface coordinates the top left point of the window is the origin. This point refers
* to the initial point of the drag event.
*/
protected Point initialPoint;
@@ -81,9 +81,9 @@ public DragContext()
}
/**
- * Returns the current screen point with the origin at the top left corner of the window.
+ * Returns the current GL surface point with the origin at the top left corner of the window.
*
- * @return the current screen point.
+ * @return the current GL surface point.
*/
public Point getPoint()
{
@@ -91,9 +91,9 @@ public Point getPoint()
}
/**
- * Set the {@link DragContext} current screen point.
+ * Set the {@link DragContext} current GL surface point.
*
- * @param point the point to assign to the current screen point.
+ * @param point the point to assign to the current GL surface point.
*
* @throws IllegalArgumentException if the point is null.
*/
@@ -110,7 +110,7 @@ public void setPoint(Point point)
}
/**
- * Returns the previous screen point with the origin at the top left corner of the window.
+ * Returns the previous GL surface point with the origin at the top left corner of the window.
*
* @return the previous point.
*/
@@ -120,9 +120,9 @@ public Point getPreviousPoint()
}
/**
- * Set the {@link DragContext} previous screen point.
+ * Set the {@link DragContext} previous GL surface point.
*
- * @param previousPoint the screen point to assign to the previous screen point.
+ * @param previousPoint the GL surface point to assign to the previous screen point.
*
* @throws IllegalArgumentException if the previousPoint is null.
*/
@@ -139,10 +139,10 @@ public void setPreviousPoint(Point previousPoint)
}
/**
- * Returns the initial screen point with the origin at the top left corner of the window. The initial point is the
- * screen point at the initiation of the drag event.
+ * Returns the initial GL surface point with the origin at the top left corner of the window. The initial point is the
+ * GL surface point at the initiation of the drag event.
*
- * @return the initial screen point.
+ * @return the initial GL surface point.
*/
public Point getInitialPoint()
{
@@ -150,9 +150,9 @@ public Point getInitialPoint()
}
/**
- * Set the {@link DragContext} initial screen point.
+ * Set the {@link DragContext} initial GL surface point.
*
- * @param initialPoint the screen point to assign to the initial screen point.
+ * @param initialPoint the GL surface point to assign to the initial screen point.
*
* @throws IllegalArgumentException if the initialPoint is null.
*/
diff --git a/src/gov/nasa/worldwind/drag/DraggableSupport.java b/src/gov/nasa/worldwind/drag/DraggableSupport.java
index 3a5e7b52a5..7af85f8eb6 100644
--- a/src/gov/nasa/worldwind/drag/DraggableSupport.java
+++ b/src/gov/nasa/worldwind/drag/DraggableSupport.java
@@ -428,9 +428,7 @@ protected Vec4 computeScreenOffsetFromReferencePosition(Position dragObjectRefer
Vec4 screenPointOffset = new Vec4(
dragContext.getInitialPoint().getX() - dragObjectScreenPoint.getX(),
- dragContext.getInitialPoint().getY() - (
- dragContext.getView().getViewport().getHeight()
- - dragObjectScreenPoint.getY() - 1.0)
+ dragContext.getInitialPoint().getY() - dragObjectScreenPoint.getY()
);
return screenPointOffset;
diff --git a/src/gov/nasa/worldwind/event/DragSelectEvent.java b/src/gov/nasa/worldwind/event/DragSelectEvent.java
index fcd36fe33a..c694b58f1b 100644
--- a/src/gov/nasa/worldwind/event/DragSelectEvent.java
+++ b/src/gov/nasa/worldwind/event/DragSelectEvent.java
@@ -42,10 +42,11 @@ public class DragSelectEvent extends SelectEvent
{
private final java.awt.Point previousPickPoint;
- public DragSelectEvent(Object source, String eventAction, MouseEvent mouseEvent, PickedObjectList pickedObjects,
- java.awt.Point previousPickPoint)
+ public DragSelectEvent(Object source, String eventAction, java.awt.Point awtPt, MouseEvent mouseEvent,
+ PickedObjectList pickedObjects,
+ java.awt.Point previousPickPoint)
{
- super(source, eventAction, mouseEvent, pickedObjects);
+ super(source, eventAction, awtPt, mouseEvent, pickedObjects);
this.previousPickPoint = previousPickPoint;
}
diff --git a/src/gov/nasa/worldwind/event/SelectEvent.java b/src/gov/nasa/worldwind/event/SelectEvent.java
index ac07024c64..1804356111 100644
--- a/src/gov/nasa/worldwind/event/SelectEvent.java
+++ b/src/gov/nasa/worldwind/event/SelectEvent.java
@@ -65,7 +65,6 @@
* @author tag
* @version $Id: SelectEvent.java 1171 2013-02-11 21:45:02Z dcollins $
*/
-@SuppressWarnings({"StringEquality"})
public class SelectEvent extends WWEvent
{
/** The user clicked the left mouse button while the cursor was over picked object. */
@@ -96,24 +95,26 @@ public class SelectEvent extends WWEvent
* The user has selected one or more of objects using a selection box. A box rollover event is generated every frame
* if one or more objects intersect the box, in which case the event's pickedObjects list contain the selected
* objects. A box rollover event is generated once when the selection becomes empty, in which case the event's
- * pickedObjects is null
. In either case, the event's pickRect contains the selection box bounds in AWT
- * screen coordinates.
+ * pickedObjects is null
. In either case, the event's pickRect contains the
+ * selection box bounds in GL surface coordinates.
*/
public static final String BOX_ROLLOVER = "gov.nasa.worldwind.SelectEvent.BoxRollover";
private final String eventAction;
- private final Point pickPoint;
- private final Rectangle pickRect;
- private final MouseEvent mouseEvent;
+ private final Point pickPoint; // GL surface coordinates
+ private final Rectangle pickRect; // GL surface coordinates
+ private final MouseEvent mouseEvent; // GL surface coordinates
+ private final Point awtMousePt; // AWT screen coordinates
private final PickedObjectList pickedObjects;
- public SelectEvent(Object source, String eventAction, MouseEvent mouseEvent, PickedObjectList pickedObjects)
+ public SelectEvent(Object source, String eventAction, Point awtPt, MouseEvent mouseEvent, PickedObjectList pickedObjects)
{
super(source);
this.eventAction = eventAction;
this.pickPoint = mouseEvent != null ? mouseEvent.getPoint() : null;
this.pickRect = null;
this.mouseEvent = mouseEvent;
+ this.awtMousePt = awtPt;
this.pickedObjects = pickedObjects;
}
@@ -124,6 +125,7 @@ public SelectEvent(Object source, String eventAction, Point pickPoint, PickedObj
this.pickPoint = pickPoint;
this.pickRect = null;
this.mouseEvent = null;
+ this.awtMousePt = null;
this.pickedObjects = pickedObjects;
}
@@ -134,6 +136,7 @@ public SelectEvent(Object source, String eventAction, Rectangle pickRectangle, P
this.pickPoint = null;
this.pickRect = pickRectangle;
this.mouseEvent = null;
+ this.awtMousePt = null;
this.pickedObjects = pickedObjects;
}
@@ -151,6 +154,10 @@ public String getEventAction()
return this.eventAction != null ? this.eventAction : "gov.nasa.worldwind.SelectEvent.UnknownEventAction";
}
+ public Point getAwtMousePt() {
+ return awtMousePt;
+ }
+
public Point getPickPoint()
{
return this.pickPoint;
diff --git a/src/gov/nasa/worldwind/geom/LatLon.java b/src/gov/nasa/worldwind/geom/LatLon.java
index acc1e29a7b..30e3385205 100644
--- a/src/gov/nasa/worldwind/geom/LatLon.java
+++ b/src/gov/nasa/worldwind/geom/LatLon.java
@@ -1272,6 +1272,7 @@ public static boolean locationsCrossDateLine(Iterable extends LatLon> location
LatLon pos = null;
for (LatLon posNext : locations)
{
+ if (posNext == null) break;
if (pos != null)
{
// A segment cross the line if end pos have different longitude signs
diff --git a/src/gov/nasa/worldwind/geom/Sector.java b/src/gov/nasa/worldwind/geom/Sector.java
index 5b1e73092c..9a38490d96 100644
--- a/src/gov/nasa/worldwind/geom/Sector.java
+++ b/src/gov/nasa/worldwind/geom/Sector.java
@@ -284,6 +284,7 @@ public static Sector boundingSector(Iterable extends LatLon> locations) {
double maxLon = Angle.NEG180.getDegrees();
for (LatLon p : locations) {
+ if (p == null) break;
double lat = p.getLatitude().getDegrees();
if (lat < minLat) {
minLat = lat;
diff --git a/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java b/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
index 479cf7fbe6..d5ccf17d09 100644
--- a/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
+++ b/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -132,7 +132,10 @@ public Globe getGlobe()
return this.globe;
}
- @SuppressWarnings({"RedundantIfStatement"})
+ @SuppressWarnings(
+ {
+ "RedundantIfStatement"
+ })
@Override
public boolean equals(Object o)
{
@@ -145,8 +148,8 @@ public boolean equals(Object o)
if (Double.compare(stateKey.verticalExaggeration, verticalExaggeration) != 0)
return false;
- if (elevationModel != null ? !elevationModel.equals(stateKey.elevationModel) :
- stateKey.elevationModel != null)
+ if (elevationModel != null ? !elevationModel.equals(stateKey.elevationModel)
+ : stateKey.elevationModel != null)
return false;
if (globe != null ? !globe.equals(stateKey.globe) : stateKey.globe != null)
return false;
@@ -238,7 +241,6 @@ public double getRadiusAt(Angle latitude, Angle longitude)
// observing that the length of the ellipsoidal point at the specified latitude and longitude indicates the
// radius at that location. The formula for the length of the ellipsoidal point was then converted into the
// simplified form below.
-
double sinLat = Math.sin(latitude.radians);
double rpm = this.equatorialRadius / Math.sqrt(1.0 - this.es * sinLat * sinLat);
@@ -294,7 +296,10 @@ public double[] getMinAndMaxElevations(Angle latitude, Angle longitude)
}
return this.elevationModel != null ? this.elevationModel.getExtremeElevations(latitude, longitude)
- : new double[] {0, 0};
+ : new double[]
+ {
+ 0, 0
+ };
}
public double[] getMinAndMaxElevations(Sector sector)
@@ -306,7 +311,10 @@ public double[] getMinAndMaxElevations(Sector sector)
throw new IllegalArgumentException(message);
}
- return this.elevationModel != null ? this.elevationModel.getExtremeElevations(sector) : new double[] {0, 0};
+ return this.elevationModel != null ? this.elevationModel.getExtremeElevations(sector) : new double[]
+ {
+ 0, 0
+ };
}
public Extent getExtent()
@@ -347,7 +355,6 @@ protected Intersection[] intersect(Line line, double equRadius, double polRadius
return null;
// Taken from Lengyel, 2Ed., Section 5.2.3, page 148.
-
double m = equRadius / polRadius; // "ratio of the x semi-axis length to the y semi-axis length"
double n = 1d; // "ratio of the x semi-axis length to the z semi-axis length"
double m2 = m * m;
@@ -373,16 +380,25 @@ protected Intersection[] intersect(Line line, double equRadius, double polRadius
if (discriminant == 0)
{
Vec4 p = line.getPointAt((-b - discriminantRoot) / (2 * a));
- return new Intersection[] {new Intersection(p, true)};
+ return new Intersection[]
+ {
+ new Intersection(p, true)
+ };
}
else // (discriminant > 0)
{
Vec4 near = line.getPointAt((-b - discriminantRoot) / (2 * a));
Vec4 far = line.getPointAt((-b + discriminantRoot) / (2 * a));
if (c >= 0) // Line originates outside the Globe.
- return new Intersection[] {new Intersection(near, false), new Intersection(far, false)};
+ return new Intersection[]
+ {
+ new Intersection(near, false), new Intersection(far, false)
+ };
else // Line originates inside the Globe.
- return new Intersection[] {new Intersection(far, false)};
+ return new Intersection[]
+ {
+ new Intersection(far, false)
+ };
}
}
@@ -492,7 +508,10 @@ public double[] getElevations(Sector sector, List extends LatLon> latLons, dou
double[] elevations)
{
if (this.elevationModel == null)
- return new double[] {0};
+ return new double[]
+ {
+ 0
+ };
double[] resolution = this.elevationModel.getElevations(sector, latLons, targetResolution, elevations);
@@ -508,6 +527,16 @@ public double[] getElevations(Sector sector, List extends LatLon> latLons, dou
return resolution;
}
+ /**
+ * Get the EGM96 offset class for this globe.
+ *
+ * @return The EGM96 offset class for this globe.
+ */
+ public EGM96 getEGM96()
+ {
+ return this.egm96;
+ }
+
public double getElevation(Angle latitude, Angle longitude)
{
if (latitude == null || longitude == null)
@@ -909,7 +938,8 @@ protected Vec4 geodeticToEllipsoidal(Angle latitude, Angle longitude, double met
double cosLon = Math.cos(longitude.radians);
double sinLon = Math.sin(longitude.radians);
- double rpm = // getRadius (in meters) of vertical in prime meridian
+ double rpm
+ = // getRadius (in meters) of vertical in prime meridian
this.equatorialRadius / Math.sqrt(1.0 - this.es * sinLat * sinLat);
double x = (rpm + metersElevation) * cosLat * sinLon;
@@ -1035,7 +1065,6 @@ protected void geodeticToCartesian(Sector sector, int numLat, int numLon, double
//
// return Position.fromRadians(lat, lon, elevation);
// }
-
/**
* Compute the geographic position to corresponds to a Cartesian point.
*
@@ -1059,7 +1088,10 @@ protected Position cartesianToGeodetic(Vec4 cart)
*
* @see #geodeticToEllipsoidal(gov.nasa.worldwind.geom.Angle, gov.nasa.worldwind.geom.Angle, double)
*/
- @SuppressWarnings({"SuspiciousNameCombination"})
+ @SuppressWarnings(
+ {
+ "SuspiciousNameCombination"
+ })
protected Position ellipsoidalToGeodetic(Vec4 cart)
{
// Contributed by Nathan Kronenfeld. Integrated 1/24/2011. Brings this calculation in line with Vermeille's
@@ -1370,4 +1402,4 @@ public static ElevationModel makeElevationModel(String key, String defaultValue)
Object configSource = Configuration.getStringValue(key, defaultValue);
return (ElevationModel) BasicFactory.create(AVKey.ELEVATION_MODEL_FACTORY, configSource);
}
-}
\ No newline at end of file
+}
diff --git a/src/gov/nasa/worldwind/globes/Globe.java b/src/gov/nasa/worldwind/globes/Globe.java
index b1bb238d7f..72b369ad69 100644
--- a/src/gov/nasa/worldwind/globes/Globe.java
+++ b/src/gov/nasa/worldwind/globes/Globe.java
@@ -39,7 +39,7 @@
* elevations for geographic positions on the surface of the globe. Globe provides methods for converting geographic
* positions (latitude, longitude, and elevation) to cartesian coordinates, and for converting cartesian to geographic.
* The origin and orientation of the cartesian coordinate system are determined by implementations of this interface.
- * Computations in Cartesian Coordinates
+ * Computations in Cartesian Coordinates
*
* Globe provides methods for performing computations in the coordinate system represented by a globe's surface in
* cartesian coordinates. These methods perform work with respect to the globe's actual shape in 3D cartesian
@@ -51,7 +51,7 @@
* #computeSurfaceNormalAtLocation(gov.nasa.worldwind.geom.Angle, gov.nasa.worldwind.geom.Angle)}
{@link
* #computeSurfaceOrientationAtPosition(gov.nasa.worldwind.geom.Angle, gov.nasa.worldwind.geom.Angle, double)}
*
- * Computations in Ellipsoidal Coordinates
+ * Computations in Ellipsoidal Coordinates
*
* Globe provides methods for performing computation on the ellipsoid represented by a globe's equatorial radius and its
* polar radius. These methods perform work with respect to the ellipsoid in 3D cartesian coordinates. Calling any of
diff --git a/src/gov/nasa/worldwind/layers/CompassLayer.java b/src/gov/nasa/worldwind/layers/CompassLayer.java
index 2c4bcb7cf8..0116a3fcf6 100644
--- a/src/gov/nasa/worldwind/layers/CompassLayer.java
+++ b/src/gov/nasa/worldwind/layers/CompassLayer.java
@@ -67,17 +67,20 @@ public class CompassLayer extends AbstractLayer
protected class OrderedIcon implements OrderedRenderable
{
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0;
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
CompassLayer.this.draw(dc);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
CompassLayer.this.draw(dc);
}
@@ -295,7 +298,8 @@ public void setLocationOffset(Vec4 locationOffset)
this.locationOffset = locationOffset;
}
- protected void doRender(DrawContext dc)
+ @Override
+ protected void doRender(DrawContext dc)
{
if (dc.isContinuous2DGlobe() && this.frameStampForDrawing == dc.getFrameTimeStamp())
return;
@@ -305,7 +309,8 @@ protected void doRender(DrawContext dc)
this.frameStampForDrawing = dc.getFrameTimeStamp();
}
- protected void doPick(DrawContext dc, Point pickPoint)
+ @Override
+ protected void doPick(DrawContext dc, Point pickPoint)
{
if (dc.isContinuous2DGlobe() && this.frameStampForPicking == dc.getFrameTimeStamp())
return;
@@ -414,7 +419,7 @@ protected void draw(DrawContext dc)
Vec4 center = new Vec4(locationSW.x + width * scale / 2, locationSW.y + height * scale / 2,
0);
double px = dc.getPickPoint().x - center.x;
- double py = viewport.getHeight() - dc.getPickPoint().y - center.y;
+ double py = dc.getPickPoint().y - center.y;
Angle pickHeading = Angle.fromRadians(Math.atan2(px, py));
pickHeading = pickHeading.degrees >= 0 ? pickHeading : pickHeading.addDegrees(360);
po.setValue("Heading", pickHeading);
diff --git a/src/gov/nasa/worldwind/layers/ScalebarLayer.java b/src/gov/nasa/worldwind/layers/ScalebarLayer.java
index 03f495b886..6cfd8af978 100644
--- a/src/gov/nasa/worldwind/layers/ScalebarLayer.java
+++ b/src/gov/nasa/worldwind/layers/ScalebarLayer.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java b/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
index d675ad6699..149ab8c2eb 100644
--- a/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
+++ b/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.view.orbit.OrbitView;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.beans.PropertyChangeEvent;
@@ -148,7 +150,6 @@ public TerrainProfileLayer() {
*
* @return true if the profile graph is minimized.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean getIsMinimized() {
return this.isMinimized;
}
@@ -171,7 +172,6 @@ public void setIsMinimized(boolean state) {
*
* @return true if the profile graph is maximized.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean getIsMaximized() {
return this.isMaximized;
}
@@ -262,7 +262,6 @@ public double getOpacity() {
*
* @return the graphic-to-viewport scale factor.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public double getToViewportScale() {
return toViewportScale;
}
@@ -275,7 +274,6 @@ public double getToViewportScale() {
*
* @param toViewportScale the graphic to viewport scale factor.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setToViewportScale(double toViewportScale) {
this.toViewportScale = toViewportScale;
}
@@ -305,7 +303,6 @@ public void setPosition(String position) {
*
* @return the screen location of the graph center if set (can be null).
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Point getLocationCenter() {
return this.locationCenter;
}
@@ -325,7 +322,6 @@ public void setLocationCenter(Point point) {
*
* @return the location offset. Will be null if no offset has been specified.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Vec4 getLocationOffset() {
return locationOffset;
}
@@ -349,7 +345,6 @@ public void setLocationOffset(Vec4 locationOffset) {
*
* @return the layer's resize behavior.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public String getResizeBehavior() {
return resizeBehavior;
}
@@ -365,7 +360,6 @@ public String getResizeBehavior() {
*
* @param resizeBehavior the desired resize behavior
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setResizeBehavior(String resizeBehavior) {
this.resizeBehavior = resizeBehavior;
}
@@ -384,7 +378,6 @@ public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
}
- @SuppressWarnings({"UnusedDeclaration"})
public String getUnit() {
return this.unit;
}
@@ -503,7 +496,6 @@ public double getProfileLenghtFactor() {
*
* @return the profile start position lat/lon.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public LatLon getStartLatLon() {
return this.startLatLon;
}
@@ -527,7 +519,6 @@ public void setStartLatLon(LatLon latLon) {
*
* @return the profile end position lat/lon.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public LatLon getEndLatLon() {
return this.endLatLon;
}
@@ -551,7 +542,6 @@ public void setEndLatLon(LatLon latLon) {
*
* @return the number of elevation samples in the profile.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public int getSamples() {
return this.samples;
}
@@ -561,7 +551,6 @@ public int getSamples() {
*
* @param number the number of elevation samples in the profile.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setSamples(int number) {
this.samples = Math.abs(number);
}
@@ -589,7 +578,6 @@ public void setZeroBased(boolean state) {
*
* @return the object position the graph follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Position getObjectPosition() {
return this.objectPosition;
}
@@ -609,7 +597,6 @@ public void setObjectPosition(Position pos) {
*
* @return the object heading the graph follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Angle getObjectHeading() {
return this.objectHeading;
}
@@ -629,7 +616,6 @@ public void setObjectHeading(Angle heading) {
*
* @return the path positions that the profile follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public List extends LatLon> getPathPositions() {
return this.pathPositions;
}
@@ -708,7 +694,6 @@ public void setPathType(String pathType) {
*
* @return the Path
used to render the profile line on the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Path getProfileLine() {
return this.selectionShape;
}
@@ -718,7 +703,6 @@ public Path getProfileLine() {
*
* @return the Path
used to render the picked position on the terrain.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Path getPickedLine() {
return this.selectionShape;
}
@@ -728,7 +712,6 @@ public Path getPickedLine() {
*
* @return true is the profile line is displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean isShowProfileLine() {
return this.showProfileLine;
}
@@ -747,7 +730,6 @@ public void setShowProfileLine(boolean state) {
*
* @return true if the picked line is displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean isShowPickedLine() {
return this.showPickedLine;
}
@@ -757,7 +739,6 @@ public boolean isShowPickedLine() {
*
* @param state if the picked line should be displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setShowPickedLine(boolean state) {
this.showPickedLine = state;
}
@@ -986,6 +967,7 @@ protected void drawGraph(DrawContext dc, Dimension dimension) {
(byte) this.color.getBlue(), (byte) 100);
gl.glBegin(GL2.GL_TRIANGLE_STRIP);
for (i = 0; i < this.samples; i++) {
+ if (this.positions[i] == null) break;
x = i * lengthStep * stepX;
y = (this.positions[i].getElevation() - min) * stepY;
gl.glVertex3d(x, 0, 0);
@@ -997,6 +979,7 @@ protected void drawGraph(DrawContext dc, Dimension dimension) {
gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity());
gl.glBegin(GL2.GL_LINE_STRIP);
for (i = 0; i < this.samples; i++) {
+ if (this.positions[i] == null) break;
x = i * lengthStep * stepX;
y = (this.positions[i].getElevation() - min) * stepY;
gl.glVertex3d(x, y, 0);
@@ -1274,12 +1257,11 @@ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimensio
this.pickedSample = -1;
Point pickPoint = dc.getPickPoint();
if (pickPoint != null && this.positions != null && !this.follow.equals(FOLLOW_CURSOR)) {
- Rectangle viewport = dc.getView().getViewport();
// Check if pickpoint is inside the graph
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) {
+ && pickPoint.getY() >= locationSW.getY()
+ && pickPoint.getY() < locationSW.getY() + mapSize.height) {
// Find sample - Note: only works when graph expends over the full width
int sample = (int) (((double) (pickPoint.getX() - locationSW.getX()) / mapSize.width) * this.samples);
if (sample >= 0 && sample < this.samples) {
diff --git a/src/gov/nasa/worldwind/layers/TiledImageLayer.java b/src/gov/nasa/worldwind/layers/TiledImageLayer.java
index 67fba48604..1a19ce23e7 100644
--- a/src/gov/nasa/worldwind/layers/TiledImageLayer.java
+++ b/src/gov/nasa/worldwind/layers/TiledImageLayer.java
@@ -39,6 +39,8 @@
import javax.imageio.ImageIO;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.xpath.XPath;
import java.awt.image.*;
import java.io.*;
diff --git a/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java b/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
index 35b79f478e..5f1c3fb356 100644
--- a/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
+++ b/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
@@ -496,7 +496,7 @@ protected Angle computePanHeading(OrbitView view, ScreenAnnotation control)
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
Angle heading = view.getHeading().add(Angle.fromRadians(Math.atan2(px, py)));
heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
return heading;
@@ -508,7 +508,7 @@ protected Angle computePanAmount(Globe globe, OrbitView view, ScreenAnnotation c
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
double pickDistance = Math.sqrt(px * px + py * py);
double pickDistanceFactor = Math.min(pickDistance / 10, 5);
@@ -547,7 +547,7 @@ protected Angle computeLookPitch(OrbitView view, ScreenAnnotation control, doubl
// Compute last pick point 'pitch' relative to look control center on y
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
double pickDistanceFactor = Math.min(Math.abs(py) / 3000, 5) * Math.signum(py);
// New pitch
Angle pitch = view.getPitch().add(Angle.fromRadians(pitchStep * pickDistanceFactor));
diff --git a/src/gov/nasa/worldwind/layers/WorldMapLayer.java b/src/gov/nasa/worldwind/layers/WorldMapLayer.java
index 5d8c84f534..151d8b451b 100644
--- a/src/gov/nasa/worldwind/layers/WorldMapLayer.java
+++ b/src/gov/nasa/worldwind/layers/WorldMapLayer.java
@@ -700,11 +700,11 @@ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimensio
// 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)
+ && pickPoint.getY() >= locationSW.getY()
+ && 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 lat = (pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90;
double pickAltitude = 1000e3;
pickPosition = new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), pickAltitude);
}
diff --git a/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java b/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
index 6b0e8ceb38..cc8a053e8e 100644
--- a/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
+++ b/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
@@ -30,7 +30,6 @@
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.*;
-import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.*;
import javax.imageio.ImageIO;
diff --git a/src/gov/nasa/worldwind/pick/PickSupport.java b/src/gov/nasa/worldwind/pick/PickSupport.java
index de36c75420..002107ce1e 100644
--- a/src/gov/nasa/worldwind/pick/PickSupport.java
+++ b/src/gov/nasa/worldwind/pick/PickSupport.java
@@ -135,7 +135,7 @@ public PickedObject getTopObject(DrawContext dc, Point pickPoint)
* objects are currently registered with this PickSupport.
*
* @param dc the draw context which receives the picked object.
- * @param pickPoint the point in AWT screen coordinates.
+ * @param pickPoint the point in GL surface coordinates.
* @param layer the layer associated with the picked object.
*
* @return the picked object added to the draw context, or null
if no picked object is drawn at the
@@ -166,11 +166,11 @@ public PickedObject resolvePick(DrawContext dc, Point pickPoint, Layer layer)
}
/**
- * Adds a picked object registered with this PickSupport that is drawn at the specified point in AWT screen
+ * Adds a picked object registered with this PickSupport that is drawn at the specified point in GL surface
* coordinates (if one exists) to the draw context's list of picked objects.
*
* @param dc the draw context which receives the picked object.
- * @param pickPoint the point in AWT screen coordinates.
+ * @param pickPoint the point in GL surface coordinates.
* @param layer the layer associated with the picked object.
*
* @return the picked object added to the draw context, or null
if no picked object is drawn at the
@@ -195,7 +195,7 @@ protected PickedObject doResolvePick(DrawContext dc, Point pickPoint, Layer laye
* screen coordinates (if any) to the draw context's list of picked objects.
*
* @param dc the draw context which receives the picked objects.
- * @param pickRect the rectangle in AWT screen coordinates.
+ * @param pickRect the rectangle in GL surface coordinates.
* @param layer the layer associated with the picked objects.
*/
protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
@@ -226,7 +226,7 @@ protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
}
/**
- * Returns the framebuffer RGB color for a point in AWT screen coordinates, formatted as a pick color code. The red,
+ * Returns the framebuffer RGB color for a point in GL surface coordinates, formatted as a pick color code. The red,
* green, and blue components are each stored as an 8-bit unsigned integer, and packed into bits 0-23 of the
* returned integer as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are blue. This format is
* consistent with the RGB integers used to create the pick colors.
@@ -235,7 +235,7 @@ protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
* outside the draw context's drawable area.
*
* @param dc the draw context to return a color for.
- * @param pickPoint the point to return a color for, in AWT screen coordinates.
+ * @param pickPoint the point to return a color for, in GL surface coordinates.
*
* @return the RGB color corresponding to the specified point.
*/
diff --git a/src/gov/nasa/worldwind/render/AbstractAnnotation.java b/src/gov/nasa/worldwind/render/AbstractAnnotation.java
index 25cb16b38f..72d1571bfc 100644
--- a/src/gov/nasa/worldwind/render/AbstractAnnotation.java
+++ b/src/gov/nasa/worldwind/render/AbstractAnnotation.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
/**
@@ -462,7 +464,6 @@ protected void drawTopLevelAnnotation(DrawContext dc, int x, int y, int width, i
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void applyScreenTransform(DrawContext dc, int x, int y, int width, int height, double scale)
{
double finalScale = scale * this.computeScale(dc);
@@ -475,7 +476,6 @@ protected void applyScreenTransform(DrawContext dc, int x, int y, int width, int
gl.glTranslated(-width / 2, 0, 0);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected double computeScale(DrawContext dc)
{
double scale = this.attributes.getScale();
@@ -489,7 +489,6 @@ protected double computeScale(DrawContext dc)
return scale;
}
- @SuppressWarnings({"UnusedDeclaration"})
protected double computeOpacity(DrawContext dc)
{
double opacity = this.attributes.getOpacity();
@@ -616,7 +615,6 @@ protected void drawBackgroundImage(DrawContext dc, int width, int height, double
this.doDrawBackgroundTexture(dc, width, height, opacity, pickPosition, texture);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void doDrawBackgroundTexture(DrawContext dc, int width, int height, double opacity, Position pickPosition,
WWTexture texture)
{
@@ -660,7 +658,6 @@ protected void doDrawBackgroundTexture(DrawContext dc, int width, int height, do
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void applyBackgroundTextureState(DrawContext dc, int width, int height, double opacity,
WWTexture texture)
{
@@ -721,7 +718,6 @@ protected void transformImageCoordsToBackgroundImageCoords(DrawContext dc, WWTex
* @param texture the texture to transform from Annotation background image coordinates to Annotation geometry
* coordinates.
*/
- @SuppressWarnings({"UnusedDeclaration"})
protected void transformBackgroundImageCoordsToAnnotationCoords(DrawContext dc, int width, int height,
WWTexture texture)
{
@@ -750,7 +746,6 @@ protected void transformBackgroundImageCoordsToAnnotationCoords(DrawContext dc,
//******************** Border Rendering **********************//
//**************************************************************//
- @SuppressWarnings({"UnusedDeclaration"})
protected void drawBorder(DrawContext dc, int width, int height, double opacity, Position pickPosition)
{
if (this.getAttributes().getBorderWidth() <= 0)
@@ -813,8 +808,7 @@ protected void drawText(DrawContext dc, int width, int height, double opacity, P
return;
java.awt.Rectangle screenInsetBounds = this.transformByModelview(dc, insetBounds);
- java.awt.Point glPickPoint = this.glPointFromAWTPoint(dc, dc.getPickPoint());
- if (!screenInsetBounds.contains(glPickPoint))
+ if (!screenInsetBounds.contains(dc.getPickPoint()))
return;
}
@@ -897,7 +891,6 @@ protected void drawPlainText(DrawContext dc, int x, int y, int lineHeight, doubl
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void drawHTML(DrawContext dc, int x, int y, int lineHeight, double opacity, Object pickObject,
Position pickPosition, String text)
{
@@ -941,14 +934,12 @@ protected void drawChildren(DrawContext dc, int width, int height, double opacit
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void doDrawChildren(DrawContext dc, java.awt.Rectangle bounds, double opacity, Position pickPosition)
{
this.layoutManager.setPickSupport(this.pickSupport);
this.layoutManager.drawAnnotations(dc, bounds, this.childList, opacity, pickPosition);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void beginDrawChildren(DrawContext dc, java.awt.Rectangle bounds)
{
this.layoutManager.beginDrawAnnotations(dc, bounds);
@@ -1051,15 +1042,6 @@ protected java.awt.Rectangle transformByModelview(DrawContext dc, java.awt.Recta
return new java.awt.Rectangle((int) origin.x, (int) origin.y, (int) size.x, (int) size.y);
}
- protected java.awt.Point glPointFromAWTPoint(DrawContext dc, java.awt.Point awtPoint)
- {
- if (dc.getView() == null || dc.getView().getViewport() == null)
- return null;
-
- java.awt.Rectangle viewport = dc.getView().getViewport();
- return new java.awt.Point(awtPoint.x, viewport.height - awtPoint.y - 1);
- }
-
//**************************************************************//
//******************** Text Utilities ************************//
//**************************************************************//
diff --git a/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java b/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
index 9c77cd54fc..a4d6b2bd29 100644
--- a/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
+++ b/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
@@ -1731,7 +1731,7 @@ protected void drawResizeControl(DrawContext dc, OrderedBrowserBalloon obb)
// Compute the screen rectangle in AWT coordinates (origin top left).
Rectangle awtScreenRect = new Rectangle(obb.screenRect.x,
- dc.getView().getViewport().height - obb.screenRect.y - obb.screenRect.height,
+ obb.screenRect.y - obb.screenRect.height,
obb.screenRect.width, obb.screenRect.height);
Color color = dc.getUniquePickColor();
diff --git a/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java b/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
index 81faf5ce86..394e81e879 100644
--- a/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
@@ -36,6 +36,8 @@
import com.jogamp.opengl.*;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.gl2.GLUgl2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwind/render/DrawContext.java b/src/gov/nasa/worldwind/render/DrawContext.java
index 750955b933..c6e8567a5e 100644
--- a/src/gov/nasa/worldwind/render/DrawContext.java
+++ b/src/gov/nasa/worldwind/render/DrawContext.java
@@ -345,14 +345,14 @@ public interface DrawContext extends WWObject, Disposable
Color getClearColor();
/**
- * Returns the framebuffer RGB color for a point in AWT screen coordinates, formatted as a pick color code. The red,
+ * Returns the framebuffer RGB color for a point in GL surface coordinates, formatted as a pick color code. The red,
* green, and blue components are each stored as an 8-bit unsigned integer, and packed into bits 0-23 of the
* returned integer as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are blue. This format is
* consistent with the RGB integers used to create the pick colors in getUniquePickColor.
*
* This returns 0 if the point contains the clear color, or is outside this draw context's drawable area.
*
- * @param point the point to return a color for, in AWT screen coordinates.
+ * @param point the point to return a color for, in GL surface coordinates.
*
* @return the RGB color corresponding to the specified point.
*
@@ -361,7 +361,7 @@ public interface DrawContext extends WWObject, Disposable
int getPickColorAtPoint(Point point);
/**
- * Returns an array of the unique framebuffer RGB colors within a rectangle in AWT screen coordinates, formatted as
+ * Returns an array of the unique framebuffer RGB colors within a rectangle in GL surface coordinates, formatted as
* pick color codes. The red, green, and blue components are each stored as an 8-bit unsigned integer, and packed
* into bits 0-23 of the returned integers as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are
* blue. This format is consistent with the RGB integers used to create the pick colors in getUniquePickColor.
@@ -376,7 +376,7 @@ public interface DrawContext extends WWObject, Disposable
* the colors that must be considered by this method and the caller. When specified, these integers must be
* formatted exactly as the integers this method returns.
*
- * @param rectangle the rectangle to return unique colors for, in AWT screen coordinates.
+ * @param rectangle the rectangle to return unique colors for, in GL surface coordinates.
* @param minAndMaxColorCodes an two element array representing the minimum and maximum RGB colors to return. May be
* null
to specify that all color codes must be returned.
*
@@ -502,7 +502,7 @@ public interface DrawContext extends WWObject, Disposable
SurfaceTileRenderer getGeographicSurfaceTileRenderer();
/**
- * Returns the current pick point in AWT screen coordinates.
+ * Returns the current pick point in GL surface coordinates.
*
* @return the current pick point, or null
if no pick point is available.
*
@@ -511,7 +511,7 @@ public interface DrawContext extends WWObject, Disposable
Point getPickPoint();
/**
- * Specifies the current pick point in AWT screen coordinates, or null
to indicate that there is no
+ * Specifies the current pick point in GL surface coordinates, or null
to indicate that there is no
* pick point. During each pick traversal, layers determine if their contents are drawn at the pick point. If so,
* layers add each unique picked object to a PickedObjectList on this draw context by calling {@link
* #addPickedObject(gov.nasa.worldwind.pick.PickedObject)}. This list can be accessed by calling {@link
@@ -525,7 +525,7 @@ public interface DrawContext extends WWObject, Disposable
void setPickPoint(Point pickPoint);
/**
- * Returns the current pick rectangle in AWT screen coordinates.
+ * Returns the current pick rectangle in GL surface coordinates.
*
* @return the current pick rectangle, or null
if no pick rectangle is current.
*
@@ -534,7 +534,7 @@ public interface DrawContext extends WWObject, Disposable
Rectangle getPickRectangle();
/**
- * Specifies the current pick rectangle in AWT screen coordinates, or null
to indicate that there is no
+ * Specifies the current pick rectangle in GL surface coordinates, or null
to indicate that there is no
* pick rectangle. During each pick traversal, layers determine if their contents intersect the pick rectangle. If
* so, layers add each unique picked object to a PickedObjectList on this draw context by calling {@link
* #addObjectInPickRectangle(gov.nasa.worldwind.pick.PickedObject)}. This is list can be accessed by calling {@link
@@ -1046,4 +1046,16 @@ public interface DrawContext extends WWObject, Disposable
boolean is2DGlobe();
boolean isContinuous2DGlobe();
+
+ /**
+ * Convert AWT effective screen location to GL surface location using DPI scaling.
+ */
+ int [] awtPointToGLpoint(Point pt);
+
+ /**
+ * Convert GL surface coordinate point to AWT device point using DPI scaling.
+ * @param glPoint
+ * @return
+ */
+ public Point glPointToAwtPoint(Point glPoint);
}
diff --git a/src/gov/nasa/worldwind/render/DrawContextImpl.java b/src/gov/nasa/worldwind/render/DrawContextImpl.java
index 4c3cf88c92..c24100b162 100644
--- a/src/gov/nasa/worldwind/render/DrawContextImpl.java
+++ b/src/gov/nasa/worldwind/render/DrawContextImpl.java
@@ -87,15 +87,15 @@ public class DrawContextImpl extends WWObjectImpl implements DrawContext
protected boolean pickingMode = false;
protected boolean deepPickingMode = false;
/**
- * Indicates the current pick point in AWT screen coordinates, or null
to indicate that there is no
+ * Indicates the current pick point in GL screen coordinates, or null
to indicate that there is no
* pick point. Initially null
.
*/
- protected Point pickPoint = null;
+ private Point pickPoint = null;
/**
- * Indicates the current pick rectangle in AWT screen coordinates, or null
to indicate that there is no
+ * Indicates the current pick rectangle in GL screen coordinates, or null
to indicate that there is no
* pick rectangle. Initially null
.
*/
- protected Rectangle pickRect = null;
+ private Rectangle pickRect = null;
protected boolean isOrderedRenderingMode = false;
protected boolean preRenderMode = false;
protected Point viewportCenterScreenPoint = null;
@@ -154,7 +154,8 @@ public OrderedRenderableEntry(OrderedRenderable orderedRenderable, double distan
protected PriorityQueue orderedRenderables =
new PriorityQueue(100, new Comparator()
{
- public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
+ @Override
+ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
{
double eA = orA.distanceFromEye;
double eB = orB.distanceFromEye;
@@ -171,47 +172,56 @@ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
*
* @throws com.jogamp.opengl.GLException - If an OpenGL context is not current when this method is called.
*/
- public void dispose()
+ @Override
+ public void dispose()
{
this.geographicSurfaceTileRenderer.dispose();
}
- public final GL getGL()
+ @Override
+ public final GL getGL()
{
return this.getGLContext().getGL();
}
- public final GLU getGLU()
+ @Override
+ public final GLU getGLU()
{
return this.glu;
}
- public final GLContext getGLContext()
+ @Override
+ public final GLContext getGLContext()
{
return this.glContext;
}
- public final int getDrawableHeight()
+ @Override
+ public final int getDrawableHeight()
{
return this.getGLDrawable().getSurfaceHeight();
}
- public final int getDrawableWidth()
+ @Override
+ public final int getDrawableWidth()
{
return this.getGLDrawable().getSurfaceWidth();
}
- public final GLDrawable getGLDrawable()
+ @Override
+ public final GLDrawable getGLDrawable()
{
return this.getGLContext().getGLDrawable();
}
- public GLRuntimeCapabilities getGLRuntimeCapabilities()
+ @Override
+ public GLRuntimeCapabilities getGLRuntimeCapabilities()
{
return this.glRuntimeCaps;
}
- public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
+ @Override
+ public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
{
if (capabilities == null)
{
@@ -223,7 +233,8 @@ public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
this.glRuntimeCaps = capabilities;
}
- public final void initialize(GLContext glContext)
+ @Override
+ public final void initialize(GLContext glContext)
{
if (glContext == null)
{
@@ -252,7 +263,8 @@ public final void initialize(GLContext glContext)
this.currentLayer = null;
}
- public final void setModel(Model model)
+ @Override
+ public final void setModel(Model model)
{
this.model = model;
if (this.model == null)
@@ -263,53 +275,63 @@ public final void setModel(Model model)
this.globe = g;
}
- public final Model getModel()
+ @Override
+ public final Model getModel()
{
return this.model;
}
- public final LayerList getLayers()
+ @Override
+ public final LayerList getLayers()
{
return this.model.getLayers();
}
- public final Sector getVisibleSector()
+ @Override
+ public final Sector getVisibleSector()
{
return this.visibleSector;
}
- public final void setVisibleSector(Sector s)
+ @Override
+ public final void setVisibleSector(Sector s)
{
// don't check for null - it is possible that no globe is active, no view is active, no sectors visible, etc.
this.visibleSector = s;
}
- public void setSurfaceGeometry(SectorGeometryList surfaceGeometry)
+ @Override
+ public void setSurfaceGeometry(SectorGeometryList surfaceGeometry)
{
this.surfaceGeometry = surfaceGeometry;
}
- public SectorGeometryList getSurfaceGeometry()
+ @Override
+ public SectorGeometryList getSurfaceGeometry()
{
return surfaceGeometry;
}
- public final Globe getGlobe()
+ @Override
+ public final Globe getGlobe()
{
return this.globe != null ? this.globe : this.model.getGlobe();
}
- public final void setView(View view)
+ @Override
+ public final void setView(View view)
{
this.view = view;
}
- public final View getView()
+ @Override
+ public final View getView()
{
return this.view;
}
- public final void setGLContext(GLContext glContext)
+ @Override
+ public final void setGLContext(GLContext glContext)
{
if (glContext == null)
{
@@ -321,27 +343,32 @@ public final void setGLContext(GLContext glContext)
this.glContext = glContext;
}
- public final double getVerticalExaggeration()
+ @Override
+ public final double getVerticalExaggeration()
{
return verticalExaggeration;
}
- public final void setVerticalExaggeration(double verticalExaggeration)
+ @Override
+ public final void setVerticalExaggeration(double verticalExaggeration)
{
this.verticalExaggeration = verticalExaggeration;
}
- public GpuResourceCache getTextureCache()
+ @Override
+ public GpuResourceCache getTextureCache()
{
return this.gpuResourceCache;
}
- public GpuResourceCache getGpuResourceCache()
+ @Override
+ public GpuResourceCache getGpuResourceCache()
{
return this.gpuResourceCache;
}
- public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
+ @Override
+ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
{
if (gpuResourceCache == null)
{
@@ -353,12 +380,14 @@ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
this.gpuResourceCache = gpuResourceCache;
}
- public TextRendererCache getTextRendererCache()
+ @Override
+ public TextRendererCache getTextRendererCache()
{
return textRendererCache;
}
- public void setTextRendererCache(TextRendererCache textRendererCache)
+ @Override
+ public void setTextRendererCache(TextRendererCache textRendererCache)
{
if (textRendererCache == null)
{
@@ -370,12 +399,14 @@ public void setTextRendererCache(TextRendererCache textRendererCache)
this.textRendererCache = textRendererCache;
}
- public AnnotationRenderer getAnnotationRenderer()
+ @Override
+ public AnnotationRenderer getAnnotationRenderer()
{
return annotationRenderer;
}
- public void setAnnotationRenderer(AnnotationRenderer ar)
+ @Override
+ public void setAnnotationRenderer(AnnotationRenderer ar)
{
if (ar == null)
{
@@ -386,57 +417,68 @@ public void setAnnotationRenderer(AnnotationRenderer ar)
annotationRenderer = ar;
}
- public LightingModel getStandardLightingModel()
+ @Override
+ public LightingModel getStandardLightingModel()
{
return standardLighting;
}
- public void setStandardLightingModel(LightingModel standardLighting)
+ @Override
+ public void setStandardLightingModel(LightingModel standardLighting)
{
this.standardLighting = standardLighting;
}
- public Point getPickPoint()
+ @Override
+ public Point getPickPoint()
{
return this.pickPoint;
}
- public void setPickPoint(Point pickPoint)
+ @Override
+ public void setPickPoint(Point pickPoint)
{
- this.pickPoint = pickPoint;
+ this.pickPoint = pickPoint;
}
- public Rectangle getPickRectangle()
+ @Override
+ public Rectangle getPickRectangle()
{
return this.pickRect;
}
- public void setPickRectangle(Rectangle pickRect)
+ @Override
+ public void setPickRectangle(Rectangle pickRect)
{
this.pickRect = pickRect;
}
- public Point getViewportCenterScreenPoint()
+ @Override
+ public Point getViewportCenterScreenPoint()
{
return viewportCenterScreenPoint;
}
- public void setViewportCenterScreenPoint(Point viewportCenterScreenPoint)
+ @Override
+ public void setViewportCenterScreenPoint(Point viewportCenterScreenPoint)
{
this.viewportCenterScreenPoint = viewportCenterScreenPoint;
}
- public Position getViewportCenterPosition()
+ @Override
+ public Position getViewportCenterPosition()
{
return viewportCenterPosition;
}
- public void setViewportCenterPosition(Position viewportCenterPosition)
+ @Override
+ public void setViewportCenterPosition(Position viewportCenterPosition)
{
this.viewportCenterPosition = viewportCenterPosition;
}
- public void addPickedObjects(PickedObjectList pickedObjects)
+ @Override
+ public void addPickedObjects(PickedObjectList pickedObjects)
{
if (pickedObjects == null)
{
@@ -457,7 +499,8 @@ public void addPickedObjects(PickedObjectList pickedObjects)
}
}
- public void addPickedObject(PickedObject pickedObject)
+ @Override
+ public void addPickedObject(PickedObject pickedObject)
{
if (null == pickedObject)
{
@@ -472,17 +515,20 @@ public void addPickedObject(PickedObject pickedObject)
this.pickedObjects.add(pickedObject);
}
- public PickedObjectList getPickedObjects()
+ @Override
+ public PickedObjectList getPickedObjects()
{
return this.pickedObjects;
}
- public PickedObjectList getObjectsInPickRectangle()
+ @Override
+ public PickedObjectList getObjectsInPickRectangle()
{
return this.objectsInPickRect;
}
- public void addObjectInPickRectangle(PickedObject pickedObject)
+ @Override
+ public void addObjectInPickRectangle(PickedObject pickedObject)
{
if (pickedObject == null)
{
@@ -494,7 +540,8 @@ public void addObjectInPickRectangle(PickedObject pickedObject)
this.objectsInPickRect.add(pickedObject);
}
- public Color getUniquePickColor()
+ @Override
+ public Color getUniquePickColor()
{
this.uniquePickNumber++;
@@ -512,7 +559,8 @@ public Color getUniquePickColor()
return new Color(this.uniquePickNumber, true); // has alpha
}
- public Color getUniquePickColorRange(int count)
+ @Override
+ public Color getUniquePickColorRange(int count)
{
if (count < 1)
return null;
@@ -532,13 +580,15 @@ public Color getUniquePickColorRange(int count)
return new Color(range.location, true); // return a pointer to the beginning of the requested range
}
- public Color getClearColor()
+ @Override
+ public Color getClearColor()
{
return this.clearColor;
}
/** {@inheritDoc} */
- public int getPickColorAtPoint(Point point)
+ @Override
+ public int getPickColorAtPoint(Point point)
{
if (point == null)
{
@@ -547,10 +597,8 @@ public int getPickColorAtPoint(Point point)
throw new IllegalArgumentException(msg);
}
- // Translate the point from AWT screen coordinates to OpenGL screen coordinates.
- Rectangle viewport = this.getView().getViewport();
int x = point.x;
- int y = viewport.height - point.y - 1;
+ int y = point.y;
// Read the framebuffer color at the specified point in OpenGL screen coordinates as a 24-bit RGB value.
if (this.pixelColors == null || this.pixelColors.capacity() < 3)
@@ -566,7 +614,8 @@ public int getPickColorAtPoint(Point point)
}
/** {@inheritDoc} */
- public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorCodes)
+ @Override
+ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorCodes)
{
if (rectangle == null)
{
@@ -577,10 +626,7 @@ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorC
Rectangle viewport = this.getView().getViewport();
- // Transform the rectangle from AWT screen coordinates to OpenGL screen coordinates and compute its intersection
- // with the viewport. Transformation to GL coordinates must be done prior to computing the intersection, because
- // the viewport is in GL coordinates. The resultant rectangle represents the area that's valid to read from GL.
- Rectangle r = new Rectangle(rectangle.x, viewport.height - rectangle.y - 1, rectangle.width, rectangle.height);
+ Rectangle r = new Rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
r = r.intersection(viewport);
if (r.isEmpty()) // Return null if the rectangle is empty.
@@ -641,52 +687,62 @@ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorC
return array;
}
- public boolean isPickingMode()
+ @Override
+ public boolean isPickingMode()
{
return this.pickingMode;
}
- public void enablePickingMode()
+ @Override
+ public void enablePickingMode()
{
this.pickingMode = true;
}
- public void disablePickingMode()
+ @Override
+ public void disablePickingMode()
{
this.pickingMode = false;
}
- public boolean isDeepPickingEnabled()
+ @Override
+ public boolean isDeepPickingEnabled()
{
return this.deepPickingMode;
}
- public void setDeepPickingEnabled(boolean tf)
+ @Override
+ public void setDeepPickingEnabled(boolean tf)
{
this.deepPickingMode = tf;
}
- public boolean isPreRenderMode()
+ @Override
+ public boolean isPreRenderMode()
{
return preRenderMode;
}
- public void setPreRenderMode(boolean preRenderMode)
+ @Override
+ public void setPreRenderMode(boolean preRenderMode)
{
this.preRenderMode = preRenderMode;
}
- public boolean isOrderedRenderingMode()
+ @Override
+ public boolean isOrderedRenderingMode()
{
return this.isOrderedRenderingMode;
}
- public void setOrderedRenderingMode(boolean tf)
+ @Override
+ public void setOrderedRenderingMode(boolean tf)
{
this.isOrderedRenderingMode = tf;
}
- public DeclutteringTextRenderer getDeclutteringTextRenderer()
+ @Override
+ public DeclutteringTextRenderer getDeclutteringTextRenderer()
{
return declutteringTextRenderer;
}
@@ -703,7 +759,8 @@ public boolean isContinuous2DGlobe()
return this.globe instanceof Globe2D && ((Globe2D) this.getGlobe()).isContinuous();
}
- public void addOrderedRenderable(OrderedRenderable orderedRenderable)
+ @Override
+ public void addOrderedRenderable(OrderedRenderable orderedRenderable)
{
if (null == orderedRenderable)
{
@@ -716,7 +773,8 @@ public void addOrderedRenderable(OrderedRenderable orderedRenderable)
}
/** {@inheritDoc} */
- public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean isBehind)
+ @Override
+ public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean isBehind)
{
if (null == orderedRenderable)
{
@@ -734,14 +792,16 @@ public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean is
new OrderedRenderableEntry(orderedRenderable, eyeDistance, System.nanoTime(), this));
}
- public OrderedRenderable peekOrderedRenderables()
+ @Override
+ public OrderedRenderable peekOrderedRenderables()
{
OrderedRenderableEntry ore = this.orderedRenderables.peek();
return ore != null ? ore.or : null;
}
- public OrderedRenderable pollOrderedRenderables()
+ @Override
+ public OrderedRenderable pollOrderedRenderables()
{
OrderedRenderableEntry ore = this.orderedRenderables.poll();
@@ -810,7 +870,8 @@ public ClutterFilter getClutterFilter()
return this.clutterFilter;
}
- public void applyClutterFilter()
+ @Override
+ public void applyClutterFilter()
{
if (this.getClutterFilter() == null)
return;
@@ -826,7 +887,8 @@ public void applyClutterFilter()
// Sort the declutterables front-to-back.
Collections.sort(declutterableArray, new Comparator()
{
- public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
+ @Override
+ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
{
double eA = orA.distanceFromEye;
double eB = orB.distanceFromEye;
@@ -854,7 +916,8 @@ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
}
/** {@inheritDoc} */
- public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
+ @Override
+ public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
{
if (orderedRenderable == null)
{
@@ -867,7 +930,8 @@ public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
}
/** {@inheritDoc} */
- public Queue getOrderedSurfaceRenderables()
+ @Override
+ public Queue getOrderedSurfaceRenderables()
{
return this.orderedSurfaceRenderables;
}
@@ -903,7 +967,8 @@ public Queue getOrderedSurfaceRenderables()
// }
// }
- public void drawUnitQuad()
+ @Override
+ public void drawUnitQuad()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -915,7 +980,8 @@ public void drawUnitQuad()
gl.glEnd();
}
- public void drawUnitQuad(TextureCoords texCoords)
+ @Override
+ public void drawUnitQuad(TextureCoords texCoords)
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -931,7 +997,8 @@ public void drawUnitQuad(TextureCoords texCoords)
gl.glEnd();
}
- public void drawUnitQuadOutline()
+ @Override
+ public void drawUnitQuadOutline()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -943,7 +1010,8 @@ public void drawUnitQuadOutline()
gl.glEnd();
}
- public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
+ @Override
+ public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
{
if (vBuf == null || nBuf == null)
return;
@@ -971,7 +1039,8 @@ public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
gl.glEnd();
}
- public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
+ @Override
+ public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
{
if (latitude == null || longitude == null)
{
@@ -997,28 +1066,33 @@ public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
return null;
}
- public SurfaceTileRenderer getGeographicSurfaceTileRenderer()
+ @Override
+ public SurfaceTileRenderer getGeographicSurfaceTileRenderer()
{
return this.geographicSurfaceTileRenderer;
}
- public Collection getPerFrameStatistics()
+ @Override
+ public Collection getPerFrameStatistics()
{
return this.perFrameStatistics;
}
- public void setPerFrameStatisticsKeys(Set statKeys, Collection stats)
+ @Override
+ public void setPerFrameStatisticsKeys(Set statKeys, Collection stats)
{
this.perFrameStatisticsKeys = statKeys;
this.perFrameStatistics = stats;
}
- public Set getPerFrameStatisticsKeys()
+ @Override
+ public Set getPerFrameStatisticsKeys()
{
return perFrameStatisticsKeys;
}
- public void setPerFrameStatistic(String key, String displayName, Object value)
+ @Override
+ public void setPerFrameStatistic(String key, String displayName, Object value)
{
if (this.perFrameStatistics == null || this.perFrameStatisticsKeys == null)
return;
@@ -1041,7 +1115,8 @@ public void setPerFrameStatistic(String key, String displayName, Object value)
this.perFrameStatistics.add(new PerformanceStatistic(key, displayName, value));
}
- public void setPerFrameStatistics(Collection stats)
+ @Override
+ public void setPerFrameStatistics(Collection stats)
{
if (stats == null)
{
@@ -1059,17 +1134,20 @@ public void setPerFrameStatistics(Collection stats)
}
}
- public long getFrameTimeStamp()
+ @Override
+ public long getFrameTimeStamp()
{
return this.frameTimestamp;
}
- public void setFrameTimeStamp(long frameTimeStamp)
+ @Override
+ public void setFrameTimeStamp(long frameTimeStamp)
{
this.frameTimestamp = frameTimeStamp;
}
- public List getVisibleSectors(double[] resolutions, long timeLimit, Sector sector)
+ @Override
+ public List getVisibleSectors(double[] resolutions, long timeLimit, Sector sector)
{
if (resolutions == null)
{
@@ -1106,19 +1184,22 @@ else if (this.visibleSectors.getSectorSize() == resolutions[resolutions.length -
return this.visibleSectors.getSectors();
}
- public void setCurrentLayer(Layer layer)
+ @Override
+ public void setCurrentLayer(Layer layer)
{
this.currentLayer = layer;
}
- public Layer getCurrentLayer()
+ @Override
+ public Layer getCurrentLayer()
{
return this.currentLayer;
}
protected LinkedHashMap credits = new LinkedHashMap();
- public void addScreenCredit(ScreenCredit credit)
+ @Override
+ public void addScreenCredit(ScreenCredit credit)
{
if (credit == null)
{
@@ -1130,27 +1211,32 @@ public void addScreenCredit(ScreenCredit credit)
this.credits.put(credit, this.frameTimestamp);
}
- public Map getScreenCredits()
+ @Override
+ public Map getScreenCredits()
{
return this.credits;
}
- public int getRedrawRequested()
+ @Override
+ public int getRedrawRequested()
{
return redrawRequested;
}
- public void setRedrawRequested(int redrawRequested)
+ @Override
+ public void setRedrawRequested(int redrawRequested)
{
this.redrawRequested = redrawRequested;
}
- public PickPointFrustumList getPickFrustums()
+ @Override
+ public PickPointFrustumList getPickFrustums()
{
return this.pickFrustumList;
}
- public void setPickPointFrustumDimension(Dimension dim)
+ @Override
+ public void setPickPointFrustumDimension(Dimension dim)
{
if (dim == null)
{
@@ -1169,25 +1255,20 @@ public void setPickPointFrustumDimension(Dimension dim)
this.pickPointFrustumDimension = new Dimension(dim);
}
- public Dimension getPickPointFrustumDimension()
+ @Override
+ public Dimension getPickPointFrustumDimension()
{
return this.pickPointFrustumDimension;
}
- public void addPickPointFrustum()
+ @Override
+ public void addPickPointFrustum()
{
//Compute the current picking frustum
if (getPickPoint() != null)
{
- Rectangle viewport = getView().getViewport();
-
- double viewportWidth = viewport.getWidth() <= 0.0 ? 1.0 : viewport.getWidth();
- double viewportHeight = viewport.getHeight() <= 0.0 ? 1.0 : viewport.getHeight();
-
- //Get the pick point and translate screen center to zero
Point ptCenter = new Point(getPickPoint());
- ptCenter.y = (int) viewportHeight - ptCenter.y;
- ptCenter.translate((int) (-viewportWidth / 2), (int) (-viewportHeight / 2));
+ ptCenter.translate(-viewportCenterScreenPoint.x, -viewportCenterScreenPoint.y);
//Number of pixels around pick point to include in frustum
int offsetX = pickPointFrustumDimension.width / 2;
@@ -1199,7 +1280,9 @@ public void addPickPointFrustum()
//Compute the distance to the near plane in screen coordinates
double width = getView().getFieldOfView().tanHalfAngle() * getView().getNearClipDistance();
- double x = width / (viewportWidth / 2.0);
+ double viewportWidth = getView().getViewport().getWidth();
+ if (viewportWidth <= 0.0) viewportWidth = 1.0;
+ double x = width / (viewportWidth/2);
double screenDist = getView().getNearClipDistance() / x;
//Create the four vectors that define the top-left, top-right, bottom-left, and bottom-right vectors
@@ -1213,10 +1296,10 @@ public void addPickPointFrustum()
getView().getNearClipDistance(), getView().getFarClipDistance());
//Create the screen rectangle associated with this frustum
- Rectangle rectScreen = new Rectangle(getPickPoint().x - offsetX,
- (int) viewportHeight - getPickPoint().y - offsetY,
- pickPointFrustumDimension.width,
- pickPointFrustumDimension.height);
+ Rectangle rectScreen = new Rectangle(getPickPoint().x - offsetX + 1,
+ getPickPoint().y - offsetY - 1,
+ pickPointFrustumDimension.width,
+ pickPointFrustumDimension.height);
//Transform the frustum to Model Coordinates
Matrix modelviewTranspose = getView().getModelviewMatrix().getTranspose();
@@ -1227,24 +1310,21 @@ public void addPickPointFrustum()
}
}
- public void addPickRectangleFrustum()
+ @Override
+ public void addPickRectangleFrustum()
{
// Do nothing if the pick rectangle is either null or has zero dimension.
if (this.getPickRectangle() == null || this.getPickRectangle().isEmpty())
return;
- View view = this.getView();
-
- Rectangle viewport = view.getViewport();
- double viewportWidth = viewport.getWidth() <= 0.0 ? 1.0 : viewport.getWidth();
- double viewportHeight = viewport.getHeight() <= 0.0 ? 1.0 : viewport.getHeight();
-
- // Get the pick rectangle, transform it from AWT screen coordinates to OpenGL screen coordinates, then translate
+ // Get the pick rectangle, transform it from GL surface coordinates to OpenGL screen coordinates, then translate
// it such that the screen's center is at the origin.
Rectangle pr = new Rectangle(this.getPickRectangle());
- pr.y = (int) viewportHeight - pr.y;
- pr.translate((int) (-viewportWidth / 2), (int) (-viewportHeight / 2));
+ pr.translate(-viewportCenterScreenPoint.x, -viewportCenterScreenPoint.y);
+ double viewportWidth = view.getViewport().getWidth();
+ if (viewportWidth <= 0.0) viewportWidth = 1.0;
+
// Create the four vectors that define the top-left, top-right, bottom-left, and bottom-right corners of the
// pick rectangle in screen coordinates.
double screenDist = viewportWidth / (2 * view.getFieldOfView().tanHalfAngle());
@@ -1265,22 +1345,24 @@ public void addPickRectangleFrustum()
// Create the screen rectangle in OpenGL screen coordinates associated with this frustum. We translate the
// specified pick rectangle from AWT coordinates to GL coordinates by inverting the y axis.
Rectangle screenRect = new Rectangle(this.getPickRectangle());
- screenRect.y = (int) viewportHeight - screenRect.y;
this.pickFrustumList.add(new PickPointFrustum(frustum, screenRect));
}
- public Collection getRenderingExceptions()
+ @Override
+ public Collection getRenderingExceptions()
{
return this.renderingExceptions;
}
- public void setRenderingExceptions(Collection exceptions)
+ @Override
+ public void setRenderingExceptions(Collection exceptions)
{
this.renderingExceptions = exceptions;
}
- public void addRenderingException(Throwable t)
+ @Override
+ public void addRenderingException(Throwable t)
{
// If the renderingExceptions Collection is non-null, it's used as the data structure that accumulates rendering
// exceptions. Otherwise this DrawContext ignores all rendering exceptions passed to this method.
@@ -1297,7 +1379,8 @@ public void addRenderingException(Throwable t)
this.renderingExceptions.add(t);
}
- public void pushProjectionOffest(Double offset)
+ @Override
+ public void pushProjectionOffest(Double offset)
{
// Modify the projection transform to shift the depth values slightly toward the camera in order to
// ensure the lines are selected during depth buffering.
@@ -1313,7 +1396,8 @@ public void pushProjectionOffest(Double offset)
gl.glLoadMatrixf(pm, 0);
}
- public void popProjectionOffest()
+ @Override
+ public void popProjectionOffest()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -1325,7 +1409,8 @@ public void popProjectionOffest()
public static final float DEFAULT_DEPTH_OFFSET_FACTOR = 1f;
public static final float DEFAULT_DEPTH_OFFSET_UNITS = 1f;
- public void drawOutlinedShape(OutlinedShape renderer, Object shape)
+ @Override
+ public void drawOutlinedShape(OutlinedShape renderer, Object shape)
{
// Draw the outlined shape using a multiple pass algorithm. The motivation for this algorithm is twofold:
//
@@ -1433,7 +1518,8 @@ public void drawOutlinedShape(OutlinedShape renderer, Object shape)
}
}
- public void beginStandardLighting()
+ @Override
+ public void beginStandardLighting()
{
if (this.standardLighting != null)
{
@@ -1442,7 +1528,8 @@ public void beginStandardLighting()
}
}
- public void endStandardLighting()
+ @Override
+ public void endStandardLighting()
{
if (this.standardLighting != null)
{
@@ -1450,7 +1537,8 @@ public void endStandardLighting()
}
}
- public boolean isSmall(Extent extent, int numPixels)
+ @Override
+ public boolean isSmall(Extent extent, int numPixels)
{
return extent != null && extent.getDiameter() <= numPixels * this.getView().computePixelSizeAtDistance(
// burkey couldnt we make this minimum dimension
@@ -1458,29 +1546,34 @@ public boolean isSmall(Extent extent, int numPixels)
extent.getCenter())); // -- so box could return small when one dim is narrow?
} // i see really skinny telephone poles that dont need to be rendered at distance but are tall
- public Terrain getTerrain()
+ @Override
+ public Terrain getTerrain()
{
return this.terrain;
}
- public Vec4 computeTerrainPoint(Angle lat, Angle lon, double offset)
+ @Override
+ public Vec4 computeTerrainPoint(Angle lat, Angle lon, double offset)
{
return this.getTerrain().getSurfacePoint(lat, lon, offset);
}
protected Terrain terrain = new Terrain()
{
- public Globe getGlobe()
+ @Override
+ public Globe getGlobe()
{
return DrawContextImpl.this.getGlobe();
}
- public double getVerticalExaggeration()
+ @Override
+ public double getVerticalExaggeration()
{
return DrawContextImpl.this.getVerticalExaggeration();
}
- public Vec4 getSurfacePoint(Position position)
+ @Override
+ public Vec4 getSurfacePoint(Position position)
{
if (position == null)
{
@@ -1504,7 +1597,8 @@ public Vec4 getSurfacePoint(Position position)
return pt;
}
- public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset)
+ @Override
+ public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset)
{
if (latitude == null || longitude == null)
{
@@ -1529,7 +1623,8 @@ public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset
return pt;
}
- public Intersection[] intersect(Position pA, Position pB)
+ @Override
+ public Intersection[] intersect(Position pA, Position pB)
{
SectorGeometryList sectorGeometry = DrawContextImpl.this.getSurfaceGeometry();
if (sectorGeometry == null)
@@ -1544,7 +1639,8 @@ public Intersection[] intersect(Position pA, Position pB)
return sectorGeometry.intersect(new Line(ptA, ptB.subtract3(ptA)));
}
- public Intersection[] intersect(Position pA, Position pB, int altitudeMode)
+ @Override
+ public Intersection[] intersect(Position pA, Position pB, int altitudeMode)
{
if (pA == null || pB == null)
{
@@ -1570,7 +1666,8 @@ else if (altitudeMode == WorldWind.CLAMP_TO_GROUND)
return this.intersect(new Position(pA, altitudeA), new Position(pB, altitudeB));
}
- public Double getElevation(LatLon location)
+ @Override
+ public Double getElevation(LatLon location)
{
if (location == null)
{
@@ -1589,25 +1686,29 @@ public Double getElevation(LatLon location)
}
};
- public void restoreDefaultBlending()
+ @Override
+ public void restoreDefaultBlending()
{
this.getGL().glBlendFunc(GL.GL_ONE, GL.GL_ZERO);
this.getGL().glDisable(GL.GL_BLEND);
}
- public void restoreDefaultCurrentColor()
+ @Override
+ public void restoreDefaultCurrentColor()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glColor4f(1, 1, 1, 1);
}
- public void restoreDefaultDepthTesting()
+ @Override
+ public void restoreDefaultDepthTesting()
{
this.getGL().glEnable(GL.GL_DEPTH_TEST);
this.getGL().glDepthMask(true);
}
- public Vec4 computePointFromPosition(Position position, int altitudeMode)
+ @Override
+ public Vec4 computePointFromPosition(Position position, int altitudeMode)
{
if (position == null)
{
@@ -1636,4 +1737,32 @@ else if (altitudeMode == WorldWind.RELATIVE_TO_GROUND)
return point;
}
+
+ /** {@inheritDoc} */
+ @Override
+ public int [] awtPointToGLpoint(Point pt) {
+ if (pt == null) return null;
+
+ int [] awtPt = { pt.x, pt.y };
+ if (glContext == null) return awtPt;
+
+ GLDrawable drawable = glContext.getGLDrawable();
+ if (drawable == null) return awtPt;
+
+ // Convert to GL surface coordinates
+ int [] glSurfacePt = drawable.getNativeSurface().convertToPixelUnits(awtPt);
+ int glSurfaceHeight = drawable.getSurfaceHeight();
+ glSurfacePt[1] = glSurfaceHeight-1 - glSurfacePt[1];
+ return glSurfacePt;
+ }
+
+ public Point glPointToAwtPoint(Point glPoint) {
+ GLDrawable drawable = glContext.getGLDrawable();
+ if (drawable == null) return glPoint;
+
+ final int viewportHeight = getView().getViewport().height;
+ int [] glPt = { glPoint.x, viewportHeight-1 - glPoint.y };
+ getGLDrawable().getNativeSurface().convertToWindowUnits(glPt);
+ return new Point(glPt[0], glPt[1]);
+ }
}
diff --git a/src/gov/nasa/worldwind/render/GeographicTextRenderer.java b/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
index a362b387dc..d3aa21fa5d 100644
--- a/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
@@ -38,6 +38,8 @@
import com.jogamp.opengl.*;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.gl2.GLUgl2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java b/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
index d8677398b8..201b35eb64 100644
--- a/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
@@ -33,6 +33,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/render/Path.java b/src/gov/nasa/worldwind/render/Path.java
index dbb8d5fef5..a72fa785a4 100644
--- a/src/gov/nasa/worldwind/render/Path.java
+++ b/src/gov/nasa/worldwind/render/Path.java
@@ -569,7 +569,7 @@ public PickedObject getTopObject(DrawContext dc, Point pickPoint) {
* AVKey.ORDINAL_LIST.
*
* @param dc the draw context which receives the picked objects.
- * @param pickRect the rectangle in AWT screen coordinates.
+ * @param pickRect the rectangle in GL surface coordinates.
* @param layer the layer associated with the picked objects.
*/
@SuppressWarnings({"unchecked"})
diff --git a/src/gov/nasa/worldwind/render/PointPlacemark.java b/src/gov/nasa/worldwind/render/PointPlacemark.java
index 08719e26d2..d2aac74ae9 100644
--- a/src/gov/nasa/worldwind/render/PointPlacemark.java
+++ b/src/gov/nasa/worldwind/render/PointPlacemark.java
@@ -40,6 +40,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.stream.*;
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java b/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
index 82dbae6710..863a50d62c 100644
--- a/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
+++ b/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
@@ -68,7 +68,8 @@ public ScreenAnnotationBalloon(String text, Point point)
}
/** {@inheritDoc} */
- protected ScreenAnnotation createAnnotation()
+ @Override
+ protected ScreenAnnotation createAnnotation()
{
ScreenAnnotation annotation = new ScreenAnnotation(this.getDecodedText(), this.screenPoint);
@@ -79,22 +80,22 @@ protected ScreenAnnotation createAnnotation()
}
/** {@inheritDoc} */
- protected ScreenAnnotation getAnnotation()
+ @Override
+ protected ScreenAnnotation getAnnotation()
{
return this.annotation;
}
/** {@inheritDoc} */
- protected void computePosition(DrawContext dc)
+ @Override
+ protected void computePosition(DrawContext dc)
{
- Rectangle viewport = dc.getView().getViewport();
-
- int y = (int) viewport.getHeight() - this.screenPoint.y - 1;
- this.getAnnotation().setScreenPoint(new Point(this.screenPoint.x, y));
+ this.getAnnotation().setScreenPoint(new Point(this.screenPoint));
}
/** {@inheritDoc} */
- public void setScreenLocation(Point point)
+ @Override
+ public void setScreenLocation(Point point)
{
if (point == null)
{
@@ -107,7 +108,8 @@ public void setScreenLocation(Point point)
}
/** {@inheritDoc} */
- public Point getScreenLocation()
+ @Override
+ public Point getScreenLocation()
{
return this.screenPoint;
}
diff --git a/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java b/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
index f90914b995..65d1660ca4 100644
--- a/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
+++ b/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
@@ -82,13 +82,15 @@ protected OrderedBrowserBalloon createOrderedRenderable()
}
/** {@inheritDoc} */
- public Point getScreenLocation()
+ @Override
+ public Point getScreenLocation()
{
return this.screenLocation;
}
/** {@inheritDoc} */
- public void setScreenLocation(Point point)
+ @Override
+ public void setScreenLocation(Point point)
{
if (point == null)
{
@@ -111,7 +113,8 @@ public void setScreenLocation(Point point)
*
* @param dc the current draw context.
*/
- protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
+ @Override
+ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
{
this.screenOffset = null;
obb.screenRect = null;
@@ -130,12 +133,11 @@ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
// bottom left). Note: The screen offset denotes how to place the screen reference point relative to the frame.
// For example, an offset of (-10, -10) in pixels places the reference point below and to the left of the frame.
// Since the screen reference point is fixed, the frame appears to move relative to the reference point.
- int y = dc.getView().getViewport().height - this.screenLocation.y;
- obb.screenRect = new Rectangle(this.screenLocation.x - this.screenOffset.x, y - this.screenOffset.y,
+ obb.screenRect = new Rectangle(this.screenLocation.x - this.screenOffset.x, this.screenLocation.y - this.screenOffset.y,
size.width, size.height);
// Compute the screen extent as the rectangle containing the balloon's screen rectangle and its screen point.
obb.screenExtent = new Rectangle(obb.screenRect);
- obb.screenExtent.add(this.screenLocation.x, y);
+ obb.screenExtent.add(this.screenLocation.x, this.screenLocation.y);
// Compute the pickable screen extent as the screen extent, plus the width of the balloon's pickable outline.
// This extent is used during picking to ensure that the balloon's outline is pickable when it exceeds the
// balloon's screen extent.
@@ -147,7 +149,8 @@ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
}
/** {@inheritDoc} */
- protected void setupDepthTest(DrawContext dc, OrderedBrowserBalloon obb)
+ @Override
+ protected void setupDepthTest(DrawContext dc, OrderedBrowserBalloon obb)
{
dc.getGL().glDisable(GL.GL_DEPTH_TEST);
}
diff --git a/src/gov/nasa/worldwind/render/ScreenCredit.java b/src/gov/nasa/worldwind/render/ScreenCredit.java
index e4a38a4d03..3e4c0533e6 100644
--- a/src/gov/nasa/worldwind/render/ScreenCredit.java
+++ b/src/gov/nasa/worldwind/render/ScreenCredit.java
@@ -47,6 +47,4 @@ public interface ScreenCredit extends Renderable
void setLink(String link);
String getLink();
-
- public void pick(DrawContext dc, java.awt.Point pickPoint);
}
diff --git a/src/gov/nasa/worldwind/render/ScreenCreditController.java b/src/gov/nasa/worldwind/render/ScreenCreditController.java
index aa2ae11949..d060ecc0e4 100644
--- a/src/gov/nasa/worldwind/render/ScreenCreditController.java
+++ b/src/gov/nasa/worldwind/render/ScreenCreditController.java
@@ -70,7 +70,8 @@ public ScreenCreditController(WorldWindow wwd)
wwd.addSelectListener(this);
}
- public void dispose()
+ @Override
+ public void dispose()
{
wwd.removeSelectListener(this);
if (wwd.getSceneController() == this)
@@ -87,7 +88,7 @@ public void setEnabled(boolean enabled)
this.enabled = enabled;
}
- public void pick(DrawContext dc, Point pickPoint)
+ public void pick(DrawContext dc, @SuppressWarnings("unused") Point pickPoint)
{
if (dc == null)
{
@@ -113,13 +114,13 @@ public void pick(DrawContext dc, Point pickPoint)
Rectangle viewport = new Rectangle(x, y, creditWidth, creditHeight);
credit.setViewport(viewport);
- credit.pick(dc, pickPoint);
x += (separation + creditWidth);
}
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -136,7 +137,7 @@ public void render(DrawContext dc)
Set> credits = dc.getScreenCredits().entrySet();
- int y = dc.getView().getViewport().height - (bottomMargin + creditHeight / 2);
+ int y = bottomMargin + creditHeight / 2;
int x = leftMargin + creditWidth / 2;
for (Map.Entry entry : credits)
@@ -156,7 +157,8 @@ public void render(DrawContext dc)
}
}
- public void selected(SelectEvent event)
+ @Override
+ public void selected(SelectEvent event)
{
if (event.getMouseEvent() != null && event.getMouseEvent().isConsumed())
return;
diff --git a/src/gov/nasa/worldwind/render/ScreenImage.java b/src/gov/nasa/worldwind/render/ScreenImage.java
index 69c33b5cb7..488d283002 100644
--- a/src/gov/nasa/worldwind/render/ScreenImage.java
+++ b/src/gov/nasa/worldwind/render/ScreenImage.java
@@ -78,13 +78,6 @@ public class ScreenImage extends WWObjectImpl implements Renderable, Exportable
* is computed in computeOffsets
and used in draw
Initially null
.
*/
protected Point screenLocation;
- /**
- * Indicates the location of this screen image in the viewport (on the screen) in AWT coordinates. This property is
- * assigned in setScreenLocation
and computeOffsets
. In computeOffsets
, this
- * is computed by converting the screenLocation
from OpenGL coordinates to AWT coordinates. Initially
- * null
.
- */
- protected Point awtScreenLocation;
protected double dx;
protected double dy;
protected Layer pickLayer;
@@ -122,7 +115,7 @@ public void render(DrawContext dc)
*/
public Point getScreenLocation()
{
- return this.awtScreenLocation;
+ return this.screenLocation;
}
/**
@@ -136,7 +129,7 @@ public Point getScreenLocation()
public Point getScreenLocation(DrawContext dc)
{
this.computeOffsets(dc);
- return this.awtScreenLocation;
+ return this.screenLocation;
}
/**
@@ -151,17 +144,16 @@ public Point getScreenLocation(DrawContext dc)
*/
public void setScreenLocation(Point screenLocation)
{
- // Use units PIXELS for the X screen offset, and and INSET_PIXELS for the Y screen offset. The Offset is in
- // OpenGL coordinates with the origin in the lower-left corner, but the Point is in AWT coordinates with the
- // origin in the upper-left corner. This offset translates the origin from the lower-left to the upper-left
- // corner.
- this.screenOffset = new Offset(screenLocation.getX(), screenLocation.getY(), AVKey.PIXELS, AVKey.INSET_PIXELS);
+ // Use units PIXELS for the X screen offset, and and PIXELS for the Y screen offset. The Offset is in
+ // OpenGL coordinates with the origin in the lower-left corner, as is the Point. This offset
+ // translates the origin from the lower-left to the upper-left corner.
+ this.screenOffset = new Offset(screenLocation.getX(), screenLocation.getY(), AVKey.PIXELS, AVKey.PIXELS);
this.imageOffset = new Offset(0.5, 0.5, AVKey.FRACTION, AVKey.FRACTION);
// Set cached screen location to the initial screen location so that it can be retrieved if getScreenLocation()
// is called before the image is rendered. This maintains backward compatibility with the previous behavior of
// ScreenImage.
- this.awtScreenLocation = new Point(screenLocation);
+ this.screenLocation = new Point(screenLocation);
}
/**
@@ -544,12 +536,7 @@ else if (this.getImageSource() == null) // If no image source is set, draw a rec
{
this.screenLocation = new Point(viewportWidth / 2, viewportHeight / 2);
}
-
- // Convert the screen location from OpenGL to AWT coordinates and store the result in awtScreenLocation. The
- // awtScreenLocation property is used in getScreenLocation to indicate the screen location in AWT
- // coordinates.
- this.awtScreenLocation = new Point(this.screenLocation.x, viewportHeight - this.screenLocation.y);
-
+
Point.Double overlayPoint;
if (this.imageOffset != null)
overlayPoint = this.imageOffset.computeOffset(this.width, this.height, null, null);
diff --git a/src/gov/nasa/worldwind/render/SurfaceText.java b/src/gov/nasa/worldwind/render/SurfaceText.java
index 3edba40f70..e6bca960ce 100644
--- a/src/gov/nasa/worldwind/render/SurfaceText.java
+++ b/src/gov/nasa/worldwind/render/SurfaceText.java
@@ -36,6 +36,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.Arrays;
diff --git a/src/gov/nasa/worldwind/render/TextRenderer.java b/src/gov/nasa/worldwind/render/TextRenderer.java
deleted file mode 100644
index 7ed52bbb85..0000000000
--- a/src/gov/nasa/worldwind/render/TextRenderer.java
+++ /dev/null
@@ -1,2095 +0,0 @@
-/*
- * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
- * Administrator of the National Aeronautics and Space Administration.
- * All rights reserved.
- *
- * The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- *
- * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
- * software:
- *
- * Jackson Parser – Licensed under Apache 2.0
- * GDAL – Licensed under MIT
- * JOGL – Licensed under Berkeley Software Distribution (BSD)
- * Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
- * A complete listing of 3rd Party software notices and licenses included in
- * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
- * notices and licenses PDF found in code directory.
- */
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-/**
- * @version $Id: TextRenderer.java 2387 2014-10-15 20:25:02Z tgaskins $
- */
-
-package gov.nasa.worldwind.render;
-
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.GLExtensions;
-import com.jogamp.opengl.util.FPSAnimator;
-import com.jogamp.opengl.util.awt.TextureRenderer;
-import com.jogamp.opengl.util.packrect.*;
-import com.jogamp.opengl.util.texture.TextureCoords;
-import jogamp.opengl.Debug;
-
-import com.jogamp.opengl.*;
-import com.jogamp.opengl.awt.GLCanvas;
-import com.jogamp.opengl.glu.GLU;
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.font.*;
-import java.awt.geom.*;
-import java.nio.*;
-import java.text.CharacterIterator;
-import java.util.*;
-import java.util.List;
-
-// For debugging purposes
-
-
-/** Renders bitmapped Java 2D text into an OpenGL window with high
- performance, full Unicode support, and a simple API. Performs
- appropriate caching of text rendering results in an OpenGL texture
- internally to avoid repeated font rasterization. The caching is
- completely automatic, does not require any user intervention, and
- has no visible controls in the public API.
-
- Using the {@link TextRenderer TextRenderer} is simple. Add a
- "TextRenderer renderer;
" field to your {@link
- com.jogamp.opengl.GLEventListener GLEventListener}. In your {@link
- com.jogamp.opengl.GLEventListener#init init} method, add:
-
-
- renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 36));
-
-
- In the {@link com.jogamp.opengl.GLEventListener#display display} method of your
- {@link com.jogamp.opengl.GLEventListener GLEventListener}, add:
-
- renderer.beginRendering(drawable.getWidth(), drawable.getHeight());
- // optionally set the color
- renderer.setColor(1.0f, 0.2f, 0.2f, 0.8f);
- renderer.draw("Text to draw", xPosition, yPosition);
- // ... more draw commands, color changes, etc.
- renderer.endRendering();
-
-
- Unless you are sharing textures and display lists between OpenGL
- contexts, you do not need to call the {@link #dispose dispose}
- method of the TextRenderer; the OpenGL resources it uses
- internally will be cleaned up automatically when the OpenGL
- context is destroyed.
-
- Note that the TextRenderer may cause the vertex and texture
- coordinate array buffer bindings to change, or to be unbound. This
- is important to note if you are using Vertex Buffer Objects (VBOs)
- in your application.
-
- Internally, the renderer uses a rectangle packing algorithm to
- pack both glyphs and full Strings' rendering results (which are
- variable size) onto a larger OpenGL texture. The internal backing
- store is maintained using a {@link
- com.jogamp.opengl.util.awt.TextureRenderer TextureRenderer}. A least
- recently used (LRU) algorithm is used to discard previously
- rendered strings; the specific algorithm is undefined, but is
- currently implemented by flushing unused Strings' rendering
- results every few hundred rendering cycles, where a rendering
- cycle is defined as a pair of calls to {@link #beginRendering
- beginRendering} / {@link #endRendering endRendering}.
-
- @author John Burkey
- @author Kenneth Russell
-*/
-public class TextRenderer {
- private static final boolean DEBUG;
-
- static {
- Debug.initSingleton();
- DEBUG = Debug.isPropertyDefined("jogl.debug.TextRenderer", true);
- }
-
- // These are occasionally useful for more in-depth debugging
- private static boolean DISABLE_GLYPH_CACHE = false;
- private static final boolean DRAW_BBOXES = false;
- static
- {
- String arg = System.getProperty("gov.nasa.worldwind.textrender.useglyphcache");
- if (arg != null && arg.toLowerCase().startsWith("f"))
- DISABLE_GLYPH_CACHE = true;
- }
-
- static final int kSize = 256;
-
- // Every certain number of render cycles, flush the strings which
- // haven't been used recently
- private static final int CYCLES_PER_FLUSH = 100;
-
- // The amount of vertical dead space on the backing store before we
- // force a compaction
- private static final float MAX_VERTICAL_FRAGMENTATION = 0.7f;
- static final int kQuadsPerBuffer = 100;
- static final int kCoordsPerVertVerts = 3;
- static final int kCoordsPerVertTex = 2;
- static final int kVertsPerQuad = 4;
- static final int kTotalBufferSizeVerts = kQuadsPerBuffer * kVertsPerQuad;
- static final int kTotalBufferSizeCoordsVerts = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertVerts;
- static final int kTotalBufferSizeCoordsTex = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertTex;
- static final int kTotalBufferSizeBytesVerts = kTotalBufferSizeCoordsVerts * 4;
- static final int kTotalBufferSizeBytesTex = kTotalBufferSizeCoordsTex * 4;
- static final int kSizeInBytes_OneVertices_VertexData = kCoordsPerVertVerts * 4;
- static final int kSizeInBytes_OneVertices_TexData = kCoordsPerVertTex * 4;
- private final Font font;
- private final boolean antialiased;
- private final boolean useFractionalMetrics;
-
- // Whether we're attempting to use automatic mipmap generation support
- private boolean mipmap;
- private RectanglePacker packer;
- private boolean haveMaxSize;
- private final RenderDelegate renderDelegate;
- private TextureRenderer cachedBackingStore;
- private Graphics2D cachedGraphics;
- private FontRenderContext cachedFontRenderContext;
- private final Map stringLocations = new HashMap();
- private final GlyphProducer mGlyphProducer;
-
- private int numRenderCycles;
-
- // Need to keep track of whether we're in a beginRendering() /
- // endRendering() cycle so we can re-enter the exact same state if
- // we have to reallocate the backing store
- private boolean inBeginEndPair;
- private boolean isOrthoMode;
- private int beginRenderingWidth;
- private int beginRenderingHeight;
- private boolean beginRenderingDepthTestDisabled;
-
- // For resetting the color after disposal of the old backing store
- private boolean haveCachedColor;
- private float cachedR;
- private float cachedG;
- private float cachedB;
- private float cachedA;
- private Color cachedColor;
- private boolean needToResetColor;
-
- // For debugging only
- private Frame dbgFrame;
-
- // Debugging purposes only
- private boolean debugged;
- Pipelined_QuadRenderer mPipelinedQuadRenderer;
-
- //emzic: added boolean flag
- private boolean useVertexArrays = true;
-
- //emzic: added boolean flag
- private boolean isExtensionAvailable_GL_VERSION_1_5;
- private boolean checkFor_isExtensionAvailable_GL_VERSION_1_5;
-
- // Whether GL_LINEAR filtering is enabled for the backing store
- private boolean smoothing = true;
-
- /** Creates a new TextRenderer with the given font, using no
- antialiasing or fractional metrics, and the default
- RenderDelegate. Equivalent to TextRenderer(font, false,
- false)
.
-
- @param font the font to render with
- */
- public TextRenderer(Font font) {
- this(font, false, false, null, false);
- }
-
- /** Creates a new TextRenderer with the given font, using no
- antialiasing or fractional metrics, and the default
- RenderDelegate. If mipmap
is true, attempts to use
- OpenGL's automatic mipmap generation for better smoothing when
- rendering the TextureRenderer's contents at a distance.
- Equivalent to TextRenderer(font, false, false)
.
-
- @param font the font to render with
- @param mipmap whether to attempt use of automatic mipmap generation
- */
- public TextRenderer(Font font, boolean mipmap) {
- this(font, false, false, null, mipmap);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and default RenderDelegate. The
- antialiased
and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. No mipmap support is requested. Equivalent to
- TextRenderer(font, antialiased, useFractionalMetrics,
- null)
.
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics) {
- this(font, antialiased, useFractionalMetrics, null, false);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and given RenderDelegate. The
- antialiased
and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. The renderDelegate
provides more control
- over the text rendered. No mipmap support is requested.
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- @param renderDelegate the render delegate to use to draw the
- text's bitmap, or null to use the default one
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate) {
- this(font, antialiased, useFractionalMetrics, renderDelegate, false);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and given RenderDelegate. The
- antialiased
and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. The renderDelegate
provides more control
- over the text rendered. If mipmap
is true, attempts
- to use OpenGL's automatic mipmap generation for better smoothing
- when rendering the TextureRenderer's contents at a distance.
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- @param renderDelegate the render delegate to use to draw the
- text's bitmap, or null to use the default one
- @param mipmap whether to attempt use of automatic mipmap generation
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate,
- boolean mipmap) {
- this.font = font;
- this.antialiased = antialiased;
- this.useFractionalMetrics = useFractionalMetrics;
- this.mipmap = mipmap;
-
- // FIXME: consider adjusting the size based on font size
- // (it will already automatically resize if necessary)
- packer = new RectanglePacker(new Manager(), kSize, kSize);
-
- if (renderDelegate == null) {
- renderDelegate = new DefaultRenderDelegate();
- }
-
- this.renderDelegate = renderDelegate;
-
- mGlyphProducer = new GlyphProducer(font.getNumGlyphs());
- }
-
- /**
- * Returns the bounding rectangle of the given String, assuming it was rendered at the origin.See
- * {@link #getBounds(CharSequence) getBounds(CharSequence)}.
- *
- * @param str The string.
- * @return The bounding rectangle for str.
- */
- public Rectangle2D getBounds(String str) {
- return getBounds((CharSequence) str);
- }
-
- /**
- * Returns the bounding rectangle of the given CharSequence, assuming it was rendered at the origin.The coordinate
- * system of the returned rectangle is Java 2D's, with increasing Y coordinates in the downward direction.The
- * relative coordinate (0, 0) in the returned rectangle corresponds to the baseline of the leftmost character of the
- * rendered string, in similar fashion to the results returned by, for example,
- * {@link java.awt.font.GlyphVector#getVisualBounds}. Most applications will use only the width and height of the
- * returned Rectangle for the purposes of centering or justifying the String. It is not specified which Java 2D
- * bounds ({@link
- * java.awt.font.GlyphVector#getVisualBounds getVisualBounds},
- * {@link java.awt.font.GlyphVector#getPixelBounds getPixelBounds}, etc.) the returned bounds correspond to,
- * although every effort is made to ensure an accurate bound.
- *
- * @param str The string.
- * @return The bounds of the string.
- */
- public Rectangle2D getBounds(CharSequence str) {
- // FIXME: this should be more optimized and use the glyph cache
- Rect r = stringLocations.get(str);
-
- if (r != null) {
- TextData data = (TextData) r.getUserData();
-
- // Reconstitute the Java 2D results based on the cached values
- return new Rectangle2D.Double(-data.origin().x, -data.origin().y,
- r.w(), r.h());
- }
-
- // Must return a Rectangle compatible with the layout algorithm --
- // must be idempotent
- return normalize(renderDelegate.getBounds(str, font,
- getFontRenderContext()));
- }
-
- /**
- * Returns the Font this renderer is using.
- *
- * @return The Font.
- */
- public Font getFont() {
- return font;
- }
-
- /**
- * * Returns a FontRenderContext which can be used for external text-related size computations.This object should be
- * considered transient and may become invalidated between
- * {@link #beginRendering beginRendering} / {@link #endRendering endRendering} pairs.
- *
- * @return A FontRenderContext.
- */
- public FontRenderContext getFontRenderContext() {
- if (cachedFontRenderContext == null) {
- cachedFontRenderContext = getGraphics2D().getFontRenderContext();
- }
-
- return cachedFontRenderContext;
- }
-
- /** Begins rendering with this {@link TextRenderer TextRenderer}
- into the current OpenGL drawable, pushing the projection and
- modelview matrices and some state bits and setting up a
- two-dimensional orthographic projection with (0, 0) as the
- lower-left coordinate and (width, height) as the upper-right
- coordinate. Binds and enables the internal OpenGL texture
- object, sets the texture environment mode to GL_MODULATE, and
- changes the current color to the last color set with this
- TextRenderer via {@link #setColor setColor}. This method
- disables the depth test and is equivalent to
- beginRendering(width, height, true).
-
- @param width the width of the current on-screen OpenGL drawable
- @param height the height of the current on-screen OpenGL drawable
- @throws com.jogamp.opengl.GLException If an OpenGL context is not current when this method is called
- */
- public void beginRendering(int width, int height) throws GLException {
- beginRendering(width, height, true);
- }
-
- /** Begins rendering with this {@link TextRenderer TextRenderer}
- into the current OpenGL drawable, pushing the projection and
- modelview matrices and some state bits and setting up a
- two-dimensional orthographic projection with (0, 0) as the
- lower-left coordinate and (width, height) as the upper-right
- coordinate. Binds and enables the internal OpenGL texture
- object, sets the texture environment mode to GL_MODULATE, and
- changes the current color to the last color set with this
- TextRenderer via {@link #setColor setColor}. Disables the depth
- test if the disableDepthTest argument is true.
-
- @param width the width of the current on-screen OpenGL drawable
- @param height the height of the current on-screen OpenGL drawable
- @param disableDepthTest whether to disable the depth test
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void beginRendering(int width, int height, boolean disableDepthTest)
- throws GLException {
- beginRendering(true, width, height, disableDepthTest);
- }
-
- /** Begins rendering of 2D text in 3D with this {@link TextRenderer
- TextRenderer} into the current OpenGL drawable. Assumes the end
- user is responsible for setting up the modelview and projection
- matrices, and will render text using the {@link #draw3D draw3D}
- method. This method pushes some OpenGL state bits, binds and
- enables the internal OpenGL texture object, sets the texture
- environment mode to GL_MODULATE, and changes the current color
- to the last color set with this TextRenderer via {@link
- #setColor setColor}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void begin3DRendering() throws GLException {
- beginRendering(false, 0, 0, false);
- }
-
- /** Changes the current color of this TextRenderer to the supplied
- one. The default color is opaque white.
-
- @param color the new color to use for rendering text
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void setColor(Color color) throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor != null) &&
- color.equals(cachedColor));
-
- if (!noNeedForFlush) {
- flushGlyphPipeline();
- }
-
- getBackingStore().setColor(color);
- haveCachedColor = true;
- cachedColor = color;
- }
-
- /** Changes the current color of this TextRenderer to the supplied
- one, where each component ranges from 0.0f - 1.0f. The alpha
- component, if used, does not need to be premultiplied into the
- color channels as described in the documentation for {@link
- com.jogamp.opengl.util.texture.Texture Texture}, although
- premultiplied colors are used internally. The default color is
- opaque white.
-
- @param r the red component of the new color
- @param g the green component of the new color
- @param b the blue component of the new color
- @param a the alpha component of the new color, 0.0f = completely
- transparent, 1.0f = completely opaque
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void setColor(float r, float g, float b, float a)
- throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor == null) &&
- (r == cachedR) && (g == cachedG) && (b == cachedB) &&
- (a == cachedA));
-
- if (!noNeedForFlush) {
- flushGlyphPipeline();
- }
-
- getBackingStore().setColor(r, g, b, a);
- haveCachedColor = true;
- cachedR = r;
- cachedG = g;
- cachedB = b;
- cachedA = a;
- cachedColor = null;
- }
-
- /** Draws the supplied CharSequence at the desired location using
- the renderer's current color. The baseline of the leftmost
- character is at position (x, y) specified in OpenGL coordinates,
- where the origin is at the lower-left of the drawable and the Y
- coordinate increases in the upward direction.
-
- @param str the string to draw
- @param x the x coordinate at which to draw
- @param y the y coordinate at which to draw
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void draw(CharSequence str, int x, int y) throws GLException {
- draw3D(str, x, y, 0, 1);
- }
-
- /**
- * * Draws the supplied String at the desired location using the renderer's current color.See
- * {@link #draw(CharSequence, int, int) draw(CharSequence, int, int)}.
- *
- * @param str The string to draw.
- * @param x The desired x location.
- * @param y The desired y location.
- */
- public void draw(String str, int x, int y) throws GLException {
- draw3D(str, x, y, 0, 1);
- }
-
- /** Draws the supplied CharSequence at the desired 3D location using
- the renderer's current color. The baseline of the leftmost
- character is placed at position (x, y, z) in the current
- coordinate system.
-
- @param str the string to draw
- @param x the x coordinate at which to draw
- @param y the y coordinate at which to draw
- @param z the z coordinate at which to draw
- @param scaleFactor a uniform scale factor applied to the width and height of the drawn rectangle
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- internal_draw3D(str, x, y, z, scaleFactor);
- }
-
- /**
- * * Draws the supplied String at the desired 3D location using the renderer's current color.See {@link #draw3D(CharSequence, float, float, float, float) draw3D(CharSequence, float, float,
- * float, float)}.
- *
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- * @param z The z location.
- * @param scaleFactor The scale factor.
- */
- public void draw3D(String str, float x, float y, float z, float scaleFactor) {
- internal_draw3D(str, x, y, z, scaleFactor);
- }
-
- /**
- * Returns the pixel width of the given character.
- *
- * @param inChar The character to measure.
- * @return The pixel width.
- */
- public float getCharWidth(char inChar) {
- return mGlyphProducer.getGlyphPixelWidth(inChar);
- }
-
- /** Causes the TextRenderer to flush any internal caches it may be
- maintaining and draw its rendering results to the screen. This
- should be called after each call to draw() if you are setting
- OpenGL state such as the modelview matrix between calls to
- draw(). */
- public void flush() {
- flushGlyphPipeline();
- }
-
- /** Ends a render cycle with this {@link TextRenderer TextRenderer}.
- Restores the projection and modelview matrices as well as
- several OpenGL state bits. Should be paired with {@link
- #beginRendering beginRendering}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void endRendering() throws GLException {
- endRendering(true);
- }
-
- /** Ends a 3D render cycle with this {@link TextRenderer TextRenderer}.
- Restores several OpenGL state bits. Should be paired with {@link
- #begin3DRendering begin3DRendering}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void end3DRendering() throws GLException {
- endRendering(false);
- }
-
- /** Disposes of all resources this TextRenderer is using. It is not
- valid to use the TextRenderer after this method is called.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void dispose() throws GLException {
- packer.dispose();
- packer = null;
- cachedBackingStore = null;
- cachedGraphics = null;
- cachedFontRenderContext = null;
-
- if (dbgFrame != null) {
- dbgFrame.dispose();
- }
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- private static Rectangle2D preNormalize(Rectangle2D src) {
- // Need to round to integer coordinates
- // Also give ourselves a little slop around the reported
- // bounds of glyphs because it looks like neither the visual
- // nor the pixel bounds works perfectly well
- int minX = (int) Math.floor(src.getMinX()) - 1;
- int minY = (int) Math.floor(src.getMinY()) - 1;
- int maxX = (int) Math.ceil(src.getMaxX()) + 1;
- int maxY = (int) Math.ceil(src.getMaxY()) + 1;
- return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
- }
-
-
- private Rectangle2D normalize(Rectangle2D src) {
- // Give ourselves a boundary around each entity on the backing
- // store in order to prevent bleeding of nearby Strings due to
- // the fact that we use linear filtering
-
- // NOTE that this boundary is quite heuristic and is related
- // to how far away in 3D we may view the text --
- // heuristically, 1.5% of the font's height
- int boundary = (int) Math.max(1, 0.015 * font.getSize());
-
- return new Rectangle2D.Double((int) Math.floor(src.getMinX() - boundary),
- (int) Math.floor(src.getMinY() - boundary),
- (int) Math.ceil(src.getWidth() + 2 * boundary),
- (int) Math.ceil(src.getHeight()) + 2 * boundary);
- }
-
- private TextureRenderer getBackingStore() {
- TextureRenderer renderer = (TextureRenderer) packer.getBackingStore();
-
- if (renderer != cachedBackingStore) {
- // Backing store changed since last time; discard any cached Graphics2D
- if (cachedGraphics != null) {
- cachedGraphics.dispose();
- cachedGraphics = null;
- cachedFontRenderContext = null;
- }
-
- cachedBackingStore = renderer;
- }
-
- return cachedBackingStore;
- }
-
- private Graphics2D getGraphics2D() {
- TextureRenderer renderer = getBackingStore();
-
- if (cachedGraphics == null) {
- cachedGraphics = renderer.createGraphics();
-
- // Set up composite, font and rendering hints
- cachedGraphics.setComposite(AlphaComposite.Src);
- cachedGraphics.setColor(Color.WHITE);
- cachedGraphics.setFont(font);
- cachedGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- (antialiased ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
- : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
- cachedGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- (useFractionalMetrics
- ? RenderingHints.VALUE_FRACTIONALMETRICS_ON
- : RenderingHints.VALUE_FRACTIONALMETRICS_OFF));
- }
-
- return cachedGraphics;
- }
-
- private void beginRendering(boolean ortho, int width, int height,
- boolean disableDepthTestForOrtho) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- if (DEBUG && !debugged) {
- debug(gl);
- }
-
- inBeginEndPair = true;
- isOrthoMode = ortho;
- beginRenderingWidth = width;
- beginRenderingHeight = height;
- beginRenderingDepthTestDisabled = disableDepthTestForOrtho;
-
- if (ortho) {
- getBackingStore().beginOrthoRendering(width, height,
- disableDepthTestForOrtho);
- } else {
- getBackingStore().begin3DRendering();
- }
-
- // Push client attrib bits used by the pipelined quad renderer
- gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS);
-
- if (!haveMaxSize) {
- // Query OpenGL for the maximum texture size and set it in the
- // RectanglePacker to keep it from expanding too large
- int[] sz = new int[1];
- gl.glGetIntegerv(GL2.GL_MAX_TEXTURE_SIZE, sz, 0);
- packer.setMaxSize(sz[0], sz[0]);
- haveMaxSize = true;
- }
-
- if (needToResetColor && haveCachedColor) {
- if (cachedColor == null) {
- getBackingStore().setColor(cachedR, cachedG, cachedB, cachedA);
- } else {
- getBackingStore().setColor(cachedColor);
- }
-
- needToResetColor = false;
- }
-
- // Disable future attempts to use mipmapping if TextureRenderer
- // doesn't support it
- if (mipmap && !getBackingStore().isUsingAutoMipmapGeneration()) {
- if (DEBUG) {
- System.err.println("Disabled mipmapping in TextRenderer");
- }
-
- mipmap = false;
- }
- }
-
- /**
- * emzic: here the call to glBindBuffer crashes on certain graphicscard/driver combinations
- * this is why the ugly try-catch block has been added, which falls back to the old textrenderer
- *
- * @param ortho
- * @throws GLException
- */
- private void endRendering(boolean ortho) throws GLException {
- flushGlyphPipeline();
-
- inBeginEndPair = false;
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- // Pop client attrib bits used by the pipelined quad renderer
- gl.glPopClientAttrib();
-
- // The OpenGL spec is unclear about whether this changes the
- // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER
- // binding
- if (getUseVertexArrays() && is15Available(gl)) {
- try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- }
- }
-
- if (ortho) {
- getBackingStore().endOrthoRendering();
- } else {
- getBackingStore().end3DRendering();
- }
-
- if (++numRenderCycles >= CYCLES_PER_FLUSH) {
- numRenderCycles = 0;
-
- if (DEBUG) {
- System.err.println("Clearing unused entries in endRendering()");
- }
-
- clearUnusedEntries();
- }
- }
-
- private void clearUnusedEntries() {
- final java.util.List deadRects = new ArrayList();
-
- // Iterate through the contents of the backing store, removing
- // text strings that haven't been used recently
- packer.visit(new RectVisitor() {
- @Override
- public void visit(Rect rect) {
- TextData data = (TextData) rect.getUserData();
-
- if (data.used()) {
- data.clearUsed();
- } else {
- deadRects.add(rect);
- }
- }
- });
-
- for (Rect r : deadRects) {
- packer.remove(r);
- stringLocations.remove(((TextData) r.getUserData()).string());
-
- int unicodeToClearFromCache = ((TextData) r.getUserData()).unicodeID;
-
- if (unicodeToClearFromCache > 0) {
- mGlyphProducer.clearCacheEntry(unicodeToClearFromCache);
- }
-
- // if (DEBUG) {
- // Graphics2D g = getGraphics2D();
- // g.setComposite(AlphaComposite.Clear);
- // g.fillRect(r.x(), r.y(), r.w(), r.h());
- // g.setComposite(AlphaComposite.Src);
- // }
- }
-
- // If we removed dead rectangles this cycle, try to do a compaction
- float frag = packer.verticalFragmentationRatio();
-
- if (!deadRects.isEmpty() && (frag > MAX_VERTICAL_FRAGMENTATION)) {
- if (DEBUG) {
- System.err.println(
- "Compacting TextRenderer backing store due to vertical fragmentation " +
- frag);
- }
-
- packer.compact();
- }
-
- if (DEBUG) {
- getBackingStore().markDirty(0, 0, getBackingStore().getWidth(),
- getBackingStore().getHeight());
- }
- }
-
- private void internal_draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- for (Glyph glyph : mGlyphProducer.getGlyphs(str)) {
- float advance = glyph.draw3D(x, y, z, scaleFactor);
- x += advance * scaleFactor;
- }
- }
-
- private void flushGlyphPipeline() {
- if (mPipelinedQuadRenderer != null) {
- mPipelinedQuadRenderer.draw();
- }
- }
-
- private void draw3D_ROBUST(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- String curStr;
- if (str instanceof String) {
- curStr = (String) str;
- } else {
- curStr = str.toString();
- }
-
- // Look up the string on the backing store
- Rect rect = stringLocations.get(curStr);
-
- if (rect == null) {
- // Rasterize this string and place it on the backing store
- Graphics2D g = getGraphics2D();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(curStr, font, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
- (int) -bbox.getMinY());
- rect = new Rect(0, 0, (int) bbox.getWidth(),
- (int) bbox.getHeight(),
- new TextData(curStr, origin, origBBox, -1));
-
- packer.add(rect);
- stringLocations.put(curStr, rect);
-
- // Re-fetch the Graphics2D in case the addition of the rectangle
- // caused the old backing store to be thrown away
- g = getGraphics2D();
-
- // OK, should now have an (x, y) for this rectangle; rasterize
- // the String
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
-
- // Clear out the area we're going to draw into
- g.setComposite(AlphaComposite.Clear);
- g.fillRect(rect.x(), rect.y(), rect.w(), rect.h());
- g.setComposite(AlphaComposite.Src);
-
- // Draw the string
- renderDelegate.draw(g, curStr, strx, stry);
-
- if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
- // Draw a bounding box on the backing store
- g.drawRect(strx - data.origOriginX(),
- stry - data.origOriginY(),
- (int) data.origRect().getWidth(),
- (int) data.origRect().getHeight());
- g.drawRect(strx - data.origin().x,
- stry - data.origin().y,
- rect.w(),
- rect.h());
- }
-
- // Mark this region of the TextureRenderer as dirty
- getBackingStore().markDirty(rect.x(), rect.y(), rect.w(),
- rect.h());
- }
-
- // OK, now draw the portion of the backing store to the screen
- TextureRenderer renderer = getBackingStore();
-
- // NOTE that the rectangles managed by the packer have their
- // origin at the upper-left but the TextureRenderer's origin is
- // at its lower left!!!
- TextData data = (TextData) rect.getUserData();
- data.markUsed();
-
- Rectangle2D origRect = data.origRect();
-
- // Align the leftmost point of the baseline to the (x, y, z) coordinate requested
- renderer.draw3DRect(x - (scaleFactor * data.origOriginX()),
- y - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY())), z,
- rect.x() + (data.origin().x - data.origOriginX()),
- renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
- (data.origin().y - data.origOriginY()),
- (int) origRect.getWidth(), (int) origRect.getHeight(), scaleFactor);
- }
-
- //----------------------------------------------------------------------
- // Debugging functionality
- //
- private void debug(GL gl) {
- dbgFrame = new Frame("TextRenderer Debug Output");
-
- GLCanvas dbgCanvas = new GLCanvas(new GLCapabilities(gl.getGLProfile()));
- dbgCanvas.setSharedContext(GLContext.getCurrent());
- dbgCanvas.addGLEventListener(new DebugListener(gl, dbgFrame));
- dbgFrame.add(dbgCanvas);
-
- final FPSAnimator anim = new FPSAnimator(dbgCanvas, 10);
- dbgFrame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- // Run this on another thread than the AWT event queue to
- // make sure the call to Animator.stop() completes before
- // exiting
- new Thread(new Runnable() {
- @Override
- public void run() {
- anim.stop();
- }
- }).start();
- }
- });
- dbgFrame.setSize(kSize, kSize);
- dbgFrame.setVisible(true);
- anim.start();
- debugged = true;
- }
-
- /** Class supporting more full control over the process of rendering
- the bitmapped text. Allows customization of whether the backing
- store text bitmap is full-color or intensity only, the size of
- each individual rendered text rectangle, and the contents of
- each individual rendered text string. The default implementation
- of this interface uses an intensity-only texture, a
- closely-cropped rectangle around the text, and renders text
- using the color white, which is modulated by the set color
- during the rendering process. */
- public static interface RenderDelegate {
- /**
- * Indicates whether the backing store of this TextRenderer should be intensity-only (the default) or
- * full-color.
- *
- * @return whether or not intensity only is on.
- */
- public boolean intensityOnly();
-
- /**
- * Computes the bounds of the given String relative to the origin.
- *
- * @param str The string to process.
- * @param font The font to use.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(String str, Font font,
- FontRenderContext frc);
-
- /**
- * Computes the bounds of the given character sequence relative to the origin.
- *
- * @param str The string to process.
- * @param font The font to use.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(CharSequence str, Font font,
- FontRenderContext frc);
-
- /**
- * Computes the bounds of the given GlyphVector, already assumed to have been created for a particular Font,
- * relative to the origin.
- *
- * @param gv The string to process.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc);
-
- /**
- * * Render the passed character sequence at the designated location using the supplied Graphics2D instance.The
- * surrounding region will already have been cleared to the RGB color (0, 0, 0) with zero alpha.The initial
- * drawing context of the passed Graphics2D will be set to use AlphaComposite.Src, the color white, the Font
- * specified in the TextRenderer's constructor, and the rendering hints specified in the TextRenderer
- * constructor.Changes made by the end user may be visible in successive calls to this method, but are not
- * guaranteed to be preserved.Implementors of this method should reset the Graphics2D's state to that desired
- * each time this method is called, in particular those states which are not the defaults.
- *
- * @param graphics The canvas to draw on.
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- */
- public void draw(Graphics2D graphics, String str, int x, int y);
-
- /**
- * * Render the passed GlyphVector at the designated location using the supplied Graphics2D instance.The
- * surrounding region will already have been cleared to the RGB color (0, 0, 0) with zero alpha.The initial
- * drawing context of the passed Graphics2D will be set to use AlphaComposite.Src, the color white, the Font
- * specified in the TextRenderer's constructor, and the rendering hints specified in the TextRenderer
- * constructor.Changes made by the end user may be visible in successive calls to this method, but are not
- * guaranteed to be preserved.Implementors of this method should reset the Graphics2D's state to that desired
- * each time this method is called, in particular those states which are not the defaults.
- *
- * @param graphics The canvas to draw on.
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- */
- public void drawGlyphVector(Graphics2D graphics, GlyphVector str,
- int x, int y);
- }
-
- private static class CharSequenceIterator implements CharacterIterator {
- CharSequence mSequence;
- int mLength;
- int mCurrentIndex;
-
- CharSequenceIterator() {
- }
-
- CharSequenceIterator(CharSequence sequence) {
- initFromCharSequence(sequence);
- }
-
- public void initFromCharSequence(CharSequence sequence) {
- mSequence = sequence;
- mLength = mSequence.length();
- mCurrentIndex = 0;
- }
-
- @Override
- public char last() {
- mCurrentIndex = Math.max(0, mLength - 1);
-
- return current();
- }
-
- @Override
- public char current() {
- if ((mLength == 0) || (mCurrentIndex >= mLength)) {
- return CharacterIterator.DONE;
- }
-
- return mSequence.charAt(mCurrentIndex);
- }
-
- @Override
- public char next() {
- mCurrentIndex++;
-
- return current();
- }
-
- @Override
- public char previous() {
- mCurrentIndex = Math.max(mCurrentIndex - 1, 0);
-
- return current();
- }
-
- @Override
- public char setIndex(int position) {
- mCurrentIndex = position;
-
- return current();
- }
-
- @Override
- public int getBeginIndex() {
- return 0;
- }
-
- @Override
- public int getEndIndex() {
- return mLength;
- }
-
- @Override
- public int getIndex() {
- return mCurrentIndex;
- }
-
- @Override
- public Object clone() {
- CharSequenceIterator iter = new CharSequenceIterator(mSequence);
- iter.mCurrentIndex = mCurrentIndex;
-
- return iter;
- }
-
- @Override
- public char first() {
- if (mLength == 0) {
- return CharacterIterator.DONE;
- }
-
- mCurrentIndex = 0;
-
- return current();
- }
- }
-
- // Data associated with each rectangle of text
- static class TextData {
- // Back-pointer to String this TextData describes, if it
- // represents a String rather than a single glyph
- private final String str;
-
- // If this TextData represents a single glyph, this is its
- // unicode ID
- int unicodeID;
-
- // The following must be defined and used VERY precisely. This is
- // the offset from the upper-left corner of this rectangle (Java
- // 2D coordinate system) at which the string must be rasterized in
- // order to fit within the rectangle -- the leftmost point of the
- // baseline.
- private final Point origin;
-
- // This represents the pre-normalized rectangle, which fits
- // within the rectangle on the backing store. We keep a
- // one-pixel border around entries on the backing store to
- // prevent bleeding of adjacent letters when using GL_LINEAR
- // filtering for rendering. The origin of this rectangle is
- // equivalent to the origin above.
- private final Rectangle2D origRect;
-
- private boolean used; // Whether this text was used recently
-
- TextData(String str, Point origin, Rectangle2D origRect, int unicodeID) {
- this.str = str;
- this.origin = origin;
- this.origRect = origRect;
- this.unicodeID = unicodeID;
- }
-
- String string() {
- return str;
- }
-
- Point origin() {
- return origin;
- }
-
- // The following three methods are used to locate the glyph
- // within the expanded rectangle coming from normalize()
- int origOriginX() {
- return (int) -origRect.getMinX();
- }
-
- int origOriginY() {
- return (int) -origRect.getMinY();
- }
-
- Rectangle2D origRect() {
- return origRect;
- }
-
- boolean used() {
- return used;
- }
-
- void markUsed() {
- used = true;
- }
-
- void clearUsed() {
- used = false;
- }
- }
-
- class Manager implements BackingStoreManager {
- private Graphics2D g;
-
- @Override
- public Object allocateBackingStore(int w, int h) {
- // FIXME: should consider checking Font's attributes to see
- // whether we're likely to need to support a full RGBA backing
- // store (i.e., non-default Paint, foreground color, etc.), but
- // for now, let's just be more efficient
- TextureRenderer renderer;
-
- if (renderDelegate.intensityOnly()) {
- renderer = TextureRenderer.createAlphaOnlyRenderer(w, h, mipmap);
- } else {
- renderer = new TextureRenderer(w, h, true, mipmap);
- }
- renderer.setSmoothing(smoothing);
-
- if (DEBUG) {
- System.err.println(" TextRenderer allocating backing store " +
- w + " x " + h);
- }
-
- return renderer;
- }
-
- @Override
- public void deleteBackingStore(Object backingStore) {
- ((TextureRenderer) backingStore).dispose();
- }
-
- @Override
- public boolean preExpand(Rect cause, int attemptNumber) {
- // Only try this one time; clear out potentially obsolete entries
- // NOTE: this heuristic and the fact that it clears the used bit
- // of all entries seems to cause cycling of entries in some
- // situations, where the backing store becomes small compared to
- // the amount of text on the screen (see the TextFlow demo) and
- // the entries continually cycle in and out of the backing
- // store, decreasing performance. If we added a little age
- // information to the entries, and only cleared out entries
- // above a certain age, this behavior would be eliminated.
- // However, it seems the system usually stabilizes itself, so
- // for now we'll just keep things simple. Note that if we don't
- // clear the used bit here, the backing store tends to increase
- // very quickly to its maximum size, at least with the TextFlow
- // demo when the text is being continually re-laid out.
- if (attemptNumber == 0) {
- if (DEBUG) {
- System.err.println(
- "Clearing unused entries in preExpand(): attempt number " +
- attemptNumber);
- }
-
- if (inBeginEndPair) {
- // Draw any outstanding glyphs
- flush();
- }
-
- clearUnusedEntries();
-
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean additionFailed(Rect cause, int attemptNumber) {
- // Heavy hammer -- might consider doing something different
- packer.clear();
- stringLocations.clear();
- mGlyphProducer.clearAllCacheEntries();
-
- if (DEBUG) {
- System.err.println(
- " *** Cleared all text because addition failed ***");
- }
-
- if (attemptNumber == 0) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean canCompact() {
- return true;
- }
-
- @Override
- public void beginMovement(Object oldBackingStore, Object newBackingStore) {
- // Exit the begin / end pair if necessary
- if (inBeginEndPair) {
- // Draw any outstanding glyphs
- flush();
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- // Pop client attrib bits used by the pipelined quad renderer
- gl.glPopClientAttrib();
-
- // The OpenGL spec is unclear about whether this changes the
- // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER
- // binding
- if (getUseVertexArrays() && is15Available(gl)) {
- try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- }
- }
-
- if (isOrthoMode) {
- ((TextureRenderer) oldBackingStore).endOrthoRendering();
- } else {
- ((TextureRenderer) oldBackingStore).end3DRendering();
- }
- }
-
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
- g = newRenderer.createGraphics();
- }
-
- @Override
- public void move(Object oldBackingStore, Rect oldLocation,
- Object newBackingStore, Rect newLocation) {
- TextureRenderer oldRenderer = (TextureRenderer) oldBackingStore;
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
-
- if (oldRenderer == newRenderer) {
- // Movement on the same backing store -- easy case
- g.copyArea(oldLocation.x(), oldLocation.y(), oldLocation.w(),
- oldLocation.h(), newLocation.x() - oldLocation.x(),
- newLocation.y() - oldLocation.y());
- } else {
- // Need to draw from the old renderer's image into the new one
- Image img = oldRenderer.getImage();
- g.drawImage(img, newLocation.x(), newLocation.y(),
- newLocation.x() + newLocation.w(),
- newLocation.y() + newLocation.h(), oldLocation.x(),
- oldLocation.y(), oldLocation.x() + oldLocation.w(),
- oldLocation.y() + oldLocation.h(), null);
- }
- }
-
- @Override
- public void endMovement(Object oldBackingStore, Object newBackingStore) {
- g.dispose();
-
- // Sync the whole surface
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
- newRenderer.markDirty(0, 0, newRenderer.getWidth(),
- newRenderer.getHeight());
-
- // Re-enter the begin / end pair if necessary
- if (inBeginEndPair) {
- if (isOrthoMode) {
- ((TextureRenderer) newBackingStore).beginOrthoRendering(beginRenderingWidth,
- beginRenderingHeight, beginRenderingDepthTestDisabled);
- } else {
- ((TextureRenderer) newBackingStore).begin3DRendering();
- }
-
- // Push client attrib bits used by the pipelined quad renderer
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS);
-
- if (haveCachedColor) {
- if (cachedColor == null) {
- ((TextureRenderer) newBackingStore).setColor(cachedR,
- cachedG, cachedB, cachedA);
- } else {
- ((TextureRenderer) newBackingStore).setColor(cachedColor);
- }
- }
- } else {
- needToResetColor = true;
- }
- }
- }
-
- public static class DefaultRenderDelegate implements RenderDelegate {
- @Override
- public boolean intensityOnly() {
- return true;
- }
-
- @Override
- public Rectangle2D getBounds(CharSequence str, Font font,
- FontRenderContext frc) {
- return getBounds(font.createGlyphVector(frc,
- new CharSequenceIterator(str)),
- frc);
- }
-
- @Override
- public Rectangle2D getBounds(String str, Font font,
- FontRenderContext frc) {
- return getBounds(font.createGlyphVector(frc, str), frc);
- }
-
- @Override
- public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc) {
- return gv.getVisualBounds();
- }
-
- @Override
- public void drawGlyphVector(Graphics2D graphics, GlyphVector str,
- int x, int y) {
- graphics.drawGlyphVector(str, x, y);
- }
-
- @Override
- public void draw(Graphics2D graphics, String str, int x, int y) {
- graphics.drawString(str, x, y);
- }
- }
-
- //----------------------------------------------------------------------
- // Glyph-by-glyph rendering support
- //
-
- // A temporary to prevent excessive garbage creation
- private final char[] singleUnicode = new char[1];
-
- /** A Glyph represents either a single unicode glyph or a
- substring of characters to be drawn. The reason for the dual
- behavior is so that we can take in a sequence of unicode
- characters and partition them into runs of individual glyphs,
- but if we encounter complex text and/or unicode sequences we
- don't understand, we can render them using the
- string-by-string method.
-
- Glyphs need to be able to re-upload themselves to the backing
- store on demand as we go along in the render sequence.
- */
-
- class Glyph {
- // If this Glyph represents an individual unicode glyph, this
- // is its unicode ID. If it represents a String, this is -1.
- private int unicodeID;
- // If the above field isn't -1, then these fields are used.
- // The glyph code in the font
- private int glyphCode;
- // The GlyphProducer which created us
- private GlyphProducer producer;
- // The advance of this glyph
- private float advance;
- // The GlyphVector for this single character; this is passed
- // in during construction but cleared during the upload
- // process
- private GlyphVector singleUnicodeGlyphVector;
- // The rectangle of this glyph on the backing store, or null
- // if it has been cleared due to space pressure
- private Rect glyphRectForTextureMapping;
- // If this Glyph represents a String, this is the sequence of
- // characters
- private String str;
- // Whether we need a valid advance when rendering this string
- // (i.e., whether it has other single glyphs coming after it)
- private boolean needAdvance;
-
- // Creates a Glyph representing an individual Unicode character
- public Glyph(int unicodeID,
- int glyphCode,
- float advance,
- GlyphVector singleUnicodeGlyphVector,
- GlyphProducer producer) {
- this.unicodeID = unicodeID;
- this.glyphCode = glyphCode;
- this.advance = advance;
- this.singleUnicodeGlyphVector = singleUnicodeGlyphVector;
- this.producer = producer;
- }
-
- // Creates a Glyph representing a sequence of characters, with
- // an indication of whether additional single glyphs are being
- // rendered after it
- public Glyph(String str, boolean needAdvance) {
- this.str = str;
- this.needAdvance = needAdvance;
- }
-
- /** Returns this glyph's unicode ID */
- public int getUnicodeID() {
- return unicodeID;
- }
-
- /** Returns this glyph's (font-specific) glyph code */
- public int getGlyphCode() {
- return glyphCode;
- }
-
- /** Returns the advance for this glyph */
- public float getAdvance() {
- return advance;
- }
-
- /** Draws this glyph and returns the (x) advance for this glyph */
- public float draw3D(float inX, float inY, float z, float scaleFactor) {
- if (str != null) {
- draw3D_ROBUST(str, inX, inY, z, scaleFactor);
- if (!needAdvance) {
- return 0;
- }
- // Compute and return the advance for this string
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), str);
- float totalAdvance = 0;
- for (int i = 0; i < gv.getNumGlyphs(); i++) {
- totalAdvance += gv.getGlyphMetrics(i).getAdvance();
- }
- return totalAdvance;
- }
-
- // This is the code path taken for individual glyphs
- if (glyphRectForTextureMapping == null) {
- upload();
- }
-
- try {
- if (mPipelinedQuadRenderer == null) {
- mPipelinedQuadRenderer = new Pipelined_QuadRenderer();
- }
-
- TextureRenderer renderer = getBackingStore();
- // Handles case where NPOT texture is used for backing store
- TextureCoords wholeImageTexCoords = renderer.getTexture().getImageTexCoords();
- float xScale = wholeImageTexCoords.right();
- float yScale = wholeImageTexCoords.bottom();
-
- Rect rect = glyphRectForTextureMapping;
- TextData data = (TextData) rect.getUserData();
- data.markUsed();
-
- Rectangle2D origRect = data.origRect();
-
- float x = inX - (scaleFactor * data.origOriginX());
- float y = inY - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY()));
-
- int texturex = rect.x() + (data.origin().x - data.origOriginX());
- int texturey = renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
- (data.origin().y - data.origOriginY());
- int width = (int) origRect.getWidth();
- int height = (int) origRect.getHeight();
-
- float tx1 = xScale * texturex / renderer.getWidth();
- float ty1 = yScale * (1.0f -
- ((float) texturey / (float) renderer.getHeight()));
- float tx2 = xScale * (texturex + width) / renderer.getWidth();
- float ty2 = yScale * (1.0f -
- ((float) (texturey + height) / (float) renderer.getHeight()));
-
- mPipelinedQuadRenderer.glTexCoord2f(tx1, ty1);
- mPipelinedQuadRenderer.glVertex3f(x, y, z);
- mPipelinedQuadRenderer.glTexCoord2f(tx2, ty1);
- mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor), y,
- z);
- mPipelinedQuadRenderer.glTexCoord2f(tx2, ty2);
- mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor),
- y + (height * scaleFactor), z);
- mPipelinedQuadRenderer.glTexCoord2f(tx1, ty2);
- mPipelinedQuadRenderer.glVertex3f(x,
- y + (height * scaleFactor), z);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return advance;
- }
-
- /** Notifies this glyph that it's been cleared out of the cache */
- public void clear() {
- glyphRectForTextureMapping = null;
- }
-
- private void upload() {
- GlyphVector gv = getGlyphVector();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(gv, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
- (int) -bbox.getMinY());
- Rect rect = new Rect(0, 0, (int) bbox.getWidth(),
- (int) bbox.getHeight(),
- new TextData(null, origin, origBBox, unicodeID));
- packer.add(rect);
- glyphRectForTextureMapping = rect;
- Graphics2D g = getGraphics2D();
- // OK, should now have an (x, y) for this rectangle; rasterize
- // the glyph
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
-
- // Clear out the area we're going to draw into
- g.setComposite(AlphaComposite.Clear);
- g.fillRect(rect.x(), rect.y(), rect.w(), rect.h());
- g.setComposite(AlphaComposite.Src);
-
- // Draw the string
- renderDelegate.drawGlyphVector(g, gv, strx, stry);
-
- if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
- // Draw a bounding box on the backing store
- g.drawRect(strx - data.origOriginX(),
- stry - data.origOriginY(),
- (int) data.origRect().getWidth(),
- (int) data.origRect().getHeight());
- g.drawRect(strx - data.origin().x,
- stry - data.origin().y,
- rect.w(),
- rect.h());
- }
-
- // Mark this region of the TextureRenderer as dirty
- getBackingStore().markDirty(rect.x(), rect.y(), rect.w(),
- rect.h());
- // Re-register ourselves with our producer
- producer.register(this);
- }
-
- private GlyphVector getGlyphVector() {
- GlyphVector gv = singleUnicodeGlyphVector;
- if (gv != null) {
- singleUnicodeGlyphVector = null; // Don't need this anymore
- return gv;
- }
- singleUnicode[0] = (char) unicodeID;
- return font.createGlyphVector(getFontRenderContext(), singleUnicode);
- }
- }
-
- class GlyphProducer {
- final int undefined = -2;
- FontRenderContext fontRenderContext;
- List glyphsOutput = new ArrayList();
- HashMap fullGlyphVectorCache = new HashMap();
- HashMap glyphMetricsCache = new HashMap();
- // The mapping from unicode character to font-specific glyph ID
- int[] unicodes2Glyphs;
- // The mapping from glyph ID to Glyph
- Glyph[] glyphCache;
- // We re-use this for each incoming string
- CharSequenceIterator iter = new CharSequenceIterator();
-
- GlyphProducer(int fontLengthInGlyphs) {
- unicodes2Glyphs = new int[512];
- glyphCache = new Glyph[fontLengthInGlyphs];
- clearAllCacheEntries();
- }
-
- public List getGlyphs(CharSequence inString) {
- glyphsOutput.clear();
- GlyphVector fullRunGlyphVector;
- fullRunGlyphVector = fullGlyphVectorCache.get(inString.toString());
- if (fullRunGlyphVector == null) {
- iter.initFromCharSequence(inString);
- fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), iter);
- fullGlyphVectorCache.put(inString.toString(), fullRunGlyphVector);
- }
- boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0);
- if (complex || DISABLE_GLYPH_CACHE) {
- // Punt to the robust version of the renderer
- glyphsOutput.add(new Glyph(inString.toString(), false));
- return glyphsOutput;
- }
-
- int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs();
- int i = 0;
- while (i < lengthInGlyphs) {
- Character letter = CharacterCache.valueOf(inString.charAt(i));
- GlyphMetrics metrics = glyphMetricsCache.get(letter);
- if (metrics == null) {
- metrics = fullRunGlyphVector.getGlyphMetrics(i);
- glyphMetricsCache.put(letter, metrics);
- }
- Glyph glyph = getGlyph(inString, metrics, i);
- if (glyph != null) {
- glyphsOutput.add(glyph);
- i++;
- } else {
- // Assemble a run of characters that don't fit in
- // the cache
- StringBuilder buf = new StringBuilder();
- while (i < lengthInGlyphs &&
- getGlyph(inString, fullRunGlyphVector.getGlyphMetrics(i), i) == null) {
- buf.append(inString.charAt(i++));
- }
- glyphsOutput.add(new Glyph(buf.toString(),
- // Any more glyphs after this run?
- i < lengthInGlyphs));
- }
- }
- return glyphsOutput;
- }
-
- public void clearCacheEntry(int unicodeID) {
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- Glyph glyph = glyphCache[glyphID];
- if (glyph != null) {
- glyph.clear();
- }
- glyphCache[glyphID] = null;
- }
- unicodes2Glyphs[unicodeID] = undefined;
- }
-
- public void clearAllCacheEntries() {
- for (int i = 0; i < unicodes2Glyphs.length; i++) {
- clearCacheEntry(i);
- }
- }
-
- public void register(Glyph glyph) {
- unicodes2Glyphs[glyph.getUnicodeID()] = glyph.getGlyphCode();
- glyphCache[glyph.getGlyphCode()] = glyph;
- }
-
- public float getGlyphPixelWidth(char unicodeID) {
- Glyph glyph = getGlyph(unicodeID);
- if (glyph != null) {
- return glyph.getAdvance();
- }
-
- // Have to do this the hard / uncached way
- singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(fontRenderContext,
- singleUnicode);
- return gv.getGlyphMetrics(0).getAdvance();
- }
-
- // Returns a glyph object for this single glyph. Returns null
- // if the unicode or glyph ID would be out of bounds of the
- // glyph cache.
- private Glyph getGlyph(CharSequence inString,
- GlyphMetrics glyphMetrics,
- int index) {
- char unicodeID = inString.charAt(index);
-
- if (unicodeID >= unicodes2Glyphs.length) {
- return null;
- }
-
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- return glyphCache[glyphID];
- }
-
- // Must fabricate the glyph
- singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
- return getGlyph(unicodeID, gv, glyphMetrics);
- }
-
- // It's unclear whether this variant might produce less
- // optimal results than if we can see the entire GlyphVector
- // for the incoming string
- private Glyph getGlyph(int unicodeID) {
- if (unicodeID >= unicodes2Glyphs.length) {
- return null;
- }
-
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- return glyphCache[glyphID];
- }
- singleUnicode[0] = (char) unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
- return getGlyph(unicodeID, gv, gv.getGlyphMetrics(0));
- }
-
- private Glyph getGlyph(int unicodeID,
- GlyphVector singleUnicodeGlyphVector,
- GlyphMetrics metrics) {
- int glyphCode = singleUnicodeGlyphVector.getGlyphCode(0);
- // Have seen huge glyph codes (65536) coming out of some fonts in some Unicode situations
- if (glyphCode >= glyphCache.length) {
- return null;
- }
- Glyph glyph = new Glyph(unicodeID,
- glyphCode,
- metrics.getAdvance(),
- singleUnicodeGlyphVector,
- this);
- register(glyph);
- return glyph;
- }
- }
-
- private static class CharacterCache {
- private CharacterCache() {
- }
-
- static final Character CACHE[] = new Character[127 + 1];
-
- static {
- for (int i = 0; i < CACHE.length; i++) {
- CACHE[i] = (char) i;
- }
- }
-
- public static Character valueOf(char c) {
- if (c <= 127) { // must cache
- return CharacterCache.CACHE[c];
- }
- return c;
- }
- }
-
- class Pipelined_QuadRenderer {
- int mOutstandingGlyphsVerticesPipeline = 0;
- FloatBuffer mTexCoords;
- FloatBuffer mVertCoords;
- boolean usingVBOs;
- int mVBO_For_ResuableTileVertices;
- int mVBO_For_ResuableTileTexCoords;
-
- Pipelined_QuadRenderer() {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- mVertCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsVerts);
- mTexCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsTex);
-
- usingVBOs = getUseVertexArrays() && is15Available(gl);
-
- if (usingVBOs) {
- try {
- int[] vbos = new int[2];
- gl.glGenBuffers(2, IntBuffer.wrap(vbos));
-
- mVBO_For_ResuableTileVertices = vbos[0];
- mVBO_For_ResuableTileTexCoords = vbos[1];
-
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileVertices);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesVerts,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
-
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileTexCoords);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesTex,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- usingVBOs = false;
- }
- }
- }
-
- public void glTexCoord2f(float v, float v1) {
- mTexCoords.put(v);
- mTexCoords.put(v1);
- }
-
- public void glVertex3f(float inX, float inY, float inZ) {
- mVertCoords.put(inX);
- mVertCoords.put(inY);
- mVertCoords.put(inZ);
-
- mOutstandingGlyphsVerticesPipeline++;
-
- if (mOutstandingGlyphsVerticesPipeline >= kTotalBufferSizeVerts) {
- this.draw();
- }
- }
-
- private void draw() {
- if (useVertexArrays) {
- drawVertexArrays();
- } else {
- drawIMMEDIATE();
- }
- }
-
- private void drawVertexArrays() {
- if (mOutstandingGlyphsVerticesPipeline > 0) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- TextureRenderer renderer = getBackingStore();
- renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
-
- mVertCoords.rewind();
- mTexCoords.rewind();
-
- gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
-
- if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileVertices);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
- mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_VertexData,
- mVertCoords); // upload only the new stuff
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);
- } else {
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, mVertCoords);
- }
-
- gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
-
- if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileTexCoords);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
- mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_TexData,
- mTexCoords); // upload only the new stuff
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, 0);
- } else {
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, mTexCoords);
- }
-
- gl.glDrawArrays(GL2.GL_QUADS, 0,
- mOutstandingGlyphsVerticesPipeline);
-
- mVertCoords.rewind();
- mTexCoords.rewind();
- mOutstandingGlyphsVerticesPipeline = 0;
- }
- }
-
- private void drawIMMEDIATE() {
- if (mOutstandingGlyphsVerticesPipeline > 0) {
- TextureRenderer renderer = getBackingStore();
- renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glBegin(GL2.GL_QUADS);
-
- try {
- int numberOfQuads = mOutstandingGlyphsVerticesPipeline / 4;
- mVertCoords.rewind();
- mTexCoords.rewind();
-
- for (int i = 0; i < numberOfQuads; i++) {
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- gl.glEnd();
- mVertCoords.rewind();
- mTexCoords.rewind();
- mOutstandingGlyphsVerticesPipeline = 0;
- }
- }
- }
- }
-
- class DebugListener implements GLEventListener {
- private GLU glu;
- private Frame frame;
-
- DebugListener(GL gl, Frame frame) {
- this.glu = GLU.createGLU(gl);
- this.frame = frame;
- }
-
- @Override
- public void display(GLAutoDrawable drawable) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
-
- if (packer == null) {
- return;
- }
-
- TextureRenderer rend = getBackingStore();
- final int w = rend.getWidth();
- final int h = rend.getHeight();
- rend.beginOrthoRendering(w, h);
- rend.drawOrthoRect(0, 0);
- rend.endOrthoRendering();
-
- if ((frame.getWidth() != w) || (frame.getHeight() != h)) {
- EventQueue.invokeLater(new Runnable() {
- @Override
- public void run() {
- frame.setSize(w, h);
- }
- });
- }
- }
-
- @Override
- public void dispose(GLAutoDrawable drawable) {
- glu=null;
- frame=null;
- }
-
- // Unused methods
- @Override
- public void init(GLAutoDrawable drawable) {
- }
-
- @Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
- }
-
- public void displayChanged(GLAutoDrawable drawable,
- boolean modeChanged, boolean deviceChanged) {
- }
- }
-
- /**
- * Sets whether vertex arrays are being used internally for rendering, or whether text is rendered using the OpenGL
- * immediate mode commands.This is provided as a concession for certain graphics cards which have poor vertex array
- * performance. Defaults to true.
- *
- * @param useVertexArrays The desired value.
- */
- public void setUseVertexArrays(boolean useVertexArrays) {
- this.useVertexArrays = useVertexArrays;
- }
-
- /**
- * Indicates whether vertex arrays are being used internally for
- * rendering, or whether text is rendered using the OpenGL
- * immediate mode commands.Defaults to true.
- * @return whether userVertexArrays is on or off.
- */
- public final boolean getUseVertexArrays() {
- return useVertexArrays;
- }
-
- /**
- * Sets whether smoothing (i.e., GL_LINEAR filtering) is enabled in the backing TextureRenderer of this
- * TextRenderer.A few graphics cards do not behave well when this is enabled, resulting in fuzzy text. Defaults to
- * true.
- *
- * @param smoothing The new smoothing setting.
- */
- public void setSmoothing(boolean smoothing) {
- this.smoothing = smoothing;
- getBackingStore().setSmoothing(smoothing);
- }
-
- /**
- * Indicates whether smoothing is enabled in the backing TextureRenderer of this TextRenderer.A few graphics cards
- * do not behave well when this is enabled, resulting in fuzzy text. Defaults to true.
- *
- * @return The current smoothing setting.
- */
- public boolean getSmoothing() {
- return smoothing;
- }
-
- private boolean is15Available(GL gl) {
- if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) {
- isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5);
- checkFor_isExtensionAvailable_GL_VERSION_1_5 = true;
- }
- return isExtensionAvailable_GL_VERSION_1_5;
- }
-}
diff --git a/src/gov/nasa/worldwind/render/TextRendererCache.java b/src/gov/nasa/worldwind/render/TextRendererCache.java
index 5f670f784e..82a710bbe6 100644
--- a/src/gov/nasa/worldwind/render/TextRendererCache.java
+++ b/src/gov/nasa/worldwind/render/TextRendererCache.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.render;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import gov.nasa.worldwind.Disposable;
import gov.nasa.worldwind.util.Logging;
diff --git a/src/gov/nasa/worldwind/render/ToolTipRenderer.java b/src/gov/nasa/worldwind/render/ToolTipRenderer.java
index b9e4b7af0f..13fb44fb69 100644
--- a/src/gov/nasa/worldwind/render/ToolTipRenderer.java
+++ b/src/gov/nasa/worldwind/render/ToolTipRenderer.java
@@ -30,6 +30,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
diff --git a/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java b/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
index af167bd955..7c410ec413 100644
--- a/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
+++ b/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.symbology;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
import gov.nasa.worldwind.*;
diff --git a/src/gov/nasa/worldwind/symbology/TacticalGraphic.java b/src/gov/nasa/worldwind/symbology/TacticalGraphic.java
index a3bd2654f8..ceed4f80ed 100644
--- a/src/gov/nasa/worldwind/symbology/TacticalGraphic.java
+++ b/src/gov/nasa/worldwind/symbology/TacticalGraphic.java
@@ -43,7 +43,7 @@
*
* See the {@link gov.nasa.worldwindx.examples.symbology.Symbology} and {@link gov.nasa.worldwindx.examples.symbology.TacticalGraphics}
* example applications for examples of how to use tactical graphics.
- *
Construction
+ * Construction
*
* TacticalGraphics are typically created by an instance of {@link TacticalGraphicFactory}. Each graphic within a symbol
* set is identified by a string identifier. The format of this identifier depends on the symbol set. For example, a
@@ -91,7 +91,7 @@
* graphic should be styled. In the example above we added a text modifier of "Alpha" to identify our shape. These
* parameters can be specified using a parameter list when the TacticalGraphic is created, as shown above. They can also
* be set after creation using setters in the TacticalGraphic interface.
- *
Modifiers
+ * Modifiers
*
* Many graphics support text or graphic modifiers. Each modifier is identified by a String key. The set of possible
* modifiers is determined by the symbol set. Modifiers can be specified in the parameter list when a graphic is
@@ -114,7 +114,7 @@
* TacticalGraphic graphic = milstd2525Factory.createGraphic("GHGPGAG----AUSX", positions, null);
* graphic.setModifier(SymbologyConstants.UNIQUE_DESIGNATION, "Boston");
*
- *
Position
+ * Position
*
* Each tactical graphic is positioned by one or more control points. How many points are required depends on the type
* of graphic. A point graphic will only require one point. A more complex shape may require three or four, and a line
@@ -139,7 +139,7 @@
*
* TacticalGraphic graphic = milstd2525Factory.createGraphic("GFGPSLA----AUSX", positions, null);
*
- *
Sub-interfaces of TacticalGraphic
+ * Sub-interfaces of TacticalGraphic
*
* TacticalGraphic describes any tactical graphic in the most general terms: a list of positions and modifiers. However,
* this general interface is not convenient for all graphics. For example, when creating a circle graphic it is more
diff --git a/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java b/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
index d24b0dcfb9..0837534eaa 100644
--- a/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
+++ b/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/symbology/milstd2525/MilStd2525IconRetriever.java b/src/gov/nasa/worldwind/symbology/milstd2525/MilStd2525IconRetriever.java
index 6523602520..3f66453745 100644
--- a/src/gov/nasa/worldwind/symbology/milstd2525/MilStd2525IconRetriever.java
+++ b/src/gov/nasa/worldwind/symbology/milstd2525/MilStd2525IconRetriever.java
@@ -55,10 +55,10 @@
*
createIcon Parameters Key Type Description SymbologyConstants.SHOW_ICON Boolean Determines
* if the symbol will be created with an icon. SymbologyConstants.SHOW_FRAME Boolean Determines
* if the symbol will be created with a frame. SymbologyConstants.SHOW_FILL Boolean Determines
- * if the symbol will be created with a fill color. AVKey.COLOR java.awt.Color Fill color applied to the symbol. If the symbol is drawn with a
- * frame, then this color will be used to fill the frame. If the symbol is not drawn with a frame, then the fill will be
- * applied to the icon itself. The fill color has no effect if Show Fill is False.
+ * if the symbol will be created with a fill color.AVKey.COLOR java.awt.Color
+ * Fill color applied to the symbol. If the symbol is drawn with a frame, then this color will be used to fill the frame.
+ * If the symbol is not drawn with a frame, then the fill will be applied to the icon itself.
+ * The fill color has no effect if Show Fill is False.
*
* @author ccrick
* @version $Id: MilStd2525IconRetriever.java 1171 2013-02-11 21:45:02Z dcollins $
diff --git a/src/gov/nasa/worldwind/terrain/RectangularTessellator.java b/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
index 869e99424a..07ea6ba500 100644
--- a/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
+++ b/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
@@ -39,6 +39,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.nio.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/util/EGM2008.java b/src/gov/nasa/worldwind/util/EGM2008.java
new file mode 100644
index 0000000000..f8e64d9900
--- /dev/null
+++ b/src/gov/nasa/worldwind/util/EGM2008.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
+ * software:
+ *
+ * Jackson Parser – Licensed under Apache 2.0
+ * GDAL – Licensed under MIT
+ * JOGL – Licensed under Berkeley Software Distribution (BSD)
+ * Gluegen – Licensed under Berkeley Software Distribution (BSD)
+ *
+ * A complete listing of 3rd Party software notices and licenses included in
+ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
+ * notices and licenses PDF found in code directory.
+ */
+
+package gov.nasa.worldwind.util;
+
+import gov.nasa.worldwind.cache.BasicMemoryCache;
+import gov.nasa.worldwind.geom.Angle;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+public class EGM2008
+{
+ public static final int N_ROW_MARKERS = 2; // The beginning and end of each row of latitude data is a flag of some sort
+ public static final int N_LONGITUDE_COLS = 8640 + N_ROW_MARKERS; // Number of float32s in a row of data in the data file.
+ public static final int N_LATITUDE_ROWS = 4321; // Number of rows.
+ public static final double GRID_RESOLUTION = 2.5d / 60d; // 2.5 minute grid
+ public static final double CELL_AREA = GRID_RESOLUTION * GRID_RESOLUTION;
+ protected static final long CACHE_SIZE = EGM2008.N_LONGITUDE_COLS * 4 * 45 * 15; // Cache 15 degrees worth of offsets.
+ public static final int N_LAT_ROW_BYTES = N_LONGITUDE_COLS * 4; // Offsets are float32
+
+ protected String offsetsFilePath;
+ protected BufferWrapper deltas;
+ protected final BasicMemoryCache offsetCache;
+
+ protected class GridCell
+ {
+ public double x1;
+ public double y1;
+ public double x2;
+ public double y2;
+
+ public GridCell(double x1, double y1)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x1 + EGM2008.GRID_RESOLUTION;
+ this.y2 = y1 + EGM2008.GRID_RESOLUTION;
+ }
+
+ public GridCell()
+ {
+ this(0, 0);
+ }
+
+ public GridCell intersect(GridCell that)
+ {
+ GridCell intersection = new GridCell();
+ intersection.x1 = Math.max(this.x1, that.x1);
+ intersection.x2 = Math.min(this.x2, that.x2);
+ intersection.y1 = Math.max(this.y1, that.y1);
+ intersection.y2 = Math.min(this.y2, that.y2);
+ return intersection;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%5.2f,%5.2f,%5.2f,%5.2f", x1, y1, x2, y2);
+ }
+
+ public double area()
+ {
+ return (this.x2 - this.x1) * (this.y2 - this.y1);
+ }
+ }
+
+ /**
+ * Allows the retrieval of geoid offsets from the EGM2008 2.5 Minute Interpolation Grid sourced from the
+ * National Geospatial-Intelligence Agency Office of Geomatics (https://earth-info.nga.mil/).
+ *
+ * The EGM2008 data path. This data file is not included in the SDK due to its size. The data may be downloaded here:
+ * https://builds.worldwind.arc.nasa.gov/artifactory/EGM2008-Data/egm2008_25.dat
+ *
+ * @param offsetsFilePath a path pointing to a file with the geoid offsets.
+ */
+ public EGM2008(String offsetsFilePath)
+ {
+ if (offsetsFilePath == null)
+ {
+ String msg = Logging.getMessage("nullValue.PathIsNull");
+ Logging.logger().severe(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ File test = new File(offsetsFilePath);
+ if (test.exists())
+ {
+ this.offsetsFilePath = offsetsFilePath;
+ }
+ else
+ {
+ Class c = EGM2008.class;
+ URL url = c.getResource("/" + offsetsFilePath);
+ if (url != null)
+ {
+ test = WWIO.getFileForLocalAddress(url);
+ this.offsetsFilePath = test.getAbsolutePath();
+ }
+ else
+ {
+ this.offsetsFilePath = null;
+ }
+ }
+ this.offsetCache = new BasicMemoryCache((EGM2008.CACHE_SIZE * 8) / 10, EGM2008.CACHE_SIZE);
+ this.offsetCache.setName(EGM2008.class.getName());
+ }
+
+ public float getOffset(Angle lat, Angle lon) throws IOException
+ {
+ return this.getOffset((float) lat.degrees, (float) lon.degrees);
+ }
+
+ public int getLatRow(double lat)
+ {
+ // Compute the row in the data file corresponding to a given latitude.
+ // Latitude row zero in the data corresponds to 90 degrees latitude (north pole) and increases southward
+ // Longitude column zero in the data corresponds to 0 degrees of longitude and increases eastward
+ float lat180 = 90f - (float) lat;
+ return (int) Math.floor(lat180 / EGM2008.GRID_RESOLUTION);
+ }
+
+ public int getLonCol(double lon)
+ {
+ // Compute the column in the data file corresponding to a given latitude and longitude.
+ // Latitude row zero in the data corresponds to 90 degrees latitude (north pole) and increases southward
+ // Longitude column zero in the data corresponds to 0 degrees of longitude and increases eastward
+ float lon360 = (float) lon;
+ if (lon < 0)
+ {
+ lon360 = lon360 + 360;
+ }
+ return (int) Math.floor(lon360 / EGM2008.GRID_RESOLUTION);
+ }
+
+ public float[][] getLatRows(int latRow) throws IOException
+ {
+ int[] interpRowIndices =
+ {
+ latRow, latRow + 1
+ };
+ float[][] latDataArray = new float[2][];
+ boolean retrievalRequired = false;
+ for (int i = 0; i < interpRowIndices.length; i++)
+ {
+ if (interpRowIndices[i] < EGM2008.N_LATITUDE_ROWS)
+ {
+ float[] latData = (float[]) this.offsetCache.getObject(interpRowIndices[i]);
+ latDataArray[i] = latData;
+ if (latData == null)
+ {
+ retrievalRequired = true;
+ }
+ }
+ }
+ if (retrievalRequired)
+ {
+ try (RandomAccessFile offsetFile = new RandomAccessFile(this.offsetsFilePath, "r"))
+ {
+ for (int i = 0; i < interpRowIndices.length; i++)
+ {
+ if (interpRowIndices[i] < EGM2008.N_LATITUDE_ROWS && latDataArray[i] == null)
+ {
+ offsetFile.seek(interpRowIndices[i] * EGM2008.N_LAT_ROW_BYTES);
+ byte[] latByteData = new byte[EGM2008.N_LAT_ROW_BYTES];
+ offsetFile.read(latByteData);
+ ByteBuffer latByteBuffer = ByteBuffer.wrap(latByteData).order(ByteOrder.LITTLE_ENDIAN);
+ FloatBuffer latFloatBuffer = latByteBuffer.asFloatBuffer();
+ float[] latData = new float[EGM2008.N_LONGITUDE_COLS];
+ latFloatBuffer.get(latData);
+ this.offsetCache.add(interpRowIndices[i], latData, EGM2008.N_LAT_ROW_BYTES);
+ latDataArray[i] = latData;
+ }
+ }
+ }
+ }
+ return latDataArray;
+ }
+
+ public float getOffset(double lat, double lon) throws IOException
+ {
+ if (this.offsetsFilePath == null)
+ {
+ return 0f;
+ }
+ int latRow = this.getLatRow(lat);
+ int lonCol = this.getLonCol(lon);
+
+ float[][] latDataArray = getLatRows(latRow);
+
+ float baseOffset = latDataArray[0][lonCol + EGM2008.N_ROW_MARKERS / 2];
+ if (latDataArray[1] == null)
+ {
+ return baseOffset;
+ }
+
+ // Interpolate with surrounding offset cells
+ float lat180 = 90f - (float) lat;
+ float lon360 = (float) lon;
+ if (lon < 0)
+ {
+ lon360 = lon360 + 360;
+ }
+ GridCell offsetCell = new GridCell(lon360, lat180);
+ double baseLat = ((double) latRow) * EGM2008.GRID_RESOLUTION;
+ double baseLon = ((double) lonCol) * EGM2008.GRID_RESOLUTION;
+ float interpOffset = 0;
+ for (int x = 0; x < 2; x++)
+ {
+ double cellLon = baseLon + ((double) x) * EGM2008.GRID_RESOLUTION;
+ for (int y = 0; y < 2; y++)
+ {
+ float cellOffset = latDataArray[y][lonCol + EGM2008.N_ROW_MARKERS / 2 + x];
+ double cellLat = baseLat + ((double) y) * EGM2008.GRID_RESOLUTION;
+ GridCell interpCell = new GridCell(cellLon, cellLat);
+ GridCell intersection = offsetCell.intersect(interpCell);
+ interpOffset += cellOffset * (intersection.area() / EGM2008.CELL_AREA);
+ }
+ }
+ return interpOffset;
+ }
+
+ public boolean isEGMDataAvailable()
+ {
+ return this.offsetsFilePath != null;
+ }
+}
diff --git a/src/gov/nasa/worldwind/util/OGLTextRenderer.java b/src/gov/nasa/worldwind/util/OGLTextRenderer.java
index 271568cc94..a5b77a291d 100644
--- a/src/gov/nasa/worldwind/util/OGLTextRenderer.java
+++ b/src/gov/nasa/worldwind/util/OGLTextRenderer.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.util;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import gov.nasa.worldwind.render.*;
/**
diff --git a/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java b/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
index e41b6a8100..0d785e5e3f 100644
--- a/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
+++ b/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.render.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/util/layertree/LayerTree.java b/src/gov/nasa/worldwind/util/layertree/LayerTree.java
index 0b4ee0937a..ca504bb616 100644
--- a/src/gov/nasa/worldwind/util/layertree/LayerTree.java
+++ b/src/gov/nasa/worldwind/util/layertree/LayerTree.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.util.layertree;
+import java.awt.Point;
+
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.render.Offset;
import gov.nasa.worldwind.util.Logging;
@@ -87,11 +89,11 @@ public LayerTree(LayerTreeModel model)
* Creates a new LayerTree
with an empty LayerTreeModel
and the specified screen
* location.
*
- * @param offset the screen location of the tree's upper left corner, relative to the screen's upper left corner.
+ * @param offset the screen location of the tree's lower left corner, relative to the screen's lower left corner.
*
* @throws IllegalArgumentException if offset
is null
.
*/
- public LayerTree(Offset offset)
+ public LayerTree(Point offset)
{
if (offset == null)
{
@@ -107,12 +109,12 @@ public LayerTree(Offset offset)
* Creates a new LayerTree
with the specified model
and the specified screen location.
*
* @param model the tree model to use.
- * @param offset the screen location of the tree's upper left corner, relative to the screen's upper left corner.
+ * @param offset the screen location of the tree's lower left corner, relative to the screen's lower left corner. (GL surface pixels)
*
* @throws IllegalArgumentException if model
is null
, or if offset
is
* null
.
*/
- public LayerTree(LayerTreeModel model, Offset offset)
+ public LayerTree(LayerTreeModel model, Point offset)
{
if (model == null)
{
@@ -139,7 +141,7 @@ public LayerTree(LayerTreeModel model, Offset offset)
* @param model this tree's model to use, or null
to create a new LayerTreeModel
.
* @param offset the screen location of this tree's upper left corner, or null
to use the default.
*/
- protected void initialize(LayerTreeModel model, Offset offset)
+ protected void initialize(LayerTreeModel model, Point offset)
{
if (model == null)
model = this.createTreeModel();
@@ -167,10 +169,10 @@ protected LayerTreeModel createTreeModel()
*
* @return new TreeLayout
.
*/
- protected TreeLayout createTreeLayout(Offset offset)
+ protected TreeLayout createTreeLayout(Point offset)
{
if (offset == null)
- offset = DEFAULT_OFFSET;
+ offset = new Point(DEFAULT_OFFSET.getX().intValue(), DEFAULT_OFFSET.getY().intValue());
BasicTreeLayout layout = new BasicTreeLayout(this, offset);
layout.getFrame().setFrameTitle(DEFAULT_FRAME_TITLE);
@@ -196,7 +198,8 @@ protected TreeLayout createTreeLayout(Offset offset)
}
/** {@inheritDoc} */
- public LayerTreeModel getModel()
+ @Override
+ public LayerTreeModel getModel()
{
return (LayerTreeModel) super.getModel();
}
diff --git a/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java b/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
index 8bb6c85172..d9325e46f8 100644
--- a/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
+++ b/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.util.tree;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.TextureCoords;
import gov.nasa.worldwind.WWObjectImpl;
import gov.nasa.worldwind.avlist.AVKey;
@@ -160,7 +161,7 @@ public BasicTreeLayout(Tree tree)
*/
public BasicTreeLayout(Tree tree, int x, int y)
{
- this(tree, new Offset((double) x, (double) y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this(tree, new Point(x, y));
}
/**
@@ -170,7 +171,7 @@ public BasicTreeLayout(Tree tree, int x, int y)
* @param screenLocation The location of the upper left corner of the tree frame. The offset is interpreted relative
* to the lower left corner of the screen.
*/
- public BasicTreeLayout(Tree tree, Offset screenLocation)
+ public BasicTreeLayout(Tree tree, Point screenLocation)
{
this.tree = tree;
this.frame = this.createFrame();
@@ -186,7 +187,8 @@ public BasicTreeLayout(Tree tree, Offset screenLocation)
// events between TreeLayout and Tree.
this.tree.addPropertyChangeListener(new PropertyChangeListener()
{
- public void propertyChange(PropertyChangeEvent propertyChangeEvent)
+ @Override
+ public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
// Ignore events originated by this TreeLayout, and repaint events. There is no need to recompute the
// tree layout just because a repaint was triggered.
@@ -341,7 +343,8 @@ public void setDrawNodeStateSymbol(boolean drawNodeStateSymbol)
}
/** {@inheritDoc} */
- public long getUpdateTime()
+ @Override
+ public long getUpdateTime()
{
return this.updateTime;
}
@@ -364,7 +367,8 @@ protected ScrollFrame createFrame()
*
* @return Size of the rendered tree.
*/
- public Dimension getSize(DrawContext dc, Dimension frameSize)
+ @Override
+ public Dimension getSize(DrawContext dc, Dimension frameSize)
{
this.updateAttributes(dc);
@@ -472,7 +476,8 @@ protected boolean mustDisplayNode(TreeNode node, int level)
}
/** {@inheritDoc} */
- public void preRender(DrawContext dc)
+ @Override
+ public void preRender(DrawContext dc)
{
// Adjust scroll position if an application has requested that the layout scroll to make a node visible.
this.scrollToNode(dc);
@@ -481,7 +486,8 @@ public void preRender(DrawContext dc)
}
/** {@inheritDoc} */
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
this.frame.render(dc);
}
@@ -514,7 +520,8 @@ protected synchronized void scrollToNode(DrawContext dc)
}
/** {@inheritDoc} */
- public void renderScrollable(DrawContext dc, Point location, Dimension frameSize, Rectangle clipBounds)
+ @Override
+ public void renderScrollable(DrawContext dc, Point location, Dimension frameSize, Rectangle clipBounds)
{
TreeModel model = this.tree.getModel();
TreeNode root = model.getRoot();
@@ -1321,7 +1328,8 @@ protected Rectangle findNodeBounds(TreeNode needle, TreeNode haystack, DrawConte
}
/** {@inheritDoc} */
- public synchronized void makeVisible(TreePath path)
+ @Override
+ public synchronized void makeVisible(TreePath path)
{
TreeNode node = this.tree.getNode(path);
if (node == null)
@@ -1345,7 +1353,7 @@ public synchronized void makeVisible(TreePath path)
*
* @return Screen location, measured in pixels from the upper left corner of the screen.
*/
- public Offset getScreenLocation()
+ public Point getScreenLocation()
{
return this.frame.getScreenLocation();
}
@@ -1356,19 +1364,21 @@ public Offset getScreenLocation()
*
* @param screenLocation New screen location.
*/
- public void setScreenLocation(Offset screenLocation)
+ public void setScreenLocation(Point screenLocation)
{
frame.setScreenLocation(screenLocation);
}
/** {@inheritDoc} */
- public TreeAttributes getAttributes()
+ @Override
+ public TreeAttributes getAttributes()
{
return this.normalAttributes;
}
/** {@inheritDoc} */
- public void setAttributes(TreeAttributes attributes)
+ @Override
+ public void setAttributes(TreeAttributes attributes)
{
if (attributes == null)
{
@@ -1464,7 +1474,8 @@ public boolean isHighlighted()
*
* @param highlighted True if the tree should be highlighted.
*/
- public void setHighlighted(boolean highlighted)
+ @Override
+ public void setHighlighted(boolean highlighted)
{
this.highlighted = highlighted;
}
diff --git a/src/gov/nasa/worldwind/util/tree/DragControl.java b/src/gov/nasa/worldwind/util/tree/DragControl.java
index ac0b8e0e28..8f6edace36 100644
--- a/src/gov/nasa/worldwind/util/tree/DragControl.java
+++ b/src/gov/nasa/worldwind/util/tree/DragControl.java
@@ -101,7 +101,7 @@ else if (event.isDragEnd())
/**
* Called when a drag begins. This implementation saves the first drag point to {@link #dragRefPoint}.
*
- * @param point Point at which dragging started.
+ * @param point Point at which dragging started (GL surface pixels)
*/
protected void beginDrag(Point point)
{
@@ -111,7 +111,7 @@ protected void beginDrag(Point point)
/**
* Called for each point within a drag action.
*
- * @param point Current drag point.
+ * @param point Current drag point. (GL surface pixels)
*/
protected abstract void drag(Point point);
diff --git a/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java b/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
index 69f3f26776..fcfb13b54d 100644
--- a/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
+++ b/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
@@ -28,13 +28,11 @@
package gov.nasa.worldwind.util.tree;
-import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.AbstractResizeHotSpot;
import java.awt.*;
import java.awt.event.*;
-import java.awt.geom.*;
/**
* A screen control for resizing a frame. This class handles the resize input events, but does does not actually draw
@@ -89,15 +87,15 @@ protected void setSize(Dimension newSize)
@Override
protected Point getScreenPoint()
{
- Point2D point2D = this.frame.getScreenPoint();
- return new Point((int)point2D.getX(), (int)point2D.getY());
+ Point point = this.frame.getScreenLocation();
+ return new Point(point);
}
/** {@inheritDoc} */
@Override
protected void setScreenPoint(Point newPoint)
{
- this.frame.setScreenLocation(new Offset(newPoint.getX(), newPoint.getY(), AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this.frame.setScreenLocation(newPoint);
}
/** {@inheritDoc} */
@@ -113,7 +111,8 @@ protected Dimension getMinimumSize()
*
* @param event The event to handle.
*/
- public void mouseWheelMoved(MouseWheelEvent event)
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent event)
{
if (event == null || event.isConsumed())
return;
diff --git a/src/gov/nasa/worldwind/util/tree/ScrollBar.java b/src/gov/nasa/worldwind/util/tree/ScrollBar.java
index 431a8084a5..a973053661 100644
--- a/src/gov/nasa/worldwind/util/tree/ScrollBar.java
+++ b/src/gov/nasa/worldwind/util/tree/ScrollBar.java
@@ -683,7 +683,8 @@ public boolean isAutoScrolling()
*
* @param dc the DrawContext
to be used
*/
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc.getFrameTimeStamp() != this.frameNumber)
{
@@ -1110,7 +1111,9 @@ protected void beginDrag(Point point)
this.dragRefValue = this.scrollBar.getValue();
}
- protected void drag(Point point)
+ /** {@inheritDoc} */
+ @Override
+ protected void drag(Point point)
{
int delta;
int adjustment;
@@ -1118,7 +1121,10 @@ protected void drag(Point point)
if (AVKey.VERTICAL.equals(scrollBar.getOrientation()))
{
- delta = point.y - this.dragRefPoint.y;
+ // scroll bar zero position is at the top in GL surface coordinates.
+ // 'point' will be in GL surface coordinates, so moving the mouse
+ // towards the bottom of the screen yields a smaller y value.
+ delta = this.dragRefPoint.y - point.y;
screenDimension = this.scrollBar.scrollBounds.height - this.scrollBar.getMinScrollKnobSize();
}
else
diff --git a/src/gov/nasa/worldwind/util/tree/ScrollFrame.java b/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
index ebb1d63c6e..057fd378fa 100644
--- a/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
+++ b/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.util.tree;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.AVKey;
@@ -98,7 +99,7 @@ public class ScrollFrame extends DragControl implements PreRenderable, Renderabl
protected Scrollable contents;
/** Indicates the location of the upper left corner of the frame. */
- protected Offset screenLocation;
+ protected Point screenLocation;
/** Indicates whether or not to draw a title bar in the frame. Default is true. */
protected boolean drawTitleBar = true;
@@ -209,11 +210,6 @@ public class ScrollFrame extends DragControl implements PreRenderable, Renderabl
protected long frameNumber = -1;
/** Indicates that the frame must be regenerated because the size or attributes have changed. */
protected boolean mustRecomputeFrameGeometry = true;
- /**
- * Indicates the location of the upper left corner of the frame, in AWT coordinates (origin at the upper left corner
- * of the screen.
- */
- protected Point2D awtScreenPoint;
/** Bounds of the full frame. */
protected Rectangle frameBounds;
/** Bounds of the frame inside the frame border. */
@@ -262,7 +258,7 @@ public ScrollFrame()
*/
public ScrollFrame(int x, int y)
{
- this(new Offset((double) x, (double) y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this(new Point(x, y));
}
/**
@@ -270,7 +266,7 @@ public ScrollFrame(int x, int y)
*
* @param screenLocation initial location of the upper left corner of the frame.
*/
- public ScrollFrame(Offset screenLocation)
+ public ScrollFrame(Point screenLocation)
{
super(null);
this.setScreenLocation(screenLocation);
@@ -628,43 +624,32 @@ public Rectangle getBounds(DrawContext dc)
{
this.updateBounds(dc);
- return new Rectangle((int) this.awtScreenPoint.getX(), (int) this.awtScreenPoint.getY(), this.frameSize.width,
+ return new Rectangle(screenLocation.x, screenLocation.y, this.frameSize.width,
this.frameSize.height);
}
/**
- * Get the location of the upper left corner of the tree, measured in screen coordinates with the origin at the
- * upper left corner of the screen.
+ * Get the location of the lower left corner of the tree, measured in screen
+ * coordinates with the origin at the lower left corner of the screen.
*
- * @return Screen location, measured in pixels from the upper left corner of the screen.
+ * @return Screen location, measured in GL surface pixels from the lower left corner of the screen.
*/
- public Offset getScreenLocation()
+ public Point getScreenLocation()
{
return this.screenLocation;
}
/**
- * Set the location of the upper left corner of the tree, measured in screen coordinates with the origin at the
- * upper left corner of the screen.
+ * Set the location of the lower left corner of the tree, measured in GL surface coordinates
+ * with the origin at the lower left corner of the screen.
*
* @param screenLocation New screen location.
*/
- public void setScreenLocation(Offset screenLocation)
+ public void setScreenLocation(Point screenLocation)
{
this.screenLocation = screenLocation;
}
- /**
- * Get the location of the upper left corner of the frame, measured from the upper left corner of the screen.
- *
- * @return The location of the upper left corner of the frame. This method will return null until the has been
- * rendered.
- */
- protected Point2D getScreenPoint()
- {
- return this.awtScreenPoint;
- }
-
/**
* Indicates the frame attributes used to draw the frame when it is not highlighted.
*
@@ -1043,9 +1028,10 @@ protected int computeTileTextureDimension(Dimension frameSize, Dimension content
}
/** {@inheritDoc} */
- public void preRender(DrawContext dc)
+ @Override
+ public void preRender(DrawContext dc)
{
- Offset screenLocation = this.getScreenLocation();
+ Point screenLocation = this.getScreenLocation();
if (screenLocation == null)
return;
@@ -1057,8 +1043,7 @@ public void preRender(DrawContext dc)
Point pickPoint = dc.getPickPoint();
if (pickPoint != null)
{
- int glY = dc.getView().getViewport().height - pickPoint.y;
- this.setHighlighted(this.pickBounds.contains(new Point(pickPoint.x, glY)));
+ this.setHighlighted(this.pickBounds.contains(pickPoint));
}
this.determineActiveAttributes();
@@ -1078,9 +1063,10 @@ public void preRender(DrawContext dc)
}
/** {@inheritDoc} */
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
- Offset screenLocation = this.getScreenLocation();
+ Point screenLocation = this.getScreenLocation();
if (screenLocation == null || this.frameBounds == null)
return;
@@ -1244,26 +1230,23 @@ public void updateBounds(DrawContext dc)
if (!this.frameSize.equals(previousFrameSize))
this.mustRecomputeFrameGeometry = true;
- // Compute point in OpenGL coordinates
- Point2D upperLeft = this.screenLocation.computeOffset(viewport.width, viewport.height, 1.0, 1.0);
-
- this.awtScreenPoint = new Point((int) upperLeft.getX(), (int) (viewport.height - upperLeft.getY()));
+ // Set frame bounds
+ this.frameBounds = new Rectangle(screenLocation.x, screenLocation.y,
+ this.frameSize.width, this.frameSize.height);
- this.frameBounds = new Rectangle((int) upperLeft.getX(), (int) upperLeft.getY() - this.frameSize.height,
- this.frameSize.width, this.frameSize.height);
-
- // Compute the pickable screen extent as the frame extent, plus the width of the frame's pickable outline.
- // This extent is used during picking to ensure that the frame's outline is pickable when it exceeds the
- // frame's screen extent.
+ // Compute the pickable screen extent in GL surface coordinates as the frame extent,
+ // plus the width of the frame's pickable outline.
+ // This extent is used during picking to ensure that the frame's outline is pickable
+ // when it exceeds the frame's screen extent.
this.pickBounds = new Rectangle(
this.frameBounds.x - this.borderPickWidth / 2,
this.frameBounds.y - this.borderPickWidth / 2,
this.frameBounds.width + this.borderPickWidth,
this.frameBounds.height + this.borderPickWidth);
- this.innerBounds = new Rectangle((int) upperLeft.getX() + this.frameBorder,
- (int) upperLeft.getY() - frameSize.height + this.frameBorder, frameSize.width - this.frameBorder * 2,
- frameSize.height - this.frameBorder * 2);
+ this.innerBounds = new Rectangle(frameBounds.x + this.frameBorder,
+ frameBounds.y + this.frameBorder, frameSize.width - this.frameBorder * 2,
+ frameSize.height - this.frameBorder * 2);
// If the content size has yet not been computed, compute it now.
if (contentSize == null)
@@ -2269,18 +2252,17 @@ protected void beginDrag(Point point)
{
if (this.isEnableMove())
{
- Point2D location = this.awtScreenPoint;
- this.dragRefPoint = new Point((int) location.getX() - point.x, (int) location.getY() - point.y);
+ this.dragRefPoint = new Point( screenLocation.x - point.x, screenLocation.y - point.y);
}
}
- public void drag(Point point)
+ @Override
+ public void drag(Point point)
{
if (this.isEnableMove())
{
- double x = point.x + this.dragRefPoint.x;
- double y = point.y + this.dragRefPoint.y;
- this.setScreenLocation(new Offset(x, y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ Point pt = new Point(point.x + this.dragRefPoint.x, point.y + this.dragRefPoint.y);
+ this.setScreenLocation(pt);
}
}
@@ -2293,8 +2275,8 @@ public void selected(SelectEvent event)
super.selected(event);
// Minimize the frame if the title bar was double clicked.
- Rectangle titleBarBounds = new Rectangle((int) this.awtScreenPoint.getX() + this.frameBorder,
- (int) this.awtScreenPoint.getY() + this.frameBorder * 2, this.innerBounds.width, this.titleBarHeight);
+ Rectangle titleBarBounds = new Rectangle(this.screenLocation.x + this.frameBorder,
+ this.screenLocation.y + this.frameBorder * 2, this.innerBounds.width, this.titleBarHeight);
if (event.isLeftDoubleClick())
{
@@ -2475,7 +2457,8 @@ class TextureTile implements Comparable
* @return -1 if this tile was accessed less recently than that tile, 0 if the access times are the same, or 1
* if this tile was accessed more recently.
*/
- public int compareTo(TextureTile that)
+ @Override
+ public int compareTo(TextureTile that)
{
if (that == null)
{
diff --git a/src/gov/nasa/worldwind/util/webview/WindowsWebViewJNI.java b/src/gov/nasa/worldwind/util/webview/WindowsWebViewJNI.java
index 74e5b23c41..254c506f8e 100644
--- a/src/gov/nasa/worldwind/util/webview/WindowsWebViewJNI.java
+++ b/src/gov/nasa/worldwind/util/webview/WindowsWebViewJNI.java
@@ -38,7 +38,7 @@
/**
* JNI bindings for the Windows WebView library. This library provides functions for creating and destroying native
* WebViews, sending user input to a WebView, and adding listeners to a WebView.
- * Message loops
+ * Message loops
*
* WebViews created by this library must be managed by a message loop in native code. This class provides methods for
* creating and running a native message loop using a Java thread. Each WebView must be associated with one message
diff --git a/src/gov/nasa/worldwind/view/BasicView.java b/src/gov/nasa/worldwind/view/BasicView.java
index 2857760067..22809dbe66 100644
--- a/src/gov/nasa/worldwind/view/BasicView.java
+++ b/src/gov/nasa/worldwind/view/BasicView.java
@@ -591,7 +591,7 @@ public void goTo(Position position, double distance)
public Line computeRayFromScreenPoint(double x, double y)
{
return ViewUtil.computeRayFromScreenPoint(this, x, y,
- this.modelview, this.projection, this.viewport);
+ this.modelview, this.projection);
}
public Position computePositionFromScreenPoint(double x, double y)
diff --git a/src/gov/nasa/worldwind/view/ViewUtil.java b/src/gov/nasa/worldwind/view/ViewUtil.java
index e2dbd2d988..dbd8d97c68 100644
--- a/src/gov/nasa/worldwind/view/ViewUtil.java
+++ b/src/gov/nasa/worldwind/view/ViewUtil.java
@@ -536,7 +536,7 @@ public static Angle normalizedRoll(Angle unnormalizedRoll)
}
public static Line computeRayFromScreenPoint(View view, double x, double y,
- Matrix modelview, Matrix projection, java.awt.Rectangle viewport)
+ Matrix modelview, Matrix projection)
{
if (modelview == null || projection == null)
{
@@ -544,12 +544,6 @@ public static Line computeRayFromScreenPoint(View view, double x, double y,
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
- if (viewport == null)
- {
- String message = Logging.getMessage("nullValue.RectangleIsNull");
- Logging.logger().severe(message);
- throw new IllegalArgumentException(message);
- }
// Compute a ray originating from the view, and passing through the screen point (x, y).
//
@@ -566,9 +560,8 @@ public static Line computeRayFromScreenPoint(View view, double x, double y,
if (eye == null)
return null;
- double yInGLCoords = viewport.height - y - 1;
- Vec4 a = view.unProject(new Vec4(x, yInGLCoords, 0, 0));
- Vec4 b = view.unProject(new Vec4(x, yInGLCoords, 1, 0));
+ Vec4 a = view.unProject(new Vec4(x, y, 0, 0));
+ Vec4 b = view.unProject(new Vec4(x, y, 1, 0));
if (a == null || b == null)
return null;
diff --git a/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java b/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
index f429cc0b49..3d622eda72 100644
--- a/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
+++ b/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
@@ -159,7 +159,6 @@ protected void onMoveTo(Position focalPosition, ViewInputAttributes.DeviceAttrib
}
}
- @SuppressWarnings("UnusedParameters")
protected void onMoveTo2D(Position focalPosition, ViewInputAttributes.DeviceAttributes deviceAttributes,
ViewInputAttributes.ActionAttributes actionAttribs)
{
@@ -314,7 +313,6 @@ protected void onHorizontalTranslateRel(Angle forwardChange, Angle sideChange,
}
}
- @SuppressWarnings("UnusedParameters")
protected void onHorizontalTranslate2D(double forwardInput, double sideInput,
double totalForwardInput, double totalSideInput,
ViewInputAttributes.DeviceAttributes deviceAttributes,
@@ -335,9 +333,9 @@ protected void onHorizontalTranslate2D(double forwardInput, double sideInput,
Point p1 = constrainToSourceBounds(this.getMouseDownPoint(), this.getWorldWindow());
Point p2 = constrainToSourceBounds(this.getMousePoint(), this.getWorldWindow());
Line ray1 = ViewUtil.computeRayFromScreenPoint(orbitView, p1.x, p1.y, this.mouseDownModelview,
- this.mouseDownProjection, this.mouseDownViewport);
+ this.mouseDownProjection);
Line ray2 = ViewUtil.computeRayFromScreenPoint(orbitView, p2.x, p2.y, this.mouseDownModelview,
- this.mouseDownProjection, this.mouseDownViewport);
+ this.mouseDownProjection);
// Compute a model coordinate plane passing through the position under the cursor when the mouse button was
// pressed. Fall back to a plane normal to the globe if the cursor was off the globe.
@@ -400,7 +398,6 @@ protected void onResetHeading(ViewInputAttributes.ActionAttributes actionAttribs
*
* @param actionAttribs input that caused the change.
*/
- @SuppressWarnings("UnusedParameters")
protected void onResetRoll(ViewInputAttributes.ActionAttributes actionAttribs)
{
View view = this.getView();
diff --git a/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java b/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
index de6ad819d8..23dc2412e0 100644
--- a/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
+++ b/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.stream.*;
import java.awt.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java b/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
index 5455ebed9f..3503bd4c49 100644
--- a/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
+++ b/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwindx.applications.sar.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
/**
diff --git a/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java b/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
index 9444f7228d..b99607e25a 100644
--- a/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
+++ b/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
@@ -40,6 +40,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.nio.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java b/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
index 53e831a7c2..c8bf39e19a 100644
--- a/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
+++ b/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
@@ -98,7 +98,7 @@ protected void doRenderNow(DrawContext dc)
protected Point adjustDrawPointToViewport(Point point, Rectangle bounds, Rectangle viewport)
{
int x = point.x;
- int y = (int) viewport.getHeight() - point.y - 1;
+ int y = point.y;
if (x + this.getOffsetX() + bounds.getWidth() > viewport.getWidth())
x = (int) (viewport.getWidth() - bounds.getWidth()) - 1 - this.getOffsetX();
diff --git a/src/gov/nasa/worldwindx/examples/AirspaceBuilder.java b/src/gov/nasa/worldwindx/examples/AirspaceBuilder.java
index 6a83dbb063..32dbb83776 100644
--- a/src/gov/nasa/worldwindx/examples/AirspaceBuilder.java
+++ b/src/gov/nasa/worldwindx/examples/AirspaceBuilder.java
@@ -57,7 +57,7 @@
* Illustrates runtime construction of 3D extruded polygons and spheres using WorldWind {@link Airspace}
* shapes. This uses a {@link PolygonEditor}
and a {@link SphereAirspaceEditor}
to enable
* runtime editing of {@link Polygon}
airspace and {@link SphereAirspace}
shapes.
- *
Usage Instructions
+ * Usage Instructions
*
* Adding and Removing Shapes Add a shape by selecting either Polygon
or
* Sphere
in the drop down box then clicking New shape
. Delete a shape by left-clicking it
@@ -75,7 +75,7 @@
* near the polygon. Remove a polygon control point by holding the Control
key and left-clicking the blue
* sphere at the vertex. Move a polygon vertex by left-clicking and dragging it. Change a polygon's bottom or top height
* by holding the Shift
key then left-click any blue sphere at a vertex and drag it.
- *
Demo Shapes
+ * Demo Shapes
*
* Select File -> Load Demo Shapes
to display a set of polygon airspace shapes built with this editor.
* The data for these shapes is located in the WorldWind project under
diff --git a/src/gov/nasa/worldwindx/examples/Annotations.java b/src/gov/nasa/worldwindx/examples/Annotations.java
index cd0e8972dc..866ba403c6 100644
--- a/src/gov/nasa/worldwindx/examples/Annotations.java
+++ b/src/gov/nasa/worldwindx/examples/Annotations.java
@@ -38,6 +38,8 @@
import gov.nasa.worldwindx.examples.util.PowerOfTwoPaddedImage;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.swing.*;
import javax.swing.Box;
import javax.swing.border.*;
diff --git a/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java b/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
index c432b47db4..9ace62fed7 100644
--- a/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
+++ b/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
@@ -72,7 +72,6 @@ public void selected(SelectEvent event) {
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void highlight(SelectEvent event, Object o) {
if (this.lastPickedPlacemark == o) {
return; // same thing selected
@@ -110,7 +109,7 @@ protected void showContextMenu(SelectEvent event) {
}
ContextMenu menu = new ContextMenu((Component) event.getSource(), menuInfo);
- menu.show(event.getMouseEvent());
+ menu.show(event.getAwtMousePt());
}
}
}
@@ -145,7 +144,7 @@ protected void makeMenuItems() {
}
}
- public void show(final MouseEvent event) {
+ public void show(final Point screenPt) {
JPopupMenu popup = new JPopupMenu();
popup.add(this.menuTitleItem);
@@ -156,7 +155,7 @@ public void show(final MouseEvent event) {
popup.add(subMenu);
}
- popup.show(sourceComponent, event.getX(), event.getY());
+ popup.show(sourceComponent, (int)screenPt.getX(), (int)screenPt.getY());
}
}
diff --git a/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java b/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java
new file mode 100644
index 0000000000..f2b403ca0d
--- /dev/null
+++ b/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
+ * software:
+ *
+ * Jackson Parser – Licensed under Apache 2.0
+ * GDAL – Licensed under MIT
+ * JOGL – Licensed under Berkeley Software Distribution (BSD)
+ * Gluegen – Licensed under Berkeley Software Distribution (BSD)
+ *
+ * A complete listing of 3rd Party software notices and licenses included in
+ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
+ * notices and licenses PDF found in code directory.
+ */
+package gov.nasa.worldwindx.examples;
+
+import gov.nasa.worldwind.Model;
+import gov.nasa.worldwind.avlist.AVKey;
+import gov.nasa.worldwind.geom.LatLon;
+import gov.nasa.worldwind.geom.Position;
+import gov.nasa.worldwind.geom.Sector;
+import gov.nasa.worldwind.globes.Earth;
+import gov.nasa.worldwind.globes.Globe;
+import gov.nasa.worldwind.layers.RenderableLayer;
+import gov.nasa.worldwind.render.PointPlacemark;
+import gov.nasa.worldwind.util.EGM2008;
+import java.awt.Dimension;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
+
+/**
+ * Shows how to apply EGM2008 offsets to Earth elevations.
+ *
+ * This EGM2008 data file is not included in the SDK due to its size. The data may be downloaded here:
+ * https://builds.worldwind.arc.nasa.gov/artifactory/EGM2008-Data/egm2008_25.dat
+ *
+ * This example looks for the EGM2008 data in the WorldWind src/config folder by default.
+ */
+public class EGM2008Offsets extends ApplicationTemplate
+{
+ public static class AppFrame extends ApplicationTemplate.AppFrame
+ {
+ /**
+ * Attempt to retrieve the best elevations for a specified list of locations. The elevations returned are the best currently
+ * available for the data set and the area bounding the locations. Since the necessary elevation data might not
+ * be in memory at the time of the call, this method iterates until the necessary elevation data is in memory
+ * and can be used to determine the locations elevations.
+ *
+ * @param locations a list of locations to determine elevations for
+ */
+ public void loadBestElevations(ArrayList locations)
+ {
+ Globe globe = this.getWwd().getModel().getGlobe();
+ ArrayList sectors = new ArrayList<>();
+ ArrayList> locationsList = new ArrayList<>();
+ double delta = 0.0001;
+ for (LatLon ll : locations)
+ {
+ double lat = ll.latitude.degrees;
+ double lon = ll.longitude.degrees;
+ sectors.add(Sector.fromDegrees(lat, lat + delta, lon, lon + delta));
+ ArrayList sectorLocations = new ArrayList<>();
+ sectorLocations.add(ll);
+ sectorLocations.add(LatLon.fromDegrees(lat + delta, lon + delta));
+ locationsList.add(sectorLocations);
+ }
+
+ double[] targetResolutions = new double[sectors.size()];
+ double[] actualResolutions = new double[sectors.size()];
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ targetResolutions[i] = globe.getElevationModel().getBestResolution(sectors.get(i));
+ }
+ boolean resolutionsAchieved = false;
+ double[] elevations = new double[2];
+ while (!resolutionsAchieved)
+ {
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ actualResolutions[i] = globe.getElevations(sectors.get(i), locationsList.get(i), targetResolutions[i], elevations);
+ }
+
+ resolutionsAchieved = true;
+ for (int i = 0, len = actualResolutions.length; i < len && resolutionsAchieved; i++)
+ {
+ resolutionsAchieved = actualResolutions[i] <= targetResolutions[i];
+ }
+ if (!resolutionsAchieved)
+ {
+ try
+ {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public AppFrame()
+ {
+ Model m = this.wwjPanel.getWwd().getModel();
+ Earth earth = (Earth) m.getGlobe();
+ final RenderableLayer layer = new RenderableLayer();
+ double[] locations = new double[]
+ {
+ 37.0, -119.0,
+ 36.0, -117.016667,
+ 89.0, 0.0,
+ -80.0, 0.0,
+ -90.0, 0.0
+ };
+ EGM2008 egm2008Offsets = new EGM2008("config/egm2008_25.dat");
+ boolean egmAvailable = egm2008Offsets.isEGMDataAvailable();
+ if (!egmAvailable)
+ {
+ System.out.println("*** EGM 2008 data not available.");
+ }
+
+ // Run the elevation query in a separate thread to avoid locking up the user interface
+ Thread t = new Thread(() ->
+ {
+ ArrayList elevLocations = new ArrayList<>();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ elevLocations.add(LatLon.fromDegrees(locations[i], locations[i + 1]));
+ }
+
+ loadBestElevations(elevLocations);
+
+ try
+ {
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ Position pos = Position.fromDegrees(locations[i], locations[i + 1], 0);
+ PointPlacemark placemark = new PointPlacemark(pos);
+ String label = String.format("lat: %7.4f, lon: %7.4f", locations[i], locations[i + 1]);
+ float egmOffset = egm2008Offsets.getOffset(pos.latitude, pos.longitude);
+ double elevation = earth.getElevation(pos.latitude, pos.longitude);
+ if (egmAvailable)
+ {
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM2008 Offset: %7.4f\nEllipsoid elevation:%7.4f\nEGM2008 Adjusted elevation: %7.4f",
+ egmOffset, elevation, elevation - egmOffset));
+ }
+ else
+ {
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM2008 Offset: N/A\nEllipsoid elevation:%7.4f\nEGM2008 Adjusted elevation: N/A",
+ elevation));
+ }
+ placemark.setLabelText(label);
+ layer.addRenderable(placemark);
+ }
+ }
+ catch (IOException iex)
+ {
+ iex.printStackTrace();
+ }
+
+ SwingUtilities.invokeLater(() ->
+ {
+ System.out.println("Elevations retrieved");
+ getWwd().redraw();
+ });
+ });
+ t.start();
+
+ try
+ {
+ // Test offsets for some coordinates
+ float lat = 47;
+ float lon = -94;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 37;
+ lon = -119;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ // Try previous coordinates to verify caching
+ lat = 47;
+ lon = -94;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 37;
+ lon = -119;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 47.02f;
+ lon = -94.02f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ float gridResolution = (float) EGM2008.GRID_RESOLUTION;
+ lat = 47 + gridResolution;
+ lon = -94 - gridResolution;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 36.0f;
+ lon = -117.0f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 36.0f;
+ lon = -117.041666666667f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ System.out.println();
+ }
+ catch (IOException iex)
+ {
+ iex.printStackTrace();
+ }
+
+ this.wwjPanel.toolTipController.setAnnotationSize(new Dimension(500, 0));
+ insertBeforeCompass(getWwd(), layer);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ ApplicationTemplate.start("WorldWind EGM2008 Offsets", AppFrame.class);
+ }
+}
diff --git a/src/gov/nasa/worldwindx/examples/EGM96Offsets.java b/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
index a64d11b1bc..39b7adf6b0 100644
--- a/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
+++ b/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
@@ -2,39 +2,50 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
*/
-
package gov.nasa.worldwindx.examples;
import gov.nasa.worldwind.Model;
+import gov.nasa.worldwind.avlist.AVKey;
+import gov.nasa.worldwind.geom.LatLon;
+import gov.nasa.worldwind.geom.Position;
+import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.globes.Earth;
+import gov.nasa.worldwind.globes.Globe;
+import gov.nasa.worldwind.layers.RenderableLayer;
+import gov.nasa.worldwind.render.PointPlacemark;
+import gov.nasa.worldwind.util.EGM96;
+import java.awt.Dimension;
import java.io.IOException;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
/**
* Shows how to apply EGM96 offsets to the Earth.
+ *
* @author tag
* @version $Id: EGM96Offsets.java 1501 2013-07-11 15:59:11Z tgaskins $
*/
@@ -42,17 +53,118 @@ public class EGM96Offsets extends ApplicationTemplate
{
public static class AppFrame extends ApplicationTemplate.AppFrame
{
+ /**
+ * Attempt to retrieve the best elevations for a specified list of locations. The elevations returned are the best currently
+ * available for the data set and the area bounding the locations. Since the necessary elevation data might not
+ * be in memory at the time of the call, this method iterates until the necessary elevation data is in memory
+ * and can be used to determine the locations elevations.
+ *
+ * @param locations a list of locations to determine elevations for
+ */
+ public void loadBestElevations(ArrayList locations)
+ {
+ Globe globe = this.getWwd().getModel().getGlobe();
+ ArrayList sectors = new ArrayList<>();
+ ArrayList> locationsList = new ArrayList<>();
+ double delta = 0.0001;
+ for (LatLon ll : locations)
+ {
+ double lat = ll.latitude.degrees;
+ double lon = ll.longitude.degrees;
+ sectors.add(Sector.fromDegrees(lat, lat + delta, lon, lon + delta));
+ ArrayList sectorLocations = new ArrayList<>();
+ sectorLocations.add(ll);
+ sectorLocations.add(LatLon.fromDegrees(lat + delta, lon + delta));
+ locationsList.add(sectorLocations);
+ }
+
+ double[] targetResolutions = new double[sectors.size()];
+ double[] actualResolutions = new double[sectors.size()];
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ targetResolutions[i] = globe.getElevationModel().getBestResolution(sectors.get(i));
+ }
+ boolean resolutionsAchieved = false;
+ double[] elevations = new double[2];
+ while (!resolutionsAchieved)
+ {
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ actualResolutions[i] = globe.getElevations(sectors.get(i), locationsList.get(i), targetResolutions[i], elevations);
+ }
+
+ resolutionsAchieved = true;
+ for (int i = 0, len = actualResolutions.length; i < len && resolutionsAchieved; i++)
+ {
+ resolutionsAchieved = actualResolutions[i] <= targetResolutions[i];
+ }
+ if (!resolutionsAchieved)
+ {
+ try
+ {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
public AppFrame()
{
Model m = this.wwjPanel.getWwd().getModel();
+ Earth earth = (Earth) m.getGlobe();
try
{
- ((Earth) m.getGlobe()).applyEGMA96Offsets("config/EGM96.dat");
+ earth.applyEGMA96Offsets("config/EGM96.dat");
}
catch (IOException e)
{
e.printStackTrace();
}
+ final RenderableLayer layer = new RenderableLayer();
+ double[] locations = new double[]
+ {
+ 37.0, -119.0,
+ 36.0, -117.016667,
+ 89.0, 0.0,
+ -80.0, 0.0,
+ -90.0, 0.0
+ };
+ Thread t = new Thread(() ->
+ {
+ ArrayList elevLocations = new ArrayList<>();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ elevLocations.add(LatLon.fromDegrees(locations[i], locations[i + 1]));
+ }
+
+ loadBestElevations(elevLocations);
+
+ EGM96 egm96Offsets = earth.getEGM96();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ Position pos = Position.fromDegrees(locations[i], locations[i + 1], 0);
+ PointPlacemark placemark = new PointPlacemark(pos);
+ String label = String.format("lat: %7.4f, lon: %7.4f", locations[i], locations[i + 1]);
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM96 Offset: %7.4f\nEGM96 Adjusted elevation: %7.4f",
+ egm96Offsets.getOffset(pos.latitude, pos.longitude),
+ earth.getElevation(pos.latitude, pos.longitude)));
+ placemark.setLabelText(label);
+ layer.addRenderable(placemark);
+ }
+ SwingUtilities.invokeLater(() ->
+ {
+ System.out.println("Elevations retrieved");
+ getWwd().redraw();
+ });
+ });
+ t.start();
+
+ this.wwjPanel.toolTipController.setAnnotationSize(new Dimension(500, 0));
+ insertBeforeCompass(getWwd(), layer);
}
}
diff --git a/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java b/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
index 85d358249b..69b42dfc81 100644
--- a/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
+++ b/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
@@ -37,6 +37,8 @@
import java.text.Format;
import java.util.ArrayList;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
/**
* @author dcollins
* @version $Id: AnalyticSurfaceLegend.java 2053 2014-06-10 20:16:57Z tgaskins $
@@ -158,7 +160,8 @@ public int getHeight(DrawContext dc)
return this.screenImage.getImageHeight(dc);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -225,27 +228,32 @@ public static AnalyticSurfaceLegend.LabelAttributes createLegendLabelAttributes(
{
return new AnalyticSurfaceLegend.LabelAttributes()
{
- public double getValue()
+ @Override
+ public double getValue()
{
return value;
}
- public String getText()
+ @Override
+ public String getText()
{
return text;
}
- public Font getFont()
+ @Override
+ public Font getFont()
{
return font;
}
- public Color getColor()
+ @Override
+ public Color getColor()
{
return color;
}
- public Point2D getOffset()
+ @Override
+ public Point2D getOffset()
{
return new Point2D.Double(xOffset, yOffset);
}
@@ -320,18 +328,16 @@ protected void drawLabel(DrawContext dc, LabelAttributes attr, double x, double
tr.beginRendering(viewport.width, viewport.height);
try
{
- double yInGLCoords = viewport.height - y - 1;
-
// Draw the text outline, in a contrasting color.
tr.setColor(WWUtil.computeContrastingColor(color));
- tr.draw(text, (int) x - 1, (int) yInGLCoords - 1);
- tr.draw(text, (int) x + 1, (int) yInGLCoords - 1);
- tr.draw(text, (int) x + 1, (int) yInGLCoords + 1);
- tr.draw(text, (int) x - 1, (int) yInGLCoords + 1);
+ tr.draw(text, (int) x - 1, (int) y - 1);
+ tr.draw(text, (int) x + 1, (int) y - 1);
+ tr.draw(text, (int) x + 1, (int) y + 1);
+ tr.draw(text, (int) x - 1, (int) y + 1);
// Draw the text over its outline, in the specified color.
tr.setColor(color);
- tr.draw(text, (int) x, (int) yInGLCoords);
+ tr.draw(text, (int) x, (int) y);
}
finally
{
@@ -411,7 +417,8 @@ public LabelRenderable(AnalyticSurfaceLegend legend, LabelAttributes attr, doubl
this.orderedLabel = new OrderedLabel(legend, attr, x, y, halign, valign);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
dc.addOrderedRenderable(this.orderedLabel);
}
@@ -437,17 +444,20 @@ public OrderedLabel(AnalyticSurfaceLegend legend, LabelAttributes attr, double x
this.valign = valign;
}
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0;
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
this.legend.drawLabel(dc, this.attr, this.x, this.y, this.halign, this.valign);
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
// Intentionally left blank.
}
diff --git a/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java b/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
index 12b60e1fa9..759426f6f4 100644
--- a/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
+++ b/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
@@ -37,7 +37,6 @@
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.ogc.kml.impl.KMLController;
-import gov.nasa.worldwind.render.Offset;
import gov.nasa.worldwind.util.*;
import javax.swing.*;
@@ -76,7 +75,7 @@ public AppFrame()
// Add the on-screen layer tree, refreshing model with the WorldWindow's current layer list. We
// intentionally refresh the tree's model before adding the layer that contains the tree itself. This
// prevents the tree's layer from being displayed in the tree itself.
- this.layerTree = new LayerTree(new Offset(20d, 160d, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this.layerTree = new LayerTree(new Point(20, 160));
this.layerTree.getModel().refresh(this.getWwd().getModel().getLayers());
// Set up a layer to display the on-screen layer tree in the WorldWindow. This layer is not displayed in
@@ -119,7 +118,8 @@ protected void addDocumentLayer(KMLRoot document)
// Set up to receive SSLHandshakeExceptions that occur during resource retrieval.
WorldWind.getRetrievalService().setSSLExceptionListener(new RetrievalService.SSLExceptionListener()
{
- public void onException(Throwable e, String path)
+ @Override
+ public void onException(Throwable e, String path)
{
System.out.println(path);
System.out.println(e);
@@ -164,14 +164,16 @@ protected void addKMLLayer(KMLRoot kmlRoot)
// we ensure that the network link tree view appearance is consistent with the KML specification.
layerNode.addPropertyChangeListener(AVKey.RETRIEVAL_STATE_SUCCESSFUL, new PropertyChangeListener()
{
- public void propertyChange(final PropertyChangeEvent event)
+ @Override
+ public void propertyChange(final PropertyChangeEvent event)
{
if (event.getSource() instanceof KMLNetworkLinkTreeNode)
{
// Manipulate the tree on the EDT.
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
((KMLNetworkLinkTreeNode) event.getSource()).expandOpenContainers(layerTree);
getWwd().redraw();
@@ -213,7 +215,8 @@ public WorkerThread(Object kmlSource, AppFrame appFrame)
* If loading the KML source fails, this prints the exception and its stack trace to the standard error stream,
* but otherwise does nothing.
*/
- public void run()
+ @Override
+ public void run()
{
try
{
@@ -226,7 +229,8 @@ public void run()
final KMLRoot finalKMLRoot = kmlRoot;
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
appFrame.addKMLLayer(finalKMLRoot);
}
@@ -287,7 +291,8 @@ protected static void makeMenu(final AppFrame appFrame)
JMenuItem openFileMenuItem = new JMenuItem(new AbstractAction("Open File...")
{
- public void actionPerformed(ActionEvent actionEvent)
+ @Override
+ public void actionPerformed(ActionEvent actionEvent)
{
try
{
@@ -311,7 +316,8 @@ public void actionPerformed(ActionEvent actionEvent)
JMenuItem openURLMenuItem = new JMenuItem(new AbstractAction("Open URL...")
{
- public void actionPerformed(ActionEvent actionEvent)
+ @Override
+ public void actionPerformed(ActionEvent actionEvent)
{
try
{
@@ -334,6 +340,7 @@ public void actionPerformed(ActionEvent actionEvent)
public static void main(String[] args)
{
//noinspection UnusedDeclaration
- final AppFrame af = (AppFrame) start("WorldWind KML Viewer", AppFrame.class);
+ @SuppressWarnings("unused")
+ final AppFrame af = (AppFrame) start("WorldWind KML Viewer", AppFrame.class);
}
}
diff --git a/src/gov/nasa/worldwindx/examples/util/BalloonController.java b/src/gov/nasa/worldwindx/examples/util/BalloonController.java
index f1708c1e95..63d1718990 100644
--- a/src/gov/nasa/worldwindx/examples/util/BalloonController.java
+++ b/src/gov/nasa/worldwindx/examples/util/BalloonController.java
@@ -163,18 +163,33 @@ public void setBalloonOffset(int balloonOffset)
//*********************** Event handling *****************************//
//********************************************************************//
+ /**
+ * Construct a mouse event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseEvent glMouseEvent(MouseEvent awtMouseEvent) {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtMouseEvent.getPoint());
+ MouseEvent e = new MouseEvent(awtMouseEvent.getComponent(), awtMouseEvent.getID(),
+ awtMouseEvent.getWhen(), awtMouseEvent.getModifiersEx(),
+ awtMouseEvent.getClickCount(), GLmousePt[0], GLmousePt[1], awtMouseEvent.isPopupTrigger(),
+ awtMouseEvent.getButton());
+ return e;
+ }
/**
* Handle a mouse click. If the top picked object has a balloon attached to it the balloon will be made visible. A
* balloon may be attached to a KML feature, or to any picked object though {@link AVKey#BALLOON}.
*
- * @param e Mouse event
+ * @param awtEv Mouse event
*/
@Override
- public void mouseClicked(MouseEvent e)
+ public void mouseClicked(MouseEvent awtEv)
{
- if (e == null || e.isConsumed())
+ if (awtEv == null || awtEv.isConsumed())
return;
+ MouseEvent e = glMouseEvent(awtEv);
+
// Implementation note: handle the balloon with a mouse listener instead of a select listener so that the balloon
// can be turned off if the user clicks on the terrain.
try
@@ -219,6 +234,9 @@ public void mouseClicked(MouseEvent e)
// Wrap the handler in a try/catch to keep exceptions from bubbling up
Logging.logger().warning(ex.getMessage() != null ? ex.getMessage() : ex.toString());
}
+
+ if (e.isConsumed())
+ awtEv.consume();
}
@Override
@@ -248,7 +266,8 @@ else if (this.resizeController != null && !this.resizeController.isResizing())
}
}
- @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
public void selected(SelectEvent event)
{
if (event == null || event.isConsumed()
@@ -984,8 +1003,7 @@ protected void showBalloon(Balloon balloon, Position position)
Vec4 screenVec4 = this.wwd.getView().project(
this.wwd.getModel().getGlobe().computePointFromPosition(position));
- Point screenPoint = new Point((int) screenVec4.x,
- (int) (this.wwd.getView().getViewport().height - screenVec4.y));
+ Point screenPoint = new Point((int) screenVec4.x, (int) screenVec4.y);
// If the balloon is attached to the screen rather than the globe, move it to the
// current point. Otherwise move it to the position under the current point.
@@ -1327,8 +1345,7 @@ protected Point getBalloonPointForScreenOverlay(KMLScreenOverlay overlay)
Rectangle viewport = this.wwd.getView().getViewport();
Point2D point2D = offset.computeOffset(viewport.width, viewport.height, 1d, 1d);
- int y = (int) point2D.getY();
- return new Point((int) point2D.getX(), viewport.height - y);
+ return new Point((int) point2D.getX(), (int) point2D.getY());
}
/**
@@ -1504,7 +1521,8 @@ public DocumentRetrievalTask(String url, KMLRoot context, String featureRef, lon
* gov.nasa.worldwind.ogc.kml.KMLRoot, String)}. If an exception occurs, or the timeout is exceeded, schedule a
* callback on the EDT to {@link BalloonController#onDocumentFailed(String, Exception)}
*/
- public void run()
+ @Override
+ public void run()
{
KMLRoot root = null;
@@ -1544,7 +1562,8 @@ else if (docSource != null)
final KMLRoot pinnedRoot = root; // Final ref that can be accessed by anonymous class
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
BalloonController.this.onDocumentLoaded(docUrl, pinnedRoot, featureRef);
}
@@ -1558,7 +1577,8 @@ public void run()
// Schedule a callback on the EDT to report the error to the BalloonController
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
BalloonController.this.onDocumentFailed(docUrl, e);
}
diff --git a/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java b/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
index 57dd7465f2..24a72f8714 100644
--- a/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
+++ b/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
@@ -644,7 +644,7 @@ protected void drag(SelectEvent event)
Point cursorOffset = new Point(event.getMouseEvent().getPoint().x - this.dragRefCursorPoint.x,
event.getMouseEvent().getPoint().y - this.dragRefCursorPoint.y);
Point targetPoint = new Point(this.dragRefPoint.x + cursorOffset.x,
- this.dragRefPoint.y - cursorOffset.y);
+ this.dragRefPoint.y + cursorOffset.y);
this.moveTo(targetPoint);
event.consume();
}
diff --git a/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java b/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
index ec266fd0b8..4716064555 100644
--- a/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
+++ b/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
@@ -45,7 +45,7 @@
* and tracks the list of objects intersecting the screen rectangle. The screen rectangle is displayed on a layer
* created by ScreenSelector, and is used as the WorldWindow's pick rectangle to perform object selection. Objects
* intersecting the screen rectangle can be accessed by calling {@link #getSelectedObjects()}.
- * Using ScreenSelector
+ * Using ScreenSelector
*
* To use ScreenSelector in an application, create a new instance of ScreenSelector and specify the application's
* WorldWindow as the sole parameter. When the user wants to define a screen selection, call {@link #enable} and the
@@ -163,8 +163,8 @@ public void endSelection(Point point)
maxX = this.startPoint.x;
}
- // Compute the selection's extremes along the y axis. The selection is defined in AWT screen coordinates, so
- // the origin is in the upper left corner and the y axis points down.
+ // Compute the selection's extremes along the y axis. The selection is defined in GL surface coordinates, so
+ // the origin is in the lower left corner and the y axis points up.
double minY, maxY;
if (this.startPoint.y < this.endPoint.y)
{
@@ -185,7 +185,7 @@ public void endSelection(Point point)
if (minY == maxY && minX < maxX)
minY = maxY - 1;
- this.rect.setRect(minX, maxY, maxX - minX, maxY - minY);
+ this.rect.setRect(minX, minY, maxX - minX, maxY - minY);
}
public void clearSelection()
@@ -215,17 +215,20 @@ public void setBorderColor(Color color)
this.borderColor = color;
}
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0; // Screen rectangle is drawn on top of other ordered renderables, except other screen objects.
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
// Intentionally left blank. SelectionRectangle is not pickable.
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -270,7 +273,7 @@ protected void drawOrderedRenderable(DrawContext dc)
gl.glOrtho(0, viewport.getWidth(), 0, viewport.getHeight(), -1, 1); // l, r, b, t, n, f
this.BEogsh.pushModelviewIdentity(gl);
gl.glTranslated(0.5, 0.5, 0.0);
- gl.glTranslated(selection.getX(), viewport.getHeight() - selection.getY(), 0);
+ gl.glTranslated(selection.getX(), selection.getY(), 0);
gl.glScaled(selection.getWidth() - 1, selection.getHeight() - 1, 1);
// Disable the depth test and enable blending so this screen rectangle appears on top of the existing
@@ -460,12 +463,14 @@ protected void sendMessage(Message message)
}
}
- public void mouseClicked(MouseEvent mouseEvent)
+ @Override
+ public void mouseClicked(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse clicked events.
}
- public void mousePressed(MouseEvent mouseEvent)
+ @Override
+ public void mousePressed(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -478,7 +483,8 @@ public void mousePressed(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseReleased(MouseEvent mouseEvent)
+ @Override
+ public void mouseReleased(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -491,17 +497,20 @@ public void mouseReleased(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseEntered(MouseEvent mouseEvent)
+ @Override
+ public void mouseEntered(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse entered events.
}
- public void mouseExited(MouseEvent mouseEvent)
+ @Override
+ public void mouseExited(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse exited events.
}
- public void mouseDragged(MouseEvent mouseEvent)
+ @Override
+ public void mouseDragged(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -513,7 +522,8 @@ public void mouseDragged(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseMoved(MouseEvent mouseEvent)
+ @Override
+ public void mouseMoved(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse moved events.
}
@@ -530,8 +540,7 @@ protected void selectionStarted(MouseEvent mouseEvent)
this.sendMessage(new Message(SELECTION_STARTED, this));
}
- @SuppressWarnings({"UnusedParameters"})
- protected void selectionEnded(MouseEvent mouseEvent)
+ protected void selectionEnded(@SuppressWarnings("unused") MouseEvent mouseEvent)
{
this.selectionRect.clearSelection();
this.getWwd().getSceneController().setPickRectangle(null);
@@ -577,19 +586,20 @@ protected Point limitPointToWorldWindow(Point point)
int x = point.x;
if (x < viewport.x)
x = viewport.x;
- if (x > viewport.x + viewport.width)
- x = viewport.x + viewport.width;
+ if (x >= viewport.x + viewport.width)
+ x = viewport.x + viewport.width - 1;
int y = point.y;
if (y < viewport.y)
y = viewport.y;
- if (y > viewport.y + viewport.height)
- y = viewport.y + viewport.height;
+ if (y >= viewport.y + viewport.height)
+ y = viewport.y + viewport.height - 1;
return new Point(x, y);
}
- public void selected(SelectEvent event)
+ @Override
+ public void selected(SelectEvent event)
{
try
{
diff --git a/src/gov/nasa/worldwindx/examples/util/StatusLayer.java b/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
index 9544a97cee..76f9d4c6e5 100644
--- a/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
+++ b/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
@@ -27,6 +27,7 @@
*/
package gov.nasa.worldwindx.examples.util;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.event.*;
diff --git a/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java b/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
index 5113946db4..ab47aad371 100644
--- a/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
+++ b/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
@@ -116,7 +116,7 @@ protected void doRenderNow(DrawContext dc)
protected Point adjustDrawPointToViewport(Point point, Rectangle bounds, Rectangle viewport)
{
int x = point.x;
- int y = (int) viewport.getHeight() - point.y - 1;
+ int y = point.y;
if (x + this.getOffsetX() + bounds.getWidth() > viewport.getWidth())
x = (int) (viewport.getWidth() - bounds.getWidth()) - 1 - this.getOffsetX();
diff --git a/src/gov/nasa/worldwindx/examples/util/ToolTipController.java b/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
index 0cadd531d9..05e58a7e63 100644
--- a/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
+++ b/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -34,6 +34,7 @@
import gov.nasa.worldwindx.examples.ApplicationTemplate;
import gov.nasa.worldwind.layers.*;
import gov.nasa.worldwind.util.*;
+import java.awt.Dimension;
/**
* Controls display of tool tips on picked objects. Any shape implementing {@link AVList} can participate. Shapes
@@ -52,6 +53,7 @@ public class ToolTipController implements SelectListener, Disposable
protected Object lastHoverObject;
protected AnnotationLayer layer;
protected ToolTipAnnotation annotation;
+ protected Dimension annotationSize = null;
/**
* Create a controller for a specified {@link WorldWindow} that displays tool tips on hover and/or rollover.
@@ -84,6 +86,16 @@ public ToolTipController(WorldWindow wwd)
this.wwd.addSelectListener(this);
}
+ public Dimension getAnnotationSize()
+ {
+ return this.annotationSize;
+ }
+
+ public void setAnnotationSize(Dimension value)
+ {
+ this.annotationSize = value;
+ }
+
public void dispose()
{
this.wwd.removeSelectListener(this);
@@ -91,14 +103,14 @@ public void dispose()
protected String getHoverText(SelectEvent event)
{
- return event.getTopObject() != null && event.getTopObject() instanceof AVList ?
- ((AVList) event.getTopObject()).getStringValue(this.hoverKey) : null;
+ return event.getTopObject() != null && event.getTopObject() instanceof AVList
+ ? ((AVList) event.getTopObject()).getStringValue(this.hoverKey) : null;
}
protected String getRolloverText(SelectEvent event)
{
- return event.getTopObject() != null && event.getTopObject() instanceof AVList ?
- ((AVList) event.getTopObject()).getStringValue(this.rolloverKey) : null;
+ return event.getTopObject() != null && event.getTopObject() instanceof AVList
+ ? ((AVList) event.getTopObject()).getStringValue(this.rolloverKey) : null;
}
public void selected(SelectEvent event)
@@ -167,6 +179,7 @@ protected void showToolTip(SelectEvent event, String text)
else
{
annotation = new ToolTipAnnotation(text);
+ annotation.getAttributes().setSize(this.annotationSize);
}
if (layer == null)
diff --git a/src/overview.html b/src/overview.html
index e8cb93b2e3..faba690f87 100644
--- a/src/overview.html
+++ b/src/overview.html
@@ -42,15 +42,15 @@
Most of WorldWind's components are defined by interfaces. This allows application developers to create their own
implementations and easily integrate them into WorldWind.
-The WorldWind
Class
+The WorldWind
Class
TODO
-Multiple WorldWind Windows
+Multiple WorldWind Windows
TODO
-Data Retrieval
+Data Retrieval
WorldWind works with enormous quantities of data and information, all of which exist primarily on remote data
@@ -99,7 +99,7 @@
Data Retrieval
Retriever and requests retrieval. Later, after retrieval has placed the data on disk, the situation will be
the local case and data can be loaded into memory within the Runnable
.
-Memory Cache
+Memory Cache
So that data can be shared among caching objects, most cached data used within WorldWind is cached in a {@link
gov.nasa.worldwind.cache.MemoryCache}. MemoryCache
enable cached data to be shared among all
@@ -114,7 +114,7 @@
File Cache
No object manages its own storage. The file cache cache manages multiple disk storage locations and unifies access to
them. The file cache is a singleton, accessible through the WorldWind
singleton.
-Picking and Selection
+Picking and Selection
WorldWind can determine the displayed objects at a given screen position in a WorldWindow
. When the
application wants to know what's displayed at a particular point, say the cursor position, it calls a method on
@@ -158,7 +158,7 @@
Picking and Selection
WorldWind provides utility classes to make it simple for layers to participate in this picking scheme. See {@link
gov.nasa.worldwind.pick.PickSupport}
-Use of Proxies
+Use of Proxies
A proxy is set by calling {@link gov.nasa.worldwind.Configuration#setValue} for each of the following keys:
@@ -176,7 +176,7 @@ Offline Mode
to attempting retrieval of a network resource — anything addressed by a URL — WorldWind checks the
offline-mode setting and does not attempt retrieval if the value is true.
-Path Types
+Path Types
There is only one way to draw a straight line on a plane, but there are several ways to draw a straight line on the
surface of a globe. Most shapes support the following path types: