diff --git a/animationController.cpp b/animationController.cpp index 6c59585..86042a0 100644 --- a/animationController.cpp +++ b/animationController.cpp @@ -31,7 +31,7 @@ namespace vb01{ float ratio = (float)(max(0, currentFrame - pastFrame)) / (nextFrame - pastFrame); Keyframe::Interpolation interp = pastKeyframe.interpolation; - float value = KeyframeChannel::interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio); + float value = KeyframeChannel::interpolate(pastKeyframe, nextKeyframe, ratio); animatable->animate(value, keyframeChannel); } } diff --git a/driver.cpp b/driver.cpp index c9e4867..d616df6 100644 --- a/driver.cpp +++ b/driver.cpp @@ -22,7 +22,7 @@ namespace vb01{ ratio = 0; Keyframe::Interpolation interp = pastKeyframe.interpolation; - float value = KeyframeChannel::interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio); + float value = KeyframeChannel::interpolate(pastKeyframe, nextKeyframe, ratio); keyframeChannel.animatable->animate(value, keyframeChannel); } diff --git a/keyframeChannel.cpp b/keyframeChannel.cpp index 2fdbfd2..51e760f 100644 --- a/keyframeChannel.cpp +++ b/keyframeChannel.cpp @@ -3,22 +3,34 @@ using namespace std; namespace vb01{ - float KeyframeChannel::interpolate(float pastValue, float nextValue, Keyframe::Interpolation mode, float ratio){ + float KeyframeChannel::interpolate(Keyframe pastKeyframe, Keyframe nextKeyframe, float ratio){ float currentValue; - switch(mode){ + switch(pastKeyframe.interpolation){ case Keyframe::CONSTANT: - currentValue = pastValue; + currentValue = pastKeyframe.value; break; case Keyframe::LINEAR: - currentValue = pastValue + (nextValue - pastValue) * ratio; - break; case Keyframe::BEZIER: - currentValue = pastValue + (nextValue - pastValue) * ratio; + vector points = vector({pastKeyframe.value, pastKeyframe.rightHandleValue, nextKeyframe.leftHandleValue, nextKeyframe.value}); + currentValue = interpolateBezier(points, ratio); break; } return currentValue; } + float KeyframeChannel::interpolateBezier(vector points, float ratio){ + int numPoints = points.size(); + vector newPoints; + + for(int i = 0; i < numPoints - 1; i++) + newPoints.push_back(points[i] + (points[i + 1] - points[i]) * ratio); + + if(newPoints.size() >= 2) + return interpolateBezier(newPoints, ratio); + else + return newPoints[0]; + } + KeyframeChannelType KeyframeChannel::getKeyframeChannelType(string typeString){ KeyframeChannelType type; if(typeString == "pos_x") diff --git a/keyframeChannel.h b/keyframeChannel.h index 08e3c84..1909287 100644 --- a/keyframeChannel.h +++ b/keyframeChannel.h @@ -26,7 +26,7 @@ namespace vb01{ struct Keyframe{ enum Interpolation{CONSTANT, LINEAR, BEZIER}; - float value, frame; + float value, leftHandleValue, rightHandleValue, frame, leftHandleFrame, rightHandleFrame; Interpolation interpolation; }; @@ -34,8 +34,9 @@ namespace vb01{ Animatable *animatable = nullptr; std::vector keyframes; + static float interpolateBezier(std::vector, float); static KeyframeChannel::Type getKeyframeChannelType(std::string); - static float interpolate(float, float, Keyframe::Interpolation, float); + static float interpolate(Keyframe, Keyframe, float); static Keyframe findKeyframe(float, KeyframeChannel, bool); static void transform(); }; diff --git a/script.py b/script.py index 2c45004..a498a3e 100644 --- a/script.py +++ b/script.py @@ -149,10 +149,12 @@ def getChannelType(channel): def readChannel(channel): channelType = getChannelType(channel) - for keyframe in channel.keyframe_points: + numKeyframes = len(channel.keyframe_points) + for i in range(numKeyframes): + keyframe = channel.keyframe_points[i] keyframeId = keyframe.co[0] interp = keyframe.interpolation - interpInt = - 1 + interpInt = -1 if interp == 'CONSTANT': interpInt = 0 @@ -163,9 +165,20 @@ def readChannel(channel): keyframeValue = keyframe.co[1] file.write(str(keyframeValue) + ' ' + str(keyframeId) + ' ' + str(interpInt)) - if interp == 'BEZIER': - file.write(' ' + str(keyframe.handle_left.x) + ' ' + str(keyframe.handle_left.y) + ' ') - file.write(str(keyframe.handle_right.x) + ' ' + str(keyframe.handle_right.y) + ' ') + + leftHandleValue = (keyframe.handle_left[1]) + leftHandleFrame = (keyframe.handle_left[0]) + rightHandleValue = (keyframe.handle_right[1]) + rightHandleFrame = (keyframe.handle_right[0]) + if interp != 'BEZIER': + rightHandleValue = keyframeValue + rightHandleFrame = keyframeId + if i > 0 and channel.keyframe_points[i - 1].interpolation != 'BEZIER': + leftHandleValue = keyframeValue + leftHandleFrame = keyframeId + + file.write(' ' + str(leftHandleValue) + ' ' + str(leftHandleFrame) + ' ') + file.write(str(rightHandleValue) + ' ' + str(rightHandleFrame) + ' ') file.write('\n') def readDriver(channel, driverName): diff --git a/vbModelReader.cpp b/vbModelReader.cpp index 0af586b..cea2e15 100644 --- a/vbModelReader.cpp +++ b/vbModelReader.cpp @@ -259,8 +259,12 @@ namespace vb01{ Keyframe keyframe; keyframe.value = atof(keyframeData[0].c_str()); - keyframe.frame = atoi(keyframeData[1].c_str()); + keyframe.frame = atof(keyframeData[1].c_str()); keyframe.interpolation = (KeyframeInterpolation)atoi(keyframeData[2].c_str()); + keyframe.leftHandleValue = atof(keyframeData[3].c_str()); + keyframe.leftHandleFrame = atof(keyframeData[4].c_str()); + keyframe.rightHandleValue = atof(keyframeData[5].c_str()); + keyframe.rightHandleFrame = atof(keyframeData[6].c_str()); keyframeChannels[currentChannel].keyframes.push_back(keyframe); numCurrentTypeKeyframes++;