Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: Change look_at to have default up of Vector3.INF #6

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

# Based on Godot 4.3 but with changes
* [x] Expose Engine.get_frame_ticks to GDScript
* [x] Change look_at to have default up of Vector3.INF and find appropriate axis itself if Vector3.INF is argument.

# Get code

Expand Down
18 changes: 16 additions & 2 deletions core/math/basis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,13 +1042,27 @@ void Basis::rotate_sh(real_t *p_values) {
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
#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.");
ERR_FAIL_COND_V_MSG(p_up.is_finite() && p_up.is_zero_approx(), Basis(), "The up vector can't be zero.");
#endif
Vector3 v_z = p_target.normalized();
if (!p_use_model_front) {
v_z = -v_z;
}
Vector3 v_x = p_up.cross(v_z);

// Find an up vector that we can rotate around
Vector3 up = p_up;
if (! up.is_finite()) {
static const Vector3 up_candidates[3] = { Vector3(0, 1, 0), Vector3(1, 0, 0), Vector3(0, 0, 1) };
for (const Vector3 candidate : up_candidates) {
Vector3 v_x = candidate.cross(v_z).normalized();
if (! v_x.is_zero_approx()) {
up = candidate;
break;
}
}
}

Vector3 v_x = 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.");
#endif
Expand Down
2 changes: 1 addition & 1 deletion core/math/basis.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ struct [[nodiscard]] Basis {

operator Quaternion() const { return get_quaternion(); }

static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(INFINITY, INFINITY, INFINITY), bool p_use_model_front = 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); }
Expand Down
4 changes: 2 additions & 2 deletions core/math/transform_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ struct [[nodiscard]] 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), bool p_use_model_front = false);
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const;
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(INFINITY, INFINITY, INFINITY), bool p_use_model_front = false);
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(INFINITY, INFINITY, INFINITY), bool p_use_model_front = false) const;

void scale(const Vector3 &p_scale);
Transform3D scaled(const Vector3 &p_scale) const;
Expand Down
3 changes: 2 additions & 1 deletion doc/classes/Basis.xml
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,13 @@
<method name="looking_at" qualifiers="static">
<return type="Basis" />
<param index="0" name="target" type="Vector3" />
<param index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<param index="1" name="up" type="Vector3" default="Vector3.INF" />
<param index="2" name="use_model_front" type="bool" default="false" />
<description>
Creates a new [Basis] with a rotation such that the forward axis (-Z) points towards the [param target] position.
By default, the -Z axis (camera forward) is treated as forward (implies +X is right). If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward 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 returned basis is orthonormalized (see [method orthonormalized]). The [param target] and [param up] vectors cannot be [constant Vector3.ZERO], and cannot be parallel to each other.
If the [param up] is Vector3.INF, it will use Vector3.UP, Vector3.RIGHT, or Vector3.BACK to rotate around.
</description>
</method>
<method name="orthonormalized" qualifiers="const">
Expand Down
7 changes: 4 additions & 3 deletions doc/classes/Node3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,13 @@
<method name="look_at">
<return type="void" />
<param index="0" name="target" type="Vector3" />
<param index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<param index="1" name="up" type="Vector3" default="Vector3.INF" />
<param index="2" name="use_model_front" type="bool" default="false" />
<description>
Rotates the node so that the local forward axis (-Z, [constant Vector3.FORWARD]) 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.
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. If the
[param up] is Vector3.INF, it will use Vector3.UP, Vector3.RIGHT, or Vector3.BACK to rotate around.
Operations take place in global space, which means that the node must be in the scene tree.
If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward the [param target] position. By default, the -Z axis (camera forward) is treated as forward (implies +X is right).
</description>
Expand All @@ -128,7 +129,7 @@
<return type="void" />
<param index="0" name="position" type="Vector3" />
<param index="1" name="target" type="Vector3" />
<param index="2" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<param index="2" name="up" type="Vector3" default="Vector3.INF" />
<param index="3" name="use_model_front" type="bool" default="false" />
<description>
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.
Expand Down
3 changes: 2 additions & 1 deletion doc/classes/Transform3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,12 @@
<method name="looking_at" qualifiers="const">
<return type="Transform3D" />
<param index="0" name="target" type="Vector3" />
<param index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<param index="1" name="up" type="Vector3" default="Vector3.INF" />
<param index="2" name="use_model_front" type="bool" default="false" />
<description>
Returns a copy of this transform rotated so 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 the [param up] is Vector3.INF, it will use Vector3.UP, Vector3.RIGHT, or Vector3.BACK to rotate around.
If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward the [param target] position. By default, the -Z axis (camera forward) is treated as forward (implies +X is right).
</description>
</method>
Expand Down
2 changes: 1 addition & 1 deletion editor/import/3d/scene_import_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1735,7 +1735,7 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() {
camera->set_environment(environment);

light1 = memnew(DirectionalLight3D);
light1->set_transform(Transform3D(Basis::looking_at(Vector3(-1, -1, -1))));
light1->set_transform(Transform3D(Basis::looking_at(Vector3(-1, -1, -1), Vector3(INFINITY, INFINITY, INFINITY))));
light1->set_shadow(true);
camera->add_child(light1);

Expand Down
4 changes: 2 additions & 2 deletions editor/plugins/node_3d_editor_gizmos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
Transform3D t = spatial_node->get_global_transform();
Vector3 camera_position = p_camera->get_camera_transform().origin;
if (!camera_position.is_equal_approx(t.origin)) {
t.set_look_at(t.origin, camera_position);
t.set_look_at(t.origin, camera_position, Vector3(INFINITY, INFINITY, INFINITY));
}

float scale = t.origin.distance_to(p_camera->get_camera_transform().origin);
Expand All @@ -672,7 +672,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,

if (!orig_camera_transform.origin.is_equal_approx(t.origin) &&
ABS(orig_camera_transform.basis.get_column(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
p_camera->look_at(t.origin);
p_camera->look_at(t.origin, Vector3(INFINITY, INFINITY, INFINITY));
}

Vector3 c0 = t.xform(Vector3(selectable_icon_size, selectable_icon_size, 0) * scale);
Expand Down
4 changes: 2 additions & 2 deletions scene/3d/node_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,8 +1195,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", "use_model_front"), &Node3D::look_at, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up", "use_model_front"), &Node3D::look_at_from_position, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("look_at", "target", "up", "use_model_front"), &Node3D::look_at, DEFVAL(Vector3(INFINITY, INFINITY, INFINITY)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up", "use_model_front"), &Node3D::look_at_from_position, DEFVAL(Vector3(INFINITY, INFINITY, INFINITY)), 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);
Expand Down
4 changes: 2 additions & 2 deletions scene/3d/node_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,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), bool p_use_model_front = false);
void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
void look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(INFINITY, INFINITY, INFINITY), bool p_use_model_front = false);
void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up = Vector3(INFINITY, INFINITY, INFINITY), bool p_use_model_front = false);

Vector3 to_local(Vector3 p_global) const;
Vector3 to_global(Vector3 p_local) const;
Expand Down
2 changes: 1 addition & 1 deletion scene/3d/path_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D:
Vector3 tangent = -t.basis.get_column(2);

// Y-axis points up by default.
t.basis = Basis::looking_at(tangent);
t.basis = Basis::looking_at(tangent, Vector3(INFINITY, INFINITY, INFINITY));
} else {
// Lock some euler axes.
Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
Expand Down
2 changes: 1 addition & 1 deletion tests/scene/test_camera_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ TEST_CASE("[SceneTree][Camera3D] Position queries") {
// The orthogonal case is simpler, so we test a more random position + rotation combination here.
// For the other cases we'll use zero translation and rotation instead.
test_camera->set_global_position(Vector3(1, 2, 3));
test_camera->look_at(Vector3(-4, 5, 1));
test_camera->look_at(Vector3(-4, 5, 1), Vector3(INFINITY, INFINITY, INFINITY));
// Width = 5, Aspect Ratio = 400 / 200 = 2, so Height is 2.5.
test_camera->set_orthogonal(5.0f, 0.5f, 1000.0f);
const Basis basis = test_camera->get_global_basis();
Expand Down
Loading