Fixed Softbody pin point

This commit is contained in:
Andrea Catania 2018-07-27 19:10:16 +02:00
parent 07129deaeb
commit 45160f0c0d
2 changed files with 71 additions and 40 deletions

View File

@ -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) {
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) {
// 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 (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,8 +689,14 @@ void SoftBody::reset_softbody_pin() {
}
}
void SoftBody::_make_cache_dirty() {
pinned_points_cache_dirty = true;
}
void SoftBody::_update_cache_pin_points_datas() {
if (pinned_points_cache_dirty) {
if (!pinned_points_cache_dirty)
return;
pinned_points_cache_dirty = false;
PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
@ -673,21 +704,9 @@ void SoftBody::_update_cache_pin_points_datas() {
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) {
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));
// 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) {
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));
}
}
}

View File

@ -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);