[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [50164] trunk/blender/source/blender/ blenkernel/intern/customdata.c: fix [#32395] BMesh data interpolation feedback loop

Campbell Barton ideasman42 at gmail.com
Thu Aug 23 19:16:12 CEST 2012


Revision: 50164
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=50164
Author:   campbellbarton
Date:     2012-08-23 17:16:11 +0000 (Thu, 23 Aug 2012)
Log Message:
-----------
fix [#32395] BMesh data interpolation feedback loop

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/customdata.c

Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-08-23 16:17:47 UTC (rev 50163)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-08-23 17:16:11 UTC (rev 50164)
@@ -1962,6 +1962,23 @@
 
 #define SOURCE_BUF_SIZE 100
 
+/* This define makes it so when we are interpolating customdata,
+ * the source is checked if it matches the destination.
+ *
+ * There are 2 ways to get around this,
+ * - Each interp function could accumulate the final result in a local, stack variable,
+ *   then apply the result at the end.
+ *
+ * - Or we can make a temp copy of the destinations custom data before applying it.
+ *   This isn't so efficient but avoids having to consider feedback loop on each interp function.
+ *   Since this is more of a corner case its also not worth worrying about speed too much.
+ *
+ * (opted for the second option for now), keeping as an ifdef since we may wan't to change how works.
+ *
+ * see bug [#32395] - Campbell.
+ */
+#define USE_INTERP_OVERLAP_FIX
+
 void CustomData_interp(const CustomData *source, CustomData *dest,
                        int *src_indices, float *weights, float *sub_weights,
                        int count, int dest_index)
@@ -1999,8 +2016,12 @@
 		if (dest->layers[dest_i].type == source->layers[src_i].type) {
 			void *src_data = source->layers[src_i].data;
 
-			for (j = 0; j < count; ++j)
+			for (j = 0; j < count; ++j) {
+				/* if this happens we need to do a temp copy, see: USE_INTERP_OVERLAP_FIX */
+				BLI_assert(dest_index != src_indices[j]);
+
 				sources[j] = (char *)src_data + typeInfo->size * src_indices[j];
+			}
 
 			dest_offset = dest_index * typeInfo->size;
 
@@ -2578,6 +2599,11 @@
 	void *source_buf[SOURCE_BUF_SIZE];
 	void **sources = source_buf;
 
+#ifdef USE_INTERP_OVERLAP_FIX
+	/* incase there is overlap with the source */
+	void *dest_block_copy = NULL;
+#endif
+
 	/* slow fallback in case we're interpolating a ridiculous number of
 	 * elements
 	 */
@@ -2590,14 +2616,35 @@
 		CustomDataLayer *layer = &data->layers[i];
 		const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
 		if (typeInfo->interp) {
-			for (j = 0; j < count; ++j)
+			for (j = 0; j < count; ++j) {
+#ifdef USE_INTERP_OVERLAP_FIX
+				void *src_block;
+				if (UNLIKELY(src_blocks[j] == dest_block)) {
+					if (dest_block_copy == NULL) {
+						CustomData_bmesh_copy_data(data, data, dest_block, &dest_block_copy);
+					}
+					src_block = dest_block_copy;
+				}
+				else {
+					src_block = src_blocks[j];
+				}
+				sources[j] = (char *)src_block + layer->offset;
+#else
 				sources[j] = (char *)src_blocks[j] + layer->offset;
+#endif
+			}
 
 			typeInfo->interp(sources, weights, sub_weights, count,
 			                 (char *)dest_block + layer->offset);
 		}
 	}
 
+#ifdef USE_INTERP_OVERLAP_FIX
+	if (dest_block_copy) {
+		CustomData_bmesh_free_block(data, &dest_block_copy);
+	}
+#endif
+
 	if (count > SOURCE_BUF_SIZE) MEM_freeN(sources);
 }
 




More information about the Bf-blender-cvs mailing list