How to make a cone turn to point in +X, -X, +Y etc directions?

I want to be able to set the apex of a cone so that it points in the positive or negative x, y or z directions. Plus, I want the cone to rotate smoothly to it’s new direction.

Of the examples that ship with three.js, this one seems to demonstrate the technique:

https://threejs.org/examples/?q=orien#webgl_math_orientation_transform

So, I’ve tried to copy the rotation technique of that example.

https://jsfiddle.net/fiddleuser04/34q6yckp/15/

If I want the cone to point in the +x direction, I create a point to ‘look at’ by adding a unit i3 vector (1,0,0) to the cone position

targetPosition = new THREE.Vector3().copy(cone.position).add(i3)

and then using the technique of the above mentioned example.

rotationMatrix.lookAt(targetPosition, cone.position, j3);     //use up = j3=(0,1,0)
targetQuaternion.setFromRotationMatrix( rotationMatrix );

Unfortunately, this approach doesn’t work. I can’t really even see what the pattern is in the behaviour I’m getting. In the case of clicking the button twice to look along an axis in a negative direction, whatever action is produced seems to get reversed on 2nd click.

Could anyone point out what my mistake is?

The “lookAt” function produces a rotation that points the Z axis in the look direction. If you play with the buttons in your example you can see that that’s the case. However there are two issues:

  • By default the cone point is aligned with the Y axis which can be fixed by rotating the cone geometry by Math.PI / 2 about X:
cone.geometry.rotateX( Math.PI / 2 );
  • And second is that when you click the buttons to along a negative axis you’re multiplying your i3, j3, k3 unit vectors by - 1 in place meaning the pointing direction will flip every time you press the button. You’ll have to ensure you don’t modify those vectors. A quick solution is to just clone them every time but it’s not recommended to frequently create new objects:
setTarget( new THREE.Vector3()
    .copy( cone.position )
    .add( i3.clone().multiplyScalar( -1 ) )
);

Here’s the fixed example:

https://jsfiddle.net/f8gqcz49/

1 Like

Thank you so much @gkjohnson for you help. I understand where I went wrong now.

Regarding my accidentally flipping the unit vectors, I noticed today that Vector3 has a sub() method, so I guess I could alternatively just do

setTarget(new THREE.Vector3().copy(cone.position).sub(i3));