group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
CharacterAnimator Class Reference

Per-entity animator. More...

#include <CharacterAnimator.hpp>

Classes

struct  Impl

Public Member Functions

 CharacterAnimator (const CharacterRig &rig, const AnimationLibrary &library)
 ~CharacterAnimator ()
 CharacterAnimator (const CharacterAnimator &)=delete
CharacterAnimatoroperator= (const CharacterAnimator &)=delete
 CharacterAnimator (CharacterAnimator &&) noexcept=delete
CharacterAnimatoroperator= (CharacterAnimator &&) noexcept=delete
void setSkinningBackend (const ISkinningBackend *backend)
 Set the skinning backend (non-owning).
void update (const AnimationInputs &inputs, float dt)
 Advance the state machine, sample + blend, and compute skin matrices.
void renderFromServer (const AnimSnapshot &serverState, const AnimationInputs &inputs)
 PR-29: render the entity at server-authoritative animation state.
void computeSkinnedVertices (std::vector< std::vector< ModelVertex > > &out) const
 Apply CPU skinning to every rig mesh, producing animated vertices.
void setDebugOverride (ClipId id, bool loop=true)
 Force a single clip to play, bypassing the graph.
ClipId debugOverride () const noexcept
 Current debug override clip (_Count = no override).
const std::array< ClipSampler, kNumSamplerSlots > & samplers () const noexcept
 Snapshot of the current sampler slots (for UI inspection).
void setDebugPlaybackSpeed (float mul) noexcept
 Playback-speed multiplier applied in debug-override mode.
void applyWeaponHoldPose (const WeaponHoldPose &pose, float weight)
 Pose both arms (and the gun-holding fingers) for a held weapon.
void updateSkinMatrices ()
 Recompute skinMatrices() = jointModelMats * inverseBindMats.
void applyRecoilImpulse (float strengthRad)
 Phase F additive recoil kick.
int numJoints () const noexcept
 Number of joints in the underlying rig.
int currentModeValue () const noexcept
 Current high-level animator mode as the underlying int of the private Mode enum (0 = Locomotion, then Crouch, Airborne, Slide, WallRun, …).
void setFrozen (bool frozen) noexcept
 Freeze animation playback.
const std::vector< glm::mat4 > & jointModelMatrices () const noexcept
 Model-space joint matrices with all procedural transforms applied (head pitch, wallrun mirror) but WITHOUT inverse-bind-matrix multiplication.
const std::vector< glm::mat4 > & skinMatrices () const noexcept
 Per-joint LBS skin matrices: procedural * modelMat * inverseBind.

Private Member Functions

void runSamplingAndSkinning (const AnimationInputs &inputs)
 PR-29: shared back end for update() and renderFromServer().

Private Attributes

std::unique_ptr< Implimpl_

Detailed Description

Per-entity animator.

Runs a small state machine that chooses which clips play, samples + blends them via ozz, converts to model-space matrices, and hands off to the skinning backend to produce deformed vertices.

Needs non-owning references to the shared rig + clip library + skinning backend, all of which must outlive the animator.

Constructor & Destructor Documentation

◆ CharacterAnimator() [1/3]

CharacterAnimator::CharacterAnimator ( const CharacterRig & rig,
const AnimationLibrary & library )
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~CharacterAnimator()

CharacterAnimator::~CharacterAnimator ( )
default

◆ CharacterAnimator() [2/3]

CharacterAnimator::CharacterAnimator ( const CharacterAnimator & )
delete
Here is the call graph for this function:

◆ CharacterAnimator() [3/3]

CharacterAnimator::CharacterAnimator ( CharacterAnimator && )
deletenoexcept
Here is the call graph for this function:

Member Function Documentation

◆ applyRecoilImpulse()

void CharacterAnimator::applyRecoilImpulse ( float strengthRad)

Phase F additive recoil kick.

Pushes an instantaneous upward pitch impulse onto the spine that decays exponentially over ~250 ms (impl detail). Called once per fired shot from the client's weapon system; the animator integrates the decay each frame inside runSamplingAndSkinning.

strengthRad is the peak additional pitch in radians, typically 0.05–0.15 (≈3–8 degrees) for a rifle and larger for heavier weapons.

Here is the caller graph for this function:

◆ applyWeaponHoldPose()

void CharacterAnimator::applyWeaponHoldPose ( const WeaponHoldPose & pose,
float weight )

Pose both arms (and the gun-holding fingers) for a held weapon.

Pure forward kinematics — no IK solving. Each bone in the chain Shoulder → UpperArm → ForeArm → Hand (plus every finger joint) is driven to its authored local rotation from pose, processed root → tip so the chain stays connected. weight ∈ [0,1] slerps from the sampled animation toward the authored hold pose (used for the weapon-swap fade); 1.0 fully replaces the arm animation with the static hold.

Mutates jointModelMatrices() in place and recomputes skinMatrices() at the end. Call once per frame after update()/renderFromServer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ computeSkinnedVertices()

void CharacterAnimator::computeSkinnedVertices ( std::vector< std::vector< ModelVertex > > & out) const

Apply CPU skinning to every rig mesh, producing animated vertices.

Parameters
outOne output vector per rig mesh; internally resized.
Here is the caller graph for this function:

◆ currentModeValue()

int CharacterAnimator::currentModeValue ( ) const
nodiscardnoexcept

Current high-level animator mode as the underlying int of the private Mode enum (0 = Locomotion, then Crouch, Airborne, Slide, WallRun, …).

Callers should treat the value as opaque.

Here is the caller graph for this function:

◆ debugOverride()

ClipId CharacterAnimator::debugOverride ( ) const
nodiscardnoexcept

Current debug override clip (_Count = no override).

Here is the caller graph for this function:

◆ jointModelMatrices()

const std::vector< glm::mat4 > & CharacterAnimator::jointModelMatrices ( ) const
nodiscardnoexcept

Model-space joint matrices with all procedural transforms applied (head pitch, wallrun mirror) but WITHOUT inverse-bind-matrix multiplication.

These are the matrices needed for hitbox capsule placement — each matrix transforms from bone-local space to the rig's model space. Apply the entity's world transform (position + yaw + scale) on top to get world space.

Valid after a call to update(). Size = numJoints().

Here is the caller graph for this function:

◆ numJoints()

int CharacterAnimator::numJoints ( ) const
nodiscardnoexcept

Number of joints in the underlying rig.

Here is the caller graph for this function:

◆ operator=() [1/2]

CharacterAnimator & CharacterAnimator::operator= ( CharacterAnimator && )
deletenoexcept
Here is the call graph for this function:

◆ operator=() [2/2]

CharacterAnimator & CharacterAnimator::operator= ( const CharacterAnimator & )
delete
Here is the call graph for this function:

◆ renderFromServer()

void CharacterAnimator::renderFromServer ( const AnimSnapshot & serverState,
const AnimationInputs & inputs )

PR-29: render the entity at server-authoritative animation state.

Bypasses the per-instance state machine (steps 1-6 of update()) — instead writes the supplied AnimSnapshot directly into the internal samplers and runs the ozz sampling + blending + LocalToModel pipeline on top. Used by the client renderer for REMOTE players whose animation state is replicated from the server via the snapshot stream; eliminates the residual ~0.4- median anim-state drift PR-27a's telemetry caught (server runs animator at 128 Hz, client at 30 Hz; both at 1.0× speed but per-clip start-time offsets persist for the lifetime of each clip).

The local player still uses update() — its prediction-driven state machine is authoritative client-side.

inputs is still consulted for per-frame post-processing that has no analog in the snapshot (head-pitch transform, wallrun mirror). Pass the SAME interp-delayed inputs you would have passed to update().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ runSamplingAndSkinning()

void CharacterAnimator::runSamplingAndSkinning ( const AnimationInputs & inputs)
private

PR-29: shared back end for update() and renderFromServer().

Reads impl_->samplers (already populated by either the state machine or a server snapshot) and runs the ozz sampling + blending + LocalToModel + skin-matrix-compose pipeline (steps 7-10 of the original update()). Consumes inputs only for head-pitch and wallrun-mirror post-processing.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ samplers()

const std::array< ClipSampler, kNumSamplerSlots > & CharacterAnimator::samplers ( ) const
nodiscardnoexcept

Snapshot of the current sampler slots (for UI inspection).

Here is the caller graph for this function:

◆ setDebugOverride()

void CharacterAnimator::setDebugOverride ( ClipId id,
bool loop = true )

Force a single clip to play, bypassing the graph.

Parameters
idClipId::_Count to clear the override.
loopLooping mode (reserved; current implementation always loops).
Here is the caller graph for this function:

◆ setDebugPlaybackSpeed()

void CharacterAnimator::setDebugPlaybackSpeed ( float mul)
noexcept

Playback-speed multiplier applied in debug-override mode.

Here is the caller graph for this function:

◆ setFrozen()

void CharacterAnimator::setFrozen ( bool frozen)
noexcept

Freeze animation playback.

While frozen, update() and renderFromServer() skip the state-machine + sampler-time updates, but still run the ozz sample → blend → LocalToModel pipeline using the last-known sampler state. This keeps the IK pass's base pose reproducible and stable — needed so the world-space anchor sliders don't drift from the idle bob while authoring. The procedural overlays (spine bend etc.) keep responding to live inputs so the gun still tracks aim pitch when the user pans the camera.

Here is the caller graph for this function:

◆ setSkinningBackend()

void CharacterAnimator::setSkinningBackend ( const ISkinningBackend * backend)

Set the skinning backend (non-owning).

Must outlive the animator. Phase-1: use CpuLbsSkinningBackend. Phase-2: GpuSkinningBackend will slot in here unchanged.

Here is the caller graph for this function:

◆ skinMatrices()

const std::vector< glm::mat4 > & CharacterAnimator::skinMatrices ( ) const
nodiscardnoexcept

Per-joint LBS skin matrices: procedural * modelMat * inverseBind.

Identical to what computeSkinnedVertices() uses internally. Used by GPU skinning (perf Phase 1B) — flatten across all visible characters into a single palette SSBO and consume by the vertex shader. Valid after a call to update(). Size = numJoints().

Here is the caller graph for this function:

◆ update()

void CharacterAnimator::update ( const AnimationInputs & inputs,
float dt )

Advance the state machine, sample + blend, and compute skin matrices.

Parameters
inputsCurrent driving inputs (velocity, yaw, movement mode, …).
dtFrame time in seconds.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ updateSkinMatrices()

void CharacterAnimator::updateSkinMatrices ( )

Recompute skinMatrices() = jointModelMats * inverseBindMats.

The LBS skinning palette and hitbox-tracking code both read these.

Here is the caller graph for this function:

Member Data Documentation

◆ impl_

std::unique_ptr<Impl> CharacterAnimator::impl_
private

The documentation for this class was generated from the following files: