summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scene/3d/soft_body.cpp108
-rw-r--r--scene/3d/soft_body.h5
2 files changed, 72 insertions, 41 deletions
diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp
index 8498dc34c0..9655152c49 100644
--- a/scene/3d/soft_body.cpp
+++ b/scene/3d/soft_body.cpp
@@ -98,7 +98,7 @@ SoftBody::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
point_index = obj_tocopy.point_index;
spatial_attachment_path = obj_tocopy.spatial_attachment_path;
spatial_attachment = obj_tocopy.spatial_attachment;
- vertex_offset_transform = obj_tocopy.vertex_offset_transform;
+ offset = obj_tocopy.offset;
}
void SoftBody::_update_pickable() {
@@ -164,6 +164,7 @@ void SoftBody::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < pinned_points_indices_size; ++i) {
p_list->push_back(PropertyInfo(Variant::INT, "attachments/" + itos(i) + "/point_index"));
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "attachments/" + itos(i) + "/spatial_attachment_path"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "attachments/" + itos(i) + "/offset"));
}
}
@@ -204,6 +205,10 @@ bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &
if ("spatial_attachment_path" == p_what) {
PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
pin_point(w[p_item].point_index, true, p_value);
+ _make_cache_dirty();
+ } else if ("offset" == p_what) {
+ PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
+ w[p_item].offset = p_value;
} else {
return false;
}
@@ -221,6 +226,8 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var
r_ret = r[p_item].point_index;
} else if ("spatial_attachment_path" == p_what) {
r_ret = r[p_item].spatial_attachment_path;
+ } else if ("offset" == p_what) {
+ r_ret = r[p_item].offset;
} else {
return false;
}
@@ -245,7 +252,6 @@ void SoftBody::_notification(int p_what) {
RID space = get_world()->get_space();
PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space);
- PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
update_physics_server();
} break;
case NOTIFICATION_READY: {
@@ -255,20 +261,30 @@ void SoftBody::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!simulation_started) {
- PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
-
- _update_cache_pin_points_datas();
- // Submit bone attachment
- const int pinned_points_indices_size = pinned_points_indices.size();
- PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
- for (int i = 0; i < pinned_points_indices_size; ++i) {
- if (!r[i].spatial_attachment) {
- // Use soft body position to update the point position
- PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (get_global_transform() * r[i].vertex_offset_transform).origin);
- } else {
- PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, (r[i].spatial_attachment->get_global_transform() * r[i].vertex_offset_transform).origin);
- }
+ if (Engine::get_singleton()->is_editor_hint())
+ return;
+
+ PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform());
+
+ set_notify_transform(false);
+ // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform
+ set_as_toplevel(true);
+ set_transform(Transform());
+ set_notify_transform(true);
+
+ } break;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+
+ if (!simulation_started)
+ return;
+
+ _update_cache_pin_points_datas();
+ // Submit bone attachment
+ const int pinned_points_indices_size = pinned_points_indices.size();
+ PoolVector<PinnedPoint>::Read r = pinned_points_indices.read();
+ for (int i = 0; i < pinned_points_indices_size; ++i) {
+ if (r[i].spatial_attachment) {
+ PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset));
}
}
} break;
@@ -408,8 +424,15 @@ void SoftBody::_draw_soft_mesh() {
void SoftBody::update_physics_server() {
- if (Engine::get_singleton()->is_editor_hint())
+ if (Engine::get_singleton()->is_editor_hint()) {
+
+ if (get_mesh().is_valid())
+ PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
+ else
+ PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL);
+
return;
+ }
if (get_mesh().is_valid()) {
@@ -651,6 +674,8 @@ SoftBody::SoftBody() :
pinned_points_cache_dirty(true) {
PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
+ //set_notify_transform(true);
+ set_physics_process_internal(true);
}
SoftBody::~SoftBody() {
@@ -664,30 +689,24 @@ void SoftBody::reset_softbody_pin() {
}
}
-void SoftBody::_update_cache_pin_points_datas() {
- if (pinned_points_cache_dirty) {
- pinned_points_cache_dirty = false;
+void SoftBody::_make_cache_dirty() {
+ pinned_points_cache_dirty = true;
+}
- PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
- for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) {
+void SoftBody::_update_cache_pin_points_datas() {
+ if (!pinned_points_cache_dirty)
+ return;
- if (!w[i].spatial_attachment_path.is_empty()) {
- w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(w[i].spatial_attachment_path));
- if (w[i].spatial_attachment) {
+ pinned_points_cache_dirty = false;
- Transform point_global_transform(get_global_transform());
- point_global_transform.translate(PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index));
+ PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
+ for (int i = pinned_points_indices.size() - 1; 0 <= i; --i) {
- // Local transform relative to spatial attachment node
- w[i].vertex_offset_transform = w[i].spatial_attachment->get_global_transform().affine_inverse() * point_global_transform;
- continue;
- } else {
- ERR_PRINTS("The node with path: " + String(w[i].spatial_attachment_path) + " was not found or is not a spatial node.");
- }
- }
- // Local transform relative to Soft body
- w[i].vertex_offset_transform.origin = PhysicsServer::get_singleton()->soft_body_get_point_offset(physics_rid, w[i].point_index);
- w[i].vertex_offset_transform.basis = Basis();
+ if (!w[i].spatial_attachment_path.is_empty()) {
+ w[i].spatial_attachment = Object::cast_to<Spatial>(get_node(w[i].spatial_attachment_path));
+ }
+ if (!w[i].spatial_attachment) {
+ ERR_PRINT("Spatial node not defined in the pinned point, Softbody undefined behaviour!");
}
}
}
@@ -699,15 +718,28 @@ void SoftBody::_pin_point_on_physics_server(int p_point_index, bool pin) {
void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) {
SoftBody::PinnedPoint *pinned_point;
if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
+
// Create new
PinnedPoint pp;
pp.point_index = p_point_index;
pp.spatial_attachment_path = p_spatial_attachment_path;
+
+ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) {
+ pp.spatial_attachment = Object::cast_to<Spatial>(get_node(p_spatial_attachment_path));
+ pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index));
+ }
+
pinned_points_indices.push_back(pp);
+
} else {
- // Update
+
pinned_point->point_index = p_point_index;
pinned_point->spatial_attachment_path = p_spatial_attachment_path;
+
+ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) {
+ pinned_point->spatial_attachment = Object::cast_to<Spatial>(get_node(p_spatial_attachment_path));
+ pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index));
+ }
}
}
diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h
index f44f337698..6cf19ef8c4 100644
--- a/scene/3d/soft_body.h
+++ b/scene/3d/soft_body.h
@@ -72,9 +72,7 @@ public:
int point_index;
NodePath spatial_attachment_path;
Spatial *spatial_attachment; // Cache
- /// This is the offset from the soft body to point or attachment to point
- /// Depend if the spatial_attachment_node is NULL or not
- Transform vertex_offset_transform; // Cache
+ Vector3 offset;
PinnedPoint();
PinnedPoint(const PinnedPoint &obj_tocopy);
@@ -186,6 +184,7 @@ public:
private:
void reset_softbody_pin();
+ void _make_cache_dirty();
void _update_cache_pin_points_datas();
void _pin_point_on_physics_server(int p_point_index, bool pin);
void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path);