From 2148717e52745776c4cf532c8b3e5f34141520ff Mon Sep 17 00:00:00 2001 From: Silc Renew Date: Wed, 8 Feb 2023 00:20:38 +0900 Subject: [PATCH] Add is_z_forward option to some methods --- core/math/basis.cpp | 4 ++-- core/math/basis.h | 2 +- core/math/transform_3d.cpp | 8 ++++---- core/math/transform_3d.h | 4 ++-- core/variant/variant_call.cpp | 16 ++++++++++++++-- doc/classes/Basis.xml | 2 ++ doc/classes/Node3D.xml | 3 +++ doc/classes/Transform3D.xml | 2 ++ doc/classes/Vector3.xml | 18 ++++++++++++++++++ doc/classes/Vector3i.xml | 18 ++++++++++++++++++ scene/3d/node_3d.cpp | 12 ++++++------ scene/3d/node_3d.h | 4 ++-- 12 files changed, 74 insertions(+), 19 deletions(-) diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 95a4187062f3..ccd4b2cccec1 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -1016,12 +1016,12 @@ void Basis::rotate_sh(real_t *p_values) { p_values[8] = d4 * s_scale_dst4; } -Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) { +Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_is_z_forward) { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero."); ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero."); #endif - Vector3 v_z = -p_target.normalized(); + Vector3 v_z = p_is_z_forward ? p_target.normalized() : -p_target.normalized(); Vector3 v_x = p_up.cross(v_z); #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other."); diff --git a/core/math/basis.h b/core/math/basis.h index bbc1d404697e..c7862390be28 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -217,7 +217,7 @@ struct _NO_DISCARD_ Basis { operator Quaternion() const { return get_quaternion(); } - static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_is_z_forward = false); Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }; Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); } diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index 8d497209f1df..f71fd97c0303 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -77,20 +77,20 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { basis.rotate(p_axis, p_angle); } -Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { +Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_is_z_forward) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal."); #endif Transform3D t = *this; - t.basis = Basis::looking_at(p_target - origin, p_up); + t.basis = Basis::looking_at(p_target - origin, p_up, p_is_z_forward); return t; } -void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { +void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_is_z_forward) { #ifdef MATH_CHECKS ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal."); #endif - basis = Basis::looking_at(p_target - p_eye, p_up); + basis = Basis::looking_at(p_target - p_eye, p_up, p_is_z_forward); origin = p_eye; } diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index bf1b4cdb6362..497b57c8827d 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -52,8 +52,8 @@ struct _NO_DISCARD_ Transform3D { void rotate(const Vector3 &p_axis, real_t p_angle); void rotate_basis(const Vector3 &p_axis, real_t p_angle); - void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); - Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const; + void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_is_z_forward = false); + Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_is_z_forward = false) const; void scale(const Vector3 &p_scale); Transform3D scaled(const Vector3 &p_scale) const; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 0c0c8f657a26..e494e36afc39 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -2083,7 +2083,7 @@ static void _register_variant_builtin_methods() { bind_method(Basis, is_equal_approx, sarray("b"), varray()); bind_method(Basis, is_finite, sarray(), varray()); bind_method(Basis, get_rotation_quaternion, sarray(), varray()); - bind_static_method(Basis, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0))); + bind_static_method(Basis, looking_at, sarray("target", "up", "is_z_forward"), varray(Vector3(0, 1, 0), false)); bind_static_method(Basis, from_scale, sarray("scale"), varray()); bind_static_method(Basis, from_euler, sarray("euler", "order"), varray((int64_t)EulerOrder::YXZ)); @@ -2126,7 +2126,7 @@ static void _register_variant_builtin_methods() { bind_method(Transform3D, scaled_local, sarray("scale"), varray()); bind_method(Transform3D, translated, sarray("offset"), varray()); bind_method(Transform3D, translated_local, sarray("offset"), varray()); - bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0))); + bind_method(Transform3D, looking_at, sarray("target", "up", "is_z_forward"), varray(Vector3(0, 1, 0), false)); bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray()); bind_method(Transform3D, is_equal_approx, sarray("xform"), varray()); bind_method(Transform3D, is_finite, sarray(), varray()); @@ -2512,6 +2512,12 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::VECTOR3, "DOWN", Vector3(0, -1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1)); _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_LEFT", Vector3(1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_RIGHT", Vector3(-1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_UP", Vector3(0, 1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_DOWN", Vector3(0, -1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_FORWARD", Vector3(0, 0, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "GLTF_BACK", Vector3(0, 0, -1)); _VariantCall::add_constant(Variant::VECTOR4, "AXIS_X", Vector4::AXIS_X); _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Y", Vector4::AXIS_Y); @@ -2555,6 +2561,12 @@ static void _register_variant_builtin_methods() { _VariantCall::add_variant_constant(Variant::VECTOR3I, "DOWN", Vector3i(0, -1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1)); _VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_LEFT", Vector3i(1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_RIGHT", Vector3i(-1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_UP", Vector3i(0, 1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_DOWN", Vector3i(0, -1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_FORWARD", Vector3i(0, 0, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "GLTF_BACK", Vector3i(0, 0, -1)); _VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X); _VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y); diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index 53dde5a286f8..72bd35a973eb 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -123,9 +123,11 @@ + Creates a Basis with a rotation such that the forward axis (-Z) points towards the [param target] position. The up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the forward axis. The resulting Basis is orthonormalized. The [param target] and [param up] vectors cannot be zero, and cannot be parallel to each other. + If [param is_z_forward] is [code]true[/code], the glTF forward axis (+Z) points towards the [param target] position. diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml index d751f2a8687f..428481bee458 100644 --- a/doc/classes/Node3D.xml +++ b/doc/classes/Node3D.xml @@ -112,11 +112,13 @@ + Rotates the node so that the local forward axis (-Z) points toward the [param target] position. The local up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the local forward axis. The resulting transform is orthogonal, and the scale is preserved. Non-uniform scaling may not work correctly. The [param target] position cannot be the same as the node's position, the [param up] vector cannot be zero, and the direction from the node's position to the [param target] vector cannot be parallel to the [param up] vector. Operations take place in global space, which means that the node must be in the scene tree. + If [param is_z_forward] is [code]true[/code], the glTF forward axis (+Z) points towards the [param target] position. @@ -124,6 +126,7 @@ + Moves the node to the specified [param position], and then rotates the node to point toward the [param target] as per [method look_at]. Operations take place in global space. diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 505d213cdbf8..43649bd8ed1f 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -93,9 +93,11 @@ + Returns a copy of the transform rotated such that the forward axis (-Z) points towards the [param target] position. The up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the forward axis. The resulting transform is orthonormalized. The existing rotation, scale, and skew information from the original transform is discarded. The [param target] and [param up] vectors cannot be zero, cannot be parallel to each other, and are defined in global/parent space. + If [param is_z_forward] is [code]true[/code], the glTF forward axis (+Z) points towards the [param target] position. diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 3957be5f1df6..a99edc839609 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -408,6 +408,24 @@ Back unit vector. Represents the local direction of back, and the global direction of south. + + Left unit vector in glTF space. + + + Right unit vector in glTF space. + + + Up unit vector in glTF space. + + + Down unit vector in glTF space. + + + Forward unit vector in glTF space. + + + Back unit vector in glTF space. + diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index 91ccfb6d8196..e40a8b9473dd 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -143,6 +143,24 @@ Back unit vector. Represents the local direction of back, and the global direction of south. + + Left unit vector in glTF space. + + + Right unit vector in glTF space. + + + Up unit vector in glTF space. + + + Down unit vector in glTF space. + + + Forward unit vector in glTF space. + + + Back unit vector in glTF space. + diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 66e8831d15ad..b84000f9a5fc 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -809,18 +809,18 @@ void Node3D::set_identity() { set_transform(Transform3D()); } -void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) { +void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up, bool p_is_z_forward) { ERR_FAIL_COND_MSG(!is_inside_tree(), "Node not inside tree. Use look_at_from_position() instead."); Vector3 origin = get_global_transform().origin; - look_at_from_position(origin, p_target, p_up); + look_at_from_position(origin, p_target, p_up, p_is_z_forward); } -void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) { +void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up, bool p_is_z_forward) { ERR_FAIL_COND_MSG(p_pos.is_equal_approx(p_target), "Node origin and target are in the same position, look_at() failed."); ERR_FAIL_COND_MSG(p_up.is_zero_approx(), "The up vector can't be zero, look_at() failed."); ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos).is_zero_approx(), "Up vector and direction between node origin and target are aligned, look_at() failed."); - Transform3D lookat = Transform3D(Basis::looking_at(p_target - p_pos, p_up), p_pos); + Transform3D lookat = Transform3D(Basis::looking_at(p_target - p_pos, p_up, p_is_z_forward), p_pos); Vector3 original_scale = get_scale(); set_global_transform(lookat); set_scale(original_scale); @@ -1056,8 +1056,8 @@ void Node3D::_bind_methods() { ClassDB::bind_method(D_METHOD("orthonormalize"), &Node3D::orthonormalize); ClassDB::bind_method(D_METHOD("set_identity"), &Node3D::set_identity); - ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Node3D::look_at, DEFVAL(Vector3(0, 1, 0))); - ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Node3D::look_at_from_position, DEFVAL(Vector3(0, 1, 0))); + ClassDB::bind_method(D_METHOD("look_at", "target", "up", "is_z_forward"), &Node3D::look_at, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up", "is_z_forward"), &Node3D::look_at_from_position, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node3D::to_local); ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node3D::to_global); diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 98bcab5fd492..f0b407ef9ea2 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -243,8 +243,8 @@ class Node3D : public Node { void global_scale(const Vector3 &p_scale); void global_translate(const Vector3 &p_offset); - void look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); - void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + void look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_is_z_forward = false); + void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_is_z_forward = false); Vector3 to_local(Vector3 p_global) const; Vector3 to_global(Vector3 p_local) const;