Need a mesh to rotate around the tangent vector of a point on a curve to face the camera

I have a curve, along which at various points I need to place a cross beam (box geometry) whose up vector points in the direction of the curve’s tangent vector. As the camera moves, I need the cross beam to rotate around its up vector such that it always faces the camera, By this, I mean that the beam should remain oriented left to right on the screen (though on a diagonal as it must be perpendicular to the curve where it crosses it).

How it should look from the sides:


Pasted Graphic 25

How it should look from above:

Here’s a fiddle containing a minimal working example: Quaternion hell - JSFiddle - Code Playground. Note that in my real application, there are many beams (implemented as an instanced mesh) that cross the curve at different points, so each beam has a different up vector it rotates around.

The challenge is essentially to calculate a rotation about the beam’s up axis based on the current rotation of the camera. This is where I’m getting stuck. I can manually add in a rotation to make the beam face the direction I want - as I have done so that it is oriented approximately correctly for the camera’s initial position (see Option 3 at end of the jsfiddle code), but I don’t know how to calculate this angle dynamically based on the rotation of the camera.

Note: this is similar to what I’m trying to achieve: InstancedMesh + implement billboard. The main difference is that I need the mesh that I’m billboarding to rotate around a Y axis that is tangent to a point on a curve rather than a Y axis that is vertical.

I’ve been stuck on this for quite some time now and I’ve hit the limits of my current skills. Any help would be greatly appreciated!

I was able to reproduce the three snapshots:

https://codepen.io/boytchev/full/yLrRvKX

image image image

3 Likes

@PavelBoytchev That is exactly what I was trying to accomplish! I can’t thank you enough - I’ve been stuck trying to solve this for about a week now, and it’s clear to me I wasn’t going to figure this out on my own. I don’t quite understand how it works yet; I think I’m going to have to hit the books in the coming days and brush up on my linear algebra. Thanks again kind sir!

Hi @PavelBoytchev,

I’ve incorporated your code into my application. The beam follows the camera as intended which is awesome, however the beam is not quite perpendicular to the curve.

Here’s how it looks with your changes:

Here’s how it looks if I use the rotation I calculated here:

  rotation = new THREE.Quaternion()
  rotation.setFromUnitVectors(new THREE.Vector3(0, 1, 0), tangent)

Note that in my fiddle I positioned the beam across the curve for simplicity - it’s normally positioned to the left or right of the curve in my application.

Do you have any thoughts on how to fine tune the calculation so that the beam remains perpendicular to the curve?

There’s also a few camera angles where the rotation of the beams changes suddenly when the camera moves as can be seen in the videos below.

Nice catch. It looks like orthogonality is incomplete. Try adding the second line:

Z.copy(X).cross(Y).normalize(); // already existing
X.copy(Y).cross(Z).normalize(); // newly added
2 Likes

That line fixed it - looks perfect now. Thanks again!