Three.js Skinning Animation (r74+) Functionality - three.js

With the old three.js (r72-) animation system it was possible to begin an animation at a specified time.
I did something along the lines of:
// anim being an instance of THREE.Animation
var duration = anim.data.length;
anim.currentTime = Math.floor(Math.random() * (Math.floor(duration) - 0 + 1)) + 0;
anim.play();
I have been less than successful in achieving this with the new animation system. Does anyone happen to know how to do this?

Got it. You need to update the mixer with the desired start time, not update the clip time directly. So:
// mixer being an instance of THREE.AnimationMixer
// clip being an instance of THREE.AnimationClip
var duration = clip.duration;
var start = (Math.random() * (duration - 0) + 0).toFixed(4);
clip.play();
mixer.update(start);
I have found that you must play the clip first before calling mixer.update(start);.

Related

Animate (walk) gltf clone objects from one position to another

I am working on a project where I imported a gltf humanoid that has animations. I am creating clones of the imported model to display in the scene, rather than creating a new one every time.
I have walk and idle animations for the loaded model. How can I animate the cloned in such a way that it appears like they are walking from one location to another another. For example, if the cloned model is at position (10, 20, 0) at time = 1s and it will be at position (13, 20, 0) at time = 2s, I would like it to appear that the model is walking between the positions. I read the new Animation System documentation and did a lot of searching but it didn't help.
Thanks for your help.
P.S: I cannot share the code from the project due to restrictions.
You can get the direction by subtracting both vectors and then normalizing it.
let direction = new THREE.Vector3().subVectors(destination.position, object.position).normalize();
Then in your render function update object position on each frame in that direction. Speed variable value is up to you (default 1).
object.position.x += direction.x * speed;
object.position.y += direction.y * speed;
object.position.z += direction.z * speed;
You would need a boolean value like isMoving or distance between objects to know when to start and stop.
object.position.distanceTo( destination.position );
https://threejs.org/docs/#api/en/math/Vector3.distanceTo
As for the animation I think you just want to call animation.play() on start and animation.stop() when you reach the destination.

Tooltip for individual points created using THREE.PointCloud in Autodesk forge

I followed this blog for adding tooltip for each point implemented using Three.PointCloud. I used world2Screen to get the location of individual points and tried using this
elem = document.elementFromPoint(x, y)
but continuously only get canvas as the output (and thus tooltip at a fixed position) instead at the clicked/hovered point.
Anyone who has may be implemented this and knows any work around.
Thanks in advance
According to the blog, the document.elementFromPoint() is used to check if the cursor isn’t over the canvas. If you want to capture the hit point of the mouse clicked one, your own raycaster can help in this case. For example:
var x = ((event.clientX - viewer.canvas.offsetLeft) / viewer.canvas.width) * 2 - 1;
var y = -((event.clientY - viewer.canvas.offsetTop) / viewer.canvas.height) * 2 + 1;
var vector = new THREE.Vector3(x, y, 0.5).unproject(this.camera);
this.raycaster.set(this.camera.position, vector.sub(this.camera.position).normalize());
var nodes = this.raycaster.intersectObject( this.pointCloud );
In the above code snippet, the event object is from the mouse clicking event, see here for detail: https://github.com/wallabyway/markupExt/blob/master/docs/markupExt.js#L48

GUI text is moving along with the player

The video attached shows the issue, the code controlling the ammo count, and the viewport/camera properties. I would like the ammo count to stay in place, rather than moving with oPlayer.
I'm new to Game-maker and game development in general, this is my first time trying to make a GUI, so issues in my code/room setup are to be expected.
Any and all help would be appreciated!
Video: https://youtu.be/38jZSsAxHh0
Code:
var vc = view_camera[0];
var cx = camera_get_view_x(vc);
var cy = camera_get_view_y(vc);
var cw = camera_get_view_width(vc);
draw_set_colour($000000);
draw_text(cx + (cw / 10),cy + 32, string(ARmaxclipammo) + string("/") + string(ARmaxammo));
The position of your text is set equall with the position of the camera. So if the camera moves in the room, The text will move across the screen as well.
You don't need to set the text position to follow the camera, because DrawGUI already allows that. All you need to do is to show the specific position of the text where you want to show it on screen.
So, as example in your code:
var cx = 50;
var cy = 50;
Will show it in the position of (50x, 50y), and DrawGUI already let it follow the camera.

Multiple overlapping animations on the same element in svg.js

I want to start a animation on an element while a previous animation is still active. However, calling animate() on the element queues the new animation at the end of the current animation.
For example, consider an animation where an element is being moved to a new position. Now, I also want to make it fade out when it reaches a certain position. The following queues the “once” animation at the end of the move, rather than at 80%.
rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
rect.animate(200).opacity(0);
});
How do I make the element start fading out when it reaches 80% of the move? The API seems to be designed for chaining animations rather simultaneous overlapping animations.
What you are trying to do is a bit more complicated. Unforrtunately its not possible to "hack" into the current animation and add a new animation on the fly.
However what you can do is adding a new property which should be animated:
var fx = rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
fx.opacity(0);
});
As you will notice that has its own problems because the oopacity immediately jumps to 80%. So this is not an approach which works for you.
Next try: Use the during method:
var morh = SVG.morph(
var fx = rect.animate(1000).move(100, 100)
.once(0.8, function(pos, eased) {
fx.during(function(pos, morphFn, easedPos) {
pos = (pos - 0.8) / 0.2
this.target().opacity(pos)
}
});
We just calculate the opacity ourselves

Is it possible to loop through a sprite group in three.js with a tween that ends in a different position for each sprite?

I'm confused.
I've made a group of 10 sprites and added them to a THREE.Object3D() called fireworkGroup. I have another Object3D called explode. The tween loops through the sprites changing them from their initial position to explode.position.
for ( var i = 0; i < fireworkGroup.children.length; i ++ )
{
explode.position.x =(Math.random() - 0.5)*4;
explode.position.y =4;
explode.position.z =2;
var tweenLaunch = new TWEEN.Tween(fireworkGroup.children[i].position).to(explode.position, 4000).easing( TWEEN.Easing.Quartic.In);
tweenLaunch.start();
}
The tween is moving all the sprites from their start position to the same end position. So I thought this might be because "tweenLaunch" is being overwritten with a different explode.position each time as the tween is rendered so I'm only seeing the last one created in the loop. When I refresh the page they do all move to a different position, consistent with the Math.random().
But then why do all the sprites move to the explode.position? If "tweenLaunch" is being overwritten then why is it not moving only the last sprite?
Is it possible to have a loop with a tween in it that also changes?
Many Thanks.
I've managed to work out what was wrong by reading around the subject on Stackoverflow questions and answers, looking at a great particle example by stemkoski then trial and error.
view-source:http://stemkoski.github.io/Three.js/Particles.html
I used console.log to look at explode.position that I was using as the second position in the tween. It wasn't holding the values I wanted (a different Math.random on each loop).
So I created fireworkAttributes:
fireworkAttributes = { startPosition: [], explodePosition: [], nextPosition: [] };
and then cloned the sprite position in the function that created the sprites using:
fireworkAttributes.explodePosition.push( sprite.position.clone() );
then looped it in it's own function:
for (var i = 0; i < fireworkGroup.children.length; i++)
{
fireworkAttributes.explodePosition[i].x = (Math.random() - 0.5)*4;
fireworkAttributes.explodePosition[i].y = 4;
fireworkAttributes.explodePosition[i].z = 2;
}
then changed the code in the original question to:
for ( var a = 0; a < fireworkGroup.children.length; a ++ )
{
//need to use this new object as tweening to fireworkAttributes.explodePosition[a] does not work
explodeSite.position = fireworkAttributes.explodePosition[a];
var tweenLaunch = new TWEEN.Tween(fireworkGroup.children[a].position).to(explodeSite.position, 4000).easing( TWEEN.Easing.Quartic.In);
tweenLaunch.start();
}
There may be a more elegant way to do this and I will be working to clean up the code where possible but this does work.

Resources