Skip to content

Commit

Permalink
Location improvements, new scaling features & memory leak fix
Browse files Browse the repository at this point in the history
  • Loading branch information
John Wedgbury committed Jun 17, 2018
1 parent 2888260 commit 5d932e4
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 120 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ allprojects {
```

#### Step 2.
Add the ARCore-Location dependency. Replace `1.0.5` with the latest release from the [releases tab on Github](https://github.com/appoly/ARCore-Location/releases)
Add the ARCore-Location dependency. Replace `1.0.6` with the latest release from the [releases tab on Github](https://github.com/appoly/ARCore-Location/releases)
```
dependencies {
compile 'com.github.appoly:ARCore-Location:1.0.5'
compile 'com.github.appoly:ARCore-Location:1.0.6'
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,33 @@ public class LocationMarker {
private LocationNodeRender renderEvent;
private float scaleModifier = 1F;
private float height = 0F;
private boolean scaleAtDistance = true;
private int onlyRenderWhenWithin = Integer.MAX_VALUE;
private ScalingMode scalingMode = ScalingMode.FIXED_SIZE_ON_SCREEN;
private float gradualScalingMinScale = 0.8F;
private float gradualScalingMaxScale = 1.4F;

public LocationMarker(double longitude, double latitude, Node node) {
this.longitude = longitude;
this.latitude = latitude;
this.node = node;
}

public float getGradualScalingMinScale() {
return gradualScalingMinScale;
}

public void setGradualScalingMinScale(float gradualScalingMinScale) {
this.gradualScalingMinScale = gradualScalingMinScale;
}

public float getGradualScalingMaxScale() {
return gradualScalingMaxScale;
}

public void setGradualScalingMaxScale(float gradualScalingMaxScale) {
this.gradualScalingMaxScale = gradualScalingMaxScale;
}

/**
* Only render this marker when within [onlyRenderWhenWithin] metres
*
Expand Down Expand Up @@ -71,21 +89,21 @@ public void setHeight(float height) {
}

/**
* Whether the marker should stay at the same size on screen, regardless of distance.
* How the markers should scale
*
* @return - true/false
* @return - ScalingMode
*/
public boolean shouldScaleAtDistance() {
return scaleAtDistance;
public ScalingMode getScalingMode() {
return scalingMode;
}

/**
* Whether the marker should stay at the same size on screen, regardless of distance.
* Whether the marker should scale, regardless of distance.
*
* @param scaleAtDistance - true/false
* @param scalingMode - ScalingMode.X
*/
public void setScaleAtDistance(boolean scaleAtDistance) {
this.scaleAtDistance = scaleAtDistance;
public void setScalingMode(ScalingMode scalingMode) {
this.scalingMode = scalingMode;
}

/**
Expand All @@ -106,7 +124,6 @@ public void setScaleModifier(float scaleModifier) {
this.scaleModifier = scaleModifier;
}


/**
* Called on each frame
*
Expand All @@ -123,4 +140,10 @@ public void setRenderEvent(LocationNodeRender renderEvent) {
this.renderEvent = renderEvent;
}

public enum ScalingMode {
FIXED_SIZE_ON_SCREEN,
NO_SCALING,
GRADUAL_TO_MAX_RENDER_DISTANCE
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.ArrayList;

import uk.co.appoly.arcorelocation.rendering.LocationNode;
import uk.co.appoly.arcorelocation.rendering.LocationNodeRender;
import uk.co.appoly.arcorelocation.sensor.DeviceLocation;
import uk.co.appoly.arcorelocation.sensor.DeviceLocationChanged;
import uk.co.appoly.arcorelocation.sensor.DeviceOrientation;
import uk.co.appoly.arcorelocation.utils.LocationUtils;

Expand All @@ -41,6 +43,8 @@ public class LocationScene {
private int bearingAdjustment = 0;
private String TAG = "LocationScene";
private boolean anchorsNeedRefresh = true;
private boolean minimalRefreshing = false;
private boolean refreshAnchorsAsLocationChanges = false;
private Handler mHandler = new Handler();
Runnable anchorRefreshTask = new Runnable() {
@Override
Expand All @@ -50,7 +54,7 @@ public void run() {
}
};
private Session mSession;

private DeviceLocationChanged locationChangedEvent;
public LocationScene(Context mContext, Activity mActivity, ArSceneView mArSceneView) {
Log.i(TAG, "Location Scene initiated.");
this.mContext = mContext;
Expand All @@ -65,6 +69,46 @@ public LocationScene(Context mContext, Activity mActivity, ArSceneView mArSceneV
deviceOrientation.resume();
}

public boolean minimalRefreshing() {
return minimalRefreshing;
}

public void setMinimalRefreshing(boolean minimalRefreshing) {
this.minimalRefreshing = minimalRefreshing;
}

public boolean refreshAnchorsAsLocationChanges() {
return refreshAnchorsAsLocationChanges;
}

public void setRefreshAnchorsAsLocationChanges(boolean refreshAnchorsAsLocationChanges) {
if (refreshAnchorsAsLocationChanges) {
stopCalculationTask();
} else {
startCalculationTask();
}
refreshAnchors();
this.refreshAnchorsAsLocationChanges = refreshAnchorsAsLocationChanges;
}

/**
* Get additional event to run as device location changes.
* Save creating extra sensor classes
*
* @return
*/
public DeviceLocationChanged getLocationChangedEvent() {
return locationChangedEvent;
}

/**
* Set additional event to run as device location changes.
* Save creating extra sensor classes
*/
public void setLocationChangedEvent(DeviceLocationChanged locationChangedEvent) {
this.locationChangedEvent = locationChangedEvent;
}

public int getAnchorRefreshInterval() {
return anchorRefreshInterval;
}
Expand All @@ -80,6 +124,18 @@ public void setAnchorRefreshInterval(int anchorRefreshInterval) {
startCalculationTask();
}

public void clearMarkers() {
for(LocationMarker lm : mLocationMarkers) {
if(lm.anchorNode != null) {
lm.anchorNode.getAnchor().detach();
lm.anchorNode.setEnabled(false);
lm.anchorNode = null;
}

}
mLocationMarkers = new ArrayList<>();
}

/**
* The distance cap for distant markers.
* ARCore doesn't like markers that are 2000km away :/
Expand Down Expand Up @@ -126,9 +182,10 @@ public void refreshAnchors() {

private void refreshAnchorsIfRequired(Frame frame) {
if (anchorsNeedRefresh) {
Log.i(TAG, "Refreshing anchors...");
anchorsNeedRefresh = false;

if(deviceLocation == null || deviceLocation.currentBestLocation == null) {
if (deviceLocation == null || deviceLocation.currentBestLocation == null) {
Log.i(TAG, "Location not yet established.");
return;
}
Expand Down Expand Up @@ -198,9 +255,12 @@ private void refreshAnchorsIfRequired(Frame frame) {
// Current camera height
float y = frame.getCamera().getDisplayOrientedPose().ty();

if(mLocationMarkers.get(i).anchorNode != null &&
if (mLocationMarkers.get(i).anchorNode != null &&
mLocationMarkers.get(i).anchorNode.getAnchor() != null) {
mLocationMarkers.get(i).anchorNode.getAnchor().detach();
mLocationMarkers.get(i).anchorNode.setAnchor(null);
mLocationMarkers.get(i).anchorNode.setEnabled(false);
mLocationMarkers.get(i).anchorNode = null;
}

// Don't immediately assign newly created anchor in-case of exceptions
Expand All @@ -218,14 +278,20 @@ private void refreshAnchorsIfRequired(Frame frame) {
}

mLocationMarkers.get(i).anchorNode.setScaleModifier(mLocationMarkers.get(i).getScaleModifier());
mLocationMarkers.get(i).anchorNode.setScaleAtDistance(mLocationMarkers.get(i).shouldScaleAtDistance());
mLocationMarkers.get(i).anchorNode.setScalingMode(mLocationMarkers.get(i).getScalingMode());
mLocationMarkers.get(i).anchorNode.setGradualScalingMaxScale(mLocationMarkers.get(i).getGradualScalingMaxScale());
mLocationMarkers.get(i).anchorNode.setGradualScalingMinScale(mLocationMarkers.get(i).getGradualScalingMinScale());
mLocationMarkers.get(i).anchorNode.setHeight(mLocationMarkers.get(i).getHeight());

if(minimalRefreshing)
mLocationMarkers.get(i).anchorNode.scaleAndRotate();
} catch (Exception e) {
e.printStackTrace();
}

}

System.gc();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ public class LocationNode extends AnchorNode {
private LocationMarker locationMarker;
private LocationNodeRender renderEvent;
private int distance;
private double distanceInAR;
private float scaleModifier = 1F;
private float height = 0F;
private boolean scaleAtDistance = true;
private float gradualScalingMinScale = 0.8F;
private float gradualScalingMaxScale = 1.4F;

private LocationMarker.ScalingMode scalingMode = LocationMarker.ScalingMode.FIXED_SIZE_ON_SCREEN;
private LocationScene locationScene;

public LocationNode(Anchor anchor, LocationMarker locationMarker, LocationScene locationScene) {
Expand Down Expand Up @@ -59,16 +63,24 @@ public int getDistance() {
return distance;
}

public double getDistanceInAR() {
return distanceInAR;
}

public void setDistance(int distance) {
this.distance = distance;
}

public boolean shouldScaleAtDistance() {
return scaleAtDistance;
public void setDistanceInAR(double distanceInAR) {
this.distanceInAR = distanceInAR;
}

public void setScaleAtDistance(boolean scaleAtDistance) {
this.scaleAtDistance = scaleAtDistance;
public LocationMarker.ScalingMode getScalingMode() {
return scalingMode;
}

public void setScalingMode(LocationMarker.ScalingMode scalingMode) {
this.scalingMode = scalingMode;
}

@Override
Expand All @@ -85,6 +97,39 @@ public void onUpdate(FrameTime frameTime) {
return;
}

Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
Vector3 nodePosition = n.getWorldPosition();

// Compute the difference vector between the camera and anchor
float dx = cameraPosition.x - nodePosition.x;
float dy = cameraPosition.y - nodePosition.y;
float dz = cameraPosition.z - nodePosition.z;

// Compute the straight-line distance.
setDistanceInAR(Math.sqrt(dx * dx + dy * dy + dz * dz));


if (locationScene.shouldOffsetOverlapping()) {
if (locationScene.mArSceneView.getScene().overlapTestAll(n).size() > 0) {
setHeight(getHeight() + 1.2F);
}
}
}

if(!locationScene.minimalRefreshing())
scaleAndRotate();


if (renderEvent != null) {
if(this.isTracking() && this.isActive() && this.isEnabled())
renderEvent.render(this);
}

}

public void scaleAndRotate() {

for (Node n : getChildren()) {
int markerDistance = (int) Math.ceil(
LocationUtils.distance(
locationMarker.latitude,
Expand All @@ -105,13 +150,24 @@ public void onUpdate(FrameTime frameTime) {

float scale = 1F;

// Make sure marker stays the same size on screen, no matter the distance
if (shouldScaleAtDistance())
scale = 0.5F * (float) renderDistance;
switch (scalingMode) {

// Make sure marker stays the same size on screen, no matter the distance
case FIXED_SIZE_ON_SCREEN:
scale = 0.5F * (float) renderDistance;

// Distant markers a little smaller
if (markerDistance > 3000)
scale *= 0.75F;

break;

case GRADUAL_TO_MAX_RENDER_DISTANCE:
float scaleDifference = gradualScalingMaxScale - gradualScalingMinScale;
scale = (gradualScalingMinScale + ((locationScene.getDistanceLimit() - markerDistance) * (scaleDifference / locationScene.getDistanceLimit()))) * renderDistance;
break;
}

// Distant markers a little smaller
if (markerDistance > 3000)
scale *= 0.75F;

scale *= scaleModifier;

Expand All @@ -125,17 +181,24 @@ public void onUpdate(FrameTime frameTime) {
//locationMarker.node.setWorldScale(new Vector3(scale, scale, scale));
n.setWorldScale(new Vector3(scale, scale, scale));

if (locationScene.shouldOffsetOverlapping()) {
if (locationScene.mArSceneView.getScene().overlapTestAll(n).size() > 0) {
setHeight(getHeight() + 1.2F);
}
}

if (renderEvent != null) {
renderEvent.render(this);
}

}
}

public float getGradualScalingMinScale() {
return gradualScalingMinScale;
}

public void setGradualScalingMinScale(float gradualScalingMinScale) {
this.gradualScalingMinScale = gradualScalingMinScale;
}

public float getGradualScalingMaxScale() {
return gradualScalingMaxScale;
}

public void setGradualScalingMaxScale(float gradualScalingMaxScale) {
this.gradualScalingMaxScale = gradualScalingMaxScale;
}
}
Loading

0 comments on commit 5d932e4

Please sign in to comment.