@nehon I found another bug while rotating a box in AnimationTrack. Seems that I can’t rotate negatively from a negative angle to another negative angle w/o something weird happening with the animation. Look at the testCase below:
[java]
package mygame;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimationFactory;
import com.jme3.animation.LoopMode;
import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.events.CinematicEvent;
import com.jme3.app.SimpleApplication;
import com.jme3.cinematic.PlayState;
import com.jme3.cinematic.events.AnimationTrack;
import com.jme3.cinematic.events.CinematicEventListener;
import com.jme3.cinematic.events.PositionTrack;
import com.jme3.input.ChaseCamera;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.swing.JOptionPane;
public class RotationBug extends SimpleApplication {
private Spatial model;
private Spatial podModel;
private Cinematic cinematic;
private ChaseCamera chaseCam;
private ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(2);
public static void main(String[] args) {
RotationBug app = new RotationBug();
app.start();
}
@Override
public void simpleInitApp() {
createScene();
cinematic = new Cinematic(rootNode, 1000);
stateManager.attach(cinematic);
AnimationFactory factory = new AnimationFactory(10, “animation”);
factory.addTimeTranslation(0, new Vector3f(0, 0, 0));
factory.addTimeRotationAngles(2, 0, 0, -3.14f); // - 90 degrees
factory.addTimeTranslation(10, new Vector3f(5, 0, 0));
AnimControl control = model.getControl(AnimControl.class);
if( control == null){
control = new AnimControl();
model.addControl(control);
}
control.addAnim(factory.buildAnimation());
cinematic.addCinematicEvent(0, new AnimationTrack(model, “animation”));
Quaternion rotQuat = new Quaternion().fromAngleAxis( -3.14f, Vector3f.UNIT_Z);
AnimationFactory factory2 = new AnimationFactory(10, “animation2”);
factory2.addTimeTranslation(0, new Vector3f(5, 0, 0));
factory2.addTimeRotation(0, rotQuat);
factory2.addTimeRotationAngles(10, 0, 0, -1.57f); // - 90 degrees
AnimControl control2 = model.getControl(AnimControl.class);
if( control2 == null){
control2 = new AnimControl();
model.addControl(control2);
}
control2.addAnim(factory2.buildAnimation());
cinematic.addCinematicEvent(10.1f, new AnimationTrack(model, “animation2”));
AnimationFactory factory3 = new AnimationFactory(3, “animation3”);
factory3.addTimeTranslation(0, new Vector3f(0, 0, 1));
factory3.addTimeTranslation(3, new Vector3f(5, 0, 1));
AnimControl control3 = podModel.getControl(AnimControl.class);
if( control3 == null){
control3 = new AnimControl();
podModel.addControl(control3);
}
control3.addAnim(factory3.buildAnimation());
cinematic.addCinematicEvent(8.1f, new AnimationTrack(podModel, “animation3”));
cinematic.addListener(new CinematicEventListener() {
public void onPlay(CinematicEvent s) {
chaseCam.setEnabled(false);
System.out.println(“play”);
System.out.println("Animation Speed: " + cinematic.getSpeed());
System.out.println("Animation State: " + cinematic.getPlayState());
System.out.println("Animation Time: " + cinematic.getTime());
}
public void onPause(CinematicEvent cinematic) {
chaseCam.setEnabled(false);
System.out.println(“pause”);
System.out.println("Animation Speed: " + cinematic.getSpeed());
System.out.println("Animation State: " + cinematic.getPlayState());
System.out.println("Animation Time: " + cinematic.getTime());
}
public void onStop(CinematicEvent cinematic) {
chaseCam.setEnabled(false);
// fade.setValue(1);
System.out.println(“stop”);
}
});
flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager);
initInputs();
cinematic.setSpeed(1);
}
Callable jumpBackwards = new Callable() {
public Object call() throws Exception {
try {
final float value = Float.parseFloat(JOptionPane.showInputDialog(null,
“Enter Time”,
“Choose Desired Jump Time”,
JOptionPane.QUESTION_MESSAGE));
RotationBug.this.enqueue(new Callable<Void>() {
public Void call() throws Exception {
cinematic.setTime(value);
return null;
}
});
} catch (Exception nFE) {
// do nothing just cancel command
}
return null;
}
};
private void createScene() {
Box pod = new Box(new Vector3f(0, 0, 1f), 1, .25f, .5f);
podModel = new Geometry(“pod #”, pod);
Material mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat2.setColor(“Color”, ColorRGBA.Blue);
podModel.setMaterial(mat2);
Box drive_unit = new Box(new Vector3f(0, 0, 0), 1, .25f, .5f); // must take from config xml file (TODO)
model = new Geometry(“Drive #”, drive_unit);
Material mat1 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat1.setColor(“Color”, ColorRGBA.Orange);
model.setMaterial(mat1);
model.center();
//podModel.center();
rootNode.attachChild(model);
rootNode.attachChild(podModel);
//jumpBackwards();
Material matSoil = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);
matSoil.setBoolean(“UseMaterialColors”, true);
matSoil.setColor(“Ambient”, ColorRGBA.Gray);
matSoil.setColor(“Diffuse”, ColorRGBA.Green);
matSoil.setColor(“Specular”, ColorRGBA.Black);
}
private void initInputs() {
inputManager.addMapping(“togglePause”, new KeyTrigger(keyInput.KEY_RETURN));
inputManager.addMapping(“jump”, new KeyTrigger(keyInput.KEY_J));
inputManager.addMapping(“increaseSpeed”, new KeyTrigger(keyInput.KEY_EQUALS));
ActionListener acl = new ActionListener() {
public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals(“togglePause”) && keyPressed) {
if (cinematic.getPlayState() == PlayState.Playing) {
cinematic.pause();
} else {
cinematic.play();
}
}
if (name.equals(“jump”) && keyPressed) {
System.out.println("Time skipped to t = "
- cinematic.getTime());
exec.submit(jumpBackwards);
}
else if (name.equals("increaseSpeed") && keyPressed) {
//pause to maintain animation accuracy
//cinematic.pause();
exec.submit(increaseSpeed);
// exec.submit(increaseSpeed);
// increase animation speed by 1x
//cinematic.setSpeed(cinematic.getSpeed() + 1);
}
}
};
inputManager.addListener(acl, "togglePause");
inputManager.addListener(acl, "jump");
inputManager.addListener(acl, "increaseSpeed");
}
/** Jump time function. Allows user to jump
- in time during the animation (forward/backward)
/
Callable jumpTime = new Callable() {
public Object call() throws Exception {
try {
//setPauseOnLostFocus(false);
final float value = Float.parseFloat(JOptionPane.showInputDialog(null,
"Enter Time",
"Choose Desired Jump Time",
JOptionPane.QUESTION_MESSAGE));
RotationBug.this.enqueue(new Callable<Void>() {
public Void call() throws Exception {
cinematic.setTime(value);
System.out.println("Jumping to time: "+cinematic.getTime());
return null;
}
});
} catch (Exception nFE) {
// do nothing just cancel command
System.out.println("Exception: Jumping in time failed");
}
return null;
}
};
/* Jump time function. Allows user to jump
- in time during the animation (forward/backward)
*/
Callable increaseSpeed = new Callable() {
public Object call() throws Exception {
try {
RotationBug.this.enqueue(new Callable<Void>() {
public Void call() throws Exception {
cinematic.pause();
cinematic.setSpeed(cinematic.getSpeed() + 1);
return null;
}
});
} catch (Exception nFE) {
// do nothing just cancel command
}
return null;
}
};
}
[/java]
notice how the orange box is tilting to the side while it should only rotate. I am noticing this in many angles, but mainly noticed it whenever the final angle is negative.