How to update the endpoints of a cylinder?

Hello,

I asked a question on StackOverflow. I made some progress but I’m still lost for the more general situation.

Basically the question is: what is the usual way to draw a cylinder between two given points, and to update the two endpoints? This should be a classical task I think… If you could show me an example, this would be great.

  1. Have 2 points.
  2. Calculate vector between these two points, ie:
const connection = end.clone().sub(start);
  1. Calculate distance from that, ie:
const connection = end.clone().sub(start);
const distance = connection.length();
  1. Convert connection vector into a direction vector, by normalising it, ie.:
const connection = end.clone().sub(start);
const distance = connection.length();
const direction = connection.clone().normalize();
  1. Now that you have all that, create the cylinder with a height of half of the distance, ie.:
const connection = end.clone().sub(start);
const distance = connection.length();
const direction = connection.clone().normalize();

const cylinder = new Three.Mesh(
  new Three. CylinderGeometry(1.0, 1.0, distance / 2.0),
  new Three.MeshNormalMaterial()
);
  1. Place the cylinder inside a pivot group (since there’s going to be rotation involved later), then place the pivot group precisely halfway between start point and end point, ie.:
const connection = end.clone().sub(start);
const distance = connection.length();
const direction = connection.clone().normalize();

const cylinder = new Three.Mesh(
  new Three. CylinderGeometry(1.0, 1.0, distance / 2.0),
  new Three.MeshNormalMaterial()
);
const pivot = new Three.Group();
pivot.add(cylinder);

const halfDistance = direction.clone().multiplyScalar(distance / 2.0);

pivot.position.copy(start);
pivot.position.add(halfDistance);

scene.add(pivot);
  1. Make pivot lookAt any of the points (it doesn’t really matter, either start or end, result’s the same), ie.:
const connection = end.clone().sub(start);
const distance = connection.length();
const direction = connection.clone().normalize();

const cylinder = new Three.Mesh(
  new Three. CylinderGeometry(1.0, 1.0, distance / 2.0),
  new Three.MeshNormalMaterial()
);
const pivot = new Three.Group();
pivot.add(cylinder);

const halfDistance = direction.clone().multiplyScalar(distance / 2.0);

pivot.position.copy(start);
pivot.position.add(halfDistance);

scene.add(pivot);

pivot.lookAt(end);
  1. You’ll notice the cylinder is sideways - not good. Rotate it locally within the pivot group (that’s why we had it in the first place) by 90 degrees:
const connection = end.clone().sub(start);
const distance = connection.length();
const direction = connection.clone().normalize();

const cylinder = new Three.Mesh(
  new Three. CylinderGeometry(1.0, 1.0, distance / 2.0),
  new Three.MeshNormalMaterial()
);
const pivot = new Three.Group();
pivot.add(cylinder);

const halfDistance = direction.clone().multiplyScalar(distance / 2.0);

pivot.position.copy(start);
pivot.position.add(halfDistance);

scene.add(pivot);

pivot.lookAt(end);
cylinder.rotation.x = Math.PI / 2.0;
  1. Congratulations - you’ve now achieved a cylinder between two points, here’s a ready example!
1 Like

Scale a cylinder of 1 unit length and use .lookAt() method.

3 Likes

Marvellous!! I didn’t know lookAt. Thanks!

I managed to do my animation, thanks to your help: Duoprism. Enjoy!

2 Likes

Good idea!
I would try to use a couple of InstancedMesh for spheres and for cylinders.

@prisoner849 I added some controls, give it a try!

What is InstancedMesh? Never seen that.

Here you are: three.js docs

1 Like

Ok thanks. I found an example here. It doesn’t work because of OrbitControls but I can understand the code: I have to mock the spheres and the cylinders to get the matrix and to use setMatrixAt. Will try tomorrow.