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 positionFrameTree; Quaterniond startingRotation; TreeMap rotationFrameTree; TreeMap scaleFrameTree; public AnimChannel(double maxTime, double ticksPerSecond){ timeTotal = maxTime; this.ticksPerSecond = ticksPerSecond; positionFrameTree = new TreeMap(); rotationFrameTree = new TreeMap(); scaleFrameTree = new TreeMap(); } public Vector3f getCurrentPosition(){ Vector3f rVal = new Vector3f(); Entry previousEntry = positionFrameTree.floorEntry(timeCurrent); Entry 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 previousEntry = rotationFrameTree.floorEntry(timeCurrent); Entry 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 previousEntry = scaleFrameTree.floorEntry(timeCurrent); Entry 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 previousEntry = positionFrameTree.floorEntry(timeCurrent); // Entry 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> 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); } }