Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
graph/src/animationsystem.cpp

191 lines
6.5 KiB
C++
Raw Normal View History

#include "animationsystem.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <json.hpp>
#include "mesh.h"
#include "stringutils.h"
#include "worldmanager.h"
#include "world.h"
#include "assetmanager.h"
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
std::ifstream file("data/" + path);
if(!file)
return nullptr;
nlohmann::json json;
file >> json;
auto cinematic = new Cinematic();
for(auto shotObject : json["shots"]) {
Shot* shot = new Shot();
shot->start = shotObject["start"];
shot->end = shotObject["end"];
shot->world = shotObject["world"];
for(auto meshObject : shotObject["meshes"]) {
CinematicMesh mesh;
mesh.name = meshObject["name"];
mesh.modelPath = meshObject["path"];
mesh.materialPath = meshObject["material"];
shot->meshes.push_back(mesh);
}
for(auto animationObject : shotObject["animations"]) {
auto animation = new Animation();
animation->targetName = animationObject["target"];
const auto property = animationObject["property"];
if(property == "position")
animation->property = AnimationProperty::Position;
else if(property == "target")
animation->property = AnimationProperty::Target;
else if(property == "fov")
animation->property = AnimationProperty::FoV;
for(auto keyframeObject : animationObject["keyframes"]) {
Keyframe keyframe;
keyframe.time = keyframeObject["time"];
if(animation->property == AnimationProperty::Position || animation->property == AnimationProperty::Target) {
auto tokens = tokenize(keyframeObject["value"]);
keyframe.valueVec3[0] = atof(tokens[0].c_str());
keyframe.valueVec3[1] = atof(tokens[1].c_str());
keyframe.valueVec3[2] = atof(tokens[2].c_str());
animation->keyframes.push_back(keyframe);
} else if(animation->property == AnimationProperty::FoV) {
keyframe.valueInt = keyframeObject["value"];
animation->keyframes.push_back(keyframe);
}
}
shot->animations.push_back(animation);
}
cinematic->shots.push_back(shot);
}
preloadShot(cinematic->shots[0]);
loadShot(cinematic->shots[0]);
return cinematic;
}
void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
float endTime = 0.0f;
for(uint32_t i = 0; i < cinematic->shots.size(); i++) {
// load the shot before it happens
if((i + 1) <= cinematic->shots.size() && i == (currentShot + 1) && !cinematic->shots[currentShot + 1]->loaded) {
preloadShot(cinematic->shots[currentShot + 1]);
cinematic->shots[currentShot + 1]->loaded = true;
}
if(i > currentShot && animationTime > cinematic->shots[i]->start) {
unloadShot(cinematic->shots[currentShot]);
currentShot = i;
loadShot(cinematic->shots[i]);
}
}
for(auto animation : cinematic->shots[currentShot]->animations) {
unsigned int frameIndex = 0;
for(size_t i = 0; i < animation->keyframes.size(); i++) {
if(animationTime < animation->keyframes[i + 1].time) {
frameIndex = i;
break;
}
}
const auto currentFrame = animation->keyframes[frameIndex];
const auto nextFrame = animation->keyframes[(frameIndex + 1) % animation->keyframes.size()];
const float delta = (animationTime - currentFrame.time) / (nextFrame.time - currentFrame.time);
switch(animation->property) {
case AnimationProperty::Position:
{
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
if(animation->target == nullptr)
worldManager.getCurrentWorld()->camera.position = pos;
else {
animation->target->position = pos;
}
}
break;
case AnimationProperty::Target:
{
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
worldManager.getCurrentWorld()->camera.target = pos;
}
break;
case AnimationProperty::FoV:
{
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
worldManager.getCurrentWorld()->camera.fov = pos;
}
break;
}
}
animationTime += deltaTime;
}
void AnimationSystem::preloadShot(Shot* shot) {
std::cout << "preloading shot..." << std::endl;
worldManager.loadWorld(shot->world);
for(auto cimMesh : shot->meshes) {
Mesh* mesh = assetManager.loadMesh(cimMesh.modelPath);
mesh->name = cimMesh.name;
mesh->material = assetManager.loadMaterial(cimMesh.materialPath);
mesh->tag = "cinematic";
for(auto animation : shot->animations) {
if(animation->targetName == mesh->name)
animation->target = mesh;
}
shot->loadedMeshes.push_back(mesh);
}
}
void AnimationSystem::loadShot(Shot* shot) {
std::cout << "loading shot..." << std::endl;
worldManager.switchWorld(shot->world);
for(auto mesh : shot->loadedMeshes)
worldManager.getCurrentWorld()->meshes.push_back(mesh);
}
void AnimationSystem::unloadShot(Shot* shot) {
std::cout << "unloading shot..." << std::endl;
World* world = worldManager.getCurrentWorld();
for(auto mesh : world->meshes) {
if(mesh->tag == "cinematic") {
//renderer->destroyMaterialBuffers(mesh->material);
delete mesh->material;
//renderer->destroyMeshBuffers(mesh);
delete mesh;
}
}
world->meshes.erase(std::remove_if(world->meshes.begin(),
world->meshes.end(),
[](Mesh* m){return m->tag == "cinematic";}),
world->meshes.end());
}