There are various methods to achieve this effect. One straightforward approach that minimizes the need for complex calculations and delegates the heavy lifting to Three.js involves nesting an Object3D within another. In this setup, the child object represents the "ring," while the parent object positions the ring at the midpoint and aligns it perpendicular to a specified line.
// Define endpoint vectors
var v1 = new THREE.Vector3(1, 3, 5);
var v2 = new THREE.Vector3(7, 8, 10);
// Calculate midpoint
var mid = new THREE.Vector3();
mid.addVectors(v1, v2);
mid.multiplyScalar(0.5);
// Create parent and child objects
var parent = new THREE.Object3D();
var child = new THREE.Object3D();
parent.add(child);
// Position the child at a point on the XY plane with radius = 1
// This point represents the "disc"
child.position.set(0, 1, 0);
// Move the parent to the midpoint
parent.position.copy(mid);
// Rotate the parent to face the end of the line
// This action ensures the "disc" is perpendicular to the line
parent.lookAt(v1);
// Obtain the world position of the child
var discPoint = new THREE.Vector3();
child.getWorldPosition(discPoint);
console.log(discPoint);
Although the local position of child
remains [0, 1, 0]
, the transformed world position after the parent's translations and rotations yields the desired outcome. An alternative approach involves utilizing Object3D.localToWorld. However, the aforementioned parent-child example serves to elucidate the process effectively.