How to rotate object based on Normal and Direction vectors?

I have a normal vector and a dir - directional vector (both normalized).
I need to rotate object regarding this purpose.

It looks like I need to use Matrix4() and makeRotationAxis, but I don’t understand how exactly it needs to be used.

Blue arrow is direction vector and red arrow is normal.

What I have:

What I want to:

I’m afraid two normalized vectors are no valid input for a rotation. Given a single normalized vector and an angle, you can use the axis-angle representation in order to perform a rotation. The methods for this use case are:

@selmernoid, it might help if you were clearer how you expect the rotation to work. Are you trying to rotate around the normal vector? In that case you don’t need a directional vector, you just need a scalar value, since if you’re rotating around an axis the only question is if you’re rotating “left hand curl” or “right hand curl” where your thumb is the normal, and by how much.

Can you maybe draw a picture of what you’re trying to achieve geometrically?

Hey, @Jim, thanks for your attention.
I’ve added images to post, hope it fully describes my problem =)

Ahh, cool, so it sounds like you want your Object3D to point one axis in the direction of the direction vector and a different axis in the direction of the normal vector. I’m not quite sure which axis you want to point towards which vector, but that doesn’t matter: once you’ve pointed any pair of axes toward the two vectors it should be easy to change them however you want with 90-degree rotations.

The other trick is I assume we can’t assume the two vectors are at a 90-degree angle to each other, which is fine.

The way you usually do that kind of orientation in Three.js is through the lookAt method together with the up vector. You could start by trying

myObj.up.copy(myNormalVector);
myObj.lookAt(myDirectionVector);

Not sure that’ll get you what you want though. lookAt points to a vector in world space, in other words if your vector is say (0, 1, 0) then instead of “looking straight up” your object will turn and look at a position 1 above the origin. So you can try making the lookAt point relative to your object:

myObj.up.copy(myNormalVector);
var adjustedDirVector = myObj.localToWorld(myScratchVector.set(0, 0, 0)).add(myDirectionVector);
myObj.lookAt(adjustedDirVector);

@Jim, Thanks a lot!

It works with single modification:
myObj.up.copy(new THREE.Vector3().crossVectors(myDirectionVector, myNormalVector));

May be it was required because I interpret incorrectly the initial state of Normal and Direction vectors

The following code might provide a helpful example. It creates an arrow and points it in specified direction.

export function arrow(position, direction, arrowSize = 1000000, vectorMagnitude = 1, skinnyFactor = 1, color = 0x3f3f4f) {
  const straightUpVector = new THREE.Vector3(0, 1, 0)
  const arrowParts = []
  const absVectorMagnitude = Math.abs(vectorMagnitude)
  const maxArrowheadPortion = 0.75
  const arrowHeadLength = Math.min(0.2, absVectorMagnitude * maxArrowheadPortion)
  const arrowShaftLength = absVectorMagnitude - arrowHeadLength
  arrowParts.push(new THREE.SphereGeometry(0.02, 32, 16))
  arrowParts.push(new THREE.CylinderGeometry( 0.01, 0.01, arrowShaftLength, 12 ).translate(0, arrowShaftLength/2, 0))  // arrow shaft
  arrowParts.push(new THREE.CylinderGeometry( 0, 0.04, arrowHeadLength, 12 ).translate(0, arrowShaftLength + arrowHeadLength/2, 0))   // arrow head
  const arrowGeometry = mergeBufferGeometries(arrowParts)
  const arrow = new THREE.Mesh(arrowGeometry, new THREE.MeshPhongMaterial({color: color}))
  arrow.scale.set(arrowSize * skinnyFactor, arrowSize * Math.sign(vectorMagnitude), arrowSize * skinnyFactor)
  arrow.position.copy(position)
  arrow.name = 'arrow'
  const q = new THREE.Quaternion().setFromUnitVectors(straightUpVector, direction.clone().normalize())
  arrow.rotation.setFromQuaternion(q)
  return arrow
}