add reverse animation and stopAnimation bindings for android

This commit is contained in:
Nick Fisher
2022-09-11 18:55:29 +10:00
parent d199bc3aee
commit b48dd130be
7 changed files with 53 additions and 35 deletions

View File

@@ -69,7 +69,8 @@ interface FilamentInterop : Library {
fun get_animation_count(asset:Pointer) : Int; fun get_animation_count(asset:Pointer) : Int;
fun get_animation_name(asset:Pointer, outPtr:Pointer, index:Int); fun get_animation_name(asset:Pointer, outPtr:Pointer, index:Int);
fun play_animation(asset:Pointer, index:Int, loop:Boolean); fun play_animation(asset:Pointer, index:Int, loop:Boolean, reverse:Boolean);
fun stop_animation(asset:Pointer, index:Int);
fun free_pointer(ptr:Pointer, size:Int); fun free_pointer(ptr:Pointer, size:Int);

View File

@@ -172,19 +172,14 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) { when (call.method) {
"initialize" -> { "initialize" -> {
print("Initializing")
val entry = flutterPluginBinding.textureRegistry.createSurfaceTexture(); val entry = flutterPluginBinding.textureRegistry.createSurfaceTexture();
executor.execute { executor.execute {
if(_viewer != null) { if(_viewer != null) {
print("Deleting existing viewer")
_lib.filament_viewer_delete(_viewer!!); _lib.filament_viewer_delete(_viewer!!);
print("Deleted viewer")
_viewer = null; _viewer = null;
} }
if(surfaceTexture != null) { if(surfaceTexture != null) {
print("Releasing existing texture")
surfaceTexture!!.release() surfaceTexture!!.release()
surfaceTexture = null; surfaceTexture = null;
} }
@@ -227,6 +222,7 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
} }
"setRendering" -> { "setRendering" -> {
_render = call.arguments as Boolean _render = call.arguments as Boolean
Log.v(TAG, "Set rendering to ${_render}")
result.success(null) result.success(null)
} }
"setFrameInterval" -> { "setFrameInterval" -> {
@@ -555,7 +551,14 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
"playAnimation" -> { "playAnimation" -> {
executor.execute { executor.execute {
val args = call.arguments as ArrayList<Any?> val args = call.arguments as ArrayList<Any?>
_lib.play_animation(Pointer(args[0] as Long), args[1] as Int, args[2] as Boolean) _lib.play_animation(Pointer(args[0] as Long), args[1] as Int, args[2] as Boolean, args[3] as Boolean)
result.success("OK")
}
}
"stopAnimation" -> {
executor.execute {
val args = call.arguments as ArrayList<Any?>
_lib.stop_animation(Pointer(args[0] as Long), args[1] as Int)
result.success("OK") result.success("OK")
} }
} }

View File

@@ -143,8 +143,8 @@ extern "C" {
((SceneAsset*)asset)->animateWeights((float*)data, numWeights, numFrames, frameRate); ((SceneAsset*)asset)->animateWeights((float*)data, numWeights, numFrames, frameRate);
} }
void play_animation(void* asset, int index, bool loop) { void play_animation(void* asset, int index, bool loop, bool reverse) {
((SceneAsset*)asset)->playAnimation(index, loop); ((SceneAsset*)asset)->playAnimation(index, loop, reverse);
} }
int get_animation_count(void* asset) { int get_animation_count(void* asset) {

View File

@@ -40,7 +40,8 @@ void apply_weights(void* asset, float* const weights, int count);
void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate); void animate_weights(void* asset, float* data, int numWeights, int numFrames, float frameRate);
void play_animation(void* asset, int index, bool loop); void play_animation(void* asset, int index, bool loop, bool reverse);
void stop_animation(void* asset, int index);
int get_animation_count(void* asset); int get_animation_count(void* asset);
@@ -63,8 +64,6 @@ void set_position(void* asset, float x, float y, float z);
void set_rotation(void* asset, float rads, float x, float y, float z); void set_rotation(void* asset, float rads, float x, float y, float z);
void stop_animation(void* asset, int index);
void set_camera_position(void* viewer, float x, float y, float z); void set_camera_position(void* viewer, float x, float y, float z);
void set_camera_rotation(void* viewer, float rads, float x, float y, float z); void set_camera_rotation(void* viewer, float rads, float x, float y, float z);

View File

@@ -34,7 +34,7 @@ SceneAsset::SceneAsset(FilamentAsset *asset, Engine *engine,
_animator = _asset->getAnimator(); _animator = _asset->getAnimator();
for (int i = 0; i < _animator->getAnimationCount(); i++) { for (int i = 0; i < _animator->getAnimationCount(); i++) {
_embeddedAnimationStatus.push_back( _embeddedAnimationStatus.push_back(
EmbeddedAnimationStatus(i, _animator->getAnimationDuration(i), false)); EmbeddedAnimationStatus(false,false));
} }
Log("Created animation buffers for %d", _embeddedAnimationStatus.size()); Log("Created animation buffers for %d", _embeddedAnimationStatus.size());
} }
@@ -105,16 +105,20 @@ void SceneAsset::updateMorphAnimation() {
} }
} }
void SceneAsset::playAnimation(int index, bool loop) { void SceneAsset::playAnimation(int index, bool loop, bool reverse) {
Log("Playing animation at index %d", index);
if (index > _animator->getAnimationCount() - 1) { if (index > _animator->getAnimationCount() - 1) {
Log("Asset does not contain an animation at index %d", index); Log("Asset does not contain an animation at index %d", index);
} else if (_embeddedAnimationStatus[index].started) {
Log("Animation already playing, call stop first.");
} else { } else {
Log("Starting animation at index %d", index); const char* name = _animator->getAnimationName(index);
_embeddedAnimationStatus[index].play = true; Log("Playing animation %d : %s", index, name);
_embeddedAnimationStatus[index].loop = loop; if (_embeddedAnimationStatus[index].started) {
Log("Animation already playing, call stop first.");
} else {
Log("Starting animation at index %d with loop : %d and reverse %d ", index, loop, reverse);
_embeddedAnimationStatus[index].play = true;
_embeddedAnimationStatus[index].loop = loop;
_embeddedAnimationStatus[index].reverse = reverse;
}
} }
} }
@@ -194,37 +198,48 @@ void SceneAsset::setTexture() {
void SceneAsset::updateEmbeddedAnimations() { void SceneAsset::updateEmbeddedAnimations() {
auto now = high_resolution_clock::now(); auto now = high_resolution_clock::now();
int animationIndex = 0;
for (auto &status : _embeddedAnimationStatus) { for (auto &status : _embeddedAnimationStatus) {
if (!status.play) { if (!status.play) {
// Log("Skipping animation %d", status.animationIndex); Log("Animation %d not playing", animationIndex);
continue; continue;
} }
duration<double> dur =
float animationLength = _animator->getAnimationDuration(animationIndex);
duration<double> elapsed =
duration_cast<duration<double>>(now - status.startedAt); duration_cast<duration<double>>(now - status.startedAt);
float animationTimeOffset = 0; float animationTimeOffset = 0;
bool finished = false; bool finished = false;
if (!status.started) { if (!status.started) {
Log("Starting");
status.started = true; status.started = true;
status.startedAt = now; status.startedAt = now;
} else if (dur.count() >= status.duration) { } else if (elapsed.count() >= animationLength) {
if (status.loop) { if (status.loop) {
status.startedAt = now; status.startedAt = now;
} else { } else {
animationTimeOffset = dur.count(); animationTimeOffset = elapsed.count();
finished = true; finished = true;
} }
} else { } else {
animationTimeOffset = dur.count(); animationTimeOffset = elapsed.count();
}
if(status.reverse) {
animationTimeOffset = _animator->getAnimationDuration(animationIndex) - animationTimeOffset;
} }
if (!finished) { if (!finished) {
_animator->applyAnimation(status.animationIndex, animationTimeOffset); _animator->applyAnimation(animationIndex, animationTimeOffset);
} else { } else {
Log("Animation %d finished", status.animationIndex); Log("Animation %d finished", animationIndex);
status.play = false; status.play = false;
status.started = false; status.started = false;
} }
animationIndex++;
} }
_animator->updateBoneMatrices(); _animator->updateBoneMatrices();

View File

@@ -53,7 +53,7 @@ namespace polyvox {
/// ///
/// Play the embedded animation (i.e. animation node embedded in the GLTF asset) under the specified index. If [loop] is true, the animation will repeat indefinitely. /// Play the embedded animation (i.e. animation node embedded in the GLTF asset) under the specified index. If [loop] is true, the animation will repeat indefinitely.
/// ///
void playAnimation(int index, bool loop); void playAnimation(int index, bool loop, bool reverse);
/// ///
/// Manually set the weights for all morph targets in the assets to the provided values. /// Manually set the weights for all morph targets in the assets to the provided values.

View File

@@ -24,7 +24,7 @@ namespace polyvox {
// 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). // 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).
// //
struct EmbeddedAnimationStatus { struct EmbeddedAnimationStatus {
EmbeddedAnimationStatus(int animationIndex, float duration, bool loop) : animationIndex(animationIndex), duration(duration), loop(loop) {} EmbeddedAnimationStatus(bool loop, bool reverse) : loop(loop), reverse(reverse) {}
// //
// A flag that is checked each frame to determine whether or not the animation should play. // A flag that is checked each frame to determine whether or not the animation should play.
@@ -35,6 +35,11 @@ namespace polyvox {
// If [play] is true, this flag will be checked when the animation is complete. If true, the animation will restart. // If [play] is true, this flag will be checked when the animation is complete. If true, the animation will restart.
// //
bool loop; bool loop;
//
// If true, the animation will be played in reverse.
//
bool reverse;
// //
// If [play] is true, this flag will be set to true when the animation is started. // If [play] is true, this flag will be set to true when the animation is started.
@@ -46,11 +51,6 @@ namespace polyvox {
// //
int animationIndex; int animationIndex;
//
// The duration of the animation (calculated from the GLTF animator).
//
float duration = 0;
// //
// The time point at which this animation was last started. // The time point at which this animation was last started.
// This is used to calculate the "animation time offset" that is passed to the Animator. // This is used to calculate the "animation time offset" that is passed to the Animator.