The goals of this lab are to
The motion assignment has been added to your AnimationFramework repository. To get the source, run
> cd cs56/AnimationToolkit > git pull > cd build > cmake .. > make
You should now have a new directory under assignments called a8-blend.
In this question, you will blend the walk motion with a strafe motion. Implement your solution in assignments/a8-blend/ABlend.cpp inside of the method blend().
// m1: First input motion // m2: Second input motion // alpha: blend value // returns the result of m1 * (1-alpha) + m2 AMotion blend(const AMotion& m1, const AMotion& m2, double alpha)
Your implementation should be based on the code from class
duration = duration1 * (1-alpha) + duration2 * alpha deltaT = 1/fps for t from 0 to duration, increment by deltaT APose pose1 = pose from motion1 APose pose2 = pose from motion2 APose newPose = lerp pose1 and pose2 by alpha result.appendKey(newPose) return result
To run the demo from the build directory, type
build> ../bin/a8-blend
Controls
Your program should have the following features
In this question, you will modify the walk motion to have the arm motion from gangnam style dancing. Implement your solution in assignements/a8-blend/ASplice.cpp.
// orig: Starting input motion // upper: Motion for the modifying the upper body (all joints which are descendants of the spine) // alpha: blend value // returns a new motion such that // the lower body matches the motion in 'orig' // the upper body is the result of blending the upper body motion with // the original's upper body motion, e.g. newupper = upper * (1-alpha) + orig * alpha AMotion spliceUpperBody(const AMotion& orig, const AMotion& upper, double alpha)
For this question, use keys for blending instead of durations, e.g.
for i in range numKeys in orig APose pose = orig.getKey(i) // compute new pose and either call appendKey() or editKey() set the pose
To run the demo from the build directory, type
build> ../bin/a8-splice
Controls
Your program should have the following features
In this question, you will modify the walk motion to have zombie arms. Implement your solution in assignements/a8-blend/AZombieArms.cpp.
To run the demo from the build directory, type
build> ../bin/a8-zombie
Part 1: Freeze Arms (5 points)
To freeze the arms, we will set both the shoulders and elbows to a constant rotation. Implement your solution in ComputeArmFreeze.
// motion: input motion // returns a new motion with the shoulders and elbows outstretched AMotion ComputeArmFreeze(const AMotion& motion)
Freeze arms should have the following features:
Part 2: Offset Arms (5 points)
To offset the arms, we will apply an offset rotation to shoulder's animation curve. We will freeze the elbows as before. Implement your solution in ComputeArmOffset.
// motion: input motion // returns a new motion with the shoulders and elbows outstretched but moving AMotion ComputeArmOffset(const AMotion& motion)
To compute the offset, we will
use the local rotation of the should on the first frame to compute an offset
rotation.
\(
R_{offset} = R_{desired} (R_i^j)^{-1}
\)
where $R_i^j$ is the local to parent rotation for the shoulder joint. $R_{desired}$ is the target rotation we want for the joint. For the right joint,
the desired rotation will be the XYZ euler angles (14, 88, -33). For the
left joint, the desired rotation will be the XYZ euler angles (-53, -88, -33).
Offset arms should have the following features:
In this question, you will modify a motion so it starts in a new location and orientation. You will need to perform the same calculation in crossfade to align two motions. Implement your solution in assignements/a8-blend/AReorient.cpp
// motion: the input motion // pos: the new starting position of the motion // heading: the new starting orientation as an angle (radians) around the world UP axis (e.g. Y) // returns a new motion whose starting pose has a root position and rotation that matches pos and heading AMotion reorient(const AMotion& motion, const AVector3& pos, double heading)
To run the demo from the build directory, type
build> ../bin/a8-reorient
Your demo should have teh following features
In this question, you will implement a cross fade transition between two motins. You have a application with a GUI to help you test. You will implement your solution in libsrc/animation/AMotionBlender-basecode.cpp.
To run the demo from the build directory, type
build> ../bin/a8-crossfade
Part 1 (5 points) Implement AMotionBlender::append.
This method should grab the keys in range
[startKeyId, endKeyId) from the input motion and append them to the output motion. Test your new
function by extending AMotionBlender::blend() to append the keys [0, startKeyId) from
motion 1 and the keys [endKeyId, motion2.getNumKeys) from motion 2. Your assignment should
look as follows: the walk motion plays and then snaps back to the origin to play the jump.
Part 2 (5 points) Implement AMotionBlender::crossfade.
So far, the transition snaps from the first motion to the
second motion. Fix this problem by implementing AMotionBlender::crossfade. This function
should blend the frame between motion 1 and motion 2 and append the blended frames to
'blend'. Extend AMotionBlender::blend to call your new crossfade function.
Now, your assignment should look as follows: the motion is smooth but the character slides to
the origin to play the jump motion.
Part 3 (5 points) Align the positions in AMotionBlender::align.
Now we have a smooth result but the jump unrealistically moves back to the origin. We want the jump to occur at the character's current location! We will fix this by aligning the sequence from motion 2 with the start transition key from motion 1. Note that you can re-use the logic from reorient!
Translate the keys so that the second sequence is aligned with the first sequence. Extend AMotionBlender::blend to call align. Your assignment should now look as follows.
Part 4 (5 points) Align the root headings in AMotionBlender::align.
Reorient the keys (e.g. rotate and translate) so that the second sequence is aligned with the first. Now your blend should look good in all cases.
Testing tip: A correct crossfade should return the original motion whenever you crossfade between the same motion. For example, try blending two walk motions over the starting 10 frames. The result should look identical to the original motion.
Option 1 (2 points) Create a unique animation or character.
Option 2 (2 points) Infinite motion. Create a character that can walk or dance or jump forever by repeatedly blending the walking motion with itself.
Option 3 (2 points) Mirror. Try creating a mirrored motion which plays forward and backward.
Option 4 (4 points) Motion analysis. Detect when feet are in contact with the floor. Draw a cube at the location of the contact so we can visualize it.
Be sure to include a gif or video of your demo for full credit!