Skip to content

Commit

Permalink
Wrap latitude, longitude and altitude into Position object inside of …
Browse files Browse the repository at this point in the history
…Navigator, Camera and LookAt.

Move field of view attribute into Camera.
Deprecate Navigator and use direct Camera control instead.
Use two-fingers tilt.
Do not change heading on tilt.
Set gesture interpret distance based on Android screen density instead of hard-coded pixels.
Add additional zoomIn, zoomOut and resetOrientation commands to BasicWorldWindowController.
Add secondary mouse button tilt support to BasicWorldWindowController.
Remove code which never executes due to a bug in WWMath.
  • Loading branch information
EMaksymenko committed Dec 7, 2020
1 parent 7431823 commit 1727068
Show file tree
Hide file tree
Showing 59 changed files with 639 additions and 647 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,17 @@ protected void onResume() {
this.navigationView.setCheckedItem(selectedItemId);
// Use this Activity's Handler to periodically print the FrameMetrics.
this.handler.sendEmptyMessageDelayed(PRINT_METRICS, PRINT_METRICS_DELAY);
// Restore the navigator's camera state from previously saved session data
this.restoreNavigatorState();
// Restore camera state from previously saved session data
this.restoreCameraState();
}

@Override
protected void onPause() {
super.onPause();
// Stop printing frame metrics when this activity is paused.
this.handler.removeMessages(PRINT_METRICS);
// Save the navigator's camera state.
this.saveNavigatorState();
// Save camera state.
this.saveCameraState();
}

@Override
Expand All @@ -163,9 +163,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
}

/**
* Saves the Navigator's camera data to a SharedPreferences object.
* Saves camera state to a SharedPreferences object.
*/
protected void saveNavigatorState() {
protected void saveCameraState() {
WorldWindow wwd = this.getWorldWindow();
if (wwd != null) {
SharedPreferences preferences = this.getPreferences(MODE_PRIVATE);
Expand All @@ -175,10 +175,10 @@ protected void saveNavigatorState() {
editor.putLong(SESSION_TIMESTAMP, getSessionTimestamp());

// Write the camera data
Camera camera = wwd.getNavigator().getAsCamera(wwd.getGlobe(), new Camera());
editor.putFloat(CAMERA_LATITUDE, (float) camera.latitude);
editor.putFloat(CAMERA_LONGITUDE, (float) camera.longitude);
editor.putFloat(CAMERA_ALTITUDE, (float) camera.altitude);
Camera camera = wwd.getCamera();
editor.putFloat(CAMERA_LATITUDE, (float) camera.position.latitude);
editor.putFloat(CAMERA_LONGITUDE, (float) camera.position.longitude);
editor.putFloat(CAMERA_ALTITUDE, (float) camera.position.altitude);
editor.putFloat(CAMERA_HEADING, (float) camera.heading);
editor.putFloat(CAMERA_TILT, (float) camera.tilt);
editor.putFloat(CAMERA_ROLL, (float) camera.roll);
Expand All @@ -189,9 +189,9 @@ protected void saveNavigatorState() {
}

/**
* Restores the Navigator's camera state from a SharedPreferences object.
* Restores camera state from a SharedPreferences object.
*/
protected void restoreNavigatorState() {
protected void restoreCameraState() {
WorldWindow wwd = this.getWorldWindow();
if (wwd != null) {
SharedPreferences preferences = this.getPreferences(MODE_PRIVATE);
Expand All @@ -215,8 +215,7 @@ protected void restoreNavigatorState() {
}

// Restore the camera state.
Camera camera = new Camera(lat, lon, alt, altMode, heading, tilt, roll);
wwd.getNavigator().setAsCamera(wwd.getGlobe(), camera);
wwd.getCamera().set(lat, lon, alt, altMode, heading, tilt, roll);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ public WorldWindow getWorldWindow() {
return null;
}

@Override
public void setWorldWindow(WorldWindow wwd) {
}

@Override
public boolean onTouchEvent(MotionEvent event) {
return false;
Expand All @@ -60,40 +56,34 @@ public static class AnimateCameraCommand implements Runnable {

protected WorldWindow wwd;

protected Camera beginCamera = new Camera();

protected Camera endCamera = new Camera();
protected Camera beginCamera;

protected Camera curCamera = new Camera();
protected Camera endCamera;

protected Position beginPos = new Position();

protected Position endPos = new Position();

protected Position curPos = new Position();
protected Camera curCamera;

protected int steps;

public AnimateCameraCommand(WorldWindow wwd, Camera end, int steps) {
this.wwd = wwd;

this.beginCamera = new Camera(wwd);
this.endCamera = new Camera(wwd);
this.curCamera = new Camera(wwd);

this.endCamera.set(end);
this.endPos.set(end.latitude, end.longitude, end.altitude);
this.steps = steps;
}

@Override
public void run() {
this.wwd.getNavigator().getAsCamera(this.wwd.getGlobe(), this.beginCamera);
this.beginPos.set(this.beginCamera.latitude, this.beginCamera.longitude, this.beginCamera.altitude);
this.beginCamera.set(this.wwd.getCamera());

for (int i = 0; i < this.steps; i++) {

double amount = (double) i / (double) (this.steps - 1);
this.beginPos.interpolateAlongPath(this.endPos, WorldWind.GREAT_CIRCLE, amount, this.curPos);
this.beginCamera.position.interpolateAlongPath(this.endCamera.position, WorldWind.GREAT_CIRCLE, amount, this.curCamera.position);

this.curCamera.latitude = this.curPos.latitude;
this.curCamera.longitude = this.curPos.longitude;
this.curCamera.altitude = this.curPos.altitude;
this.curCamera.heading = WWMath.interpolateAngle360(amount, this.beginCamera.heading, this.endCamera.heading);
this.curCamera.tilt = WWMath.interpolateAngle180(amount, this.beginCamera.tilt, this.endCamera.tilt);
this.curCamera.roll = WWMath.interpolateAngle180(amount, this.beginCamera.roll, this.endCamera.roll);
Expand All @@ -111,7 +101,7 @@ public static class SetCameraCommand implements Runnable {

private WorldWindow wwd;

private Camera camera = new Camera();
private Camera camera;

private SetCameraCommand() {
}
Expand All @@ -127,6 +117,7 @@ public static SetCameraCommand obtain(WorldWindow wwd, Camera camera) {

private SetCameraCommand set(WorldWindow wwd, Camera camera) {
this.wwd = wwd;
this.camera = new Camera(wwd);
this.camera.set(camera);
return this;
}
Expand All @@ -138,7 +129,7 @@ private SetCameraCommand reset() {

@Override
public void run() {
this.wwd.getNavigator().setAsCamera(this.wwd.getGlobe(), this.camera);
this.wwd.getCamera().set(this.camera);
this.wwd.requestRedraw();
pool.release(this.reset());
}
Expand Down Expand Up @@ -249,40 +240,40 @@ protected void onStart() {
exec.execute(new ClearFrameMetricsCommand(wwd));

// After a 1/2 second delay, fly to NASA Ames Research Center over 100 frames.
Camera cam = new Camera(arc.latitude, arc.longitude, 10e3, WorldWind.ABSOLUTE, 0, 0, 0);
Camera cam = new Camera(this.getWorldWindow()).set(arc.latitude, arc.longitude, 10e3, WorldWind.ABSOLUTE, 0, 0, 0);
exec.execute(new AnimateCameraCommand(wwd, cam, 100));

// After a 1/2 second delay, rotate the camera to look at NASA Goddard Space Flight Center over 50 frames.
double azimuth = arc.greatCircleAzimuth(gsfc);
cam = new Camera(arc.latitude, arc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 70, 0);
cam = new Camera(this.getWorldWindow()).set(arc.latitude, arc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 70, 0);
exec.execute(new SleepCommand(500));
exec.execute(new AnimateCameraCommand(wwd, cam, 50));

// After a 1/2 second delay, fly the camera to NASA Goddard Space Flight Center over 200 frames.
Location midLoc = arc.interpolateAlongPath(gsfc, WorldWind.GREAT_CIRCLE, 0.5, new Location());
azimuth = midLoc.greatCircleAzimuth(gsfc);
exec.execute(new SleepCommand(500));
cam = new Camera(midLoc.latitude, midLoc.longitude, 1000e3, WorldWind.ABSOLUTE, azimuth, 0, 0);
cam = new Camera(this.getWorldWindow()).set(midLoc.latitude, midLoc.longitude, 1000e3, WorldWind.ABSOLUTE, azimuth, 0, 0);
exec.execute(new AnimateCameraCommand(wwd, cam, 100));
cam = new Camera(gsfc.latitude, gsfc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 70, 0);
cam = new Camera(this.getWorldWindow()).set(gsfc.latitude, gsfc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 70, 0);
exec.execute(new AnimateCameraCommand(wwd, cam, 100));

// After a 1/2 second delay, rotate the camera to look at ESA Centre for Earth Observation over 50 frames.
azimuth = gsfc.greatCircleAzimuth(esrin);
cam = new Camera(gsfc.latitude, gsfc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 90, 0);
cam = new Camera(this.getWorldWindow()).set(gsfc.latitude, gsfc.longitude, 10e3, WorldWind.ABSOLUTE, azimuth, 90, 0);
exec.execute(new SleepCommand(500));
exec.execute(new AnimateCameraCommand(wwd, cam, 50));

// After a 1/2 second delay, fly the camera to ESA Centre for Earth Observation over 200 frames.
midLoc = gsfc.interpolateAlongPath(esrin, WorldWind.GREAT_CIRCLE, 0.5, new Location());
exec.execute(new SleepCommand(500));
cam = new Camera(midLoc.latitude, midLoc.longitude, 1000e3, WorldWind.ABSOLUTE, azimuth, 60, 0);
cam = new Camera(this.getWorldWindow()).set(midLoc.latitude, midLoc.longitude, 1000e3, WorldWind.ABSOLUTE, azimuth, 60, 0);
exec.execute(new AnimateCameraCommand(wwd, cam, 100));
cam = new Camera(esrin.latitude, esrin.longitude, 100e3, WorldWind.ABSOLUTE, azimuth, 30, 0);
cam = new Camera(this.getWorldWindow()).set(esrin.latitude, esrin.longitude, 100e3, WorldWind.ABSOLUTE, azimuth, 30, 0);
exec.execute(new AnimateCameraCommand(wwd, cam, 100));

// After a 1/2 second delay, back the camera out to look at ESA Centre for Earth Observation over 100 frames.
cam = new Camera(esrin.latitude, esrin.longitude, 2000e3, WorldWind.ABSOLUTE, 0, 0, 0);
cam = new Camera(this.getWorldWindow()).set(esrin.latitude, esrin.longitude, 2000e3, WorldWind.ABSOLUTE, 0, 0, 0);
exec.execute(new SleepCommand(500));
exec.execute(new AnimateCameraCommand(wwd, cam, 100));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import android.os.Bundle;
import android.view.Choreographer;

import gov.nasa.worldwind.Navigator;
import gov.nasa.worldwind.geom.Camera;
import gov.nasa.worldwind.layer.ShowTessellationLayer;

public class BasicStressTestActivity extends GeneralGlobeActivity implements Choreographer.FrameCallback {
Expand All @@ -21,16 +21,16 @@ public class BasicStressTestActivity extends GeneralGlobeActivity implements Cho
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setAboutBoxTitle("About the " + this.getResources().getText(R.string.title_basic_stress_test));
this.setAboutBoxText("Continuously moves the navigator in an Easterly direction from a low altitude.");
this.setAboutBoxText("Continuously moves the camera in an Easterly direction from a low altitude.");

// Add the ShowTessellation layer to provide some visual feedback regardless of texture details
this.getWorldWindow().getLayers().addLayer(new ShowTessellationLayer());

// Initialize the Navigator so that it's looking in the direction of movement and the horizon is visible.
Navigator navigator = this.getWorldWindow().getNavigator();
navigator.setAltitude(1e3); // 1 km
navigator.setHeading(90); // looking east
navigator.setTilt(75); // looking at the horizon
// Initialize the Camera so that it's looking in the direction of movement and the horizon is visible.
Camera camera = this.getWorldWindow().getCamera();
camera.position.altitude = 1e3; // 1 km
camera.heading = 90; // looking east
camera.tilt = 75; // looking at the horizon
}

@Override
Expand All @@ -40,9 +40,9 @@ public void doFrame(long frameTimeNanos) {
double frameDurationSeconds = (frameTimeNanos - this.lastFrameTimeNanos) * 1.0e-9;
double cameraDegrees = (frameDurationSeconds * this.cameraDegreesPerSecond);

// Move the navigator to continuously bring new tiles into view.
Navigator navigator = getWorldWindow().getNavigator();
navigator.setLongitude(navigator.getLongitude() + cameraDegrees);
// Move the camera to continuously bring new tiles into view.
Camera camera = getWorldWindow().getCamera();
camera.position.longitude += cameraDegrees;

// Redraw the WorldWindow to display the above changes.
this.getWorldWindow().requestRedraw();
Expand All @@ -63,7 +63,7 @@ protected void onPause() {
@Override
protected void onResume() {
super.onResume();
// Use this Activity's Choreographer to animate the Navigator.
// Use this Activity's Choreographer to animate the Camera.
Choreographer.getInstance().postFrameCallback(this);
this.lastFrameTimeNanos = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import android.os.Bundle;
import android.view.Choreographer;

import gov.nasa.worldwind.Navigator;
import gov.nasa.worldwind.geom.Camera;
import gov.nasa.worldwind.geom.Location;
import gov.nasa.worldwind.layer.LayerList;
import gov.nasa.worldwindx.experimental.AtmosphereLayer;
Expand All @@ -34,18 +34,18 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAboutBoxTitle("About the " + this.getResources().getText(R.string.title_day_night_cycle));
setAboutBoxText("Demonstrates how to display a continuous day-night cycle on the WorldWind globe.\n" +
"This gradually changes both the Navigator's location and the AtmosphereLayer's light location.");
"This gradually changes both the Camera's location and the AtmosphereLayer's light location.");

// Initialize the Atmosphere layer's light location to our custom location. By default the light location is
// always behind the viewer.
LayerList layers = this.getWorldWindow().getLayers();
this.atmosphereLayer = (AtmosphereLayer) layers.getLayer(layers.indexOfLayerNamed("Atmosphere"));
this.atmosphereLayer.setLightLocation(this.sunLocation);

// Initialize the Navigator so that the sun is behind the viewer.
Navigator navigator = this.getWorldWindow().getNavigator();
navigator.setLatitude(20);
navigator.setLongitude(this.sunLocation.longitude);
// Initialize the Camera so that the sun is behind the viewer.
Camera camera = this.getWorldWindow().getCamera();
camera.position.latitude = 20;
camera.position.longitude = this.sunLocation.longitude;

// Use this Activity's Choreographer to animate the day-night cycle.
Choreographer.getInstance().postFrameCallback(this);
Expand All @@ -59,9 +59,9 @@ public void doFrame(long frameTimeNanos) {
double cameraDegrees = (frameDurationSeconds * this.cameraDegreesPerSecond);
double lightDegrees = (frameDurationSeconds * this.lightDegreesPerSecond);

// Move the navigator to simulate the Earth's rotation about its axis.
Navigator navigator = getWorldWindow().getNavigator();
navigator.setLongitude(navigator.getLongitude() - cameraDegrees);
// Move the camera to simulate the Earth's rotation about its axis.
Camera camera = getWorldWindow().getCamera();
camera.position.longitude -= cameraDegrees;

// Move the sun location to simulate the Sun's rotation about the Earth.
this.sunLocation.set(this.sunLocation.latitude, this.sunLocation.longitude - lightDegrees);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ public class GeneralGlobeActivity extends BasicGlobeActivity {
protected TextView altView;
protected ImageView crosshairs;
protected ViewGroup overlay;
// Use pre-allocated navigator state objects to avoid per-event memory allocations
// Use pre-allocated lookAt state object to avoid per-event memory allocations
private LookAt lookAt = new LookAt();
private Camera camera = new Camera();
// Track the navigation event time so the overlay refresh rate can be throttled
private long lastEventTime;
// Animation object used to fade the overlays
Expand Down Expand Up @@ -81,12 +80,11 @@ public void onNavigatorEvent(WorldWindow wwd, NavigatorEvent event) {
// and also it is moving but at an (arbitrary) maximum refresh rate of 20 Hz.
if (eventAction == WorldWind.NAVIGATOR_STOPPED || elapsedTime > 50) {

// Get the current navigator state to apply to the overlays
event.getNavigator().getAsLookAt(wwd.getGlobe(), lookAt);
event.getNavigator().getAsCamera(wwd.getGlobe(), camera);
// Get the current camera state to apply to the overlays
event.getCamera().getAsLookAt(lookAt);

// Update the overlays
updateOverlayContents(lookAt, camera);
updateOverlayContents(lookAt, event.getCamera());
updateOverlayColor(eventAction);

lastEventTime = currentTime;
Expand Down Expand Up @@ -129,16 +127,16 @@ protected void fadeCrosshairs() {
}

/**
* Displays navigator state information in the status overlay views.
* Displays camera state information in the status overlay views.
*
* @param lookAt Where the navigator is looking
* @param lookAt Where the camera is looking
* @param camera Where the camera is positioned
*/
protected void updateOverlayContents(LookAt lookAt, Camera camera) {
latView.setText(formatLatitude(lookAt.latitude));
lonView.setText(formatLongitude(lookAt.longitude));
elevView.setText(formatElevaton(wwd.getGlobe().getElevationAtLocation(lookAt.latitude, lookAt.longitude)));
altView.setText(formatAltitude(camera.altitude));
latView.setText(formatLatitude(lookAt.position.latitude));
lonView.setText(formatLongitude(lookAt.position.longitude));
elevView.setText(formatElevaton(wwd.getGlobe().getElevationAtLocation(lookAt.position.latitude, lookAt.position.longitude)));
altView.setText(formatAltitude(camera.position.altitude));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import gov.nasa.worldwind.PickedObject;
import gov.nasa.worldwind.PickedObjectList;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.geom.Line;
import gov.nasa.worldwind.geom.LookAt;
import gov.nasa.worldwind.geom.Position;
Expand Down Expand Up @@ -83,12 +84,12 @@ protected void onCreate(Bundle savedInstanceState) {
this.wwd.getLayers().addLayer(sightlineLayer);

// Override the WorldWindow's built-in navigation behavior with conditional dragging support.
this.controller = new SimpleSelectDragNavigateController();
this.controller = new SimpleSelectDragNavigateController(this.wwd);
this.wwd.setWorldWindowController(this.controller);

// And finally, for this demo, position the viewer to look at the sightline position
LookAt lookAt = new LookAt().set(pos.latitude, pos.longitude, pos.altitude, WorldWind.ABSOLUTE, 2e4 /*range*/, 0 /*heading*/, 45 /*tilt*/, 0 /*roll*/);
this.getWorldWindow().getNavigator().setAsLookAt(this.getWorldWindow().getGlobe(), lookAt);
this.getWorldWindow().getCamera().setFromLookAt(lookAt);
}

/**
Expand Down Expand Up @@ -133,6 +134,10 @@ public boolean onScroll(MotionEvent downEvent, MotionEvent moveEvent, float dist
}
});

public SimpleSelectDragNavigateController(WorldWindow wwd) {
super(wwd);
}

/**
* Delegates events to the select/drag handlers or the native World Wind navigation handlers.
*/
Expand Down
Loading

0 comments on commit 1727068

Please sign in to comment.