5

I want to aim for objects with cameras' vision (as the user would look at the object, not point at it with mouse).

I'm casting a ray from the camera like this

rotation.x = camera.rotation.x;
    rotation.y = camera.rotation.y;
    rotation.z = camera.rotation.z;
    raycaster.ray.direction.copy( direction ).applyEuler(rotation);
    raycaster.ray.origin.copy( camera.position );

var intersections = raycaster.intersectObjects( cubes.children );

This gets me the intersections but it seems to wander off sometimes. So I'd like to add aim (crosshair). That would be somekind on object (mesh) at the end or in the middle of the ray.

How can I add it? When I created a regular line it was in front of the camera so the screen would go black.

Noripsni
  • 425
  • 1
  • 5
  • 21

1 Answers1

10

You can add a crosshair constructed from simple geometry to your camera like this:

var material = new THREE.LineBasicMaterial({ color: 0xAAFFAA });

// crosshair size
var x = 0.01, y = 0.01;

var geometry = new THREE.Geometry();

// crosshair
geometry.vertices.push(new THREE.Vector3(0, y, 0));
geometry.vertices.push(new THREE.Vector3(0, -y, 0));
geometry.vertices.push(new THREE.Vector3(0, 0, 0));
geometry.vertices.push(new THREE.Vector3(x, 0, 0));    
geometry.vertices.push(new THREE.Vector3(-x, 0, 0));

var crosshair = new THREE.Line( geometry, material );

// place it in the center
var crosshairPercentX = 50;
var crosshairPercentY = 50;
var crosshairPositionX = (crosshairPercentX / 100) * 2 - 1;
var crosshairPositionY = (crosshairPercentY / 100) * 2 - 1;

crosshair.position.x = crosshairPositionX * camera.aspect;
crosshair.position.y = crosshairPositionY;

crosshair.position.z = -0.3;

camera.add( crosshair );
scene.add( camera );

Three.js r107

http://jsfiddle.net/5ksydn6u/2/


In case you dont have a special usecase where you need to retrieve the position and rotation from your camera like you are doing, I guess your "wandering off" could be fixed by calling your raycaster with these arguments.:

raycaster.set( camera.getWorldPosition(), camera.getWorldDirection() );
var intersections = raycaster.intersectObjects( cubes.children );

Cast visible ray Then you can visualize your raycast in 3D space by drawing an arrow with the arrow helper. Do this after your raycast:

scene.remove ( arrow );
arrow = new THREE.ArrowHelper( camera.getWorldDirection(), camera.getWorldPosition(), 100, Math.random() * 0xffffff );
scene.add( arrow );
Falk Thiele
  • 4,424
  • 2
  • 17
  • 44
  • Thank you, for very thorough answer! – Noripsni Jul 28 '15 at 05:14
  • I have used this code to create a crosshair successfully in the scene, however the crosshair passes behind all of the other objects in the scene. Is there a way to always force the crosshair to appear on top? – igneosaur Oct 07 '15 at 00:54
  • You will have to control the rendering order, or utilize the [second scene](http://stackoverflow.com/a/12666937/4977165) approach. Another thing would be creating the crosshair as HTML-Overlay. – Falk Thiele Oct 07 '15 at 07:10
  • 8
    To draw the arrow based on the ray (instead of the camera), I used this instead: `scene.add(new Three.ArrowHelper( raycaster.ray.direction, raycaster.ray.origin, 100, Math.random() * 0xffffff ));` – Russ Aug 10 '16 at 18:09
  • 1
    @Falk Thiele i love you – codeboi May 20 '21 at 13:23