Browse Source

Merge pull request #20550 from AndreaCatania/soft_fix

Soft Body - Pin Point fix, Material fix
Max Hilbrunner 7 years ago
parent
commit
3f01f40e91
2 changed files with 76 additions and 43 deletions
  1. 74 40
      scene/3d/soft_body.cpp
  2. 2 3
      scene/3d/soft_body.h

+ 74 - 40
scene/3d/soft_body.cpp

@@ -98,7 +98,7 @@ SoftBody::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) {
 	point_index = obj_tocopy.point_index;
 	point_index = obj_tocopy.point_index;
 	spatial_attachment_path = obj_tocopy.spatial_attachment_path;
 	spatial_attachment_path = obj_tocopy.spatial_attachment_path;
 	spatial_attachment = obj_tocopy.spatial_attachment;
 	spatial_attachment = obj_tocopy.spatial_attachment;
-	vertex_offset_transform = obj_tocopy.vertex_offset_transform;
+	offset = obj_tocopy.offset;
 }
 }
 
 
 void SoftBody::_update_pickable() {
 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) {
 	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::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::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) {
 	if ("spatial_attachment_path" == p_what) {
 		PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
 		PoolVector<PinnedPoint>::Write w = pinned_points_indices.write();
 		pin_point(w[p_item].point_index, true, p_value);
 		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 {
 	} else {
 		return false;
 		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;
 		r_ret = r[p_item].point_index;
 	} else if ("spatial_attachment_path" == p_what) {
 	} else if ("spatial_attachment_path" == p_what) {
 		r_ret = r[p_item].spatial_attachment_path;
 		r_ret = r[p_item].spatial_attachment_path;
+	} else if ("offset" == p_what) {
+		r_ret = r[p_item].offset;
 	} else {
 	} else {
 		return false;
 		return false;
 	}
 	}
@@ -245,7 +252,6 @@ void SoftBody::_notification(int p_what) {
 
 
 			RID space = get_world()->get_space();
 			RID space = get_world()->get_space();
 			PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, 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();
 			update_physics_server();
 		} break;
 		} break;
 		case NOTIFICATION_READY: {
 		case NOTIFICATION_READY: {
@@ -255,20 +261,30 @@ void SoftBody::_notification(int p_what) {
 		} break;
 		} break;
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 		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;
 		} break;
@@ -408,8 +424,15 @@ void SoftBody::_draw_soft_mesh() {
 
 
 void SoftBody::update_physics_server() {
 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;
 		return;
+	}
 
 
 	if (get_mesh().is_valid()) {
 	if (get_mesh().is_valid()) {
 
 
@@ -430,6 +453,9 @@ void SoftBody::become_mesh_owner() {
 	if (!mesh_owner) {
 	if (!mesh_owner) {
 		mesh_owner = true;
 		mesh_owner = true;
 
 
+		Vector<Ref<Material> > copy_materials;
+		copy_materials.append_array(materials);
+
 		ERR_FAIL_COND(!mesh->get_surface_count());
 		ERR_FAIL_COND(!mesh->get_surface_count());
 
 
 		// Get current mesh array and create new mesh array with necessary flag for softbody
 		// Get current mesh array and create new mesh array with necessary flag for softbody
@@ -443,11 +469,10 @@ void SoftBody::become_mesh_owner() {
 		Ref<ArrayMesh> soft_mesh;
 		Ref<ArrayMesh> soft_mesh;
 		soft_mesh.instance();
 		soft_mesh.instance();
 		soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_format);
 		soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_format);
+		soft_mesh->surface_set_material(0, mesh->surface_get_material(0));
 
 
 		set_mesh(soft_mesh);
 		set_mesh(soft_mesh);
 
 
-		Vector<Ref<Material> > copy_materials;
-		copy_materials.append_array(materials);
 		for (int i = copy_materials.size() - 1; 0 <= i; --i) {
 		for (int i = copy_materials.size() - 1; 0 <= i; --i) {
 			set_surface_material(i, copy_materials[i]);
 			set_surface_material(i, copy_materials[i]);
 		}
 		}
@@ -651,6 +676,8 @@ SoftBody::SoftBody() :
 		pinned_points_cache_dirty(true) {
 		pinned_points_cache_dirty(true) {
 
 
 	PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
 	PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
+	//set_notify_transform(true);
+	set_physics_process_internal(true);
 }
 }
 
 
 SoftBody::~SoftBody() {
 SoftBody::~SoftBody() {
@@ -664,30 +691,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 +720,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) {
 void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) {
 	SoftBody::PinnedPoint *pinned_point;
 	SoftBody::PinnedPoint *pinned_point;
 	if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
 	if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
+
 		// Create new
 		// Create new
 		PinnedPoint pp;
 		PinnedPoint pp;
 		pp.point_index = p_point_index;
 		pp.point_index = p_point_index;
 		pp.spatial_attachment_path = p_spatial_attachment_path;
 		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);
 		pinned_points_indices.push_back(pp);
+
 	} else {
 	} else {
-		// Update
+
 		pinned_point->point_index = p_point_index;
 		pinned_point->point_index = p_point_index;
 		pinned_point->spatial_attachment_path = p_spatial_attachment_path;
 		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));
+		}
 	}
 	}
 }
 }
 
 

+ 2 - 3
scene/3d/soft_body.h

@@ -72,9 +72,7 @@ public:
 		int point_index;
 		int point_index;
 		NodePath spatial_attachment_path;
 		NodePath spatial_attachment_path;
 		Spatial *spatial_attachment; // Cache
 		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();
 		PinnedPoint(const PinnedPoint &obj_tocopy);
 		PinnedPoint(const PinnedPoint &obj_tocopy);
@@ -186,6 +184,7 @@ public:
 
 
 private:
 private:
 	void reset_softbody_pin();
 	void reset_softbody_pin();
+	void _make_cache_dirty();
 	void _update_cache_pin_points_datas();
 	void _update_cache_pin_points_datas();
 	void _pin_point_on_physics_server(int p_point_index, bool pin);
 	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);
 	void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path);