- Home /
How to rotate relative to camera angle/position
I am trying to make rotate an object relative to its camera. I think quaternion angles are the way to go but nothing I have tried so far works.
basically depending on how the camera looks at an object (from top, at 45 degree,or from side, or back or anything in between) I want to rotate it left/right or up/down depending but not in local or global space but relatively to the camera. so if camera is looking at model at at a 45 degree angle i wish to make it rotate around both y and z axis ( depending on that angle). (but this also means looking at it from the back or the front will have another change in axis)
I just don't know how i would go about it.
Edit: Adding image of what i would like to know how to do:
Can you illustrate with some drawings or even screenshots (where you position manually)?
You could just send the rotation of the camera to the object in question (if that is what you are trying to do). Or do you mean you want the object to look at the player at all times. I agree with $$anonymous$$ryptos on this one i think we need some more details.
no I am using a AR system (QCAR) and when an object shows up I want to be able to rotate it. I noticed from the code that the camera moves around the model when i move my ImageTarget.
so even though I dont want the object to look at me whenever I move the camera, I want my swipes (left/right, and up/down) to rotate the model relative to the camera eg: the camera is at a 45 degree angle up/down from front on image target and at a 45 degree angle to the size of the object) when i swipe left it needs to rotate around the y axis and around the z axis by a certain amount each to make it look like the whole model is rotating left around (0,0,0). I had a bit of it working with eurler angles but as soon as it got a bit more complex I ran into gimble lock.
Image Posted:
Answer by Raigex · Aug 10, 2012 at 07:22 PM
After you have no idea how much trial and error and learning Quaternions i have finally figured out how to do this rotation.
Thanks to everyone that has posted an answer but the answers are not what I needed. As far as i understood them all answers were for a stationary camera, or to move the camera around. I needed to rotate an object relative to a dynamically changing camera.
THis is my solution (my rotate function)
public void Rotate(float RotateLeftRight, float RotateUpDown) { float angleX = Camera.mainCamera.transform.localEulerAngles.x; float angleY = Camera.mainCamera.transform.localEulerAngles.y; //Debug.Log(angleX + " , " + angleY); //Camera's angle at z is not needed.
float percentAngleX = (float)angleX / 90.0f; float percentAngleY = 0.0f;
float x = 0.0f; float y = 0.0f; float z = 0.0f;
if(angleY < 90) { //Only worry about x and z for up down percentAngleY = angleY /90.0f; x += RotateUpDown (1 - percentAngleY); z += RotateUpDown percentAngleY;
y += RotateLeftRight (1- percentAngleX); x += RotateLeftRight (percentAngleX) (percentAngleY); z += RotateLeftRight (percentAngleX) * (1 - percentAngleY); }
else if(angleY < 180) { percentAngleY = (angleY - 90.0f) / 90.0f;
z += RotateUpDown (1 - percentAngleY); x -= RotateUpDown (percentAngleY);
y += RotateLeftRight (1- percentAngleX); z -= RotateLeftRight (percentAngleX) (percentAngleY); x += RotateLeftRight (percentAngleX) * (1 - percentAngleY);
} else if(angleY < 270) { percentAngleY = (angleY - 180.0f) / 90.0f; x -= RotateUpDown (1 - percentAngleY); z -= RotateUpDown (percentAngleY);
y += RotateLeftRight (1- percentAngleX); x -= RotateLeftRight (percentAngleX) (percentAngleY); z -= RotateLeftRight (percentAngleX) * (1 - percentAngleY); } else if(angleY < 360) { percentAngleY = (angleY - 270.0f) / 90.0f;
z -= RotateUpDown (1 - percentAngleY); x += RotateUpDown (percentAngleY);
y += RotateLeftRight (1- percentAngleX); z -= RotateLeftRight (percentAngleX) (percentAngleY); x += RotateLeftRight (percentAngleX) * (1 - percentAngleY); }
Vector3 relativeUp = transform.InverseTransformDirection(Vector3.down); Vector3 relativeRight = transform.InverseTransformDirection(Vector3.left); Vector3 relativeForeward = transform.InverseTransformDirection(Vector3.forward);
rotateBy = Quaternion.AngleAxis(z, relativeForeward) Quaternion.AngleAxis(y , relativeUp) Quaternion.AngleAxis(x , relativeRight);
newDeltaObtained = true;
}
Then in my update function update my rotation
void Update()
{
if(newDeltaObtained) { this.gameObject.transform.localRotation *= rotateBy;
newDeltaObtained = false; } }
This code allows me to rotate the object with relative to the camera regardless of where the camera is pointing and at what angle it is pointing there. It took me a long time to figure this out (over 21 hours) so i hope other looking for something like this can no see it.
New rotate code here:
public void Rotate(float rotateLeftRight, float rotateUpDown, bool isPlayer)
{
useUpdate = false;
//Unsure of how much below code changes outcome.
float sensitivity = 0;
if (isPlayer)
{
sensitivity = .5f;
}
else
{
sensitivity = .25f;
}
//Get Main camera in Use.
Camera cam = Camera.mainCamera;
//Gets the world vector space for cameras up vector
Vector3 relativeUp = cam.transform.TransformDirection(Vector3.up);
//Gets world vector for space cameras right vector
Vector3 relativeRight = cam.transform.TransformDirection(Vector3.right);
//Turns relativeUp vector from world to objects local space
Vector3 objectRelativeUp = transform.InverseTransformDirection(relativeUp);
//Turns relativeRight vector from world to object local space
Vector3 objectRelaviveRight = transform.InverseTransformDirection(relativeRight);
rotateBy = Quaternion.AngleAxis(rotateLeftRight / gameObject.transform.localScale.x * sensitivity, objectRelativeUp)
* Quaternion.AngleAxis(-rotateUpDown / gameObject.transform.localScale.x * sensitivity, objectRelaviveRight);
newDeltaObtained = true;
}
Thanks man, your code works perfectly and you saved me a heap of headaches!
I have an updated version of this code it is much cleaner. The above code also has a bug it only works at certain angles.
Really? I have had no problem with it so far. Could you post the updated code?
Updated, also the new code uses Unity functions so it is much cleaner.
Where you getting inputs from, I mean floats rotateLeftRight and rotateUpDown. You calculate them from mouse move but how? Thanks.
Answer by Cambesa · Feb 16, 2017 at 09:10 AM
There's a function called Transform.RotateAround(), to make it rotate around the camera-based axis you could use:
cubeTransform.RotateAround(Vector3.zero, Camera.main.transform.up, swipeLeft);
In which cubeTransform is the transform to rotate and swipeLeft the distance swiped to the left in that frame.
This is by far the best answer right now -- the long answer above seems to contain some out-of-date code. RotateAround is deprecated right now so you'll get a warning for it, but you can just use Rotate ins$$anonymous$$d with the axis and amount to move, so for example if you were using mouse drags you could do the following:
cubeTransform.Rotate(Camera.main.transform.up, -Input.GetAxis("$$anonymous$$ouse X"));
cubeTransform.Rotate(Camera.main.transform.right, Input.GetAxis("$$anonymous$$ouse Y"));
(And then if you need to flip the rotation in either direction, just make the "Input.GetAxis()" positive or negative.)
Answer by ScroodgeM · Aug 09, 2012 at 10:35 PM
to make it look like the whole model is rotating left around (0,0,0)
if i understood you right, you need
transform.LookAt(myCamera);
that will rotate object so it always looks by it's Z-axis to camera
Answer by RodrigoSeVeN · Aug 10, 2012 at 12:37 PM
Inspired by @Scroodge 's approach, I got to this solution.
This script goes on the camera. All you need to do is insert/switch/adapt your swipe input to the 'Rotate' part, the last line on the code below(and remove the 'Input.GetAxis' that is just for testing input).
Also, you just need to call the MovedCamera() function whenever you reposition your camera and is about to use the swipe function, so you update the rotation of 'axis' and is ready to rotate the object properly. Remember that the 'axis' object is positioned at (0,0,0). Moving it or having the object not positioned on the center, will give you wrong rotations.
var axis:Transform;
var target:Transform;
function MovedCamera(){
target.parent=null;
axis.LookAt(transform);
target.parent=axis;
}
function Update () {
if(Input.GetKeyDown("space"))MovedCamera();
axis.Rotate(Vector3.up*Time.deltaTime*Input.GetAxis("Horizontal"), Space.Self);
}
Answer by TrevorUG · Jan 09, 2017 at 08:13 AM
this suits me just fine:
void Update ()
{
Vector3 rot;
rot = camera.transform.forward * -Input.GetAxis ("Horizontal") * vel;
// above: gets the rotation relative to the camera
transform.Rotate (rot);
}