## Rigid Hierarchical Animation * Used in early 3D animation * Characters are a collection of rigid pieces (pelvis, torso, arms, etc) * Joints 'crack' as each piece is not flexible or connected ## Per-vertex animation and Morph Targets * per-vertex: the vertices of the mesh are animated by an artist, and motion data is exported, which tells the game engine how to move each vertex at runtime. * data intensive; little use in real-time games * morph-target animation: vertices of a mesh are moved by an animator to create a relatively small set of fixed, extreme poses. Animations are produced by blending between two or more of these fixed poses at runtime. * LERP between poses * often used for facial animation * ![Morph Target Face Animation](morph_target_face.png) ## Skinned Animation * More efficient performance and memory usage * first used in games such as Super Mario 64 * most prevalent technique, used in both games and films * the dinosaurs from Jurrassic Park, Solid Snake (Metal Gear Solid 4), Gollum (Lord of the Rings), Nathan Drake (Uncharted), Buzz Lightyear (Toy Story), Marcus Fenix (Gears of War) and Joel (The Last of Us) * Uses 'Skeleton' * skin is bound to the joints of the skeleton; its vertices track the movements of the joints. Each vertex of the skin mesh can be weighted to multiple joints, so the skin can stretch in a natural way as the joints move. * ![Skeleton and Joints Example](skeleton_joints.png) * Skeletons made out of joints * Joints made out of * joint name (string or hash) * parent joint index * Inverse bind pose transform matrix: position, orientation, etc. of the joint ## Bind pose/rest pose/T-pose * Base pose prior to binding/transformation/movement * ![Bind Pose](t_pose.png) ## Local pose * Each joint pose is a transformation relative to its parent joint * an affine transform * Can be stored as a 3 entry struct (R,T,S): * rotation quaternion (R) * translation vector (T) * Scale value (for uniform scaling) or vector (non-uniform scaling) (S) * Poses can be represented in world-space coordinates using a 'global pose' transformation matrix ## Clip * A single animation sequence * Usually a well defined action such as walk, run, throw, etc. * Can affect a single set of joints in the character (such as an arm) * Game character movements are typically broken down into literally thousands of clips ## Timelines * Represent the animation over time * Key poses/key frames are present within the timeline with linear interpolation (LERP) blending between them * ![Key Poses](key_poses.png) * Slow motion/playing in reverse/etc. is just a matter of expanding/compressing/reversing the timeline * Mixing multiple clips requires normalizing their timelines if the clips each have different base durations in order to remain in sync * ![Normalized Local Time](normalized_time.png) ## Frames and Samples * A 'frame' is a time period, e.g. 1/30 or 1/60 seconds * A 'sample' is a single point in time * ![Frames and samples](frames_and_samples.png) ## Clock synchronization * A global clock can be used to synchronize multiple animations between multiple characters * ![Global Clock Timeline](global_clock.png) ## Animation data storage format * The animation data can contain things besides joint poses, called 'metachannels' * Event triggers * locators * texture coordinate scrolling * texture animation * animated material parameters * animated lighting parameters * any other parameters that need to change over time and are in some way synchronized with an animation. * Can be stored in code via the following UML: * ![Animation UML](animation_uml.png) ## Skinning * Attaching the vertices of a 3D mesh to a posed skeleton * Each vertex is bound to one or more joints, with a weight associated with each joint (the 'weighting factor') * Uses a 'skinning matrix' to transform the vertices relative to the joint poses * ![Vertex Skinning Transform](vertex_skinning_transform.png) ## LERP blending * Used to combine multiple animations which affect the same joints * Temporal Interpolation: used to find the location in between non-integer frame indices * Cross Fading: blending between the end of one animation and the beginning of another in order to achieve a smooth transition * ![Smooth Transition](smooth_transition.png) * ![Freeze Transition](freeze_transition.png) * Directional Locomotion: To blend animations when the character is both turning and moving at the same time * Targeted or pivoting movement * ![Targeted and Pivoting Movement](targeted_and_pivoting_movement.png) ## Additive Blending/Additive Animation Clips * Uses a 'difference clip'/'additive animation clip' which contains the changes needed to move from a 'reference clip' into a 'source clip' * D = S - R * Once a difference clip is calculated, it can be used on other unrelated clips, not just the original reference * Weaknesses: Tends to over-rotate the joints in a skeleton, especially when multiple difference clips are combined * Keep hip rotations to a minimum in the reference clip. * The shoulder and elbow joints should usually be in neutral poses in the reference clip to minimize over-rotation of the arms when the difference clip is added to other targets. * Animators should create a new difference animation for each core pose (e.g., standing upright, crouched down, lying prone, etc.). This allows the animator to account for the way in which a real human would move when in each of these stances. ## Applications of additive blending * Stance Variation * ![Stance Variation](stance_variation.png) * Locomotion Noise * ![Locomotion Noise](locomotion_noise.png) * Aim and Look At * ![Aim and Look At](aim_and_look_at.png) * Overloading the time axis ## Procedural Animations (animation Post Processing) * Animations generated/calculated at run time * Bounce vehicle when driving * Sway trees and bushes with wind ## Inverse Kinematics (animation post processing) * Attempts to lock a joint to a target location * e.g. a hand picks up an object * Uses error minimization to find the closest possible location * ![Inverse Kinematics Error](inverse_kinematics_error.png) ## Rag Dolls (Animation post processing) * Physically simulated rigid bodies (limp/lifeless) ## Data compression techniques * Things to do to save memory/disk space: * Channel omission (e.g. channels which do not change over time) * Quantization (reduce size of each channel, e.g. 32 to 16 bits) * Sampling Frequency/Key Omission (reduce sample rate/omit some samples) * Curved based compression (calculates B-splines based on sample data and stores the generated function instead) * ![B Splines graph](b_splines_graph.png) * Wavelet compression (split animation curve into sum or orthonormal wavelets) * Selective Loading/Streaming ## Animation Pipeline ![Animation Pipeline](animation_pipeline.png) ## Action State Machines * Used to abstract the current 'state' of movement in the character (e.g. running, walking, etc.) * Each state has its own animation (e.g. idle animation, etc.) * Ensures smooth transition between states * Each state machine exists in a separate state layer * ![Layered Action State Machine](layered_asm.png) * All current clips on the same character can be combined via a flat weighted average or blend trees * ![Blend Trees](blend_trees.png) * Naughty dog engine uses Scheme script to define state machines (define-state complex :name "move-b-to-f" :tree (anim-node-lerp (anim-node-additive (anim-node-additive (anim-node-clip "move-f") (anim-node-clip "move-f-look-lr") (anim-node-clip "move-f-look-ud") ) (anim-node-additive (anim-node-additive (anim-node-clip "move-b") (anim-node-clip "move-b-look-lr") ) (anim-node-clip "move-b-look-ud") ) ) ## Transitions between states * Parameters: * Source and Destination states * Transition type (immediate, cross faded, etc.?) * Duration * Ease in/ease out curve * transition window (time when transition is valid) * Transition matrix: represents the valid states that can be transitioned between (e.g. walk to run is a valid transition) * In Medal of Honor: Pacific Assault, the matrix was represented via wildcard naming ... * Uncharted/Naughty Dog Used Scheme definitions: (define-state complex :name "s_turret-idle" :tree (aim-tree (anim-node-clip "turret-aim-all--base") "turret-aim-all--left-right" "turret-aim-all--up-down" ) :transitions ( (transition "reload" "s_turret-reload" (range - -) :fade-time 0.2) (transition "step-left" "s_turret-step-left" (range - -) :fade-time 0.2) (transition "step-right" "s_turret-step-right" (range - -) :fade-time 0.2) (transition "fire" "s_turret-fire" (range - -) :fade-time 0.1) (transition-group "combat-gunout-idle^move") (transition-end "s_turret-idle") ) ) ## Attachments * Used to constrain a joint within an area/range, e.g. to within a parent joint's range of movement * stored just like regular joints * ![Attachment](attachment.png) ## Reference Locator * A common reference point used to orient multiple animated characters * ![Reference Locator](reference_locator.png) ## Hand and foot inverse kinematics * Used to make sure hand grabbing/foot movement along ground looks realistic * Usually can be enabled or disabled within the animation pipeline * Well suited for minor corrections if the joint is near the target * Does not necessarily ensure proper orientation * May have significant performance costs * May not necessarily 'feel' realistic/fun to play ## Other movement constraints * Look-at * Cover-registration (align the character behind 'cover' objects) * Cover entry and departure * Traversal aids (guided movement through an area/obstacle(s))