add manual bone transform animation

This commit is contained in:
Nick Fisher
2022-12-15 16:56:57 +08:00
parent eb705347fc
commit f50b5328db
18 changed files with 1422 additions and 500 deletions

View File

@@ -38,7 +38,30 @@ void grab_end(void* viewer);
void apply_weights(void* asset, float* const weights, int count);
void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate);
void set_animation(
void* asset,
float* morphData,
int numMorphWeights,
float* boneData,
const char** boneNames,
const char** meshNames,
int numBones,
int numFrames,
float frameLengthInMs
);
void set_bone_transform(
void* asset,
const char* boneName,
const char* entityName,
float transX,
float transY,
float transZ,
float quatX,
float quatY,
float quatZ,
float quatW
);
void play_animation(void* asset, int index, bool loop, bool reverse);
void stop_animation(void* asset, int index);
@@ -47,9 +70,9 @@ int get_animation_count(void* asset);
void get_animation_name(void* asset, char* const outPtr, int index);
void get_target_name(void* asset, const char* meshName, char* const outPtr, int index );
void get_morph_target_name(void* asset, const char* meshName, char* const outPtr, int index );
int get_target_name_count(void* asset, const char* meshName);
int get_morph_target_name_count(void* asset, const char* meshName);
void remove_asset(void* viewer, void* asset);

View File

@@ -31,7 +31,7 @@ namespace polyvox {
SceneAsset(FilamentAsset* asset, Engine* engine, NameComponentManager* ncm, LoadResource loadResource, FreeResource freeResource);
~SceneAsset();
unique_ptr<vector<string>> getTargetNames(const char* meshName);
unique_ptr<vector<string>> getMorphTargetNames(const char* meshName);
unique_ptr<vector<string>> getAnimationNames();
///
@@ -57,18 +57,39 @@ namespace polyvox {
///
/// Manually set the weights for all morph targets in the assets to the provided values.
/// See [animateWeights] if you want to automatically
/// See [setAnimation] if you want to do the same across a number of frames (and extended to bone transforms).
///
void applyWeights(float* weights, int count);
void setMorphTargetWeights(float* weights, int count);
///
/// Update the asset's morph target weights every "frame" (which is an arbitrary length of time, i.e. this is not the same as a frame at the framerate of the underlying rendering framework).
/// Accordingly:
/// length(data) = numWeights * numFrames
/// total_animation_duration_in_ms = number_of_frames * frameLengthInMs
/// [data] will be copied; you should ensure this is freed after invoking this function.
/// Animates the asset's morph targets/bone transforms according to the frame weights/transforms specified in [morphData]/[boneData].
/// The duration of each "frame" is specified by [frameLengthInMs] (i.e. this is not the framerate of the renderer).
/// [morphData] is a contiguous chunk of floats whose length will be (numMorphWeights * numFrames).
/// [boneData] is a contiguous chunk of floats whose length will be (numBones * 7 * numFrames) (where 7 is 3 floats for translation, 4 for quat rotation).
/// [morphData] and [boneData] will both be copied, so remember to free these after calling this function.
///
void animateWeights(float* data, int numWeights, int numFrames, float frameLengthInMs);
void setAnimation(
float* morphData,
int numMorphWeights,
float* boneData,
const char** boneNames,
const char** meshNames,
int numBones,
int numFrames,
float frameLengthInMs
);
void setBoneTransform(
const char* boneName,
const char* meshName,
float transX,
float transY,
float transZ,
float quatX,
float quatY,
float quatZ,
float quatW
);
void transformToUnitCube();
@@ -77,6 +98,8 @@ namespace polyvox {
void setPosition(float x, float y, float z);
void setRotation(float rads, float x, float y, float z);
const utils::Entity* getCameraEntities();
@@ -93,15 +116,15 @@ namespace polyvox {
Engine* _engine = nullptr;
NameComponentManager* _ncm;
void updateMorphAnimation();
void updateRuntimeAnimation();
void updateEmbeddedAnimations();
Animator* _animator;
// animation flags;
unique_ptr<MorphAnimationStatus> _morphAnimationBuffer;
vector<EmbeddedAnimationStatus> _embeddedAnimationStatus;
unique_ptr<RuntimeAnimation> _runtimeAnimationBuffer;
vector<GLTFAnimation> _embeddedAnimationStatus;
LoadResource _loadResource;
FreeResource _freeResource;

View File

@@ -4,11 +4,14 @@
#include <memory>
#include <chrono>
#include <iostream>
#include <vector>
#include "ResourceBuffer.hpp"
namespace polyvox {
using namespace std;
using namespace std;
//
// Typedef for a function that loads a resource into a ResourceBuffer from an asset URI.
//
@@ -22,11 +25,13 @@ namespace polyvox {
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
//
// Holds the current state of a bone animation embeded in a GLTF asset.
// Currently, an instance will be constructed for every animation in an asset whenever a SceneAsset is created (and thus will persist for the lifetime of the SceneAsset).
// Holds the current state of a GLTF animation.
// Whenever a SceneAsset is created, an instance of GLTFAnimation will be created for every embedded animation.
// On each frame loop, we check if [play] is true, and if so, advance the animation to the correct frame based on [startedAt].
// The [GLTFAnimation] will persist for the lifetime of the SceneAsset.
//
struct EmbeddedAnimationStatus {
EmbeddedAnimationStatus(bool loop, bool reverse) : loop(loop), reverse(reverse) {}
struct GLTFAnimation {
GLTFAnimation(bool loop, bool reverse) : loop(loop), reverse(reverse) {}
//
// A flag that is checked each frame to determine whether or not the animation should play.
@@ -59,34 +64,64 @@ namespace polyvox {
//
time_point_t startedAt;
};
//
// Holds the current state of a morph-target animation in a GLTF asset.
// An animation created by manually passing frame data for morph weights/bone transforms.
//
struct MorphAnimationStatus {
struct RuntimeAnimation {
MorphAnimationStatus(float* data,
int numWeights,
int numFrames,
float frameLengthInMs) : numFrames(numFrames), frameLengthInMs(frameLengthInMs), numWeights(numWeights) {
size_t size = numWeights * numFrames * sizeof(float);
frameData = (float*)malloc(size);
memcpy(frameData, data, size);
RuntimeAnimation(float* morphData,
int numMorphWeights,
float* boneData,
const char** boneNames,
const char** meshNames,
int numBones,
int numFrames,
float frameLengthInMs) :
mNumFrames(numFrames),
mFrameLengthInMs(frameLengthInMs),
mNumMorphWeights(numMorphWeights),
mNumBones(numBones) {
if(numMorphWeights > 0) {
size_t morphSize = numMorphWeights * mNumFrames * sizeof(float);
mMorphFrameData = (float*)malloc(morphSize);
memcpy(mMorphFrameData, morphData, morphSize);
}
if(numBones > 0) {
size_t boneSize = numBones * numFrames * 7 * sizeof(float);
mBoneFrameData = (float*)malloc(boneSize);
memcpy(mBoneFrameData, boneData, boneSize);
}
for(int i =0; i < numBones; i++) {
mBoneNames.push_back(string(boneNames[i]));
mMeshNames.push_back(string(meshNames[i]));
}
}
~MorphAnimationStatus() {
delete(frameData);
~RuntimeAnimation() {
delete(mMorphFrameData);
delete(mBoneFrameData);
}
int frameIndex = -1;
int numFrames = -1;
float frameLengthInMs = 0;
int mNumFrames = -1;
float mFrameLengthInMs = 0;
time_point_t startTime;
float* frameData = nullptr;
int numWeights = 0;
float* mMorphFrameData = nullptr;
int mNumMorphWeights = 0;
float* mBoneFrameData = nullptr;
int mNumBones = 0;
vector<string> mBoneNames;
vector<string> mMeshNames;
};
}