Permalink
Browse files

Fixes google-ar#479: sets tilt axis on Planet to allow rendering plan…

…ets (especially Uranus) more realistically.
  • Loading branch information...
kenkawakenkenke committed Dec 23, 2018
1 parent 26185e7 commit c7e29d90c9705e658d800288ad5af35e953db0e4
@@ -43,6 +43,8 @@
public class Planet extends Node implements Node.OnTapListener {
private final String planetName;
private final float planetScale;
private final float orbitDegreesPerSecond;
private final float axisTilt;
private final ModelRenderable planetRenderable;
private final SolarSettings solarSettings;

@@ -56,11 +58,15 @@ public Planet(
Context context,
String planetName,
float planetScale,
float orbitDegreesPerSecond,
float axisTilt,
ModelRenderable planetRenderable,
SolarSettings solarSettings) {
this.context = context;
this.planetName = planetName;
this.planetScale = planetScale;
this.orbitDegreesPerSecond = orbitDegreesPerSecond;
this.axisTilt = axisTilt;
this.planetRenderable = planetRenderable;
this.solarSettings = solarSettings;
setOnTapListener(this);
@@ -96,8 +102,16 @@ public void onActivate() {
}

if (planetVisual == null) {
planetVisual = new RotatingNode(solarSettings, false);
planetVisual.setParent(this);
// Put a rotator to counter the effects of orbit, and allow the planet orientation to remain
// still with respect to the parent (typically, the Sun). This is important to allow the axis
// of planets like Uranus (which has high tilt) to keep tilted towards the same direction
// wherever it is in its orbit.
RotatingNode counterOrbit = new RotatingNode(solarSettings, true, true, 0f);
counterOrbit.setDegreesPerSecond(orbitDegreesPerSecond);
counterOrbit.setParent(this);

planetVisual = new RotatingNode(solarSettings, false,false, axisTilt);
planetVisual.setParent(counterOrbit);
planetVisual.setRenderable(planetRenderable);
planetVisual.setLocalScale(new Vector3(planetScale, planetScale, planetScale));
}
@@ -32,11 +32,15 @@

private final SolarSettings solarSettings;
private final boolean isOrbit;
private final boolean clockwise;
private final float axisTiltDeg;
private float lastSpeedMultiplier = 1.0f;

public RotatingNode(SolarSettings solarSettings, boolean isOrbit) {
public RotatingNode(SolarSettings solarSettings, boolean isOrbit, boolean clockwise, float axisTiltDeg) {
this.solarSettings = solarSettings;
this.isOrbit = isOrbit;
this.clockwise = clockwise;
this.axisTiltDeg = axisTiltDeg;
}

@Override
@@ -99,7 +103,7 @@ private void startAnimation() {
if (orbitAnimation != null) {
return;
}
orbitAnimation = createAnimator();
orbitAnimation = createAnimator(clockwise, axisTiltDeg);
orbitAnimation.setTarget(this);
orbitAnimation.setDuration(getAnimationDuration());
orbitAnimation.start();
@@ -114,16 +118,23 @@ private void stopAnimation() {
}

/** Returns an ObjectAnimator that makes this node rotate. */
private static ObjectAnimator createAnimator() {
private static ObjectAnimator createAnimator(boolean clockwise, float axisTiltDeg) {
// Node's setLocalRotation method accepts Quaternions as parameters.
// First, set up orientations that will animate a circle.
Quaternion orientation1 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 0);
Quaternion orientation2 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 120);
Quaternion orientation3 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 240);
Quaternion orientation4 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 360);
Quaternion[] orientations = new Quaternion[4];
// Rotation to apply first, to tilt its axis.
Quaternion baseOrientation = Quaternion.axisAngle(new Vector3(1.0f, 0f, 0.0f), axisTiltDeg);
for(int i = 0; i < orientations.length; i++) {
float angle = i * 360 / (orientations.length - 1);
if (clockwise) {
angle = 360 - angle;
}
Quaternion orientation = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), angle);
orientations[i] = Quaternion.multiply(baseOrientation, orientation);
}

ObjectAnimator orbitAnimation = new ObjectAnimator();
orbitAnimation.setObjectValues(orientation1, orientation2, orientation3, orientation4);
orbitAnimation.setObjectValues(orientations);

// Next, give it the localRotation property.
orbitAnimation.setPropertyName("localRotation");
@@ -404,23 +404,23 @@ public void onStopTrackingTouch(SeekBar seekBar) {}
sunVisual.setOnTapListener(
(hitTestResult, motionEvent) -> solarControls.setEnabled(!solarControls.isEnabled()));

createPlanet("Mercury", sun, 0.4f, 47f, mercuryRenderable, 0.019f);
createPlanet("Mercury", sun, 0.4f, 47f, mercuryRenderable, 0.019f, 0.03f);

createPlanet("Venus", sun, 0.7f, 35f, venusRenderable, 0.0475f);
createPlanet("Venus", sun, 0.7f, 35f, venusRenderable, 0.0475f, 2.64f);

Node earth = createPlanet("Earth", sun, 1.0f, 29f, earthRenderable, 0.05f);
Node earth = createPlanet("Earth", sun, 1.0f, 29f, earthRenderable, 0.05f, 23.4f);

createPlanet("Moon", earth, 0.15f, 100f, lunaRenderable, 0.018f);
createPlanet("Moon", earth, 0.15f, 100f, lunaRenderable, 0.018f, 6.68f);

createPlanet("Mars", sun, 1.5f, 24f, marsRenderable, 0.0265f);
createPlanet("Mars", sun, 1.5f, 24f, marsRenderable, 0.0265f, 25.19f);

createPlanet("Jupiter", sun, 2.2f, 13f, jupiterRenderable, 0.16f);
createPlanet("Jupiter", sun, 2.2f, 13f, jupiterRenderable, 0.16f, 3.13f);

createPlanet("Saturn", sun, 3.5f, 9f, saturnRenderable, 0.1325f);
createPlanet("Saturn", sun, 3.5f, 9f, saturnRenderable, 0.1325f, 26.73f);

createPlanet("Uranus", sun, 5.2f, 7f, uranusRenderable, 0.1f);
createPlanet("Uranus", sun, 5.2f, 7f, uranusRenderable, 0.1f, 82.23f);

createPlanet("Neptune", sun, 6.1f, 5f, neptuneRenderable, 0.074f);
createPlanet("Neptune", sun, 6.1f, 5f, neptuneRenderable, 0.074f, 28.32f);

return base;
}
@@ -431,16 +431,17 @@ private Node createPlanet(
float auFromParent,
float orbitDegreesPerSecond,
ModelRenderable renderable,
float planetScale) {
float planetScale,
float axisTilt) {
// Orbit is a rotating node with no renderable positioned at the sun.
// The planet is positioned relative to the orbit so that it appears to rotate around the sun.
// This is done instead of making the sun rotate so each planet can orbit at its own speed.
RotatingNode orbit = new RotatingNode(solarSettings, true);
RotatingNode orbit = new RotatingNode(solarSettings, true, false, 0);
orbit.setDegreesPerSecond(orbitDegreesPerSecond);
orbit.setParent(parent);

// Create the planet and position it relative to the sun.
Planet planet = new Planet(this, name, planetScale, renderable, solarSettings);
Planet planet = new Planet(this, name, planetScale, orbitDegreesPerSecond, axisTilt, renderable, solarSettings);
planet.setParent(orbit);
planet.setLocalPosition(new Vector3(auFromParent * AU_TO_METERS, 0.0f, 0.0f));

0 comments on commit c7e29d9

Please sign in to comment.