Skip to content

feat: animations - #45

Merged
AhmedSobhy01 merged 36 commits into
mainfrom
feat/animation
Apr 25, 2026
Merged

feat: animations#45
AhmedSobhy01 merged 36 commits into
mainfrom
feat/animation

Conversation

@AhmedAmrNabil

@AhmedAmrNabil AhmedAmrNabil commented Apr 19, 2026

Copy link
Copy Markdown
Owner

WARNING: 1000 lines for new configs only, the pr is only 1000 lines

Animation system overview

The system has four files with clear responsibilities: bone.hpp handles keyframe data and interpolation, skeleton.hpp owns the bone registry and node hierarchy, animation.hpp wraps an assimp animation into channels, and animator.hpp drives playback each frame.


bone.hppBoneAnimation

Each bone's animation is stored as three independent keyframe tracks: positions (glm::vec3), rotations (glm::quat), scales (glm::vec3). The interpolate(t) method finds the two keyframes bracketing the current time via findIndex, computes a normalized factor between them, then runs glm::mix for position/scale and glm::slerp for rotation (slerp takes the shortest arc on the quaternion sphere). The result is composed into a single mat4 via translate × rotate × scale.


skeleton.hppSkeleton + SkeletonNode

Skeleton holds two things: a boneInfoMap mapping bone names → BonePose (an integer ID + offsetMatrix), and a flat nodes vector of SkeletonNode. The flat vector is topologically sorted — parents always appear before children — which lets the animator traverse it with a plain for loop instead of recursion. The offsetMatrix is the inverse of a bone's bind-pose world transform; it moves vertices from world space into the bone's local space before the animated transform is applied.


animation.hppAnimation

Thin wrapper around aiAnimation. The constructor reads duration, ticks-per-second (defaulting to 25 if assimp returns 0), and iterates mChannels to build a BoneAnimation per node, stored in a channels map keyed by node name.


animator.hppAnimator::computeBoneTransform

This is the core loop. For each node in topological order:

  1. Start with the node's bind-pose localTransform
  2. If channels has an entry for this node name, replace it with channel.interpolate(currentTime)
  3. Accumulate: globalTransforms[i] = globalTransforms[parentIndex] * localTransform (root uses localTransform directly)
  4. Cache in nodeTransforms by name (for non-skinned nodes like attached meshes or lights)
  5. If this node is a registered bone, write finalBoneMatrices[id] = globalInverseTransform * globalTransforms[i] * offsetMatrix

finalBoneMatrices is the uniform array sent to the vertex shader. Each vertex stores up to N bone IDs and weights; the shader computes a weighted sum of those matrices to get the final vertex position.


Things worth reviewing

MAX_BONES 110 is a hard cap — worth confirming the target models don't exceed it, since overflow is silent (the id < finalBoneMatrices.size() check just skips the bone). The speed multiplier in update scales ticksPerSecond directly, so a speed of 2.0 doubles playback rate. isFinished() only fires on non-looping animations once currentTime >= duration.

note: if you didn't notice by now but this comment is generated by claude, if you need to understand anything ask me

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds initial support for skeletal (skinning) and node-based animations by extending the model loader to import animation/skeleton data, updating the renderer/shaders to upload bone matrices via a UBO, and introducing ECS animation component/system wiring.

Changes:

  • Import skeleton + animation clips from Assimp into Model, and add AnimationComponent + AnimationSystem to drive Animator updates per-frame.
  • Extend ForwardRenderer and lit.vert to support skinned rendering via a Bones uniform block and per-draw bone matrix uploads.
  • Add a new animation playground config demonstrating animated model usage.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/states/play-state.hpp Runs the new AnimationSystem during the play loop.
src/common/uniform-buffer/uniform-buffer.hpp Adds a small UBO wrapper used for bone matrices.
src/common/systems/forward-renderer.hpp Extends render command data to optionally carry an Animator and adds a bones UBO.
src/common/systems/forward-renderer.cpp Uploads bone matrices and applies node transforms during command building.
src/common/systems/animation-system.hpp Declares the new ECS animation system.
src/common/systems/animation-system.cpp Updates animators per-entity and handles default clip replay when finished.
src/common/shader/shader.hpp Adds bindUniformBlock() helper for UBO binding.
src/common/model/model.hpp Adds skeleton/animation storage and bone data processing helpers.
src/common/model/model.cpp Loads animations/skeleton nodes and populates per-vertex bone IDs/weights.
src/common/mesh/mesh.hpp Adds vertex attribute locations for bone IDs/weights (and a new include).
src/common/components/mesh-renderer.hpp Stores nodeName and hasBones for renderer animation decisions.
src/common/components/component-deserializer.hpp Registers the new AnimationComponent.
src/common/components/animation.hpp Defines AnimationComponent and clip mapping.
src/common/components/animation.cpp Implements JSON deserialization and clip playback.
src/common/animation/skeleton.hpp Adds skeleton node graph + bone pose lookup.
src/common/animation/bone.hpp Adds bone keyframe interpolation support.
src/common/animation/animator.hpp Adds animator runtime for skeletal + node transform evaluation.
src/common/animation/animation.hpp Adds Animation container to load Assimp channels.
config/playgrounds/animation.jsonc Adds a sample scene showcasing animated model usage.
assets/shaders/lit.vert Adds skinning path and Bones UBO support in the lit vertex shader.
CMakeLists.txt Adds new animation component/system sources to the build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/common/systems/animation-system.hpp Outdated
Comment thread src/common/mesh/mesh.hpp Outdated
Comment thread src/common/model/model.cpp Outdated
Comment thread src/common/uniform-buffer/uniform-buffer.hpp
Comment thread src/common/model/model.cpp
Comment thread src/common/animation/animator.hpp
Comment thread src/common/animation/bone.hpp Outdated
Comment thread src/common/uniform-buffer/uniform-buffer.hpp
Comment thread src/common/systems/forward-renderer.cpp Outdated
Comment thread src/common/animation/animator.hpp Outdated
@AhmedSobhy01 AhmedSobhy01 changed the title Feat: animations feat: animations Apr 22, 2026
@github-actions github-actions Bot added the core label Apr 23, 2026
@AhmedAmrNabil
AhmedAmrNabil requested a review from Copilot April 23, 2026 02:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 28 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/common/systems/animation-system.hpp Outdated
Comment thread src/common/components/animation.cpp
Comment thread src/common/systems/animation-system.cpp Outdated
Comment thread src/common/animation/bone.hpp Outdated
Comment thread src/common/shader/shader.hpp
Comment thread src/common/components/animation.hpp
Comment thread src/common/animation/animator.hpp
Comment thread src/common/uniform-buffer/uniform-buffer.hpp
Comment thread src/common/systems/forward-renderer.cpp
Comment thread src/common/systems/forward-renderer.cpp
Comment thread src/common/model/model.cpp
Comment thread src/common/animation/animator.hpp Outdated
Comment thread src/common/animation/animation.hpp Outdated
Comment thread src/common/model/model.cpp
Comment thread src/common/systems/forward-renderer.cpp
Comment thread src/common/systems/forward-renderer.cpp
AhmedSobhy01
AhmedSobhy01 previously approved these changes Apr 24, 2026

@LoayAhmed304 LoayAhmed304 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

- Implemented Animation, Animator, Bone, and Skeleton classes to handle skeletal animations.
- Added AnimationComponent to manage animations within entities.
- Integrated animation loading in the Model class, supporting multiple animations.
- Created AnimationSystem to update animations based on input and delta time.
- Enhanced ForwardRenderer to support animated meshes with bone transformations.
- Introduced UniformBuffer class for efficient bone matrix handling in shaders.
- Updated MeshRendererComponent to indicate if a mesh uses bones for skinning.
- Added deserialization for AnimationComponent to load animation data from JSON.
@AhmedSobhy01
AhmedSobhy01 merged commit b179235 into main Apr 25, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants