How Do I Rotate a Basis Toward a Destination By a Fix Amount

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ncallaway

My goal is to rotate on Spatial towards a desired final rotation with a fixed angular speed (in radians/sec).

The behavior I want is essentially what is implemented in Unity’s Quaternion.RotateTowards (Unity - Scripting API: Quaternion.RotateTowards).

Rotates a rotation from towards to.

The from quaternion is rotated towards to by an angular step of maxDegreesDelta (but note that the rotation will not overshoot).

I think implementing this would be relatively easy with the axis angle representation of a Quat, so in the alternative I would be happy to learn how to obtain an axis angle representation of the rotation of a Basis or a Quat. I see this in the C++ source code for Basis (Basis::get_axis_angle https://github.com/godotengine/godot/blob/master/core/math/basis.cpp#L880), but I don’t see a similar method for GDScript or C#.

:bust_in_silhouette: Reply From: ThePixelGuy

I believe you can do this with trigonometric functions.
Here’s an example of what I mean:

var i = PI / 2
var SPEED = 1.0
func _process(delta):
	transform.basis.x = Vector3(sin(i), 0.0, cos(i))
	transform.basis.z = Vector3(-cos(i), 0.0, -sin(i))
	i += delta * SPEED
	if (i > 2.0 * PI)
		i = 0.0

Haven’t tried it, but it should spin the node that it is attached to counter-clockwise.

Thanks! I ended up implementing my own ToAxisAngle function:

  public static void ToAxisAngle(this Quat q, out Vector3 axis, out float angle)
  {
      var quat = q;
      if (q.w > 1) { quat = q.Normalized(); }

      angle = 2 * Mathf.Acos(quat.w);

      float s = Mathf.Sqrt(1 - (quat.w * quat.w));
      axis = new Vector3(quat.x, quat.y, quat.z);
      if (s > 0.001f) { axis = axis / s; }
      else { angle = 0; }
}

I was then able to use that ToAxisAngle function to implement RotateTowards.

Thanks!

ncallaway | 2020-08-18 15:26