Commit: 5143a10288a67ab8e2a3ccf0232675004cb962a7
Author: ishbosamiya
Date:   Wed Jul 7 17:54:41 2021 +0530
Branches: soc-2021-adaptive-cloth
https://developer.blender.org/rB5143a10288a67ab8e2a3ccf0232675004cb962a7

adaptive_cloth: fix: add_empty_interp_element() crash sometimes

Since the elements have a reference to the `Arena`, if the `Arena` changes in 
size, which can happen because of `add_empty_element()`, then the references 
can become invalid. Realloc can create memory space elsewhere and copy the 
contents, the references to the previous memory space are not updated which 
means references to the previous memory space are invalid.

There are three ways to fix this:
 - Create a copy and work on the copy, this is inefficient
 - Get a reference to that element again, this is efficient but may not be 
possible always
 - Don't use the reference after an operation that can lead to the invalidation 
of the reference, this is the most efficient way but may not be possible always

Decided to go with the third way in this case.

Side note: Having a borrow checker completely eliminates such problems. Rust 
should be the way forward.

===================================================================

M       source/blender/blenkernel/BKE_cloth_remesh.hh

===================================================================

diff --git a/source/blender/blenkernel/BKE_cloth_remesh.hh 
b/source/blender/blenkernel/BKE_cloth_remesh.hh
index 3587659fd36..1979b0dc2ab 100644
--- a/source/blender/blenkernel/BKE_cloth_remesh.hh
+++ b/source/blender/blenkernel/BKE_cloth_remesh.hh
@@ -1340,8 +1340,21 @@ template<typename END, typename EVD, typename EED, 
typename EFD> class Mesh {
     auto pos = (node_1.pos + node_2.pos) * 0.5;
     /* The normal calculation might not be valid but good enough */
     auto normal = (node_1.normal + node_2.normal) * 0.5;
+
+    std::optional<END> extra_data = std::nullopt;
+    if (node_1.extra_data && node_2.extra_data) {
+      extra_data = node_1.extra_data.value().interp(node_2.extra_data.value());
+    }
+    else if (node_1.extra_data) {
+      extra_data = node_1.extra_data;
+    }
+    else if (node_2.extra_data) {
+      extra_data = node_2.extra_data;
+    }
+
     auto &new_node = this->add_empty_node(pos, normal);
-    new_node.extra_data = interp(node_1.extra_data, node_2.extra_data);
+    new_node.extra_data = extra_data;
+
     return new_node;
   }
 
@@ -1354,8 +1367,21 @@ template<typename END, typename EVD, typename EED, 
typename EFD> class Mesh {
   Vert<EVD> &add_empty_interp_vert(const Vert<EVD> &vert_1, const Vert<EVD> 
&vert_2)
   {
     auto uv = (vert_1.uv + vert_2.uv) * 0.5;
+
+    std::optional<EVD> extra_data = std::nullopt;
+    if (vert_1.extra_data && vert_2.extra_data) {
+      extra_data = vert_1.extra_data.value().interp(vert_2.extra_data.value());
+    }
+    else if (vert_1.extra_data) {
+      extra_data = vert_1.extra_data;
+    }
+    else if (vert_2.extra_data) {
+      extra_data = vert_2.extra_data;
+    }
+
     auto &new_vert = this->add_empty_vert(uv);
-    new_vert.extra_data = interp(vert_1.extra_data, vert_2.extra_data);
+    new_vert.extra_data = extra_data;
+
     return new_vert;
   }
 
@@ -1367,8 +1393,20 @@ template<typename END, typename EVD, typename EED, 
typename EFD> class Mesh {
    */
   Edge<EED> &add_empty_interp_edge(const Edge<EED> &edge_1, const Edge<EED> 
&edge_2)
   {
+    std::optional<EED> extra_data = std::nullopt;
+    if (edge_1.extra_data && edge_2.extra_data) {
+      extra_data = edge_1.extra_data.value().interp(edge_2.extra_data.value());
+    }
+    else if (edge_1.extra_data) {
+      extra_data = edge_1.extra_data;
+    }
+    else if (edge_2.extra_data) {
+      extra_data = edge_2.extra_data;
+    }
+
     auto &new_edge = this->add_empty_edge();
-    new_edge.extra_data = interp(edge_1.extra_data, edge_2.extra_data);
+    new_edge.extra_data = extra_data;
+
     return new_edge;
   }
 
@@ -1382,8 +1420,21 @@ template<typename END, typename EVD, typename EED, 
typename EFD> class Mesh {
   {
     /* The normal calculation might not be valid but good enough */
     auto normal = (face_1.normal + face_2.normal) * 0.5;
+
+    std::optional<EFD> extra_data = std::nullopt;
+    if (face_1.extra_data && face_2.extra_data) {
+      extra_data = face_1.extra_data.value().interp(face_2.extra_data.value());
+    }
+    else if (face_1.extra_data) {
+      extra_data = face_1.extra_data;
+    }
+    else if (face_2.extra_data) {
+      extra_data = face_2.extra_data;
+    }
+
     auto &new_face = this->add_empty_face(normal);
-    new_face.extra_data = interp(face_1.extra_data, face_2.extra_data);
+    new_face.extra_data = extra_data;
+
     return new_face;
   }

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to