mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-24 12:47:12 +01:00
Backported from godot4: Add the ability to look-at in model-space.
This is a much simpler attempt to solve the same problem as #76060, but
without breaking any compatibility.
* Adds a description of what model space is in the Vector3 enums
(MODEL_* constants). This has the proper axes laid out for imported 3D
assets.
* Adds the option to `look_at` using model_space, which uses
Vector3.MODEL_FRONT as forward vector.
The attempt of this PR is to still break the assumption that there is a
single direction of forward (which is not the case in Godot)
and make it easier to understand where 3D models are facing, as well as
orienting them via look_at.
- reduz
5fdc1232ef
Also bound the new Basis helper methods.
This commit is contained in:
parent
422314a8fd
commit
951ae7b11d
@ -217,12 +217,17 @@ Basis Basis::transposed() const {
|
||||
return tr;
|
||||
}
|
||||
|
||||
Basis Basis::create_looking_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
Basis Basis::create_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_equal_approx(Vector3()), Basis(), "The target vector can't be zero.");
|
||||
ERR_FAIL_COND_V_MSG(p_up.is_equal_approx(Vector3()), Basis(), "The up vector can't be zero.");
|
||||
#endif
|
||||
Vector3 v_z = -p_target.normalized();
|
||||
Vector3 v_z = p_target.normalized();
|
||||
|
||||
if (!p_use_model_front) {
|
||||
v_z = -v_z;
|
||||
}
|
||||
|
||||
Vector3 v_x = p_up.cross(v_z);
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(v_x.is_equal_approx(Vector3()), Basis(), "The target vector and up vector can't be parallel to each other.");
|
||||
@ -235,19 +240,20 @@ Basis Basis::create_looking_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
return basis;
|
||||
}
|
||||
|
||||
Basis Basis::create_from_scale(const Vector3 &p_scale) {
|
||||
return Basis(p_scale.x, 0, 0, 0, p_scale.y, 0, 0, 0, p_scale.z);
|
||||
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
return Basis::create_looking_at(p_target, p_up, p_use_model_front);
|
||||
}
|
||||
|
||||
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
return Basis::create_looking_at(p_target, p_up);
|
||||
}
|
||||
void Basis::set_look_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
void Basis::set_look_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_MSG(p_target.is_equal_approx(Vector3()), "The target vector can't be zero.");
|
||||
ERR_FAIL_COND_MSG(p_up.is_equal_approx(Vector3()), "The up vector can't be zero.");
|
||||
#endif
|
||||
Vector3 v_z = -p_target.normalized();
|
||||
Vector3 v_z = p_target.normalized();
|
||||
|
||||
if (!p_use_model_front) {
|
||||
v_z = -v_z;
|
||||
}
|
||||
|
||||
Vector3 v_x = p_up.cross(v_z);
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_MSG(v_x.is_equal_approx(Vector3()), "The target vector and up vector can't be parallel to each other.");
|
||||
@ -258,6 +264,9 @@ void Basis::set_look_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
set_columns(v_x, v_y, v_z);
|
||||
}
|
||||
|
||||
Basis Basis::create_from_scale(const Vector3 &p_scale) {
|
||||
return Basis(p_scale.x, 0, 0, 0, p_scale.y, 0, 0, 0, p_scale.z);
|
||||
}
|
||||
Basis Basis::from_scale(const Vector3 &p_scale) {
|
||||
return Basis::create_from_scale(p_scale);
|
||||
}
|
||||
|
@ -286,12 +286,11 @@ struct _NO_DISCARD_CLASS_ Basis {
|
||||
// only be used in cases of single normals, or when the basis changes each time.
|
||||
Vector3 xform_normal(const Vector3 &p_vector) const { return get_normal_xform_basis().xform_normal_fast(p_vector); }
|
||||
|
||||
static Basis create_looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
|
||||
static Basis create_looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||
Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||
void set_look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||
|
||||
static Basis create_from_scale(const Vector3 &p_scale);
|
||||
|
||||
Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
|
||||
void set_look_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
|
||||
|
||||
Basis from_scale(const Vector3 &p_scale);
|
||||
|
||||
operator Quaternion() const { return get_quaternion(); }
|
||||
|
@ -82,14 +82,14 @@ void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
|
||||
basis.rotate(p_axis, p_phi);
|
||||
}
|
||||
|
||||
void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
|
||||
basis = Basis::create_looking_at(p_target - p_eye, p_up);
|
||||
void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
basis = Basis::create_looking_at(p_target - p_eye, p_up, p_use_model_front);
|
||||
origin = p_eye;
|
||||
}
|
||||
|
||||
Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
|
||||
Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) const {
|
||||
Transform t = *this;
|
||||
t.set_look_at(origin, p_target, p_up);
|
||||
t.set_look_at(origin, p_target, p_up,p_use_model_front);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ struct _NO_DISCARD_CLASS_ Transform {
|
||||
void rotate_local(const Vector3 &p_axis, real_t p_phi);
|
||||
void rotate_basis(const Vector3 &p_axis, real_t p_phi);
|
||||
|
||||
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
|
||||
Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
|
||||
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front = false);
|
||||
Transform looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front = false) const;
|
||||
|
||||
void scale(const Vector3 &p_scale);
|
||||
Transform scaled(const Vector3 &p_scale) const;
|
||||
|
@ -1541,6 +1541,8 @@ struct _VariantCall {
|
||||
VCALL_PTR0R(Basis, orthogonalized);
|
||||
VCALL_PTR0R(Basis, is_symmetric);
|
||||
VCALL_PTR0R(Basis, diagonalize);
|
||||
VCALL_PTR3R(Basis, looking_at);
|
||||
VCALL_PTR3(Basis, set_look_at);
|
||||
|
||||
static void _call_Basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) {
|
||||
switch (p_args[0]->type) {
|
||||
@ -3375,6 +3377,8 @@ void register_variant_methods() {
|
||||
ADDFUNC0R(BASIS, BASIS, Basis, orthogonalized, varray());
|
||||
ADDFUNC0R(BASIS, BOOL, Basis, is_symmetric, varray());
|
||||
ADDFUNC0R(BASIS, BASIS, Basis, diagonalize, varray());
|
||||
ADDFUNC3R(BASIS, BASIS, Basis, looking_at, VECTOR3, "target", VECTOR3, "up", BOOL, "use_model_front", varray(Vector3(0, 1, 0), false));
|
||||
ADDFUNC3(BASIS, NIL, Basis, set_look_at, VECTOR3, "target", VECTOR3, "up", BOOL, "use_model_front", varray(Vector3(0, 1, 0), false));
|
||||
ADDFUNC1R(BASIS, VECTOR3, Basis, xform, NIL, "v3_or_v3i", varray());
|
||||
ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, NIL, "v3_or_v3i", varray());
|
||||
|
||||
@ -3387,8 +3391,8 @@ void register_variant_methods() {
|
||||
ADDFUNC2(TRANSFORM, NIL, Transform, rotate, VECTOR3, "axis", REAL, "phi", varray());
|
||||
ADDFUNC2(TRANSFORM, NIL, Transform, rotate_local, VECTOR3, "axis", REAL, "phi", varray());
|
||||
ADDFUNC2(TRANSFORM, NIL, Transform, rotate_basis, VECTOR3, "axis", REAL, "phi", varray());
|
||||
ADDFUNC3(TRANSFORM, NIL, Transform, set_look_at, VECTOR3, "eye", VECTOR3, "target", VECTOR3, "up", varray());
|
||||
ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray());
|
||||
ADDFUNC4(TRANSFORM, NIL, Transform, set_look_at, VECTOR3, "eye", VECTOR3, "target", VECTOR3, "up", BOOL, "use_model_front", varray(false));
|
||||
ADDFUNC3R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", BOOL, "use_model_front", varray(false));
|
||||
ADDFUNC1(TRANSFORM, NIL, Transform, scale, VECTOR3, "scale", varray());
|
||||
ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray());
|
||||
ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled_local, VECTOR3, "scale", varray());
|
||||
@ -3530,6 +3534,13 @@ void register_variant_methods() {
|
||||
_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, "MODEL_LEFT", Vector3(1, 0, 0));
|
||||
_VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_RIGHT", Vector3(-1, 0, 0));
|
||||
_VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_TOP", Vector3(0, 1, 0));
|
||||
_VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_BOTTOM", Vector3(0, -1, 0));
|
||||
_VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_FRONT", Vector3(0, 0, 1));
|
||||
_VariantCall::add_variant_constant(Variant::VECTOR3, "MODEL_REAR", Vector3(0, 0, -1));
|
||||
|
||||
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X);
|
||||
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y);
|
||||
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z);
|
||||
|
@ -225,6 +225,25 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="looking_at">
|
||||
<return type="Basis" />
|
||||
<argument index="0" name="target" type="Vector3" />
|
||||
<argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
|
||||
<argument index="2" name="use_model_front" type="bool" default="false" />
|
||||
<description>
|
||||
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.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_look_at">
|
||||
<argument index="0" name="target" type="Vector3" />
|
||||
<argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
|
||||
<argument index="2" name="use_model_front" type="bool" default="false" />
|
||||
<description>
|
||||
Sets this 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.
|
||||
</description>
|
||||
</method>
|
||||
<method name="orthogonalize">
|
||||
<description>
|
||||
</description>
|
||||
|
@ -125,9 +125,10 @@
|
||||
<method name="look_at">
|
||||
<return type="void" />
|
||||
<argument index="0" name="target" type="Vector3" />
|
||||
<argument index="1" name="up" type="Vector3" />
|
||||
<argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
|
||||
<argument index="2" name="use_model_front" type="bool" default="false" />
|
||||
<description>
|
||||
Rotates the node so that the local forward axis (-Z) points toward the [code]target[/code] position.
|
||||
Rotates the node so that the local forward axis (-Z, [constant Vector3.FORWARD]) points toward the [code]target[/code] position. If the [param use_model_front] options is specified, then the model is oriented in reverse, towards the model front axis (+Z, [constant Vector3.MODEL_FRONT]), which is more useful for orienting 3D models.
|
||||
The local up axis (+Y) points as close to the [code]up[/code] 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 [code]target[/code] position cannot be the same as the node's position, the [code]up[/code] vector cannot be zero, and the direction from the node's position to the [code]target[/code] vector cannot be parallel to the [code]up[/code] vector.
|
||||
Operations take place in global space.
|
||||
@ -137,7 +138,8 @@
|
||||
<return type="void" />
|
||||
<argument index="0" name="position" type="Vector3" />
|
||||
<argument index="1" name="target" type="Vector3" />
|
||||
<argument index="2" name="up" type="Vector3" />
|
||||
<argument index="2" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
|
||||
<argument index="3" name="use_model_front" type="bool" default="false" />
|
||||
<description>
|
||||
Moves the node to the specified [code]position[/code], and then rotates itself to point toward the [code]target[/code] as per [method look_at]. Operations take place in global space.
|
||||
</description>
|
||||
|
@ -104,8 +104,9 @@
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="target" type="Vector3" />
|
||||
<argument index="1" name="up" type="Vector3" />
|
||||
<argument index="2" name="use_model_front" type="bool" default="false" />
|
||||
<description>
|
||||
Returns a copy of the transform rotated such that its -Z axis points towards the [code]target[/code] position.
|
||||
Returns a copy of the transform rotated such that its (-Z, [constant Vector3.FORWARD]) axis points towards the [code]target[/code] position. If the [param use_model_front] options is specified, then the model is oriented in reverse, towards the model front axis (+Z, [constant Vector3.MODEL_FRONT]), which is more useful for orienting 3D models.
|
||||
The transform will first be rotated around the given [code]up[/code] vector, and then fully aligned to the target by a further rotation around an axis perpendicular to both the [code]target[/code] and [code]up[/code] vectors.
|
||||
Operations take place in global space.
|
||||
</description>
|
||||
|
@ -389,10 +389,28 @@
|
||||
Down unit vector.
|
||||
</constant>
|
||||
<constant name="FORWARD" value="Vector3( 0, 0, -1 )">
|
||||
Forward unit vector. Represents the local direction of forward, and the global direction of north.
|
||||
Forward unit vector. Represents the local direction of forward, and the global direction of north. Keep in mind that the forward direction for lights, cameras, etc is different from 3D assets like characters, which face towards the camera by convention. Use [constant Vector3.MODEL_FRONT] and similar constants when working in 3D asset space.
|
||||
</constant>
|
||||
<constant name="BACK" value="Vector3( 0, 0, 1 )">
|
||||
Back unit vector. Represents the local direction of back, and the global direction of south.
|
||||
</constant>
|
||||
<constant name="MODEL_LEFT" value="Vector3(1, 0, 0)">
|
||||
Unit vector pointing towards the left side of imported 3D assets.
|
||||
</constant>
|
||||
<constant name="MODEL_RIGHT" value="Vector3(-1, 0, 0)">
|
||||
Unit vector pointing towards the right side of imported 3D assets.
|
||||
</constant>
|
||||
<constant name="MODEL_TOP" value="Vector3(0, 1, 0)">
|
||||
Unit vector pointing towards the top side (up) of imported 3D assets.
|
||||
</constant>
|
||||
<constant name="MODEL_BOTTOM" value="Vector3(0, -1, 0)">
|
||||
Unit vector pointing towards the bottom side (down) of imported 3D assets.
|
||||
</constant>
|
||||
<constant name="MODEL_FRONT" value="Vector3(0, 0, 1)">
|
||||
Unit vector pointing towards the front side (facing forward) of imported 3D assets.
|
||||
</constant>
|
||||
<constant name="MODEL_REAR" value="Vector3(0, 0, -1)">
|
||||
Unit vector pointing towards the rear side (back) of imported 3D assets.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
@ -900,22 +900,20 @@ void Spatial::set_identity() {
|
||||
set_transform(Transform());
|
||||
}
|
||||
|
||||
void Spatial::look_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
void Spatial::look_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
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_use_model_front);
|
||||
}
|
||||
|
||||
void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
|
||||
void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed.");
|
||||
ERR_FAIL_COND_MSG(p_up == Vector3(), "The up vector can't be zero, look_at() failed.");
|
||||
ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed.");
|
||||
|
||||
Transform lookat;
|
||||
lookat.origin = p_pos;
|
||||
|
||||
Vector3 original_scale(get_scale());
|
||||
lookat = lookat.looking_at(p_target, p_up);
|
||||
set_global_transform(lookat);
|
||||
Vector3 forward = p_target - p_pos;
|
||||
Basis lookat_basis = Basis::create_looking_at(forward, p_up, p_use_model_front);
|
||||
Vector3 original_scale = get_scale();
|
||||
set_global_transform(Transform(lookat_basis, p_pos));
|
||||
set_scale(original_scale);
|
||||
}
|
||||
|
||||
@ -1048,8 +1046,8 @@ void Spatial::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("orthonormalize"), &Spatial::orthonormalize);
|
||||
ClassDB::bind_method(D_METHOD("set_identity"), &Spatial::set_identity);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Spatial::look_at);
|
||||
ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Spatial::look_at_from_position);
|
||||
ClassDB::bind_method(D_METHOD("look_at", "target", "up", "use_model_front"), &Spatial::look_at, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up", "use_model_front"), &Spatial::look_at_from_position, DEFVAL(Vector3(0, 1, 0)), DEFVAL(false));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_merging_mode", "mode"), &Spatial::set_merging_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_merging_mode"), &Spatial::get_merging_mode);
|
||||
|
@ -237,8 +237,8 @@ public:
|
||||
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);
|
||||
void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up);
|
||||
void look_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front = false);
|
||||
void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front = false);
|
||||
|
||||
Vector3 to_local(Vector3 p_global) const;
|
||||
Vector3 to_global(Vector3 p_local) const;
|
||||
|
Loading…
Reference in New Issue
Block a user