summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/collision_object_3d.cpp125
-rw-r--r--scene/3d/collision_object_3d.h15
-rw-r--r--scene/3d/collision_shape_3d.cpp14
-rw-r--r--scene/3d/collision_shape_3d.h2
-rw-r--r--scene/3d/gi_probe.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp1
-rw-r--r--scene/3d/mesh_instance_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp2
-rw-r--r--scene/3d/ray_cast_3d.cpp2
-rw-r--r--scene/3d/skeleton_3d.cpp87
-rw-r--r--scene/3d/skeleton_3d.h2
-rw-r--r--scene/3d/skeleton_ik_3d.cpp69
12 files changed, 178 insertions, 145 deletions
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 688509a979..914b3ad816 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -31,12 +31,27 @@
#include "collision_object_3d.h"
#include "core/config/engine.h"
-#include "mesh_instance_3d.h"
#include "scene/scene_string_names.h"
#include "servers/physics_server_3d.h"
void CollisionObject3D::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (_are_collision_shapes_visible()) {
+ debug_shape_old_transform = get_global_transform();
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ debug_shapes_to_update.insert(E->key());
+ }
+ _update_debug_shapes();
+ }
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (debug_shapes_count > 0) {
+ _clear_debug_shapes();
+ }
+ } break;
+
case NOTIFICATION_ENTER_WORLD: {
if (area) {
PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform());
@@ -62,6 +77,8 @@ void CollisionObject3D::_notification(int p_what) {
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
}
+ _on_transform_changed();
+
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
@@ -75,11 +92,6 @@ void CollisionObject3D::_notification(int p_what) {
}
} break;
- case NOTIFICATION_PREDELETE: {
- if (debug_shape_count > 0) {
- _clear_debug_shapes();
- }
- } break;
}
}
@@ -175,6 +187,33 @@ void CollisionObject3D::_update_pickable() {
}
}
+bool CollisionObject3D::_are_collision_shapes_visible() {
+ return is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint();
+}
+
+void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
+ if (_are_collision_shapes_visible()) {
+ if (debug_shapes_to_update.is_empty()) {
+ callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0);
+ }
+ debug_shapes_to_update.insert(p_owner);
+ }
+}
+
+void CollisionObject3D::_shape_changed(const Ref<Shape3D> &p_shape) {
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ShapeData &shapedata = E->get();
+ ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
+ ShapeData::ShapeBase &s = shapes[i];
+ if (s.shape == p_shape && s.debug_shape.is_valid()) {
+ Ref<Mesh> mesh = s.shape->get_debug_mesh();
+ RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
+ }
+ }
+ }
+}
+
void CollisionObject3D::_update_debug_shapes() {
for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
if (shapes.has(shapedata_idx->get())) {
@@ -182,23 +221,30 @@ void CollisionObject3D::_update_debug_shapes() {
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
for (int i = 0; i < shapedata.shapes.size(); i++) {
ShapeData::ShapeBase &s = shapes[i];
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
- s.debug_shape = nullptr;
- --debug_shape_count;
- }
if (s.shape.is_null() || shapedata.disabled) {
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ s.debug_shape = RID();
+ --debug_shapes_count;
+ }
continue;
}
+ if (s.debug_shape.is_null()) {
+ s.debug_shape = RS::get_singleton()->instance_create();
+ RS::get_singleton()->instance_set_scenario(s.debug_shape, get_world_3d()->get_scenario());
+
+ if (!s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) {
+ s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed),
+ varray(s.shape), CONNECT_DEFERRED);
+ }
+
+ ++debug_shapes_count;
+ }
+
Ref<Mesh> mesh = s.shape->get_debug_mesh();
- MeshInstance3D *mi = memnew(MeshInstance3D);
- mi->set_transform(shapedata.xform);
- mi->set_mesh(mesh);
- add_child(mi);
- mi->force_update_transform();
- s.debug_shape = mi;
- ++debug_shape_count;
+ RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
+ RS::get_singleton()->instance_set_transform(s.debug_shape, get_global_transform() * shapedata.xform);
}
}
}
@@ -211,23 +257,28 @@ void CollisionObject3D::_clear_debug_shapes() {
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
for (int i = 0; i < shapedata.shapes.size(); i++) {
ShapeData::ShapeBase &s = shapes[i];
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
- s.debug_shape = nullptr;
- --debug_shape_count;
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ s.debug_shape = RID();
+ if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_update_shape_data))) {
+ s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_update_shape_data));
+ }
}
}
}
-
- debug_shape_count = 0;
+ debug_shapes_count = 0;
}
-void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) {
- if (debug_shapes_to_update.is_empty()) {
- call_deferred("_update_debug_shapes");
+void CollisionObject3D::_on_transform_changed() {
+ if (debug_shapes_count > 0 && !debug_shape_old_transform.is_equal_approx(get_global_transform())) {
+ debug_shape_old_transform = get_global_transform();
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ShapeData &shapedata = E->get();
+ const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr();
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
+ RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform);
+ }
}
- debug_shapes_to_update.insert(p_owner);
}
}
@@ -270,8 +321,6 @@ void CollisionObject3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes);
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner);
- ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes);
-
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
@@ -316,7 +365,11 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl
ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner];
+ if (sd.disabled == p_disabled) {
+ return;
+ }
sd.disabled = p_disabled;
+
for (int i = 0; i < sd.shapes.size(); i++) {
if (area) {
PhysicsServer3D::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
@@ -421,7 +474,7 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
- const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
+ ShapeData::ShapeBase &s = shapes[p_owner].shapes.write[p_shape];
int index_to_remove = s.index;
if (area) {
@@ -430,8 +483,12 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove);
}
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) {
+ s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_shape_changed));
+ }
+ --debug_shapes_count;
}
shapes[p_owner].shapes.remove(p_shape);
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index e3901979d3..7ff3c5efde 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -48,7 +48,7 @@ class CollisionObject3D : public Node3D {
Object *owner = nullptr;
Transform xform;
struct ShapeBase {
- Node *debug_shape = nullptr;
+ RID debug_shape;
Ref<Shape3D> shape;
int index = 0;
};
@@ -65,25 +65,30 @@ class CollisionObject3D : public Node3D {
bool ray_pickable = true;
Set<uint32_t> debug_shapes_to_update;
- int debug_shape_count = 0;
+ int debug_shapes_count = 0;
+ Transform debug_shape_old_transform;
void _update_pickable();
+ bool _are_collision_shapes_visible();
void _update_shape_data(uint32_t p_owner);
+ void _shape_changed(const Ref<Shape3D> &p_shape);
+ void _update_debug_shapes();
+ void _clear_debug_shapes();
protected:
CollisionObject3D(RID p_rid, bool p_area);
void _notification(int p_what);
static void _bind_methods();
+
+ void _on_transform_changed();
+
friend class Viewport;
virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
virtual void _mouse_enter();
virtual void _mouse_exit();
- void _update_debug_shapes();
- void _clear_debug_shapes();
-
public:
void set_collision_layer(uint32_t p_layer);
uint32_t get_collision_layer() const;
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index bec87914c0..70d9cebb83 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -161,12 +161,10 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
}
if (!shape.is_null()) {
shape->unregister_owner(this);
- shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
}
shape = p_shape;
if (!shape.is_null()) {
shape->register_owner(this);
- shape->connect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
}
update_gizmo();
if (parent) {
@@ -176,8 +174,9 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
}
}
- if (is_inside_tree()) {
- _shape_changed();
+ if (is_inside_tree() && parent) {
+ // If this is a heightfield shape our center may have changed
+ _update_in_shape_owner(true);
}
update_configuration_warnings();
}
@@ -209,10 +208,3 @@ CollisionShape3D::~CollisionShape3D() {
}
//RenderingServer::get_singleton()->free(indicator);
}
-
-void CollisionShape3D::_shape_changed() {
- // If this is a heightfield shape our center may have changed
- if (parent) {
- _update_in_shape_owner(true);
- }
-}
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h
index 56a4ae3039..f69c1e38eb 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/collision_shape_3d.h
@@ -47,8 +47,6 @@ class CollisionShape3D : public Node3D {
bool disabled = false;
protected:
- void _shape_changed();
-
void _update_in_shape_owner(bool p_xform_only = false);
protected:
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 4d7fc29f15..6505fb1ee8 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -454,7 +454,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
mmi->set_multimesh(baker.create_debug_multimesh());
add_child(mmi);
#ifdef TOOLS_ENABLED
- if (get_tree()->get_edited_scene_root() == this) {
+ if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) {
mmi->set_owner(this);
} else {
mmi->set_owner(get_owner());
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 5339b8a8da..50044ddc67 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -613,6 +613,7 @@ void GPUParticles3D::_bind_methods() {
GPUParticles3D::GPUParticles3D() {
particles = RS::get_singleton()->particles_create();
+ RS::get_singleton()->particles_set_mode(particles, RS::PARTICLES_MODE_3D);
set_base(particles);
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
set_emitting(true);
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 27d5487a1a..c495f68890 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -427,7 +427,7 @@ void MeshInstance3D::create_debug_tangents() {
add_child(mi);
#ifdef TOOLS_ENABLED
- if (this == get_tree()->get_edited_scene_root()) {
+ if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) {
mi->set_owner(this);
} else {
mi->set_owner(get_owner());
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 93d3e946fd..dd1a797568 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -292,6 +292,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
get_script_instance()->call("_integrate_forces", state);
}
set_ignore_transform_notification(false);
+ _on_transform_changed();
if (contact_monitor) {
contact_monitor->locked = true;
@@ -1985,6 +1986,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) {
set_ignore_transform_notification(true);
set_global_transform(global_transform);
set_ignore_transform_notification(false);
+ _on_transform_changed();
// Update skeleton
if (parent_skeleton) {
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 95638ce514..475f8c07fd 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -428,7 +428,7 @@ void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
color = get_tree()->get_debug_collisions_color();
}
- if (p_check_collision) {
+ if (p_check_collision && collided) {
if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) {
// If base color is already quite reddish, highlight collision with green color
color = Color(0.0, 1.0, 0.0, color.a);
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index ebbb8985c9..59233708f6 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -237,53 +237,57 @@ void Skeleton3D::_notification(int p_what) {
for (int i = 0; i < len; i++) {
Bone &b = bonesptr[order[i]];
- if (b.global_pose_override_amount >= 0.999) {
- b.pose_global = b.global_pose_override;
- } else {
- if (b.disable_rest) {
- if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * pose;
- } else {
- b.pose_global = pose;
- }
+ if (b.disable_rest) {
+ if (b.enabled) {
+ Transform pose = b.pose;
+ if (b.custom_pose_enable) {
+ pose = b.custom_pose * pose;
+ }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * pose;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * pose;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global;
- } else {
- b.pose_global = Transform();
- }
+ b.pose_global = pose;
+ b.pose_global_no_override = pose;
}
-
} else {
- if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
- } else {
- b.pose_global = b.rest * pose;
- }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * b.rest;
- } else {
- b.pose_global = b.rest;
- }
+ b.pose_global = Transform();
+ b.pose_global_no_override = Transform();
}
}
- if (b.global_pose_override_amount >= CMP_EPSILON) {
- b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount);
+ } else {
+ if (b.enabled) {
+ Transform pose = b.pose;
+ if (b.custom_pose_enable) {
+ pose = b.custom_pose * pose;
+ }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * (b.rest * pose);
+ } else {
+ b.pose_global = b.rest * pose;
+ b.pose_global_no_override = b.rest * pose;
+ }
+ } else {
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * b.rest;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * b.rest;
+ } else {
+ b.pose_global = b.rest;
+ b.pose_global_no_override = b.rest;
+ }
}
}
+ if (b.global_pose_override_amount >= CMP_EPSILON) {
+ b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount);
+ }
+
if (b.global_pose_override_reset) {
b.global_pose_override_amount = 0.0;
}
@@ -408,6 +412,14 @@ Transform Skeleton3D::get_bone_global_pose(int p_bone) const {
return bones[p_bone].pose_global;
}
+Transform Skeleton3D::get_bone_global_pose_no_override(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+ if (dirty) {
+ const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
+ }
+ return bones[p_bone].pose_global_no_override;
+}
+
// skeleton creation api
void Skeleton3D::add_bone(const String &p_name) {
ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1);
@@ -912,6 +924,7 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override);
ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose);
+ ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_no_override);
ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose);
ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose);
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 2941ac2c45..508cd7c329 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -83,6 +83,7 @@ private:
Transform pose;
Transform pose_global;
+ Transform pose_global_no_override;
bool custom_pose_enable = false;
Transform custom_pose;
@@ -160,6 +161,7 @@ public:
void set_bone_rest(int p_bone, const Transform &p_rest);
Transform get_bone_rest(int p_bone) const;
Transform get_bone_global_pose(int p_bone) const;
+ Transform get_bone_global_pose_no_override(int p_bone) const;
void clear_bones_global_pose_override();
void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false);
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 898f94ccc1..bd1c202205 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -246,7 +246,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform;
} else {
// End effector in local transform
- const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors[0].tip_bone));
+ const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose_no_override(p_task->end_effectors[0].tip_bone));
// Update the end_effector (local transform) by blending with current pose
p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta);
@@ -270,18 +270,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
return; // Skip solving
}
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, true);
-
- if (p_task->chain.middle_chain_item) {
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.middle_chain_item->bone, Transform(), 0.0, true);
- }
-
- for (int i = 0; i < p_task->chain.tips.size(); i += 1) {
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true);
- }
-
- // Update the transforms to their global poses
- // (Needed to sync IK with animation)
+ // Update the initial root transform so its synced with any animation changes
_update_chain(p_task->skeleton, &p_task->chain.chain_root);
make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta);
@@ -298,48 +287,22 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
Transform new_bone_pose(ci->initial_transform);
new_bone_pose.origin = ci->current_pos;
- // The root bone needs to be rotated differently so it isn't frozen in place.
- if (ci == &p_task->chain.chain_root && !ci->children.is_empty()) {
- new_bone_pose = new_bone_pose.looking_at(ci->children[0].current_pos);
- const Vector3 bone_rest_dir = p_task->skeleton->get_bone_rest(ci->children[0].bone).origin.normalized().abs();
- const Vector3 bone_rest_dir_abs = bone_rest_dir.abs();
- if (bone_rest_dir_abs.x > bone_rest_dir_abs.y && bone_rest_dir_abs.x > bone_rest_dir_abs.z) {
- if (bone_rest_dir.x < 0) {
- new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), -Math_PI / 2.0f);
- } else {
- new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), Math_PI / 2.0f);
- }
- } else if (bone_rest_dir_abs.y > bone_rest_dir_abs.x && bone_rest_dir_abs.y > bone_rest_dir_abs.z) {
- if (bone_rest_dir.y < 0) {
- new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), Math_PI / 2.0f);
- } else {
- new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), -Math_PI / 2.0f);
- }
- } else {
- if (bone_rest_dir.z < 0) {
- // Do nothing!
- } else {
- new_bone_pose.basis.rotate_local(Vector3(0, 0, 1), Math_PI);
- }
- }
- } else {
- if (!ci->children.is_empty()) {
- /// Rotate basis
- const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized());
- const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());
+ if (!ci->children.is_empty()) {
+ /// Rotate basis
+ const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized());
+ const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());
- if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) {
- const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
- new_bone_pose.basis.rotate(rot_axis, rot_angle);
- }
+ if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) {
+ const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
+ new_bone_pose.basis.rotate(rot_axis, rot_angle);
+ }
+ } else {
+ // Set target orientation to tip
+ if (override_tip_basis) {
+ new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
} else {
- // Set target orientation to tip
- if (override_tip_basis) {
- new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
- } else {
- new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
- }
+ new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
}
@@ -362,7 +325,7 @@ void FabrikInverseKinematic::_update_chain(const Skeleton3D *p_sk, ChainItem *p_
return;
}
- p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone);
+ p_chain_item->initial_transform = p_sk->get_bone_global_pose_no_override(p_chain_item->bone);
p_chain_item->current_pos = p_chain_item->initial_transform.origin;
ChainItem *items = p_chain_item->children.ptrw();