Skip to content

Commit

Permalink
More functionality and comments in example
Browse files Browse the repository at this point in the history
  • Loading branch information
johnwedgbury committed May 19, 2018
1 parent 425dc5a commit 7a55e48
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package uk.co.appoly.arcorelocation;

import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.Node;

import uk.co.appoly.arcorelocation.rendering.LocationNode;
Expand All @@ -22,20 +21,46 @@ public class LocationMarker {
// Node to render
public Node node;

public LocationNodeRender getRenderEvent() {
return renderEvent;
}

public void setRenderEvent(LocationNodeRender renderEvent) {
this.renderEvent = renderEvent;
}

// Called on each frame if not null
private LocationNodeRender renderEvent;
private float height = 0F;

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

/**
* Height based on camera height
*/
public float getHeight() {
return height;
}

/**
* Height based on camera height
*
* @param height
*/
public void setHeight(float height) {
this.height = height;
}

/**
* Called on each frame
*
* @return
*/
public LocationNodeRender getRenderEvent() {
return renderEvent;
}

/**
* Called on each frame.
*/
public void setRenderEvent(LocationNodeRender renderEvent) {
this.renderEvent = renderEvent;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@
import com.google.ar.core.Frame;
import com.google.ar.core.Pose;
import com.google.ar.core.Session;
import com.google.ar.core.TrackingState;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.ArSceneView;
import com.google.ar.sceneform.Scene;
import com.google.ar.sceneform.SceneView;
import com.google.ar.sceneform.math.Quaternion;
import com.google.ar.sceneform.math.Vector3;

import java.util.ArrayList;

Expand All @@ -30,34 +24,29 @@

public class LocationScene {

public ArSceneView mArSceneView;
public DeviceLocation deviceLocation;
public DeviceOrientation deviceOrientation;
public Context mContext;
public Activity mActivity;
public ArrayList<LocationMarker> mLocationMarkers = new ArrayList<>();
// Anchors are currently re-drawn on an interval. There are likely better
// ways of doing this, however it's sufficient for now.
private final static int ANCHOR_REFRESH_INTERVAL = 1000 * 5; // 5 seconds
public static Context mContext;
public static Activity mActivity;
public static ArSceneView mArSceneView;

public ArrayList<LocationMarker> mLocationMarkers = new ArrayList<>();

public static DeviceLocation deviceLocation;
public static DeviceOrientation deviceOrientation;

private int anchorRefreshInterval = 1000 * 5; // 5 seconds
// Limit of where to draw markers within AR scene.
// They will auto scale, but this helps prevents rendering issues
public static int distanceLimit = 20;

private int distanceLimit = 20;
private boolean offsetOverlapping = false;
// Bearing adjustment. Can be set to calibrate with true north
private int bearingAdjustment = 0;

private String TAG = "LocationScene";
private boolean anchorsNeedRefresh = true;
private Handler mHandler = new Handler();

Runnable anchorRefreshTask = new Runnable() {
@Override
public void run() {
anchorsNeedRefresh = true;
mHandler.postDelayed(anchorRefreshTask, ANCHOR_REFRESH_INTERVAL);
mHandler.postDelayed(anchorRefreshTask, anchorRefreshInterval);
}
};
private Session mSession;
Expand All @@ -71,16 +60,71 @@ public LocationScene(Context mContext, Activity mActivity, ArSceneView mArSceneV

startCalculationTask();

deviceLocation = new DeviceLocation();
deviceOrientation = new DeviceOrientation();
deviceLocation = new DeviceLocation(this);
deviceOrientation = new DeviceOrientation(this);
deviceOrientation.resume();
}

public int getAnchorRefreshInterval() {
return anchorRefreshInterval;
}

/**
* Set the interval at which anchors should be automatically re-calculated.
*
* @param anchorRefreshInterval
*/
public void setAnchorRefreshInterval(int anchorRefreshInterval) {
this.anchorRefreshInterval = anchorRefreshInterval;
stopCalculationTask();
startCalculationTask();
}

/**
* The distance cap for distant markers.
* ARCore doesn't like markers that are 2000km away :/
*
* @return
*/
public int getDistanceLimit() {
return distanceLimit;
}

/**
* The distance cap for distant markers.
* ARCore doesn't like markers that are 2000km away :/
* Default 20
*/
public void setDistanceLimit(int distanceLimit) {
this.distanceLimit = distanceLimit;
}

public boolean shouldOffsetOverlapping() {
return offsetOverlapping;
}

/**
* Attempts to raise markers vertically when they overlap.
* Needs work!
*
* @param offsetOverlapping
*/
public void setOffsetOverlapping(boolean offsetOverlapping) {
this.offsetOverlapping = offsetOverlapping;
}

public void processFrame(Frame frame) {
refreshAnchorsIfRequired(frame);
}

public void refreshAnchorsIfRequired(Frame frame) {
/**
* Force anchors to be re-calculated
*/
public void refreshAnchors() {
anchorsNeedRefresh = true;
}

private void refreshAnchorsIfRequired(Frame frame) {
if (anchorsNeedRefresh) {
anchorsNeedRefresh = false;

Expand Down Expand Up @@ -147,13 +191,14 @@ public void refreshAnchorsIfRequired(Frame frame) {
frame.getCamera().getPose()
.compose(Pose.makeTranslation(xRotated, y + (float) heightAdjustment, zRotated)));

mLocationMarkers.get(i).anchorNode = new LocationNode(newAnchor, mLocationMarkers.get(i));
mLocationMarkers.get(i).anchorNode = new LocationNode(newAnchor, mLocationMarkers.get(i), this);
mLocationMarkers.get(i).anchorNode.setParent(mArSceneView.getScene());
mLocationMarkers.get(i).anchorNode.addChild(mLocationMarkers.get(i).node);

if(mLocationMarkers.get(i).getRenderEvent() != null) {
if (mLocationMarkers.get(i).getRenderEvent() != null) {
mLocationMarkers.get(i).anchorNode.setRenderEvent(mLocationMarkers.get(i).getRenderEvent());
}
mLocationMarkers.get(i).anchorNode.setHeight(mLocationMarkers.get(i).getHeight());

} catch (Exception e) {
e.printStackTrace();
Expand All @@ -163,20 +208,36 @@ public void refreshAnchorsIfRequired(Frame frame) {
}
}


/**
* Adjustment for compass bearing.
*
* @return
*/
public int getBearingAdjustment() {
return bearingAdjustment;
}

/**
* Adjustment for compass bearing.
* You may use this for a custom method of improving precision.
*
* @param i
*/
public void setBearingAdjustment(int i) {
bearingAdjustment = i;
anchorsNeedRefresh = true;
}

/**
* Resume sensor services. Important!
*/
public void resume() {
deviceOrientation.resume();
}

/**
* Pause sensor services. Important!
*/
public void pause() {
deviceOrientation.pause();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.co.appoly.arcorelocation.rendering;

import android.util.Log;

import com.google.ar.core.Anchor;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.FrameTime;
Expand All @@ -13,14 +15,28 @@

public class LocationNode extends AnchorNode {

LocationMarker locationMarker;
private String TAG = "LocationNode";

private LocationMarker locationMarker;
private LocationNodeRender renderEvent;
private int distance;
private float scaleModifier = 1F;
private float height = 0F;
private boolean scaleAtDistance = true;
private LocationScene locationScene;

public LocationNode(Anchor anchor, LocationMarker locationMarker) {
public LocationNode(Anchor anchor, LocationMarker locationMarker, LocationScene locationScene) {
super(anchor);
this.locationMarker = locationMarker;
this.locationScene = locationScene;
}

public float getHeight() {
return height;
}

public void setHeight(float height) {
this.height = height;
}

public float getScaleModifier() {
Expand All @@ -47,6 +63,14 @@ public void setDistance(int distance) {
this.distance = distance;
}

public boolean shouldScaleAtDistance() {
return scaleAtDistance;
}

public void setScaleAtDistance(boolean scaleAtDistance) {
this.scaleAtDistance = scaleAtDistance;
}

@Override
public void onUpdate(FrameTime frameTime) {

Expand All @@ -64,9 +88,9 @@ public void onUpdate(FrameTime frameTime) {
int markerDistance = (int) Math.ceil(
LocationUtils.distance(
locationMarker.latitude,
LocationScene.deviceLocation.currentBestLocation.getLatitude(),
locationScene.deviceLocation.currentBestLocation.getLatitude(),
locationMarker.longitude,
LocationScene.deviceLocation.currentBestLocation.getLongitude(),
locationScene.deviceLocation.currentBestLocation.getLongitude(),
0,
0)
);
Expand All @@ -76,11 +100,14 @@ public void onUpdate(FrameTime frameTime) {
// Limit the distance of the Anchor within the scene.
// Prevents uk.co.appoly.arcorelocation.rendering issues.
int renderDistance = markerDistance;
if (renderDistance > LocationScene.distanceLimit)
renderDistance = LocationScene.distanceLimit;
if (renderDistance > locationScene.getDistanceLimit())
renderDistance = locationScene.getDistanceLimit();

float scale = 1F;

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

// Distant markers a little smaller
if (markerDistance > 3000)
Expand All @@ -89,15 +116,21 @@ public void onUpdate(FrameTime frameTime) {
scale *= scaleModifier;

Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
Vector3 cardPosition = n.getWorldPosition();
n.setWorldPosition(new Vector3(n.getWorldPosition().x, 0F, n.getWorldPosition().z));
Vector3 direction = Vector3.subtract(cameraPosition, cardPosition);
Vector3 nodePosition = n.getWorldPosition();
n.setWorldPosition(new Vector3(n.getWorldPosition().x, getHeight(), n.getWorldPosition().z));
Vector3 direction = Vector3.subtract(cameraPosition, nodePosition);
Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());

n.setWorldRotation(lookRotation);
//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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ public class DeviceLocation implements LocationListener {
private static final int TWO_MINUTES = 1000 * 60 * 2;
public Location currentBestLocation;
private LocationManager locationManager;
private LocationScene locationScene;

public DeviceLocation() {
public DeviceLocation(LocationScene locationScene) {
this.locationScene = locationScene;

try {
// Getting LocationManager object
locationManager = (LocationManager) LocationScene.mContext.getSystemService(Context.LOCATION_SERVICE);
locationManager = (LocationManager) locationScene.mContext.getSystemService(Context.LOCATION_SERVICE);
// Creating an empty criteria object


Expand All @@ -40,7 +42,7 @@ public DeviceLocation() {


} catch (SecurityException e) {
Toast.makeText(LocationScene.mContext, "Enable location permissions from settings", Toast.LENGTH_SHORT).show();
Toast.makeText(locationScene.mContext, "Enable location permissions from settings", Toast.LENGTH_SHORT).show();
}
}

Expand Down
Loading

0 comments on commit 7a55e48

Please sign in to comment.