/*
* This file is part of MoleculeViewer.
*
* MoleculeViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MoleculeViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MoleculeViewer. If not, see <http://www.gnu.org/licenses/>.
*/
package astex;
class AnimationObject {
public enum Mode {
Rock, Roll, Recenter, Command, MoleculeAnimation
}
/** The angle through which we rock (in degrees). */
private double rockAngle = 7.5;
/** The sleep duration. */
private int sleepDuration = 100;
/** The current animation mode. */
private Mode animationMode = Mode.Rock;
/** The number of steps for an animation. */
private int stepCount = 0;
/** The current step. */
private int step = 0;
/** The command to execute every animation step. */
private String animationCommand = null;
/** The MoleculeViewer we are animating. */
private MoleculeViewer moleculeViewer = null;
/** The MoleculeViewer. */
public void setMoleculeViewer(MoleculeViewer mv){
moleculeViewer = mv;
}
/** Set the current mode. */
public void setMode(Mode v){
animationMode = v;
}
/** Set the sleep duration. */
public void setSleepDuration(int sd){
sleepDuration = sd;
}
/** Get the sleep duration. */
public int getSleepDuration(){
return sleepDuration;
}
/** Set the rock angle. */
public void setRockAngle(double a){
rockAngle = a;
}
/** Set the rock rate. */
public void setRockRate(double r){
deltaAngle = r;
}
/** Set the number of steps. */
public void setSteps(int s){
stepCount = s;
step = 0;
}
/** Get the number of steps in this animation. */
public int getSteps(){
return stepCount;
}
/** Set the command. */
public void setCommand(String c){
animationCommand = c;
}
/** Start center. */
private double sx = 0.0, sy = 0.0, sz = 0.0, sr = 0.0, scf = 0.0, scb = 0.0;
/** Finish center. */
private double fx = 0.0, fy = 0.0, fz = 0.0, fr = 0.0, fcf = 0.0, fcb = 0.0;
/** Start matrix. */
private Matrix startMatrix = null;
/** Finish matrix. */
private Matrix finishMatrix = null;
/** Set the start view. */
public void setStartCenter(double x, double y, double z, double r,
double cf, double cb){
sx = x; sy = y; sz = z; sr = r; scf = cf; scb = cb;
}
/** Set the start view. */
public void setFinishCenter(double x, double y, double z, double r,
double cf, double cb){
fx = x; fy = y; fz = z; fr = r; fcf = cf; fcb = cb;
}
/** Set the start matrix for view change. */
public void setStartMatrix(Matrix ms){
startMatrix = new Matrix(ms);
}
/** Set the start matrix for view change. */
public void setFinishMatrix(Matrix ms){
finishMatrix = new Matrix(ms);
}
private double currentAngle = 0.0;
private double deltaAngle = 5.0;
private double lastRock = 0.0;
/** Initialise the animation object. */
public void initialise(){
step = 0;
}
/** Execute the actual animation function. */
public boolean executeAnimationFunction(){
if(step == stepCount){
return false;
}
//FILE.out.print("step %3d/", step);
//FILE.out.print("%03d\n", stepCount);
boolean retCode = animate();
step++;
return retCode;
}
boolean interactive = false;
/** Do the step. */
public boolean animate(){
MoleculeRenderer moleculeRenderer = moleculeViewer.getMoleculeRenderer();
interactive = moleculeViewer.interactiveAnimation();
if(animationMode == Mode.Rock){
if(step == 0){
currentAngle = 0.0;
lastRock = 0.0;
deltaAngle = 360.0/(double)stepCount;
}
currentAngle += deltaAngle * Math.PI/180.0;
double multiplier = Math.sin(currentAngle);
if(currentAngle < Math.PI*0.5){
multiplier *= multiplier;
}else if(currentAngle > Math.PI * 1.5){
multiplier *= -multiplier;
}
double disp = rockAngle * (Math.PI/180.0) * multiplier;
double diff = disp - lastRock;
diff *= 180.0 / Math.PI;
FILE.out.print("diff %.3f\n", diff);
FILE.out.print("curr %.3f\n", currentAngle*180.0/Math.PI);
String command = String.format("view -rotatez %.3f;", diff);
moleculeRenderer.execute(command);
lastRock = disp;
}else if(animationMode == Mode.MoleculeAnimation){
}else if(animationMode == Mode.Command){
}else if(animationMode == Mode.Roll){
if(step == 0){
deltaAngle = rockAngle/(double)stepCount;
if(!interactive){
System.out.println("delta " + deltaAngle);
}
}
if(!interactive){
Log.info("step %d", step);
Log.info("stepCount %d", stepCount);
}
String command = String.format("view -rotatez %g;", deltaAngle);
moleculeRenderer.execute(command);
}else if(animationMode == Mode.Recenter){
if(step == 0){
Point3d center = moleculeRenderer.renderer.getCenter();
double r = moleculeRenderer.renderer.getRadius();
if(!interactive){
System.out.println("###### step is 0 center is " + center);
System.out.println("###### step is 0 radius is " + r);
}
setStartCenter(center.x, center.y, center.z, r,
moleculeRenderer.renderer.front,
moleculeRenderer.renderer.back);
if(finishMatrix != null){
setStartMatrix(moleculeRenderer.renderer.rotationMatrix);
}
}
double frac = step / (double)(stepCount - 1);
double cx = sx + frac * (fx - sx);
double cy = sy + frac * (fy - sy);
double cz = sz + frac * (fz - sz);
double cr = sr + frac * (fr - sr);
double clipf = scf + frac * (fcf - scf);
double clipb = scb + frac * (fcb - scb);
final StringBuilder command = new StringBuilder("center");
command.append(String.format(" %g", cx));
command.append(String.format(" %g", cy));
command.append(String.format(" %g; ", cz));
command.append(String.format("radius %g;", cr));
command.append(String.format("clip %g ", clipf));
command.append(String.format("%g;", clipb));
if(startMatrix != null){
Matrix m = Matrix.interpolate(startMatrix, finishMatrix, frac);
if(!interactive){
System.out.println(m.returnScript());
}
command.append(m.returnScript());
}
if(!interactive){
System.out.println("command |" + command +"|");
}
moleculeRenderer.execute(command.toString());
}else{
System.out.println("executeAnimationFunction: unknown animation mode " +
animationMode);
}
if(animationCommand != null){
String cmd = processCommand(animationCommand);
moleculeRenderer.execute(cmd);
}
return true;
}
/** Introduce variables etc. */
public String processCommand(String s){
int len = s.length();
StringBuilder sb = new StringBuilder(len);
for(int i = 0; i < len; i++){
char c = s.charAt(i);
if(c == '$'){
i++;
c = s.charAt(i);
if(c == '{'){
int start = i + 1;
int end = -1;
do {
i++;
c = s.charAt(i);
} while(c != '}');
end = i;
//System.out.println("value " + s.substring(start, end));
String value = s.substring(start, end);
String tokens[] = FILE.split(value, ",");
double startValue = 0.0;
double stopValue = 0.0;
if(tokens.length == 1){
startValue = 0.0;
stopValue = FILE.readDouble(tokens[0]);
}else if(tokens.length == 2){
startValue = FILE.readDouble(tokens[0]);
stopValue = FILE.readDouble(tokens[1]);
}
double frac = (double)step/(double)(stepCount - 1);
double val = startValue + frac * (stopValue - startValue);
i++;
c = s.charAt(i);
if(c == 'd'){
sb.append(String.format("%d", (long)val));
}else{
sb.append(String.format("%g", val));
}
}
}else{
sb.append(c);
}
}
if(!interactive){
System.out.println("command |" + sb.toString() + "|");
}
return sb.toString();
}
}