- Home /
How do I rotate a Vector3 based on two other Vector3?
See the picture for a better understanding.
(BTW the example is in 2D but i need this in 3D)
Picture Subtitle:
Red and yellow dot: origins of the vector3
Blue Vector3: Imagine those as a forward vector3 of an object
Green Vector3: A vector3 i obtained from rotating the red dot blue transform
Orange Vector3: the vector3 that i want to obtain, it has the same rotation as the green one but relative to its origin
Purple rotation: Same rotation on both sides
I've already tried messing with quaternions but I cant figure how to make this work, when using the quaternions it looked like they were rotating based on the wrong origin...
Answer by jamesvhyde · Jul 22, 2020 at 04:39 PM
I think you are trying to obtain the orange vector, and you don't care about the purple rotation itself? In that case, there is no need to mess with quaternions. You can use the local coordinate systems.
I also think that maybe it's not working how you want because the ScreenPointToRay method gives you a direction and an origin, and the two have to be used in conjunction. It will be a little off if you just rotate the direction vector, because the origin of the ray is on the near clipping plane, not at the camera position as might be expected.
Here is some code in two behaviors that I think is doing what you want:
public class CameraMouseRay : MonoBehaviour
{
public Vector3 localDirection { get; private set; }
public Vector3 localOrigin { get; private set; }
void Update()
{
Ray ray = GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
localDirection = transform.InverseTransformVector(ray.direction);
localOrigin = transform.InverseTransformPoint(ray.origin);
}
}
public class CameraLocalRay : MonoBehaviour
{
public CameraMouseRay mouseCamera;
void Update()
{
Vector3 localDir = mouseCamera.localDirection;
Vector3 worldDir = transform.TransformVector(localDir);
Vector3 localOrg = mouseCamera.localOrigin;
Vector3 worldOrg = transform.TransformPoint(localOrg);
Debug.DrawRay(worldOrg, worldDir * 100, Color.yellow);
}
}
The CameraMouseRay component goes on the camera that the player is looking through, and the CameraLocalRay component goes on the second camera.
Answer by Namey5 · Jul 22, 2020 at 09:54 AM
Assuming;
Va = Red-Blue
Vb = Red-Green
Vc = Yellow-Blue
Vd = Yellow-Orange
You can think of a quaternion as a rotation - as such, you can just find and store the rotation from Va to Vb and apply the same rotation to Vc;
Quaternion rot = Quaternion.FromToRotation (Va, Vb);
Vector3 Vd = rot * Vc;
Thanks for the answer, but it isn't working correctly (at least as I intended to xD)
The code im using (simplified):
var _ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var _rot = Quaternion.FromToRotation(_forward, _ray.direction);
_final = _rot * _forward2;
I think the problem is that its rotation the _foward2 based on the _foward vector origin.
Basically think this way:
I have two cameras, one's the main. (_forward is from the main one and _forward2 is from the other)
I want to make a raycast based on mouse position and then make another raycast from the second camera like it has a player that had the mouse in the same position (sorry if this sounds confusing)
@jamesvhyde 's answer works just as well and brings up a good point - ScreenPointToRay is cast from the camera's near plane. However, all you need to do is combine the ray's components and compare them with the camera's to get a more useable vector;
Vector3 rayDir = ((ray.origin + ray.direction) - cam.transform.position).normalized;
From there you should be able to use that in the quaternion example as well. Both work - the space transformations may be a bit easier to follow, but the quaternions are simpler to write and faster performance-wise. It's really up to you, I would just be careful using Camera.main in a core Update loop (cache it on first use, etc).
Your answer