split animation components into GltfAnimation/MorphAnimation/BoneAnimation
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
#include <utils/Entity.h>
|
||||
|
||||
#include "c_api/APIExport.h"
|
||||
#include "scene/AnimationManager.hpp"
|
||||
|
||||
@@ -26,15 +28,65 @@ extern "C"
|
||||
animationManager->update(frameTimeInNanos);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_addGltfAnimationComponent(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf || !sceneAsset->isInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->addAnimationComponent(entityId);
|
||||
|
||||
animationManager->addGltfAnimationComponent(reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset));
|
||||
return true;
|
||||
}
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_removeAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_removeGltfAnimationComponent(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf || !sceneAsset->isInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->removeGltfAnimationComponent(reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset));
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_addBoneAnimationComponent(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf || !sceneAsset->isInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
|
||||
animationManager->addBoneAnimationComponent(reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset));
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_removeBoneAnimationComponent(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf || !sceneAsset->isInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->removeBoneAnimationComponent(reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset));
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addMorphAnimationComponent(TAnimationManager *tAnimationManager, EntityId entity)
|
||||
{
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->removeAnimationComponent(entityId);
|
||||
animationManager->addMorphAnimationComponent(utils::Entity::import(entity));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_removeMorphAnimationComponent(TAnimationManager *tAnimationManager, EntityId entity)
|
||||
{
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
animationManager->removeMorphAnimationComponent(utils::Entity::import(entity));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_setMorphAnimation(
|
||||
@@ -66,26 +118,26 @@ extern "C"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_clearMorphAnimation(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto entity = utils::Entity::import(entityId);
|
||||
animManager->clearMorphAnimationBuffer(entity);
|
||||
animationManager->clearMorphAnimationBuffer(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPose(TAnimationManager *tAnimationManager, TSceneAsset *sceneAsset)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
animManager->resetToRestPose(instance);
|
||||
animationManager->resetToRestPose(instance);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addBoneAnimation(
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_addBoneAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const frameData,
|
||||
@@ -95,13 +147,24 @@ extern "C"
|
||||
float fadeInInSecs,
|
||||
float maxDelta)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
animManager->addBoneAnimation(reinterpret_cast<GltfSceneAssetInstance *>(asset), skinIndex, boneIndex, frameData, numFrames, frameLengthInMs,
|
||||
fadeOutInSecs, fadeInInSecs, maxDelta);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
|
||||
if (sceneAsset->isInstance())
|
||||
{
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
animationManager->addBoneAnimationComponent(instance);
|
||||
animationManager->addBoneAnimation(instance, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId AnimationManager_getBone(
|
||||
@@ -110,11 +173,11 @@ extern "C"
|
||||
int skinIndex,
|
||||
int boneIndex)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto entities = animManager->getBoneEntities(reinterpret_cast<GltfSceneAssetInstance *>(asset), skinIndex);
|
||||
auto entities = animationManager->getBoneEntities(reinterpret_cast<GltfSceneAssetInstance *>(asset), skinIndex);
|
||||
if (boneIndex < entities.size())
|
||||
{
|
||||
return utils::Entity::smuggle(entities[boneIndex]);
|
||||
@@ -131,12 +194,12 @@ extern "C"
|
||||
float *const out,
|
||||
int numBones)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
const auto transforms = animManager->getBoneRestTranforms(instance, skinIndex);
|
||||
const auto transforms = animationManager->getBoneRestTranforms(instance, skinIndex);
|
||||
auto numTransforms = transforms.size();
|
||||
if (numTransforms != numBones)
|
||||
{
|
||||
@@ -164,12 +227,12 @@ extern "C"
|
||||
int boneIndex,
|
||||
float *const out)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
auto transform = animManager->getInverseBindMatrix(instance, skinIndex, boneIndex);
|
||||
auto transform = animationManager->getInverseBindMatrix(instance, skinIndex, boneIndex);
|
||||
for (int colNum = 0; colNum < 4; colNum++)
|
||||
{
|
||||
for (int rowNum = 0; rowNum < 4; rowNum++)
|
||||
@@ -180,9 +243,9 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_playAnimation(
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_playGltfAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int index,
|
||||
bool loop,
|
||||
bool reverse,
|
||||
@@ -190,29 +253,48 @@ extern "C"
|
||||
float crossfade,
|
||||
float startOffset)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
|
||||
animManager->playGltfAnimation(instance, index, loop, reverse, replaceActive, crossfade, startOffset);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
|
||||
if (sceneAsset->isInstance())
|
||||
{
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
animationManager->addGltfAnimationComponent(instance);
|
||||
animationManager->playGltfAnimation(instance, index, loop, reverse, replaceActive, crossfade, startOffset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_stopAnimation(
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_stopGltfAnimation(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int index)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(sceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
|
||||
animManager->stopGltfAnimation(instance, index);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
|
||||
if (sceneAsset->isInstance())
|
||||
{
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
animationManager->stopGltfAnimation(instance, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setGltfAnimationFrame(
|
||||
@@ -221,41 +303,79 @@ extern "C"
|
||||
int animationIndex,
|
||||
int frame)
|
||||
{
|
||||
auto *animManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto *animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
auto asset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if (asset->getType() == SceneAsset::SceneAssetType::Gltf && asset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(asset);
|
||||
animManager->setGltfAnimationFrame(instance, animationIndex, frame);
|
||||
animationManager->setGltfAnimationFrame(instance, animationIndex, frame);
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE float AnimationManager_getAnimationDuration(
|
||||
EMSCRIPTEN_KEEPALIVE float AnimationManager_getGltfAnimationDuration(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
int animationIndex)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
return ((AnimationManager *)tAnimationManager)->getGltfAnimationDuration(instance, animationIndex);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
|
||||
if (sceneAsset->isInstance())
|
||||
{
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
|
||||
return animationManager->getGltfAnimationDuration(instance, animationIndex);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getAnimationCount(
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getGltfAnimationCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset)
|
||||
TSceneAsset *tSceneAsset)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getGltfAnimationNames(instance);
|
||||
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return -1;
|
||||
}
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
if(sceneAsset->isInstance()) {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
auto names = animationManager->getGltfAnimationNames(instance);
|
||||
TRACE("Animation count : %d", names.size());
|
||||
return (int)names.size();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getAnimationName(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_getGltfAnimationName(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
char *const outPtr,
|
||||
int index)
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getGltfAnimationNames(instance);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
strcpy(outPtr, "FILAMENT_ERROR_NOT_FOUND");
|
||||
return;
|
||||
}
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAssetInstance *instance;
|
||||
if(sceneAsset->isInstance()) {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
} else {
|
||||
instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset->getInstanceAt(0));
|
||||
}
|
||||
auto names = animationManager->getGltfAnimationNames(instance);
|
||||
std::string name = names[index];
|
||||
strcpy(outPtr, name.c_str());
|
||||
}
|
||||
@@ -278,8 +398,7 @@ extern "C"
|
||||
{
|
||||
auto instance = ((GltfSceneAssetInstance *)sceneAsset);
|
||||
auto entities = ((AnimationManager *)tAnimationManager)->getBoneEntities(instance, skinIndex);
|
||||
// Note: This needs implementation of a method to get bone names from entities
|
||||
// Current source doesn't show how bone names are retrieved
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool AnimationManager_updateBoneMatrices(
|
||||
@@ -293,11 +412,27 @@ extern "C"
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int AnimationManager_getMorphTargetNameCount(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
TSceneAsset *tSceneAsset,
|
||||
EntityId childEntity)
|
||||
{
|
||||
auto asset = ((GltfSceneAsset *)sceneAsset);
|
||||
auto names = ((AnimationManager *)tAnimationManager)->getMorphTargetNames(asset, childEntity);
|
||||
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
|
||||
|
||||
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||
GltfSceneAsset *gltfAsset;
|
||||
|
||||
if (sceneAsset->isInstance())
|
||||
{
|
||||
auto *instance = reinterpret_cast<GltfSceneAssetInstance *>(sceneAsset);
|
||||
gltfAsset = reinterpret_cast<GltfSceneAsset *>(instance->getInstanceOwner());
|
||||
} else {
|
||||
gltfAsset = reinterpret_cast<GltfSceneAsset *>(sceneAsset);
|
||||
}
|
||||
|
||||
auto names = animationManager->getMorphTargetNames(gltfAsset, childEntity);
|
||||
return (int)names.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#include <chrono>
|
||||
#include <variant>
|
||||
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
void BoneAnimationComponentManager::addAnimationComponent(FilamentInstance *target) {
|
||||
if(!hasComponent(target->getRoot())) {
|
||||
EntityInstanceBase::Type componentInstance = addComponent(target->getRoot());
|
||||
this->elementAt<0>(componentInstance) = { target };
|
||||
}
|
||||
}
|
||||
|
||||
void BoneAnimationComponentManager::removeAnimationComponent(FilamentInstance *target) {
|
||||
if(hasComponent(target->getRoot())) {
|
||||
removeComponent(target->getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
void BoneAnimationComponentManager::update() {
|
||||
TRACE("Updating with %d components", getComponentCount());
|
||||
for (auto it = begin(); it < end(); it++)
|
||||
{
|
||||
const auto &entity = getEntity(it);
|
||||
|
||||
auto componentInstance = getInstance(entity);
|
||||
auto &animationComponent = elementAt<0>(componentInstance);
|
||||
|
||||
auto &boneAnimations = animationComponent.animations;
|
||||
|
||||
auto target = animationComponent.target;
|
||||
auto animator = target->getAnimator();
|
||||
///
|
||||
/// When fading in/out, interpolate between the "current" transform (which has possibly been set by the glTF animation loop above)
|
||||
/// and the first (for fading in) or last (for fading out) frame.
|
||||
///
|
||||
for (int i = (int)boneAnimations.size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto animationStatus = boneAnimations[i];
|
||||
|
||||
auto now = high_resolution_clock::now();
|
||||
|
||||
auto elapsedInMillis = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count());
|
||||
auto elapsedInSecs = elapsedInMillis / 1000.0f;
|
||||
|
||||
// if we're not looping and the amount of time elapsed is greater than the animation duration plus the fade-in/out buffer,
|
||||
// then the animation is completed and we can delete it
|
||||
if (elapsedInSecs >= (animationStatus.durationInSecs + animationStatus.fadeInInSecs + animationStatus.fadeOutInSecs))
|
||||
{
|
||||
if(!animationStatus.loop) {
|
||||
boneAnimations.erase(boneAnimations.begin() + i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if we're fading in, treat elapsedFrames is zero (and fading out, treat elapsedFrames as lengthInFrames)
|
||||
float elapsedInFrames = (elapsedInMillis - (1000 * animationStatus.fadeInInSecs)) / animationStatus.frameLengthInMs;
|
||||
int currFrame = std::floor(elapsedInFrames);
|
||||
int nextFrame = currFrame;
|
||||
|
||||
// offset from the end if reverse
|
||||
if (animationStatus.reverse)
|
||||
{
|
||||
currFrame = animationStatus.lengthInFrames - currFrame;
|
||||
if (currFrame > 0)
|
||||
{
|
||||
nextFrame = currFrame - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextFrame = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currFrame < animationStatus.lengthInFrames - 1)
|
||||
{
|
||||
nextFrame = currFrame + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextFrame = currFrame;
|
||||
}
|
||||
}
|
||||
currFrame = std::clamp(currFrame, 0, animationStatus.lengthInFrames - 1);
|
||||
nextFrame = std::clamp(nextFrame, 0, animationStatus.lengthInFrames - 1);
|
||||
|
||||
float frameDelta = elapsedInFrames - currFrame;
|
||||
|
||||
// linearly interpolate this animation between its last/current frames
|
||||
// this is to avoid jerky animations when the animation framerate is slower than our tick rate
|
||||
|
||||
math::float3 currScale, newScale;
|
||||
math::quatf currRotation, newRotation;
|
||||
math::float3 currTranslation, newTranslation;
|
||||
math::mat4f curr = animationStatus.frameData[currFrame];
|
||||
decomposeMatrix(curr, &currTranslation, &currRotation, &currScale);
|
||||
|
||||
if(frameDelta > 0) {
|
||||
math::mat4f next = animationStatus.frameData[nextFrame];
|
||||
decomposeMatrix(next, &newTranslation, &newRotation, &newScale);
|
||||
newScale = mix(currScale, newScale, frameDelta);
|
||||
newRotation = slerp(currRotation, newRotation, frameDelta);
|
||||
newTranslation = mix(currTranslation, newTranslation, frameDelta);
|
||||
} else {
|
||||
newScale = currScale;
|
||||
newRotation = currRotation;
|
||||
newTranslation = currTranslation;
|
||||
}
|
||||
|
||||
const Entity joint = target->getJointsAt(animationStatus.skinIndex)[animationStatus.boneIndex];
|
||||
|
||||
// now calculate the fade out/in delta
|
||||
// if we're fading in, this will be 0.0 at the start of the fade and 1.0 at the end
|
||||
auto fadeDelta = elapsedInSecs / animationStatus.fadeInInSecs;
|
||||
|
||||
// // if we're fading out, this will be 1.0 at the start of the fade and 0.0 at the end
|
||||
if(fadeDelta > 1.0f) {
|
||||
fadeDelta = 1 - ((elapsedInSecs - animationStatus.durationInSecs - animationStatus.fadeInInSecs) / animationStatus.fadeOutInSecs);
|
||||
}
|
||||
|
||||
fadeDelta = std::clamp(fadeDelta, 0.0f, animationStatus.maxDelta);
|
||||
|
||||
auto jointTransform = mTransformManager.getInstance(joint);
|
||||
|
||||
// linearly interpolate this animation between its current (interpolated) frame and the current transform (i.e. as set by the gltf frame)
|
||||
// // if we are fading in or out, apply a delta
|
||||
if (fadeDelta >= 0.0f && fadeDelta <= 1.0f) {
|
||||
math::float3 fadeScale;
|
||||
math::quatf fadeRotation;
|
||||
math::float3 fadeTranslation;
|
||||
auto currentTransform = mTransformManager.getTransform(jointTransform);
|
||||
decomposeMatrix(currentTransform, &fadeTranslation, &fadeRotation, &fadeScale);
|
||||
newScale = mix(fadeScale, newScale, fadeDelta);
|
||||
newRotation = slerp(fadeRotation, newRotation, fadeDelta);
|
||||
newTranslation = mix(fadeTranslation, newTranslation, fadeDelta);
|
||||
}
|
||||
|
||||
mTransformManager.setTransform(jointTransform, composeMatrix(newTranslation, newRotation, newScale));
|
||||
|
||||
animator->updateBoneMatrices();
|
||||
|
||||
if (animationStatus.loop && elapsedInSecs >= (animationStatus.durationInSecs + animationStatus.fadeInInSecs + animationStatus.fadeOutInSecs))
|
||||
{
|
||||
animationStatus.start = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
#include <chrono>
|
||||
#include <variant>
|
||||
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
void GltfAnimationComponentManager::addAnimationComponent(FilamentInstance *target) {
|
||||
if(!hasComponent(target->getRoot())) {
|
||||
EntityInstanceBase::Type componentInstance = addComponent(target->getRoot());
|
||||
this->elementAt<0>(componentInstance) = { target };
|
||||
}
|
||||
}
|
||||
|
||||
void GltfAnimationComponentManager::removeAnimationComponent(FilamentInstance *target) {
|
||||
if(hasComponent(target->getRoot())) {
|
||||
removeComponent(target->getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
void GltfAnimationComponentManager::update() {
|
||||
TRACE("Updating with %d components", getComponentCount());
|
||||
for (auto it = begin(); it < end(); it++)
|
||||
{
|
||||
const auto &entity = getEntity(it);
|
||||
|
||||
auto componentInstance = getInstance(entity);
|
||||
auto &animationComponent = elementAt<0>(componentInstance);
|
||||
|
||||
auto target = animationComponent.target;
|
||||
auto animator = target->getAnimator();
|
||||
auto &gltfAnimations = animationComponent.animations;
|
||||
|
||||
for (int i = ((int)gltfAnimations.size()) - 1; i >= 0; i--)
|
||||
{
|
||||
auto now = high_resolution_clock::now();
|
||||
|
||||
auto animationStatus = gltfAnimations[i];
|
||||
|
||||
auto elapsedInSecs = animationStatus.startOffset + float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count()) / 1000.0f;
|
||||
|
||||
if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
||||
{
|
||||
animator->applyAnimation(animationStatus.index, animationStatus.durationInSecs - 0.001);
|
||||
animator->updateBoneMatrices();
|
||||
gltfAnimations.erase(gltfAnimations.begin() + i);
|
||||
animationComponent.fadeGltfAnimationIndex = -1;
|
||||
continue;
|
||||
}
|
||||
animator->applyAnimation(animationStatus.index, elapsedInSecs);
|
||||
|
||||
if (animationComponent.fadeGltfAnimationIndex != -1 && elapsedInSecs < animationComponent.fadeDuration)
|
||||
{
|
||||
// cross-fade
|
||||
auto fadeFromTime = animationComponent.fadeOutAnimationStart + elapsedInSecs;
|
||||
auto alpha = elapsedInSecs / animationComponent.fadeDuration;
|
||||
animator->applyCrossFade(animationComponent.fadeGltfAnimationIndex, fadeFromTime, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
animator->updateBoneMatrices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void AnimationComponentManager::addGltfAnimationComponent(FilamentInstance *target) {
|
||||
// if(!hasComponent(target->getRoot())) {
|
||||
// EntityInstanceBase::Type componentInstance;
|
||||
// componentInstance = addComponent(instance->getRoot());
|
||||
// this->elementAt<0>(componentInstance) = GltfAnimationComponent animationComponent { target };
|
||||
// }
|
||||
// }
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // auto entity = std::get<Entity>(target);
|
||||
// // if(!hasComponent(entity)) {
|
||||
// // componentInstance = addComponent(entity);
|
||||
// // this->elementAt<0>(componentInstance) = animationComponent;
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
|
||||
// void AnimationComponentManager::removeAnimationComponent(std::variant<FilamentInstance *, Entity> target)
|
||||
// {
|
||||
// AnimationComponent animationComponent;
|
||||
// animationComponent.target = target;
|
||||
// EntityInstanceBase::Type componentInstance;
|
||||
// if (std::holds_alternative<FilamentInstance *>(target))
|
||||
// {
|
||||
// auto instance = std::get<FilamentInstance *>(target);
|
||||
// if(hasComponent(instance->getRoot())) {
|
||||
// removeComponent(instance->getRoot());
|
||||
// }
|
||||
// } else {
|
||||
// auto entity = std::get<Entity>(target);
|
||||
// if(hasComponent(entity)) {
|
||||
// removeComponent(entity);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// void AnimationComponentManager::update()
|
||||
// {
|
||||
|
||||
// for (auto it = begin(); it < end(); it++)
|
||||
// {
|
||||
// const auto &entity = getEntity(it);
|
||||
|
||||
// auto componentInstance = getInstance(entity);
|
||||
// auto &animationComponent = elementAt<0>(componentInstance);
|
||||
|
||||
// auto &morphAnimations = animationComponent.morphAnimations;
|
||||
|
||||
// if (std::holds_alternative<FilamentInstance *>(animationComponent.target))
|
||||
// {
|
||||
// auto target = std::get<FilamentInstance *>(animationComponent.target);
|
||||
// auto animator = target->getAnimator();
|
||||
// auto &gltfAnimations = animationComponent.gltfAnimations;
|
||||
// auto &boneAnimations = animationComponent.boneAnimations;
|
||||
|
||||
// if(gltfAnimations.size() > 0) {
|
||||
// for (int i = ((int)gltfAnimations.size()) - 1; i >= 0; i--)
|
||||
// {
|
||||
// auto now = high_resolution_clock::now();
|
||||
|
||||
// auto animationStatus = animationComponent.gltfAnimations[i];
|
||||
|
||||
// auto elapsedInSecs = animationStatus.startOffset + float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count()) / 1000.0f;
|
||||
|
||||
// if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
||||
// {
|
||||
// animator->applyAnimation(animationStatus.index, animationStatus.durationInSecs - 0.001);
|
||||
// animator->updateBoneMatrices();
|
||||
// gltfAnimations.erase(gltfAnimations.begin() + i);
|
||||
// animationComponent.fadeGltfAnimationIndex = -1;
|
||||
// continue;
|
||||
// }
|
||||
// animator->applyAnimation(animationStatus.index, elapsedInSecs);
|
||||
|
||||
// if (animationComponent.fadeGltfAnimationIndex != -1 && elapsedInSecs < animationComponent.fadeDuration)
|
||||
// {
|
||||
// // cross-fade
|
||||
// auto fadeFromTime = animationComponent.fadeOutAnimationStart + elapsedInSecs;
|
||||
// auto alpha = elapsedInSecs / animationComponent.fadeDuration;
|
||||
// animator->applyCrossFade(animationComponent.fadeGltfAnimationIndex, fadeFromTime, alpha);
|
||||
// }
|
||||
// }
|
||||
|
||||
// animator->updateBoneMatrices();
|
||||
// }
|
||||
|
||||
// ///
|
||||
// /// When fading in/out, interpolate between the "current" transform (which has possibly been set by the glTF animation loop above)
|
||||
// /// and the first (for fading in) or last (for fading out) frame.
|
||||
// ///
|
||||
// for (int i = (int)boneAnimations.size() - 1; i >= 0; i--)
|
||||
// {
|
||||
// auto animationStatus = boneAnimations[i];
|
||||
|
||||
// auto now = high_resolution_clock::now();
|
||||
|
||||
// auto elapsedInMillis = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count());
|
||||
// auto elapsedInSecs = elapsedInMillis / 1000.0f;
|
||||
|
||||
// // if we're not looping and the amount of time elapsed is greater than the animation duration plus the fade-in/out buffer,
|
||||
// // then the animation is completed and we can delete it
|
||||
// if (elapsedInSecs >= (animationStatus.durationInSecs + animationStatus.fadeInInSecs + animationStatus.fadeOutInSecs))
|
||||
// {
|
||||
// if(!animationStatus.loop) {
|
||||
// boneAnimations.erase(boneAnimations.begin() + i);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // if we're fading in, treat elapsedFrames is zero (and fading out, treat elapsedFrames as lengthInFrames)
|
||||
// float elapsedInFrames = (elapsedInMillis - (1000 * animationStatus.fadeInInSecs)) / animationStatus.frameLengthInMs;
|
||||
// int currFrame = std::floor(elapsedInFrames);
|
||||
// int nextFrame = currFrame;
|
||||
|
||||
// // offset from the end if reverse
|
||||
// if (animationStatus.reverse)
|
||||
// {
|
||||
// currFrame = animationStatus.lengthInFrames - currFrame;
|
||||
// if (currFrame > 0)
|
||||
// {
|
||||
// nextFrame = currFrame - 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// nextFrame = 0;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (currFrame < animationStatus.lengthInFrames - 1)
|
||||
// {
|
||||
// nextFrame = currFrame + 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// nextFrame = currFrame;
|
||||
// }
|
||||
// }
|
||||
// currFrame = std::clamp(currFrame, 0, animationStatus.lengthInFrames - 1);
|
||||
// nextFrame = std::clamp(nextFrame, 0, animationStatus.lengthInFrames - 1);
|
||||
|
||||
// float frameDelta = elapsedInFrames - currFrame;
|
||||
|
||||
// // linearly interpolate this animation between its last/current frames
|
||||
// // this is to avoid jerky animations when the animation framerate is slower than our tick rate
|
||||
|
||||
// math::float3 currScale, newScale;
|
||||
// math::quatf currRotation, newRotation;
|
||||
// math::float3 currTranslation, newTranslation;
|
||||
// math::mat4f curr = animationStatus.frameData[currFrame];
|
||||
// decomposeMatrix(curr, &currTranslation, &currRotation, &currScale);
|
||||
|
||||
// if(frameDelta > 0) {
|
||||
// math::mat4f next = animationStatus.frameData[nextFrame];
|
||||
// decomposeMatrix(next, &newTranslation, &newRotation, &newScale);
|
||||
// newScale = mix(currScale, newScale, frameDelta);
|
||||
// newRotation = slerp(currRotation, newRotation, frameDelta);
|
||||
// newTranslation = mix(currTranslation, newTranslation, frameDelta);
|
||||
// } else {
|
||||
// newScale = currScale;
|
||||
// newRotation = currRotation;
|
||||
// newTranslation = currTranslation;
|
||||
// }
|
||||
|
||||
// const Entity joint = target->getJointsAt(animationStatus.skinIndex)[animationStatus.boneIndex];
|
||||
|
||||
// // now calculate the fade out/in delta
|
||||
// // if we're fading in, this will be 0.0 at the start of the fade and 1.0 at the end
|
||||
// auto fadeDelta = elapsedInSecs / animationStatus.fadeInInSecs;
|
||||
|
||||
// // // if we're fading out, this will be 1.0 at the start of the fade and 0.0 at the end
|
||||
// if(fadeDelta > 1.0f) {
|
||||
// fadeDelta = 1 - ((elapsedInSecs - animationStatus.durationInSecs - animationStatus.fadeInInSecs) / animationStatus.fadeOutInSecs);
|
||||
// }
|
||||
|
||||
// fadeDelta = std::clamp(fadeDelta, 0.0f, animationStatus.maxDelta);
|
||||
|
||||
// auto jointTransform = _transformManager.getInstance(joint);
|
||||
|
||||
// // linearly interpolate this animation between its current (interpolated) frame and the current transform (i.e. as set by the gltf frame)
|
||||
// // // if we are fading in or out, apply a delta
|
||||
// if (fadeDelta >= 0.0f && fadeDelta <= 1.0f) {
|
||||
// math::float3 fadeScale;
|
||||
// math::quatf fadeRotation;
|
||||
// math::float3 fadeTranslation;
|
||||
// auto currentTransform = _transformManager.getTransform(jointTransform);
|
||||
// decomposeMatrix(currentTransform, &fadeTranslation, &fadeRotation, &fadeScale);
|
||||
// newScale = mix(fadeScale, newScale, fadeDelta);
|
||||
// newRotation = slerp(fadeRotation, newRotation, fadeDelta);
|
||||
// newTranslation = mix(fadeTranslation, newTranslation, fadeDelta);
|
||||
// }
|
||||
|
||||
// _transformManager.setTransform(jointTransform, composeMatrix(newTranslation, newRotation, newScale));
|
||||
|
||||
// animator->updateBoneMatrices();
|
||||
|
||||
// if (animationStatus.loop && elapsedInSecs >= (animationStatus.durationInSecs + animationStatus.fadeInInSecs + animationStatus.fadeOutInSecs))
|
||||
// {
|
||||
// animationStatus.start = now;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for (int i = (int)morphAnimations.size() - 1; i >= 0; i--)
|
||||
// {
|
||||
|
||||
// auto now = high_resolution_clock::now();
|
||||
|
||||
// auto animationStatus = morphAnimations[i];
|
||||
|
||||
// auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count()) / 1000.0f;
|
||||
|
||||
// if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
||||
// {
|
||||
// morphAnimations.erase(morphAnimations.begin() + i);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// int frameNumber = static_cast<int>(elapsedInSecs * 1000.0f / animationStatus.frameLengthInMs) % animationStatus.lengthInFrames;
|
||||
// // offset from the end if reverse
|
||||
// if (animationStatus.reverse)
|
||||
// {
|
||||
// frameNumber = animationStatus.lengthInFrames - frameNumber;
|
||||
// }
|
||||
// auto baseOffset = frameNumber * animationStatus.morphIndices.size();
|
||||
// for (int i = 0; i < animationStatus.morphIndices.size(); i++)
|
||||
// {
|
||||
// auto morphIndex = animationStatus.morphIndices[i];
|
||||
// // set the weights appropriately
|
||||
// _renderableManager.setMorphWeights(
|
||||
// _renderableManager.getInstance(animationStatus.meshTarget),
|
||||
// animationStatus.frameData.data() + baseOffset + i,
|
||||
// 1,
|
||||
// morphIndex);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <chrono>
|
||||
#include <variant>
|
||||
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace thermion
|
||||
{
|
||||
|
||||
void MorphAnimationComponentManager::addAnimationComponent(utils::Entity target) {
|
||||
if(!hasComponent(target)) {
|
||||
EntityInstanceBase::Type componentInstance = addComponent(target);
|
||||
this->elementAt<0>(componentInstance) = MorphAnimationComponent { };
|
||||
}
|
||||
}
|
||||
|
||||
void MorphAnimationComponentManager::removeAnimationComponent(utils::Entity target) {
|
||||
if(hasComponent(target)) {
|
||||
removeComponent(target);
|
||||
}
|
||||
}
|
||||
|
||||
void MorphAnimationComponentManager::update() {
|
||||
TRACE("Updating %d morph animation components", getComponentCount());
|
||||
for (auto it = begin(); it < end(); it++)
|
||||
{
|
||||
const auto &entity = getEntity(it);
|
||||
|
||||
auto componentInstance = getInstance(entity);
|
||||
|
||||
auto &animationComponent = elementAt<0>(componentInstance);
|
||||
auto &animations = animationComponent.animations;
|
||||
|
||||
TRACE("Component has %d animations", animations.size());
|
||||
|
||||
for (int i = (int)animations.size() - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
auto now = high_resolution_clock::now();
|
||||
|
||||
auto &animation = animationComponent.animations[i];
|
||||
|
||||
auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animation.start).count()) / 1000.0f;
|
||||
|
||||
if (!animation.loop && elapsedInSecs >= animation.durationInSecs)
|
||||
{
|
||||
animations.erase(animations.begin() + i);
|
||||
TRACE("Animation %d completed", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
int frameNumber = static_cast<int>(elapsedInSecs * 1000.0f / animation.frameLengthInMs) % animation.lengthInFrames;
|
||||
// offset from the end if reverse
|
||||
if (animation.reverse)
|
||||
{
|
||||
frameNumber = animation.lengthInFrames - frameNumber;
|
||||
}
|
||||
|
||||
auto baseOffset = frameNumber * animation.morphIndices.size();
|
||||
for (int i = 0; i < animation.morphIndices.size(); i++)
|
||||
{
|
||||
auto morphIndex = animation.morphIndices[i];
|
||||
auto renderableInstance = mRenderableManager.getInstance(entity);
|
||||
|
||||
mRenderableManager.setMorphWeights(
|
||||
renderableInstance,
|
||||
animation.frameData.data() + baseOffset + i,
|
||||
1,
|
||||
morphIndex);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "Log.hpp"
|
||||
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "components/AnimationComponentManager.hpp"
|
||||
#include "scene/AnimationManager.hpp"
|
||||
#include "scene/SceneAsset.hpp"
|
||||
#include "scene/GltfSceneAssetInstance.hpp"
|
||||
@@ -25,12 +27,9 @@ namespace thermion
|
||||
{
|
||||
auto &transformManager = _engine->getTransformManager();
|
||||
auto &renderableManager = _engine->getRenderableManager();
|
||||
_animationComponentManager = std::make_unique<AnimationComponentManager>(transformManager, renderableManager);
|
||||
}
|
||||
|
||||
AnimationManager::~AnimationManager()
|
||||
{
|
||||
_animationComponentManager = std::nullptr_t();
|
||||
_gltfAnimationComponentManager = std::make_unique<GltfAnimationComponentManager>(transformManager, renderableManager);
|
||||
_morphAnimationComponentManager = std::make_unique<MorphAnimationComponentManager>(transformManager, renderableManager);
|
||||
_boneAnimationComponentManager = std::make_unique<BoneAnimationComponentManager>(transformManager, renderableManager);
|
||||
}
|
||||
|
||||
bool AnimationManager::setMorphAnimationBuffer(
|
||||
@@ -41,16 +40,20 @@ namespace thermion
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
{
|
||||
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
if (!_animationComponentManager->hasComponent(entity))
|
||||
if (!_morphAnimationComponentManager->hasComponent(entity))
|
||||
{
|
||||
_animationComponentManager->addAnimationComponent(entity);
|
||||
_morphAnimationComponentManager->addAnimationComponent(entity);
|
||||
}
|
||||
|
||||
auto animationComponentInstance = _morphAnimationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _morphAnimationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.animations;
|
||||
|
||||
MorphAnimation morphAnimation;
|
||||
|
||||
morphAnimation.meshTarget = entity;
|
||||
morphAnimation.frameData.clear();
|
||||
morphAnimation.frameData.insert(
|
||||
morphAnimation.frameData.begin(),
|
||||
@@ -65,15 +68,12 @@ namespace thermion
|
||||
morphAnimation.durationInSecs = (frameLengthInMs * numFrames) / 1000.0f;
|
||||
|
||||
morphAnimation.start = high_resolution_clock::now();
|
||||
morphAnimation.lengthInFrames = static_cast<int>(
|
||||
morphAnimation.durationInSecs * 1000.0f /
|
||||
frameLengthInMs);
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.morphAnimations;
|
||||
morphAnimation.lengthInFrames = numFrames;
|
||||
|
||||
morphAnimations.emplace_back(morphAnimation);
|
||||
|
||||
auto& foo = morphAnimations[morphAnimations.size() - 1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,9 +82,9 @@ namespace thermion
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.morphAnimations;
|
||||
auto animationComponentInstance = _morphAnimationComponentManager->getInstance(entity);
|
||||
auto &animationComponent = _morphAnimationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &morphAnimations = animationComponent.animations;
|
||||
morphAnimations.clear();
|
||||
}
|
||||
|
||||
@@ -309,17 +309,17 @@ namespace thermion
|
||||
animation.fadeInInSecs = fadeInInSecs;
|
||||
animation.maxDelta = maxDelta;
|
||||
animation.skinIndex = skinIndex;
|
||||
if (!_animationComponentManager->hasComponent(instance->getInstance()->getRoot()))
|
||||
if (!_boneAnimationComponentManager->hasComponent(instance->getInstance()->getRoot()))
|
||||
{
|
||||
Log("ERROR: specified entity is not animatable (has no animation component attached).");
|
||||
return false;
|
||||
}
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getInstance()->getRoot());
|
||||
auto animationComponentInstance = _boneAnimationComponentManager->getInstance(instance->getInstance()->getRoot());
|
||||
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &boneAnimations = animationComponent.boneAnimations;
|
||||
auto &animationComponent = _boneAnimationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
// auto &boneAnimations = animationComponent.boneAnimations;
|
||||
|
||||
boneAnimations.emplace_back(animation);
|
||||
// boneAnimations.emplace_back(animation);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -334,27 +334,30 @@ namespace thermion
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_animationComponentManager->hasComponent(instance->getEntity()))
|
||||
if (!_gltfAnimationComponentManager->hasComponent(instance->getEntity()))
|
||||
{
|
||||
_gltfAnimationComponentManager->addComponent(instance->getEntity());
|
||||
Log("ERROR: specified entity is not animatable (has no animation component attached).");
|
||||
return;
|
||||
}
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getEntity());
|
||||
auto animationComponentInstance = _gltfAnimationComponentManager->getInstance(instance->getEntity());
|
||||
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto &animationComponent = _gltfAnimationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
|
||||
animationComponent.target = instance->getInstance();
|
||||
|
||||
if (replaceActive)
|
||||
{
|
||||
if (animationComponent.gltfAnimations.size() > 0)
|
||||
if (animationComponent.animations.size() > 0)
|
||||
{
|
||||
auto &last = animationComponent.gltfAnimations.back();
|
||||
auto &last = animationComponent.animations.back();
|
||||
animationComponent.fadeGltfAnimationIndex = last.index;
|
||||
animationComponent.fadeDuration = crossfade;
|
||||
auto now = high_resolution_clock::now();
|
||||
auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - last.start).count()) / 1000.0f;
|
||||
animationComponent.fadeOutAnimationStart = elapsedInSecs;
|
||||
animationComponent.gltfAnimations.clear();
|
||||
animationComponent.animations.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -384,9 +387,9 @@ namespace thermion
|
||||
bool found = false;
|
||||
|
||||
// don't play the animation if it's already running
|
||||
for (int i = 0; i < animationComponent.gltfAnimations.size(); i++)
|
||||
for (int i = 0; i < animationComponent.animations.size(); i++)
|
||||
{
|
||||
if (animationComponent.gltfAnimations[i].index == index)
|
||||
if (animationComponent.animations[i].index == index)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
@@ -394,22 +397,22 @@ namespace thermion
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
animationComponent.gltfAnimations.push_back(animation);
|
||||
animationComponent.animations.push_back(animation);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationManager::stopGltfAnimation(GltfSceneAssetInstance *instance, int index)
|
||||
{
|
||||
|
||||
auto animationComponentInstance = _animationComponentManager->getInstance(instance->getEntity());
|
||||
auto &animationComponent = _animationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
auto animationComponentInstance = _gltfAnimationComponentManager->getInstance(instance->getEntity());
|
||||
auto &animationComponent = _gltfAnimationComponentManager->elementAt<0>(animationComponentInstance);
|
||||
|
||||
auto erased = std::remove_if(animationComponent.gltfAnimations.begin(),
|
||||
animationComponent.gltfAnimations.end(),
|
||||
auto erased = std::remove_if(animationComponent.animations.begin(),
|
||||
animationComponent.animations.end(),
|
||||
[=](GltfAnimation &anim)
|
||||
{ return anim.index == index; });
|
||||
animationComponent.gltfAnimations.erase(erased,
|
||||
animationComponent.gltfAnimations.end());
|
||||
animationComponent.animations.erase(erased,
|
||||
animationComponent.animations.end());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -417,6 +420,7 @@ namespace thermion
|
||||
{
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
auto renderableInstance = rm.getInstance(entity);
|
||||
|
||||
rm.setMorphWeights(
|
||||
renderableInstance,
|
||||
weights,
|
||||
@@ -477,7 +481,9 @@ namespace thermion
|
||||
void AnimationManager::update(uint64_t frameTimeInNanos)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
_animationComponentManager->update();
|
||||
_gltfAnimationComponentManager->update();
|
||||
_morphAnimationComponentManager->update();
|
||||
_boneAnimationComponentManager->update();
|
||||
}
|
||||
|
||||
math::mat4f AnimationManager::getInverseBindMatrix(GltfSceneAssetInstance *instance, int skinIndex, int boneIndex)
|
||||
@@ -507,15 +513,37 @@ namespace thermion
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnimationManager::addAnimationComponent(EntityId entity)
|
||||
bool AnimationManager::addGltfAnimationComponent(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
_animationComponentManager->addAnimationComponent(utils::Entity::import(entity));
|
||||
_gltfAnimationComponentManager->addAnimationComponent(instance->getInstance());
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::removeAnimationComponent(EntityId entity)
|
||||
void AnimationManager::removeGltfAnimationComponent(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
_animationComponentManager->removeComponent(utils::Entity::import(entity));
|
||||
_gltfAnimationComponentManager->removeAnimationComponent(instance->getInstance());
|
||||
}
|
||||
|
||||
bool AnimationManager::addBoneAnimationComponent(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
_boneAnimationComponentManager->addAnimationComponent(instance->getInstance());
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::removeBoneAnimationComponent(GltfSceneAssetInstance *instance)
|
||||
{
|
||||
_boneAnimationComponentManager->removeAnimationComponent(instance->getInstance());
|
||||
}
|
||||
|
||||
bool AnimationManager::addMorphAnimationComponent(utils::Entity entity)
|
||||
{
|
||||
_morphAnimationComponentManager->addAnimationComponent(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnimationManager::removeMorphAnimationComponent(utils::Entity entity)
|
||||
{
|
||||
_morphAnimationComponentManager->removeAnimationComponent(entity);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user