How to update Line2 dynamically?

sandbox: Threejs basic example (forked) - CodeSandbox

const buffer = new Float32Array([0,0,0, 1,1,0, 2,0,0, 1,-1,0])
const material = new LineMaterial({ color: 0xffffff })
const geometry = new LineGeometry()
geometry.setPositions(buffer)

const line = new Line2(geometry, material)

// Would like to change it dynamically ...
buffer[0] = 0.5

geometry.needsUpdate = true // ❌
geometry.attributes.positions.needsUpdate = true // ❌
geometry.attributes.uv.needsUpdate = true // ❌
geometry.attributes.instanceStart.needsUpdate = true // ❌
geometry.attributes.instanceStart.data.needsUpdate = true // ❌
geometry.attributes.instanceEnd.needsUpdate = true // ❌
geometry.attributes.instanceEnd.data.needsUpdate = true // ❌

Hi!
Maybe this post will be helpful: Out of control memory when updating position of lines within animate function - #5 by prisoner849

thanks! this is almost the solution, i wonder though, in that box you use multiple lines with instanceStart and instanceEnd, whereas i have a single lineSegments ([0,0,0, 1,1,0, 2,0,0, 1,-1,0]). what does instanceStart and End mean exactly in my case, since my LineGeometry has four vectors?

made a small sandbox to demonstrate the behaviour: Threejs basic example (forked) - CodeSandbox

AFAIK, FatLines in its core uses instancing. So each segment is an instance of a plane (I think), that has instanced values for its start and its end. When you create fat lines, it internally creates an instanced mesh or a mesh with InstancedBufferGeometry (not sure which one).
How it processed in shaders is something of the black magic for me in general, though I can figure out of how some parts of it work and create funny things, like this: FatLines + noise
or this (there is no forum post of it yet, but I’ve got it on a plan)

See, what happens, when you call .setPositions(): three.js/LineSegmentsGeometry.js at 154e543b1e43e3156f0be02bcd34c39652350072 · mrdoob/three.js · GitHub
There is no original array anymore, it creates InstancedInterleavedBuffer for two InstancedInterleavedAttributes - instanceStart, instanceEnd

Ah, and yes, internally, it’s Mesh with InstancedBufferGeometry.

Thus, you need to do something like this:

setTimeout(() => {
  geometry.attributes.instanceEnd.setY(0, 0.5);
  geometry.attributes.instanceStart.setY(1, 0.5);
  geometry.attributes.instanceStart.needsUpdate = true
  geometry.attributes.instanceEnd.needsUpdate = true
}, 500)

moving more than the first point seems to be really tricky. do you think it makes even sense to mess with internals or should i just call setPositions every frame, though i seems to me it would re-create buffers in that case, seems expensive and wasteful …

That’s what the OP of this topic did, and had problems with growing of memory.

thanks for the help! really appreciate it! i figured it out, non-indexed segments always break my head :smile:

1 Like

You’re welcome :handshake: :slightly_smiling_face:

I’ve asked this on the post prisoner849 mentioned on May 7, '22, but I’m writing here too:
Had the same problem, and still don’t know though If it’s possible to animate a line2 with more than 2 points, or even with a dynamically assigned new set of points each frame. It feels like this should be a basic feature but drawing a visible line on the screen that animates by growing, distorting, translating and changing width each frame seems to be impossible. Am I right?

1 Like