add animation ticker inside render loop
This commit is contained in:
@@ -61,6 +61,8 @@ using namespace filament;
|
||||
using namespace filament::math;
|
||||
using namespace gltfio;
|
||||
using namespace utils;
|
||||
using namespace std::chrono;
|
||||
|
||||
|
||||
namespace filament {
|
||||
class IndirectLight;
|
||||
@@ -148,13 +150,19 @@ FilamentViewer::FilamentViewer(
|
||||
manipulator =
|
||||
Manipulator<float>::Builder().orbitHomePosition(0.0f, 0.0f, 0.0f).targetPosition(0.0f, 0.0f, 0).build(Mode::ORBIT);
|
||||
_asset = nullptr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
FilamentViewer::~FilamentViewer() {
|
||||
|
||||
}
|
||||
|
||||
void printWeights(float* weights, int numWeights) {
|
||||
for(int i =0; i < numWeights; i++) {
|
||||
// std::cout << weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
void FilamentViewer::loadResources(string relativeResourcePath) {
|
||||
const char* const* const resourceUris = _asset->getResourceUris();
|
||||
const size_t resourceUriCount = _asset->getResourceUriCount();
|
||||
@@ -186,47 +194,10 @@ void FilamentViewer::releaseSourceAssets() {
|
||||
_freeResource((void*)materialProviderResources.data, materialProviderResources.size, nullptr);
|
||||
}
|
||||
|
||||
void FilamentViewer::animateWeightsInternal(float* data, int numWeights, int length, float frameRate) {
|
||||
int frameIndex = 0;
|
||||
int numFrames = length / numWeights;
|
||||
float frameLength = 1000 / frameRate;
|
||||
|
||||
applyWeights(data, numWeights);
|
||||
auto animationStartTime = std::chrono::high_resolution_clock::now();
|
||||
while(frameIndex < numFrames) {
|
||||
duration dur = std::chrono::high_resolution_clock::now() - animationStartTime;
|
||||
int msElapsed = dur.count();
|
||||
if(msElapsed > frameLength) {
|
||||
std::cout << "frame" << frameIndex << std::endl;
|
||||
frameIndex++;
|
||||
applyWeights(data + (frameIndex * numWeights), numWeights);
|
||||
animationStartTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FilamentViewer::animateWeights(float* data, int numWeights, int length, float frameRate) {
|
||||
int numFrames = length / numWeights;
|
||||
float frameLength = 1000 / frameRate;
|
||||
|
||||
thread* t = new thread(
|
||||
[=](){
|
||||
int frameIndex = 0;
|
||||
|
||||
applyWeights(data, numWeights);
|
||||
auto animationStartTime = std::chrono::high_resolution_clock::now();
|
||||
while(frameIndex < numFrames) {
|
||||
duration dur = std::chrono::high_resolution_clock::now() - animationStartTime;
|
||||
int msElapsed = dur.count();
|
||||
if(msElapsed > frameLength) {
|
||||
frameIndex++;
|
||||
applyWeights(data + (frameIndex * numWeights), numWeights);
|
||||
animationStartTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
}
|
||||
});
|
||||
transformToUnitCube();
|
||||
morphAnimationBuffer = std::make_unique<MorphAnimationBuffer>(data, numWeights, length / numWeights, 1000 / frameRate );
|
||||
}
|
||||
|
||||
void FilamentViewer::loadGltf(const char* const uri, const char* const relativeResourcePath) {
|
||||
@@ -254,8 +225,6 @@ void FilamentViewer::loadGltf(const char* const uri, const char* const relativeR
|
||||
|
||||
transformToUnitCube();
|
||||
|
||||
startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
}
|
||||
|
||||
StringList FilamentViewer::getTargetNames(const char* meshName) {
|
||||
@@ -307,9 +276,8 @@ void FilamentViewer::animateBones() {
|
||||
}
|
||||
|
||||
void FilamentViewer::playAnimation(int index) {
|
||||
_activeAnimation = index;
|
||||
embeddedAnimationBuffer = make_unique<EmbeddedAnimationBuffer>(index, _animator->getAnimationDuration(index));
|
||||
}
|
||||
|
||||
|
||||
void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const iblPath) {
|
||||
ResourceBuffer skyboxBuffer = _loadResource(skyboxPath);
|
||||
@@ -380,23 +348,106 @@ void FilamentViewer::render() {
|
||||
manipulator->getLookAt(&eye, &target, &upward);
|
||||
|
||||
_mainCamera->lookAt(eye, target, upward);
|
||||
|
||||
if(_animator) {
|
||||
|
||||
duration dur = std::chrono::high_resolution_clock::now() - startTime;
|
||||
if (_activeAnimation >= 0 && _animator->getAnimationCount() > 0) {
|
||||
_animator->applyAnimation(_activeAnimation, dur.count() / 1000);
|
||||
_animator->updateBoneMatrices();
|
||||
}
|
||||
|
||||
if(morphAnimationBuffer) {
|
||||
updateMorphAnimation();
|
||||
}
|
||||
|
||||
if(embeddedAnimationBuffer) {
|
||||
updateEmbeddedAnimation();
|
||||
}
|
||||
|
||||
// Render the scene, unless the renderer wants to skip the frame.
|
||||
if (_renderer->beginFrame(_swapChain)) {
|
||||
_renderer->render(_view);
|
||||
_renderer->endFrame();
|
||||
} else {
|
||||
std::cout << "Skipping frame" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//void FilamentViewer::updateAnimation(AnimationBuffer animation, std::function<void(int)> moo) {
|
||||
// if(morphAnimationBuffer.frameIndex >= animation.numFrames) {
|
||||
// this.animation = null;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(animation.frameIndex == -1) {
|
||||
// animation->frameIndex++;
|
||||
// animation->lastTime = std::chrono::high_resolution_clock::now();
|
||||
// callback(); // applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
||||
// } else {
|
||||
// duration dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->lastTime;
|
||||
// float msElapsed = dur.count();
|
||||
// if(msElapsed > animation->frameLength) {
|
||||
// animation->frameIndex++;
|
||||
// animation->lastTime = std::chrono::high_resolution_clock::now();
|
||||
// callback(); // applyWeights(frameData + (frameIndex * numWeights), numWeights);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
void FilamentViewer::updateMorphAnimation() {
|
||||
|
||||
if(morphAnimationBuffer->frameIndex >= morphAnimationBuffer->numFrames) {
|
||||
morphAnimationBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if(morphAnimationBuffer->frameIndex == -1) {
|
||||
morphAnimationBuffer->frameIndex++;
|
||||
morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||
applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
||||
} else {
|
||||
duration dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->lastTime;
|
||||
float microsElapsed = dur.count();
|
||||
if(microsElapsed > (morphAnimationBuffer->frameLength * 1000000)) {
|
||||
morphAnimationBuffer->frameIndex++;
|
||||
morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||
applyWeights(morphAnimationBuffer->frameData + (morphAnimationBuffer->frameIndex * morphAnimationBuffer->numWeights), morphAnimationBuffer->numWeights);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FilamentViewer::updateEmbeddedAnimation() {
|
||||
duration<double> dur = duration_cast<duration<double>>(std::chrono::high_resolution_clock::now() - embeddedAnimationBuffer->lastTime);
|
||||
float startTime = 0;
|
||||
if(!embeddedAnimationBuffer->hasStarted) {
|
||||
embeddedAnimationBuffer->hasStarted = true;
|
||||
embeddedAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||
} else if(dur.count() >= embeddedAnimationBuffer->duration) {
|
||||
embeddedAnimationBuffer = nullptr;
|
||||
return;
|
||||
} else {
|
||||
startTime = dur.count();
|
||||
}
|
||||
|
||||
|
||||
_animator->applyAnimation(embeddedAnimationBuffer->animationIndex, startTime);
|
||||
_animator->updateBoneMatrices();
|
||||
|
||||
}
|
||||
//
|
||||
//if(morphAnimationBuffer.frameIndex >= morphAnimationBuffer.numFrames) {
|
||||
// this.morphAnimationBuffer = null;
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//if(morphAnimationBuffer.frameIndex == -1) {
|
||||
// applyWeights(morphAnimationBuffer->frameData, morphAnimationBuffer->numWeights);
|
||||
// morphAnimationBuffer->frameIndex++;
|
||||
// morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||
//} else {
|
||||
// duration dur = std::chrono::high_resolution_clock::now() - morphAnimationBuffer->lastTime;
|
||||
// float msElapsed = dur.count();
|
||||
// if(msElapsed > morphAnimationBuffer->frameLength) {
|
||||
// frameIndex++;
|
||||
// applyWeights(frameData + (frameIndex * numWeights), numWeights);
|
||||
// morphAnimationBuffer->lastTime = std::chrono::high_resolution_clock::now();
|
||||
// }
|
||||
//}
|
||||
|
||||
void FilamentViewer::updateViewportAndCameraProjection(int width, int height, float contentScaleFactor) {
|
||||
if (!_view || !_mainCamera || !manipulator) {
|
||||
return;
|
||||
|
||||
@@ -42,6 +42,8 @@ using namespace camutils;
|
||||
|
||||
namespace mimetic {
|
||||
|
||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
|
||||
|
||||
struct StringList {
|
||||
StringList(const char** strings, const int count) : strings(strings), count(count) {};
|
||||
const char** strings;
|
||||
@@ -61,7 +63,31 @@ namespace mimetic {
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
typedef std::chrono::duration<float, std::milli> duration;
|
||||
struct MorphAnimationBuffer {
|
||||
|
||||
MorphAnimationBuffer(float* frameData,
|
||||
int numWeights,
|
||||
int numFrames,
|
||||
float frameLength) : frameData(frameData), numWeights(numWeights), numFrames(numFrames), frameLength(frameLength) {
|
||||
}
|
||||
|
||||
int frameIndex = -1;
|
||||
int numFrames;
|
||||
float frameLength;
|
||||
time_point_t lastTime;
|
||||
|
||||
float* frameData;
|
||||
int numWeights;
|
||||
};
|
||||
|
||||
struct EmbeddedAnimationBuffer {
|
||||
|
||||
EmbeddedAnimationBuffer(int animationIndex, float duration) : animationIndex(animationIndex), duration(duration) {}
|
||||
bool hasStarted = false;
|
||||
int animationIndex;
|
||||
float duration = 0;
|
||||
time_point_t lastTime;
|
||||
};
|
||||
|
||||
using LoadResource = std::function<ResourceBuffer(const char* uri)>;
|
||||
using FreeResource = std::function<void * (void *mem, size_t s, void *)>;
|
||||
@@ -88,7 +114,14 @@ namespace mimetic {
|
||||
void loadResources(std::string relativeResourcePath);
|
||||
void transformToUnitCube();
|
||||
void cleanup();
|
||||
void animateWeightsInternal(float* data, int numWeights, int length, float frameRate);
|
||||
void updateMorphAnimation();
|
||||
void updateEmbeddedAnimation();
|
||||
|
||||
// animation flags;
|
||||
bool isAnimating;
|
||||
unique_ptr<MorphAnimationBuffer> morphAnimationBuffer;
|
||||
unique_ptr<EmbeddedAnimationBuffer> embeddedAnimationBuffer;
|
||||
|
||||
void* _layer;
|
||||
|
||||
LoadResource _loadResource;
|
||||
@@ -96,10 +129,6 @@ namespace mimetic {
|
||||
|
||||
ResourceBuffer materialProviderResources;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point startTime;
|
||||
|
||||
int _activeAnimation = -1;
|
||||
|
||||
Scene* _scene;
|
||||
View* _view;
|
||||
Engine* _engine;
|
||||
@@ -114,7 +143,6 @@ namespace mimetic {
|
||||
FilamentAsset* _asset = nullptr;
|
||||
NameComponentManager* _ncm;
|
||||
|
||||
|
||||
Entity _sun;
|
||||
Texture* _skyboxTexture;
|
||||
Skybox* _skybox;
|
||||
@@ -131,6 +159,7 @@ namespace mimetic {
|
||||
float _cameraFocalLength = 0.0f;
|
||||
|
||||
GPUMorphHelper* morphHelper;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -57,12 +57,14 @@ namespace gltfio {
|
||||
cgltf_mesh const *mesh = node->mesh;
|
||||
|
||||
if (mesh) {
|
||||
std::cout << "Mesh " << mesh->name << " with " << mesh->weights_count << " weights " << std::endl;
|
||||
std::cout << "Mesh " << mesh->name << " with " << mesh->weights_count << " weights and " << mesh->primitives_count << " primitives." << std::endl;
|
||||
if(strcmp(meshName, mesh->name) == 0) {
|
||||
targetMesh = mesh;
|
||||
std::cout << "Adding primitive to mesh with " << mesh->primitives_count << " primitives." << std::endl;
|
||||
for(int i = 0; i < numPrimitives; i++)
|
||||
addPrimitive(mesh, primitiveIndices[i]);
|
||||
for(int i = 0; i < numPrimitives; i++) {
|
||||
int primitiveIndex = primitiveIndices[i];
|
||||
std::cout << "Adding primitive at index " << primitiveIndex << " to morpher " << std::endl;
|
||||
addPrimitive(mesh, primitiveIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user