First working animations, but lots of bugs and refactoring needed.

This commit is contained in:
Zed A. Shaw 2026-10-07 12:11:15 -04:00
parent 8b41591360
commit a1c8208b47
158 changed files with 17271 additions and 0 deletions

View file

@ -0,0 +1,115 @@
#pragma once
#include <vector>
#include <unordered_map>
#include <glm/glm.hpp>
#include <assimp/scene.h>
#include <functional>
#include "animdata.hpp"
#include "bone.hpp"
#include "model.hpp"
#include "assimp_glm_helpers.hpp"
struct Bone;
struct AssimpNodeData {
glm::mat4 transformation;
std::string name;
int children_count;
std::vector<AssimpNodeData> children;
};
struct Animation {
float $duration{0.0f};
int $ticks_per_sec{0};
std::vector<Bone> $bones;
AssimpNodeData $root_node;
std::unordered_map<std::string, BoneInfo> $bone_info_map;
Animation() = default;
Animation(const std::string& animationPath, Model *model) {
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(animationPath, aiProcess_Triangulate);
dbc::check(scene != nullptr, $F("Scene for animation {} failed to load.", animationPath));
dbc::check(scene->mRootNode, $F("Scene {} doesn't have a root node.", animationPath));
auto animation = scene->mAnimations[0];
$duration = animation->mDuration;
$ticks_per_sec = animation->mTicksPerSecond;
aiMatrix4x4 globalTransformation = scene->mRootNode->mTransformation;
globalTransformation = globalTransformation.Inverse();
ReadHierarchyData($root_node, scene->mRootNode);
ReadMissingBones(animation, *model);
}
~Animation() {
}
Bone* FindBone(const std::string& name) {
auto iter = std::find_if($bones.begin(), $bones.end(),
[&](const auto& bone) {
return bone.GetBoneName() == name;
}
);
return iter == $bones.end() ? nullptr : &(*iter);
}
float GetTicksPerSecond() {
return $ticks_per_sec;
}
float GetDuration() {
return $duration;
}
const AssimpNodeData& GetRootNode() {
return $root_node;
}
const std::unordered_map<std::string, BoneInfo>& GetBoneIDMap()
{
return $bone_info_map;
}
void ReadMissingBones(const aiAnimation* animation, Model& model) {
// this code is weird as hell
int size = animation->mNumChannels;
auto& boneInfoMap = model.bone_info_map;
int& boneCount = model.bone_counter;
for(int i = 0; i < size; i++) {
auto channel = animation->mChannels[i];
std::string boneName = channel->mNodeName.data;
if(!boneInfoMap.contains(boneName)) {
boneInfoMap[boneName].id = boneCount;
boneCount++;
}
dbc::check(boneCount < MAX_BONES, "Too many bones!");
$bones.emplace_back(boneName,
boneInfoMap[boneName].id, channel);
}
$bone_info_map = boneInfoMap;
}
void ReadHierarchyData(AssimpNodeData& dest, const aiNode* src) {
dbc::check(src != nullptr, "aiNode src is null?!");
dest.name = src->mName.data;
dest.transformation = AssimpGLMHelpers::ConvertMatrixToGLMFormat(src->mTransformation);
dest.children_count = src->mNumChildren;
for(size_t i = 0; i < src->mNumChildren; i++) {
AssimpNodeData newData;
ReadHierarchyData(newData, src->mChildren[i]);
dest.children.push_back(newData);
}
}
};