Reputation: 2705
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.
Upvotes: 0
Views: 462
Reputation: 17596
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/[email protected]";
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>
Upvotes: 3