1
\$\begingroup\$

I'm using unity3d to create a six-degree of freedom flying game. The game takes in input from a standard dual-stick gamepad (like the Logitech f310).

In unity each of the gamepad's joystick's axes are stored as a float value range from a negative minimum to a positive maximum. Minimum value when the joystick is pushed all the way down, maximum value when the joystick is pushed all the way up, and zero when the joystick is centered at rest. (see diagram)

Joystick Diagram

This gives me three float values which can then store as a 3 vector for which I want to use to rotate my object.

inputVector = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), Input.GetAxis("Pitch"));

In unity3d a gameobject's rotation/orientation is stored in a quaternion. this is a mathematical structure that can represent rotation in 3d like a 3x3 matrix, but with fewer variables and without being sensitive to small angles, doesn't suffer from gimbal lock like Euler angles, and also rotations represented with it can be combined easily without issue unlike angle-axis representation.

With all that out of the way, I'm trying use my "input" vector (or at least the three separate values for my three joystick axes) to rotate my quaternion so I can have 3D rotational movement without singularities like gimbal lock and such.

I already know that unity has two functions related to this, Quaterion.Euler() and Quaternion.AngleAxis() but both of these have issues when dealing with 3D rotations, .Euler() gives gimbal lock, and .AngleAxis() ignores the magnitude of the individual axes being input which I suppose is the reason for no smooth rotations.

I've looked far and wide and not found a solution that fits my bill. Either I'm missing something or maybe I need to do the reverse of a quaternion rotation a point in 3D, but I need assistance.

\$\endgroup\$
2
  • \$\begingroup\$ Do you want to map your input to an orientation (so each position of your joysticks is a different orientation) or - more common in games - do you want to map your input to a rotation (so the position of your joysticks tells the game how to rotate the object, and it will continue to rotate if you hold a position, with the rest position of the joysticks being no rotation)? For the former you will need to do some sacrifice because the joysticks don't wrap around, and for the latter you are overthinking this. \$\endgroup\$
    – Theraot
    May 4 at 11:40
  • \$\begingroup\$ @Theraot The latter please. \$\endgroup\$
    – RhinoPak
    May 4 at 12:00

1 Answer 1

1
\$\begingroup\$

You only need to axis - I'm not sure what the third one is anyway - as rotating an object around two axis will also result in some rotation around the third.

And you can Euler angles to process the input, without worry of gimbal lock, because:

  • The orientation of your object would be in Quaternions and will remain in Quaternions regardless of how you process the input. The same argument would hold if you were working with a basis (3x3 matrix).
  • The input rotation shall only represent small angles. The axis should go from -1 to 1. If it does not, then normalize it to make it so.

The process is as follows:

  1. Each frame you take the input of the axis in the range -1 to 1.
  2. You interpret them as Euler angles.
  3. Convert into a Quaternion or Axis-Angle.
  4. Scale the rotation according to the delta time (and thus making the behavior frame rate independent). You might also scale it by a "sensitivity" factor to tweak how fast it rotates. For a Quaternion, this is an unclamped interpolation from the identity rotation. For the Axis-Angle, this is multiplying the angle.
  5. Then convert the result to Quaternion or basis (3x3 matrix) - depending on what you are using to represent the orientation of the object.
  6. And compose it with the orientation of the object. This step is either Quaternion or Matrix multiplication.

The result is that the object it rotates each frame some amount depending on the input (and the "sensitivity").

If the input is zero (being that the rest point of the joystick, or within its dead zone), there should be no rotation. And further away from the rest point, you should get more rotation (i.e. the object rotates faster).

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much! \$\endgroup\$
    – RhinoPak
    May 4 at 14:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .