0

I am working on the object viewer like sketchfab in Unity and currently doing camera rotation using mouse. So far everything seems to work, but I would like to clamp the rotation on the vertical axis, but have some trouble accomplishing this.

This is how I've done my camera rotation:

[SerializeField] Transform camPivot = null;
[SerializeField] float     speed    = 850.0F;

private Quaternion      _camRot         { get; set; } = Quaternion.identity;
private float           _polar          { get; set; } = 0;
private float           _elevation      { get; set; } = 0;

void DoRotation()
{
    this._polar     += Input.GetAxis("Mouse X") * this.speed * Mathf.Deg2Rad;
    this._elevation -= Input.GetAxis("Mouse Y") * this.speed * Mathf.Deg2Rad;

    this._camRot = Quaternion.AngleAxis(this._elevation, Vector3.right);
    this._camRot = Quaternion.AngleAxis(this._polar, Vector3.up) * this._camRot;
}
private void Update()
{
    this.DoRotation();

    this.camPivot.localRotation = Quaternion.Slerp(this.camPivot.localRotation, this._camRot, Time.unscaledDeltaTime * 5.0F);
}

Also I want to always make sure z rotation is zero as I only need to rotate the camera pivot horizontally and vertically, I tried setting camPivot euler z value to 0, but it gives me some really weird behavior.

var euler = this.viewCamera.Pivot.eulerAngles; euler.z = 0.0f;
    this.viewCamera.Pivot.eulerAngles = euler;

enter image description here

Ruzihm
  • 19,749
  • 5
  • 36
  • 48
UnknownUser
  • 327
  • 2
  • 14
  • What do you mean by "really weird behaviour"? Also, it's not clear if the pivot is a child of some other object that might be rotated in some way. So what happens if you use `Pivot.localEulerAngles` instead? All of your other calculations seem to be based on the pivot's local rotation so it going against expectations might be rooted in that difference. – Ruzihm Sep 26 '19 at 17:42
  • Hey there! I tried using localEulerAngles, but it gives me same type of behaviour, which is if I go almost 90 or -90 degrees vertically everything starts to 'spin'. I guess it could be that Gimbal lock issue, but I'm not sure as I'm not really familiar with the Eulers and Quaternions that much. The parent object of the camPivot and the parent of the parent and such are all at zero pos and rot and I do not change any of that at any point only the camPivot. – UnknownUser Sep 26 '19 at 18:35
  • 1
    Have you tried clamping _elevation to +- 90 using `this._elevation = Mathf.Clamp(this._elevation, -90f, 90f);` and getting rid of the `this.viewCamera.Pivot.eulerAngles = euler;` lines? Seems like that's the easiest way to prevent this controller from flipping the camera. – Ruzihm Sep 26 '19 at 18:58
  • This is perfect! Why haven't I thought of that.. Works great, thank you! :) I have this one more thing which I'm not sure of, if I try to rotate on the horizontal axis very quickly with my mouse, so move mouse to rotate really frequently, it sometimes 'locks' and doesn't let me to rotate it, it goes slightly to opposite direction. Not sure what could be causing this type of behavior. – UnknownUser Sep 26 '19 at 19:21
  • And I actually used the same way to set the euler like I showed in the question, except I used local euler angles and it seems to work fine now. I guess it's because I clamped the vertical rotation and that prevented the Gimbal lock issue. But that would be my guess. – UnknownUser Sep 26 '19 at 19:24
  • If you're turning the mouse left/right very quickly, it's likely that you're rotating it far enough between frames that `Slerp` recognizes that the shortest distance between the rotations is to move it the other direction. Slerp always interpolates across the shortest distance along the outside of a sphere. – Ruzihm Sep 26 '19 at 19:29

1 Answers1

1

A very simple solution is to clamp _elevation to ±90 using Mathf.Clamp:

void DoRotation()
{
    this._polar     += Input.GetAxis("Mouse X") * this.speed * Mathf.Deg2Rad;
    this._elevation -= Input.GetAxis("Mouse Y") * this.speed * Mathf.Deg2Rad;
    this._elevation = Mathf.Clamp(this._elevation, -90f, 90f);

    this._camRot = Quaternion.AngleAxis(this._elevation, Vector3.right);
    this._camRot = Quaternion.AngleAxis(this._polar, Vector3.up) * this._camRot;
}
Ruzihm
  • 19,749
  • 5
  • 36
  • 48