Skip to content

Commit

Permalink
Allow constructing Quat from two Vector3s
Browse files Browse the repository at this point in the history
  • Loading branch information
timothyqiu committed Jun 12, 2024
1 parent b203829 commit 9744387
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
41 changes: 22 additions & 19 deletions core/math/quat.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ class _NO_DISCARD_CLASS_ Quat {
r_axis.z = z * r;
}

void set_shortest_arc(const Vector3 &p_from, const Vector3 &p_to) {
Vector3 c = p_from.cross(p_to);
real_t d = p_from.dot(p_to);

if (d < -1 + (real_t)CMP_EPSILON) {
x = 0;
y = 1;
z = 0;
w = 0;
} else {
real_t s = Math::sqrt((1 + d) * 2);
real_t rs = 1 / s;

x = c.x * rs;
y = c.y * rs;
z = c.z * rs;
w = s * 0.5f;
}
}

void operator*=(const Quat &p_q);
Quat operator*(const Quat &p_q) const;

Expand Down Expand Up @@ -135,25 +155,8 @@ class _NO_DISCARD_CLASS_ Quat {
return *this;
}

Quat(const Vector3 &p_v0, const Vector3 &p_v1) // shortest arc
{
Vector3 c = p_v0.cross(p_v1);
real_t d = p_v0.dot(p_v1);

if (d < -1 + (real_t)CMP_EPSILON) {
x = 0;
y = 1;
z = 0;
w = 0;
} else {
real_t s = Math::sqrt((1 + d) * 2);
real_t rs = 1 / s;

x = c.x * rs;
y = c.y * rs;
z = c.z * rs;
w = s * 0.5f;
}
Quat(const Vector3 &p_v0, const Vector3 &p_v1) {
set_shortest_arc(p_v0, p_v1);
}

inline Quat() :
Expand Down
2 changes: 2 additions & 0 deletions core/variant_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Quat, get_euler);
VCALL_LOCALMEM1(Quat, set_euler);
VCALL_LOCALMEM2(Quat, set_axis_angle);
VCALL_LOCALMEM2(Quat, set_shortest_arc);

VCALL_LOCALMEM0R(Color, to_argb32);
VCALL_LOCALMEM0R(Color, to_abgr32);
Expand Down Expand Up @@ -1906,6 +1907,7 @@ void register_variant_methods() {
ADDFUNC0R(QUAT, VECTOR3, Quat, get_euler, varray());
ADDFUNC1(QUAT, NIL, Quat, set_euler, VECTOR3, "euler", varray());
ADDFUNC2(QUAT, NIL, Quat, set_axis_angle, VECTOR3, "axis", REAL, "angle", varray());
ADDFUNC2(QUAT, NIL, Quat, set_shortest_arc, VECTOR3, "from", VECTOR3, "to", varray());

ADDFUNC0R(COLOR, INT, Color, to_argb32, varray());
ADDFUNC0R(COLOR, INT, Color, to_abgr32, varray());
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/Quat.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@
Sets the quaternion to a rotation specified by Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle).
</description>
</method>
<method name="set_shortest_arc">
<argument index="0" name="from" type="Vector3" />
<argument index="1" name="to" type="Vector3" />
<description>
Makes this quaternion represent the shortest arc between [code]from[/code] and [code]to[/code]. These can be imagined as two points intersecting a sphere's surface, with a radius of [code]1.0[/code].
</description>
</method>
<method name="slerp">
<return type="Quat" />
<argument index="0" name="to" type="Quat" />
Expand Down

0 comments on commit 9744387

Please sign in to comment.