285 lines
12 KiB
Java
285 lines
12 KiB
Java
package electrosphere.renderer.anim;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
import java.util.TreeMap;
|
|
import java.util.Map.Entry;
|
|
|
|
import org.joml.Quaterniond;
|
|
import org.joml.Vector3f;
|
|
|
|
/**
|
|
* A single channel of keyframes in an animation
|
|
*/
|
|
public class AnimChannel {
|
|
|
|
double timeCurrent;
|
|
double timeTotal;
|
|
double ticksPerSecond;
|
|
String nodeID;
|
|
|
|
|
|
Vector3f startingPosition;
|
|
TreeMap<Double,Keyframe> positionFrameTree;
|
|
|
|
|
|
Quaterniond startingRotation;
|
|
TreeMap<Double,Keyframe> rotationFrameTree;
|
|
|
|
TreeMap<Double,Keyframe> scaleFrameTree;
|
|
|
|
|
|
public AnimChannel(double maxTime, double ticksPerSecond){
|
|
timeTotal = maxTime;
|
|
this.ticksPerSecond = ticksPerSecond;
|
|
positionFrameTree = new TreeMap<Double,Keyframe>();
|
|
rotationFrameTree = new TreeMap<Double,Keyframe>();
|
|
scaleFrameTree = new TreeMap<Double,Keyframe>();
|
|
}
|
|
|
|
public Vector3f getCurrentPosition(){
|
|
Vector3f rVal = new Vector3f();
|
|
|
|
Entry<Double,Keyframe> previousEntry = positionFrameTree.floorEntry(timeCurrent);
|
|
Entry<Double,Keyframe> nextEntry = positionFrameTree.ceilingEntry(timeCurrent);
|
|
Keyframe previousFrame = null;
|
|
Keyframe nextFrame = null;
|
|
if(previousEntry == nextEntry){
|
|
nextEntry = positionFrameTree.higherEntry(timeCurrent);
|
|
}
|
|
if(previousEntry != null){
|
|
previousFrame = previousEntry.getValue();
|
|
}
|
|
if(nextEntry != null){
|
|
nextFrame = nextEntry.getValue();
|
|
}
|
|
if(previousFrame != null && nextFrame != null){
|
|
double percent_Next = ((timeCurrent - previousFrame.time) / (nextFrame.time - previousFrame.time));
|
|
rVal = new Vector3f().add(new Vector3f().add(previousFrame.position).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(nextFrame.position).mul((float)(percent_Next)));
|
|
} else if(previousFrame != null){
|
|
rVal = new Vector3f().add(previousFrame.position);
|
|
} else if(nextFrame != null){
|
|
rVal = new Vector3f().add(nextFrame.position);
|
|
}
|
|
|
|
|
|
// if(positionFrameCurrent != null){
|
|
// if(positionFrameNext != null){
|
|
// double percent_Next = ((timeCurrent - positionFrameCurrent.time) / (positionFrameNext.time - positionFrameCurrent.time));
|
|
// rVal = new Vector3f().add(new Vector3f().add(positionFrameCurrent.position).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(positionFrameNext.position).mul((float)(percent_Next)));
|
|
// } else {
|
|
// rVal = new Vector3f().add(positionFrameCurrent.position);
|
|
// }
|
|
// // rVal.add(new Vector3f().add(positionFrameCurrent.position).mul(()/(positionFrameNext.time - positionFrameCurrent.time)));
|
|
// }
|
|
// rVal = rVal.sub(startingPosition);
|
|
return rVal;
|
|
}
|
|
|
|
public Quaterniond getCurrentRotation(){
|
|
Quaterniond rVal = new Quaterniond();
|
|
|
|
Entry<Double,Keyframe> previousEntry = rotationFrameTree.floorEntry(timeCurrent);
|
|
Entry<Double,Keyframe> nextEntry = rotationFrameTree.ceilingEntry(timeCurrent);
|
|
Keyframe previousFrame = null;
|
|
Keyframe nextFrame = null;
|
|
if(previousEntry == nextEntry){
|
|
nextEntry = rotationFrameTree.higherEntry(timeCurrent);
|
|
}
|
|
if(previousEntry != null){
|
|
previousFrame = previousEntry.getValue();
|
|
}
|
|
if(nextEntry != null){
|
|
nextFrame = nextEntry.getValue();
|
|
}
|
|
if(previousFrame != null && nextFrame != null){
|
|
double percent_Next = ((timeCurrent - previousFrame.time) / (nextFrame.time - previousFrame.time));
|
|
rVal = new Quaterniond(previousFrame.rotation).slerp(nextFrame.rotation, (float)percent_Next);
|
|
// rVal = new Vector3f().add(new Vector3f().add(previousFrame.position).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(nextFrame.position).mul((float)(percent_Next)));
|
|
} else if(previousFrame != null){
|
|
rVal = new Quaterniond(previousFrame.rotation);
|
|
// rVal = new Vector3f().add(previousFrame.position);
|
|
} else if(nextFrame != null){
|
|
rVal = new Quaterniond(nextFrame.rotation);
|
|
// rVal = new Vector3f().add(nextFrame.position);
|
|
}
|
|
|
|
// if(rotationFrameCurrent != null){
|
|
// if(rotationFrameNext != null){
|
|
// double percent_Next = ((timeCurrent - rotationFrameCurrent.time) / (rotationFrameNext.time - rotationFrameCurrent.time));
|
|
// // rVal = new Quaternionf(rotationFrameCurrent.rotation).normalize();//.add(rotationFrameCurrent.rotation);
|
|
// rVal = new Quaternionf(rotationFrameCurrent.rotation).slerp(rotationFrameNext.rotation, (float)percent_Next);
|
|
// // rVal = new Quaternionf(rotationFrameCurrent.rotation).normalize().slerp(new Quaternionf(rotationFrameNext.rotation).normalize(), (float)(percent_Next)).rotateAxis((float)(-Math.PI/2), new Vector3f(1,0,0));
|
|
// } else {
|
|
// rVal = new Quaternionf(rotationFrameCurrent.rotation);//.add(rotationFrameCurrent.rotation);
|
|
// }
|
|
// }
|
|
// rVal = rVal.mul(new Quaternionf(startingRotation).invert());
|
|
return rVal;
|
|
}
|
|
|
|
public Vector3f getCurrentScale(){
|
|
Vector3f rVal = new Vector3f();
|
|
|
|
Entry<Double,Keyframe> previousEntry = scaleFrameTree.floorEntry(timeCurrent);
|
|
Entry<Double,Keyframe> nextEntry = scaleFrameTree.ceilingEntry(timeCurrent);
|
|
Keyframe previousFrame = null;
|
|
Keyframe nextFrame = null;
|
|
if(previousEntry == nextEntry){
|
|
nextEntry = scaleFrameTree.higherEntry(timeCurrent);
|
|
}
|
|
if(previousEntry != null){
|
|
previousFrame = previousEntry.getValue();
|
|
}
|
|
if(nextEntry != null){
|
|
nextFrame = nextEntry.getValue();
|
|
}
|
|
if(previousFrame != null && nextFrame != null){
|
|
double percent_Next = ((timeCurrent - previousFrame.time) / (nextFrame.time - previousFrame.time));
|
|
// rVal = new Vector3f().add(new Vector3f().add(previousFrame.position).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(nextFrame.position).mul((float)(percent_Next)));
|
|
rVal = new Vector3f().add(new Vector3f().add(previousFrame.scale).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(nextFrame.scale).mul((float)(percent_Next)));
|
|
} else if(previousFrame != null){
|
|
// rVal = new Vector3f().add(previousFrame.position);
|
|
rVal = new Vector3f().add(previousFrame.scale);
|
|
} else if(nextFrame != null){
|
|
// rVal = new Vector3f().add(nextFrame.position);
|
|
rVal = new Vector3f().add(nextFrame.scale);
|
|
}
|
|
|
|
// if(scaleFrameCurrent != null){
|
|
// if(scaleFrameNext != null){
|
|
// double percent_Next = ((timeCurrent - scaleFrameCurrent.time) / (scaleFrameNext.time - scaleFrameCurrent.time));
|
|
// rVal = new Vector3f().add(new Vector3f().add(scaleFrameCurrent.scale).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(scaleFrameNext.scale).mul((float)(percent_Next)));
|
|
// } else {
|
|
// rVal = new Vector3f().add(scaleFrameCurrent.scale);
|
|
// }
|
|
// // rVal.add(new Vector3f().add(positionFrameCurrent.position).mul(()/(positionFrameNext.time - positionFrameCurrent.time)));
|
|
// }
|
|
return rVal;
|
|
}
|
|
|
|
public void incrementTime(double incrementValue){
|
|
timeCurrent = timeCurrent + incrementValue;
|
|
// Entry<Double,Keyframe> previousEntry = positionFrameTree.floorEntry(timeCurrent);
|
|
// Entry<Double,Keyframe> nextEntry = positionFrameTree.ceilingEntry(timeCurrent);
|
|
// boolean blend = true;
|
|
// if(previousEntry == nextEntry){
|
|
// if((nextEntry) == null){
|
|
// blend = false;
|
|
// }
|
|
// }
|
|
// if(positionFrameTree.higherEntry(timeCurrent) != null){
|
|
|
|
// }
|
|
// while(positionFrameNext != null && timeCurrent > positionFrameNext.time){
|
|
// positionFrameCurrent = positionFrameNext;
|
|
// if(positionFrameIterator.hasNext()){
|
|
// positionFrameNext = positionFrameIterator.next();
|
|
// } else {
|
|
// positionFrameNext = null;
|
|
// }
|
|
// }
|
|
// while(rotationFrameNext != null && timeCurrent > rotationFrameNext.time){
|
|
// rotationFrameCurrent = rotationFrameNext;
|
|
// if(rotationFrameIterator.hasNext()){
|
|
// rotationFrameNext = rotationFrameIterator.next();
|
|
// } else {
|
|
// rotationFrameNext = null;
|
|
// }
|
|
// }
|
|
// while(scaleFrameNext != null && timeCurrent > scaleFrameNext.time){
|
|
// scaleFrameCurrent = scaleFrameNext;
|
|
// if(scaleFrameIterator.hasNext()){
|
|
// scaleFrameNext = scaleFrameIterator.next();
|
|
// } else {
|
|
// scaleFrameNext = null;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
public void setTime(double time){
|
|
this.timeCurrent = time;
|
|
}
|
|
|
|
public void rewind(){
|
|
timeCurrent = 0;
|
|
|
|
//TODO: Make sure has at least two frames
|
|
// positionFrameIterator = positionFrame.listIterator();
|
|
// if(positionFrameIterator.hasNext()){
|
|
// positionFrameCurrent = positionFrameIterator.next();
|
|
// if(positionFrameIterator.hasNext()){
|
|
// positionFrameNext = positionFrameIterator.next();
|
|
// nextPositionTime = positionFrameNext.time;
|
|
// } else {
|
|
// positionFrameNext = null;
|
|
// }
|
|
// }
|
|
|
|
// rotationFrameIterator = rotationFrame.listIterator();
|
|
// if(rotationFrameIterator.hasNext()){
|
|
// rotationFrameCurrent = rotationFrameIterator.next();
|
|
// if(rotationFrameIterator.hasNext()){
|
|
// rotationFrameNext = rotationFrameIterator.next();
|
|
// } else {
|
|
// rotationFrameNext = null;
|
|
// }
|
|
// }
|
|
|
|
// scaleFrameIterator = scaleFrame.listIterator();
|
|
// if(scaleFrameIterator.hasNext()){
|
|
// scaleFrameCurrent = scaleFrameIterator.next();
|
|
// if(scaleFrameIterator.hasNext()){
|
|
// scaleFrameNext = scaleFrameIterator.next();
|
|
// } else {
|
|
// scaleFrameNext = null;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
public void describeChannel(){
|
|
System.out.println("Target object: " + nodeID);
|
|
System.out.println("Time: " + timeCurrent + "/" + timeTotal);
|
|
System.out.println(positionFrameTree.size() + " position Frames");
|
|
System.out.println(rotationFrameTree.size() + " rotation Frames");
|
|
System.out.println(scaleFrameTree.size() + " scale Frames");
|
|
}
|
|
|
|
public void fullDescribeChannel(){
|
|
System.out.println("Target object: " + nodeID);
|
|
System.out.println("Time: " + timeCurrent + "/" + timeTotal);
|
|
System.out.println(positionFrameTree.size() + " position Frames");
|
|
Iterator<Map.Entry<Double,Keyframe>> frameIterator = positionFrameTree.entrySet().iterator();
|
|
while(frameIterator.hasNext()){
|
|
System.out.println(frameIterator.next());
|
|
}
|
|
System.out.println(rotationFrameTree.size() + " rotation Frames");
|
|
frameIterator = rotationFrameTree.entrySet().iterator();
|
|
while(frameIterator.hasNext()){
|
|
System.out.println(frameIterator.next());
|
|
}
|
|
System.out.println(scaleFrameTree.size() + " scale Frames");
|
|
frameIterator = scaleFrameTree.entrySet().iterator();
|
|
while(frameIterator.hasNext()){
|
|
System.out.println(frameIterator.next());
|
|
}
|
|
}
|
|
|
|
public String getNodeID(){
|
|
return nodeID;
|
|
}
|
|
|
|
public void addPositionFrame(double time, Keyframe frame){
|
|
positionFrameTree.put(time, frame);
|
|
}
|
|
|
|
public void addRotationFrame(double time, Keyframe frame){
|
|
rotationFrameTree.put(time, frame);
|
|
}
|
|
|
|
public void addScaleFrame(double time, Keyframe frame){
|
|
scaleFrameTree.put(time, frame);
|
|
}
|
|
|
|
}
|