Skeletal animation issue (always plays default T-pose (keyframe 0) in (looped) animations using AnimationAction.play()).
Animations are imported from an .FBX file with a skeleton and animations using the FBXLoader.
I've trimmed the AnimationClip.tracks array() to remove the first keyframe(s), but it keeps including the base keyframe 0 T-pose during animations.
I tried emptying the AnimationClip.tracks array. If I then play() the associated AnimationAction, it still sets up some pose, suggesting the problem might not lie in the AnimationClip at all, but rather in parent Action/Mixer.
I've also tried offsetting the AnimationAction using "startAt(0.0333..)". But it still adds in the base pose during play().
//setup mixer for object
scene.mixer = new THREE.AnimationMixer( scene.obj );
// actions array (quick reference)
scene.actions = [];
for (i in scene.obj.animations) {
scene.actions.push(scene.mixer.clipAction(scene.obj.animations[ i ] ));
// offset keyframe 0 (doesnt work since it still uses the keyframe 0 "T-pose" when the animation has finished playing and optionally loops)
scene.actions[i].startAt(0.0334);
// tried trimming with subClip fn, but again it'll throw in the T-pose.
subClip(scene.actions[3].getClip(), 0.03333333432674409 /* 30 fps: skip first frame # 0.03333333432674408 */, 2);
// emptying the tracks array also doesnt work, since its still setting bones when I play/stop the AnimationAction.
scene.actions[3].getClip().tracks = [];
scene.actions[3].getClip().resetDuration();
}
function subClip(clip, start, end) {
for (i in clip.tracks) {
var track = clip.tracks[i];
// (we depend on internal behaviour of trim() which uses Array.slice,
// and doesn't modify the original array).
clip.tracks[i].trim(start, end);
// Once trim has been called, our track now has its own copies of
// times/values, and no shared data. It's now safe to modify in-place,
// which shift() does.
clip.tracks[i].shift(-start);
}
// after modifying (key)frames, reset duration to new length
clip.resetDuration();
}
I expect none of the keyframe 0 data to be used during animations. Especially on loop: they quite visibly stutter. (because of the jump in position + strange interpolation to the next pose).
Solved this by exporting all animations into one large model file instead of a seperate file for every animation. Afterwards you can manually cut them up into seperate clips and it'll work just fine.
Related
This question builds on the (correct) answer provided to this. I simply haven't been able to get any further..
With the help of an interpolator function, d3.js's tween allows smooth graphical transition between existing and new (ie to be set) DOM element values. At the simplest level, for a given animation we have a target element, an start state, an end state, a transition, a tween function and an interpolator.
Now, say I want every so often to programmatically update the contents of an input (text field) element. The value to be entered is non-interpolable (either the text is submitted, or it is not. There is no in-between state). In providing a closure (allowing for text retrieval at the scheduled transition time), tween would seem to be a good vehicle for the updates. Either I replace the interpolator with a fixed value, ensure the start and end values are identical, or find some other way of forcing it to fire at t=1. That's the theory..
To this end, in my case each property (not value) is modified in it's own update call, into which are passed transition, element index and parent element selection.
First cut:
an outer, 'governing' transition with delay values staggered using a multiple of the current element's index
playback_transition = d3.transition()
.delay(function(d, i, j) {
return (time_interval * i);
})
.duration(function() {
return 1; // the minimum
});
within a call to playback_transition.each() pass the transition as a parameter to a dependent animation by means of an update() interface
within this dependent animation, apply the transition and tween to the current element(s):
input // a UI dialog element
.transition()
.tween(i.toString(), setChordname( waveplot.chordname ));
Where:
function setChordname(newValue) {
return function() {
var i = newValue; // a string
return function(t) {
this.value = i;
inputChanged.call(this);
};
};
};
and
function inputChanged() {
if (!this.value) return;
try {
var chord = chordify.chordObjFromChordName(this.value);
purge(); // rid display of superceded elements
plotChord(chord, options); // calculate & draw chord using new input property
} catch (e) {
console.log(e.toString());
}
}
PROBLEM
While setChordname always fires (each chord is in turn correctly found and it's value stored), of the scheduled returned functions, only the first fires and results in display of the associated waveform. For all subsequent return function occurrences, it is as if they had never been scheduled.
From the display:
direct user update to the input field still works fine
only the first of setChordname's return functions fire, but, for this initial chord, carries right through, correctly displaying the cluster of associated chord and note waves.
From this, we can say that the problem has nothing to do with the integrity of the waveplotting functions.
From the console
transitions are accumulating correctly.
chord supply is all good
associated (ie initial) tween fires at t=1. (specifically, tween appears to accept omission of an interpolator function).
looking at the output of transition.toSource(), though the associated outer index increases by single figure leaps, tween itself is always paired with an empty pair of curly brackets.
transition = [[{__transition__:{8:{tween:{}, time:1407355314749, eas..
For the moment, apart from this and the initial execution, the tween factory return function behaviour is a mystery.
From Experiment
Neither of the following have any impact:
Extending the period before the initial transition takes effect
Extending (by a multiple) each staggered transition delay
Furthermore
the same transition configuration used in a different scenario works fine.
These seem to eliminate timing issues as a possible cause, leaving the focus more on the integrity of the tween setup, or conditions surrounding waveplot append/remove.
Afraid it might be interfering with input property text submission via the tween, I also tried disabling a parallel event listener (listening for 'change' events, triggering a call to inputChanged()). Apart from no longer being able to enter own chordnames by hand, no impact.
In addition to 'change', I tried out a variety of event.types ('submit', 'input', 'click' etc). No improvement.
The single most important clue is (to my mind) that only the first setChordname() return function is executed. This suggests that some fundamental rule of tween usage is being breached. The most likely candidate seems to be that the return value of tween **must* be an interpolator.
3 related questions, glad of answers to any:
Anything blatently wrong in this approach?
For a shared transition scenario such as this, do you see a better approach to transitioning a non-interpolable (and normally user-supplied) input property than using tween ?
Provided they are staggered in time, multiple transitions may be scheduled on the same element - but what about multiple tweens? Here, as the staggered transition/tween combos are operating on only one element, they seem likely to be passed identical data (d) and index(i) in every call. Impact?
I'm now able to answer my own question. Don't be put off by the initial couple of paragraphs: there are a couple of valuable lessons further down..
Ok, there were one or two trivial DOM-to-d3 reworking issues in my adoption of the original code. Moreover, an extra returned function construct managed to find it's way into this:
Was:
function setChordname(newValue) {
return function() { <--- Nasty..
var i = newValue;
return function(t) {
this.value = i;
inputChanged.call(this);
};
};
};
Should have been:
function setChordname(newValue) {
var i = newValue;
return function(t) {
this.value = i;
inputChanged.call(this);
};
};
The fundamental problem, however, was that the transition -passed in as a parameter to an update() function- seems in this case to have been blocked or ignored.
Originally (as documented in the question) defined as:
input // a UI dialog element
.transition()
.tween(i.toString(), setChordname( waveplot.chordname ));
..but should have been defined as:
transition
.select("#chordinput") // id attribute of the input element
.tween(i.toString(), setChordname( waveplot.chordname ));
My guess is that the first version tries to create a new transition (with no delay or duration defined), whereas the second uses the transition passed in through the update() interface.
Strange is that:
what worked for another dependent animation did not for this.
the staggered delays and their associated durations were nevertheless accepted by the original version, allowing me to be misled by console logs..
Just to round this topic off, I can point out the the following (event-based) approach seems to work just as well as the tween variant with non-interpolable values documented above. I can switch freely between the two with no apparent difference in the resulting animations:
transition
.select("#chordinput") // id attribute of the input element
.each("start", setChordname( waveplot.chordname ));
Thug
I am using C++11 with GNU tool chain with gtkmm3, on Ubuntu 12.04 LTS 32 bit.
I have been playing wtih some of the examples for gtkmm3 in Programming with gtkmm 3.
Based on 17.2.1.Example there, I inherited from Gtk::DrawingArea (MyDrawingArea here) and overrode the on_draw() event handler as follows:
MyDrawingArea.hpp
...
protected:
bool on_draw ( const Cairo::RefPtr<Cairo::Context>& cr ) override;
MyDrawingArea.cpp
bool MyDrawingArea::on_draw( const Cairo::RefPtr<Cairo::Context>& cr )
{
Gtk::Allocation allocation = get_allocation( );
const int width = allocation.get_width( );
const int height = allocation.get_height( );
int coord1{ height - 3 };
cr->set_line_width( 3.0 );
this->get_window( )->freeze_updates( );
cr->set_source_rgb( 0, 0.40, 0.60 );
cr->move_to( 0, coord1 );
cr->line_to( width, coord1 );
cr->stroke( );
cr->set_source_rgb( 1, 0.05, 1 );
cr->move_to( mXStart, coord1 );
cr->line_to( mXStart, mYAxis * 1.5 );
cr->show_text( to_string( mYAxis ) );
cr->stroke( );
mXStart += 5;
this->get_window( )->thaw_updates( );
return true;
}
My goal is to draw a simple bar graph based on a calculation I do in a little test application, the idea being that each time the on_draw() event is called, the next bar would be moved 5 units to the right on mXAxis and a vertical line would be drawn based on the new mYaxis value, which is computed based on the results of the new calculation.
When I want to repaint my graph and trigger the MyDrawingArea::on_draw() event, I call MyDrawingArea.show_all() from my application after the calculation has completed, and new x and y axes have been set.
However, this does not work as I expected: MyDrawingArea.show_all() invalidates the entire drawing window and draws from scratch: the new graph line appears in its proper place, but the previous ones are erased. I also tried MyDrawingArea.queue_draw(), which had the same effect. But I want to persist the previous graph results so I can get a profile of the calculation results, as I calculate with different values.
This implementation is also causing the bottom line on my graph (my x axis on the graph)- drawn by the first stroke() call in my code example, to be rendered anew on each call to on_draw() - although this should not be necassary since this line persists for the lifetime of MyDrawingArea - it should not be necessary to invalidate and then re-draw it on each new on_draw() event, as my code is currently doing, because I am haven't yet found a way to handle this.
I am very new to Cairo, so I'm sure I'm probably doing this completely wrong, but explicit, task-oriented documentation appears to be sparse - have not found anything that explains how to do this, although I'm sure it is quite simple.
What do I need to do to draw a new line on Gtk::DrawingArea, while persisting previous graph lines that have already been drawn on previous passes, and establish graphics elements that will persist for the lifetime of the Gtk::DrawingArea widget. Obviously using show_all() or queue_draw() and doing it all in the on_draw() event is not the way to go.
In general, you must draw the entire widget and Cairo will clip the drawing to the predefined dirty region. See also GTK reference manual for the "GtkWidget::draw" signal for performance tips:
The signal handler will get a cr with a clip region already set to the
widget's dirty region, i.e. to the area that needs repainting.
Complicated widgets that want to avoid redrawing themselves completely
can get the full extents of the clip region with
gdk_cairo_get_clip_rectangle(), or they can get a finer-grained
representation of the dirty region with
cairo_copy_clip_rectangle_list().
So you may be able to redraw only the region you want with gtk_widget_queue_draw_area().
Is there a way to continously plot changing array data? I've got a ILLinePlot to graph the line to changing data on a button event, but I would like to make it continuous.
while (true)
{
float[] RefArray = A.GetArrayForWrite();
//RefArray[0] = 100;
Shuffle<float>(ref RefArray);
Console.Write(A.ToString());
scene = new ILScene();
pc = scene.Add(new ILPlotCube());
linePlot = pc.Add(new ILLinePlot(A.T, lineColor: Color.Green));
ilPanel1.Scene = scene;
ilPanel1.Invalidate();
}
The problem I'm running into is that the loop runs, and i can see updates of the array, but the ILPanel does not update. I'm thinking maybe it's because the main loop can't be accessed due to this infinite loop, so I put it in its own thread as well, but it's still not rendering as I hoped...
As Paul pointed out, there is a more efficient attempt to do this:
private void ilPanel1_Load(object sender, EventArgs e) {
using (ILScope.Enter()) {
// create some test data
ILArray<float> A = ILMath.tosingle(ILMath.rand(1, 50));
// add a plot cube and a line plot (with markers)
ilPanel1.Scene.Add(new ILPlotCube(){
new ILLinePlot(A, markerStyle: MarkerStyle.Rectangle)
});
// register update event
ilPanel1.BeginRenderFrame += (o, args) =>
{
// use a scope for automatic memory cleanup
using (ILScope.Enter()) {
// fetch the existint line plot object
var linePlot = ilPanel1.Scene.First<ILLinePlot>();
// fetch the current positions
var posBuffer = linePlot.Line.Positions;
ILArray<float> data = posBuffer.Storage;
// add a random offset
data = data + ILMath.tosingle(ILMath.randn(1, posBuffer.DataCount) * 0.005f);
// update the positions of the line plot
linePlot.Line.Positions.Update(data);
// fit the line plot inside the plot cube limits
ilPanel1.Scene.First<ILPlotCube>().Reset();
// inform the scene to take the update
linePlot.Configure();
}
};
// start the infinite rendering loop
ilPanel1.Clock.Running = true;
}
}
Here, the full update runs inside an anonymous function, registered to BeginRenderFrame.
The scene objects are reused instead of getting recreated in every rendering frame. At the end of the update, the scene needs to know, you are done by calling Configure on the affected node or some node among its parent nodes. This prevents the scene from rendering partial updates.
Use an ILNumerics arteficial scope in order to clean up after every update. This is especially profitable once larger arrays are involved. I added a call to ilPanel1.Scene.First<ILPlotCube>().Reset() in order to rescale the limits of the plot cube to the new data content.
At the end, start the rendering loop by starting the Clock of ILPanel.
The result is a dynamic line plot, updating itself at every rendering frame.
I think you need to call Configure() after any modification of a shape or its buffers. Use the BeginRenderFrame event to do your modifications and you should not add infinitely many shapes / new scenes. It is better to reuse them!
Let me know, if you need an example...
I have an animation with about 20 frames. I need to be able to access local transforms for each bone for a given animation frame. I know how to access the bone and its local transform (a sample of the code)
Transform root, spine1;
getChildFromName(gameObj, "Jnt_Root", out root);
getChildFromName(root, "Jnt_Spine1", out spine1);
spine1.localRotation = someValue;
All of this works fine, but I don't know the values I'm getting are from which animation frame? I assume its from frame 1 (can verify using debugger but that's not the point)
The questions is how to get and set these values for a specific frame? Thanks!
Something like this should work for getting the current transforms:
AnimationState state = animation["your_animation"];
state.enabled = true;
state.normalizedTime = (1.0f/totalAnimationTime) * specificFrame;
animation.Sample();
// get all transforms of this animation, extract your root and spine from here.
Transform[] transforms = animation.gameObject.GetComponentsInChildren<Transform>();
Or if you're trying to sample while the animation is running you could do something like:
if(animation["your_animation"].normalizedTime > 0.3 && animation["your_animation"].normalizedTime < 0.5) {
//... do something at this point in time. You'll have to figure out the frame
//from the time
}
Last I checked you can't explicitly extract a particular frame. But if you know the total length of your animation (time-wise), you can move the animation to that point with something like: (1.0f/totalAnimationTime) * specificFrame; (this assumes the keyframes are uniformly spaced.)
Once stored you should be able to modify the transforms directly but I've never tried.
I'm trying to animate sprites along a path in Three.js using Tween.js by chaining the animations in order to have something like this :
----#----#----#----#----#---- etc
Every sprite has its own tween animation, and I just delay each tween animation at the beginning. Each sprite has in fact N animations along the path (that is not a straight line) and I chain them to have a loop effect.
Everything goes well if the FPS is perfectly stable, but my problem is that if at some point I have a FPS drop, the animations of the different sprites are not in sync anymore, and the space between sprites is not equal anymore. I potentially end up with something like this :
---#--#----#-#-#-----#--- etc
I was wondering if there is a better approach for this, like having only one tween animation for all the sprites, but I don't know how to introduce the offset between each sprite on many line segments.
I cannot post the exact code has it is part of a bigger app, and won't be usable as is, but it looks like this :
// create animations
for each (sprite) {
for each (segment) {
var currentAnimation = new TWEEN.Tween(sprite.position).to({
x : segment.endpoint.x,
y : segment.endpoint.y,
z : segment.endpoint.z
}, animationTime).easing(TWEEN.Easing.Linear.None);
currentAnimation.delay(delayTime * currentSpriteNumber);
previousAnimation.chain(currentAnimation);
}
lastAnimation.chain(firstAnimation);
lastAnimation.onComplete(onEachSpriteAnimationCompleted);
}
// start the animations
for each (sprite) {
spriteFirstAnimation.start();
}
// to remove the delay when each sprite animation has made one loop,
// and instantly replace the sprite at the beginning of the path
// (my paths are not closed)
var onEachSpriteAnimationCompleted = function() {
sprite.position.set(starting position);
for each (sprite animation) {
animation.delay(0);
}
}