/*
*
*
*/
package ch.ethz.karto.map3d;
import javax.media.opengl.GLAutoDrawable;
/**
*
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich.
*/
public class Map3DShearAnimation extends Map3DRotationAnimation {
/**
* Duration of a full rotation in seconds.
*/
private float cycleDuration = 2f;
private float animationAmplitude = 1f;
private boolean inverseDirection = false;
private int nRosePetals = 3;
public enum AnimationType {
updown, leftright, circular, rose
};
private AnimationType animationType = AnimationType.updown;
public Map3DShearAnimation(GLAutoDrawable glAutoDrawable) {
super(glAutoDrawable);
}
@Override
public void update(Map3DViewer map3DViewer) {
// this method is called from Map3DViewer.display(). Do not call methods
// in Map3DView that again call display()!
super.update(map3DViewer);
if (cycleDuration <= 0 || !this.isAnimating()) {
return;
}
switch (this.animationType) {
case circular:
this.circularAnimation(map3DViewer);
break;
case leftright:
this.leftRightAnimation(map3DViewer);
break;
case updown:
this.updownAnimation(map3DViewer);
break;
case rose:
this.roseAnimation(map3DViewer);
break;
}
}
private void circularAnimation(Map3DViewer map3DViewer) {
float dirDelta = 360.f / (cycleDuration * FPS);
double dir = Math.toDegrees(Math.atan2(map3DViewer.shearY, map3DViewer.shearX));
dir += dirDelta;
if (dir > 180) {
dir -= 360;
}
dir = Math.toRadians(dir);
map3DViewer.shearX = (float) (Math.cos(dir)) * animationAmplitude;
map3DViewer.shearY = (float) (Math.sin(dir)) * animationAmplitude;
}
private void updownAnimation(Map3DViewer map3DViewer) {
float d = 2f * animationAmplitude / (cycleDuration * FPS);
if (inverseDirection) {
d = -d;
}
float newShear = map3DViewer.shearY + d;
if (newShear > animationAmplitude) {
d = -d;
map3DViewer.shearY = animationAmplitude;
inverseDirection = !inverseDirection;
}
if (newShear < -animationAmplitude) {
d = -d;
map3DViewer.shearY = -animationAmplitude;
inverseDirection = !inverseDirection;
}
map3DViewer.shearY += d;
map3DViewer.shearX = 0;
}
private void leftRightAnimation(Map3DViewer map3DViewer) {
float d = 2f * animationAmplitude / (cycleDuration * FPS);
if (inverseDirection) {
d = -d;
}
float newShear = map3DViewer.shearX + d;
if (newShear > animationAmplitude || newShear < -animationAmplitude) {
d = -d;
inverseDirection = !inverseDirection;
}
map3DViewer.shearY = 0;
map3DViewer.shearX += d;
}
double roseDir = 0;
private void roseAnimation(Map3DViewer map3DViewer) {
int n = nRosePetals % 2 == 1 ? nRosePetals : nRosePetals / 2;
double dirDelta = Math.toRadians(360.f / (cycleDuration * FPS) / n);
roseDir += dirDelta;
double r = Math.cos(n * roseDir) * animationAmplitude;
map3DViewer.shearX = (float) (Math.cos(roseDir) * r);
map3DViewer.shearY = (float) (Math.sin(roseDir) * r);
}
public float getCycleDuration() {
return cycleDuration;
}
public void setCycleDuration(float cycleDuration) {
if (cycleDuration < 0) {
throw new IllegalArgumentException();
}
this.cycleDuration = cycleDuration;
}
public AnimationType getAnimationType() {
return animationType;
}
public void setAnimationType(AnimationType animationType) {
this.animationType = animationType;
}
public float getAnimationAmplitude() {
return animationAmplitude;
}
public void setAnimationAmplitude(float animationAmplitude) {
this.animationAmplitude = animationAmplitude;
}
public int getNRosePetals() {
return nRosePetals;
}
public void setNRosePetals(int nRosePetals) {
this.nRosePetals = nRosePetals;
}
}