Updating plane vertices in animation loop

He guys, new to ThreeJS and I totally love it. I made a simple animated flag, but now I want to be able (when I scroll my website) to change the amount of vertices that are moved i.e. the intensity.

My code here:

const animate = function () {
		const time = clock.getElapsedTime();

		plane.geometry.vertices.map(vertices => {
			vertices.z = 0.42 * Math.sin(vertices.x * 2 + time);
		});

		plane.geometry.verticesNeedUpdate = true;

		requestAnimationFrame(animate);
		renderer.render(scene, camera);
	};

	animate();

I am unable to figure out how I can do this. I mean for example:

setTimeout(() => {
		plane.geometry.vertices.map(vertices => {
			vertices.z = 3.42 * Math.sin(vertices.x * 2 + clock.getElapsedTime());
		});

		plane.geometry.verticesNeedUpdate = true;
    }, 5000)

does nothing. So basically what I want to do is increase the amount in:

vertices.z = 3.42 * Math.sin(vertices.x * 2 + clock.getElapsedTime());

and after increasing it, decrease it again back to normal, depending on where the user is scrolling the website.

If I update the rotation for example it does work, but changing the above vertices code does nothing :frowning:

  1. It’s best to avoid using Geometry - wherever possible, use BufferGeometry instead.
  2. Can you please share a runnable code (or jsfiddle or codepen) that shows the issue? It’s a bit easier to find the issue this way.
1 Like

Yes I have put the code in codepen.

I will look into the “buffer geometry” but I dont understand a thing about it haha, thank you very much for your reply mjurczyk!

Are you looking for this? https://jsfiddle.net/4tre32qz/

Math.sin() returns values in the range [-1,1]. If you want to increase the range, you have to multiply them with a value > 1.

1 Like

Hey Mugen, yeah thats what I want sort off. But as you can see in my code when I change the values, nothing is updated visually.

As an example:

setTimeout(() => {
  plane.geometry.vertices.map(vertices => {
    vertices.z = 2.42 * Math.sin(vertices.x * 6 + clock.getElapsedTime());
  });
});

This does nothing. But when I do (for example):

plane.rotation.set(10, 10, 5);

then the plane does actually rotate. So yeah, increasing the plane.geometry.vertices values does nothing, while other stuff like “rotation” does work.

I took a look at BufferGeometry but I really dont understand it. I got a “plane” but after that I have no clue on how to animate it like I did in my current example. It goes above my head lol, if possible i’d rather stick to simple geometry for now :slight_smile:

Why are you doing this in setTimeout()?

Just for testing purposes :wink:

I would normally do it when triggering a scroll event which watches when certain elements come into the user his screen. When one does, I need to increase the values for i.e. 2 seconds, then decrease them again.

If you are new, the examples from the collection ( Collection of examples from discourse.threejs.org ) may help you.

Based on the example from 2019 https://hofk.de/main/discourse.threejs/2019/ColorStripeChanging/ColorStripeChanging.html I have animated a wave.

See https://hofk.de/main/discourse.threejs/2020/ColorWave/ColorWave.html

Some things have changed since 2019. Instead of .addAttribute now .setAttribute .

Also the notation for dynamic has changed.
Now .setUsage( THREE.DynamicDrawUsage )

Hope I could help. :slightly_smiling_face:

Yeah thats exactly what I want to do, but AFTER the animation has started. So basically what I want is:

  1. Start the animation with: vertices.z = 0.42 * Math.sin(vertices.x * 2 + time);
  2. After a timeout of 5 seconds use: vertices.z = 1.42 * Math.sin(vertices.x * 2 + time);
  3. After another 5 seconds go back to: vertices.z = 0.42 * Math.sin(vertices.x * 2 + time);

That is what I would like to archieve, but as said… when I change the values, nothing happens :slight_smile:

You don’t see any effect since the vertex displacement in setTimeout() is overwritten in animate().

/cc

Well, do not perform the vertex displacement twice. Change the existing one in animate().

Yeah but how… I mean the animate() is an infinite loop. I cannot do that kind of stuff in there or can i?
If i set a timeout for example, it will be automatically executed an infinite times?

Or when I scroll on my website and get to a certain point. How would I change values inside the animate() loop… that is impossible is it not?

Ill give it a try and let you guys know the outcome. Thanks for your reply!