0

I'm learning Three Js and I have the following problem: I have an arrow of a fixed length r centered at position (x, y, z) and I want the arrow to rotate to track the mouse. If the mouse is further away from the center than r, I want the z component of the arrow to be 0, but if the mouse is within distance r from the center, I want the arrow's z component to be set to the remaining length i.e. Math.sqrt((arrowLength * arrowLength) - (dx*dx) - (dy*dy)).

How do I do this?

My question is similar to this question but the key difference is that I don't know the dz component in advance.

Rylan Schaeffer
  • 1,945
  • 2
  • 28
  • 50

1 Answers1

3

You can use .unproject() method of Vector3() to cast a vector from camera's NDC space to world space.

body{
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 1).setLength(6);
let renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);

window.addEventListener("resize", onWindowResize);

let pointer = new THREE.Vector3();
let lookAt = new THREE.Vector3();
window.addEventListener("pointermove", event => {
  pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
  lookAt.copy(pointer).unproject(camera).setLength(5);
  o.lookAt(lookAt);
})

let g = new THREE.ConeGeometry(0.2, 2, 32);
g.translate(0, 1, 0);
g.rotateX(Math.PI * 0.5);
let m = new THREE.MeshNormalMaterial();
let o = new THREE.Mesh(g, m);
scene.add(o);

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});

function onWindowResize() {

  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);

}

</script>
prisoner849
  • 16,894
  • 4
  • 34
  • 68
  • I have a quick follow up question. I noticed this only works if the cone is positioned at (0, 0, 0). If the cone is positioned elsewhere, the cone doesn't seem to track the mouse – Rylan Schaeffer Jan 30 '22 at 22:43
  • Also, if I can ask another follow up question, what does the `.setLength()` do? Changing that value seems to have no effect on the resulting visualization. Same with removing it altogether. – Rylan Schaeffer Jan 30 '22 at 22:50
  • This also seems to cease functioning properly if I change any other parameters e.g. if I change the cone height from 2 to 3. – Rylan Schaeffer Jan 30 '22 at 23:24
  • Also, the cone visually doesn't seem to have a max length. It grows longer and longer the further the cursor moves away. – Rylan Schaeffer Jan 30 '22 at 23:43
  • Also, I just discovered that resizing the window changes the position of the cone :( – Rylan Schaeffer Jan 30 '22 at 23:50