[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [50194] trunk/blender/source/blender/ blenkernel/intern/customdata.c: alternate fix for bug [#32395],

Campbell Barton ideasman42 at gmail.com
Fri Aug 24 19:01:35 CEST 2012


Revision: 50194
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=50194
Author:   campbellbarton
Date:     2012-08-24 17:01:35 +0000 (Fri, 24 Aug 2012)
Log Message:
-----------
alternate fix for bug [#32395],
now customdata is interpolated into a temp variable and applied at the end of each layer interpolation function.

So this now works for CDDM customdata interpolation and avoids duplicating the customdata when the source and destination overlap.

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-24 16:55:25 UTC (rev 50193)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-08-24 17:01:35 UTC (rev 50194)
@@ -72,25 +72,29 @@
 	const char *structname;  /* name of the struct used, for file writing */
 	int structnum;     /* number of structs per element, for file writing */
 
-	/* default layer name.
+	/**
+	 * default layer name.
 	 * note! when NULL this is a way to ensure there is only ever one item
 	 * see: CustomData_layertype_is_singleton() */
 	const char *defaultname;
 
-	/* a function to copy count elements of this layer's data
+	/**
+	 * a function to copy count elements of this layer's data
 	 * (deep copy if appropriate)
 	 * if NULL, memcpy is used
 	 */
 	void (*copy)(const void *source, void *dest, int count);
 
-	/* a function to free any dynamically allocated components of this
+	/**
+	 * a function to free any dynamically allocated components of this
 	 * layer's data (note the data pointer itself should not be freed)
 	 * size should be the size of one element of this layer's data (e.g.
 	 * LayerTypeInfo.size)
 	 */
 	void (*free)(void *data, int count, int size);
 
-	/* a function to interpolate between count source elements of this
+	/**
+	 * a function to interpolate between count source elements of this
 	 * layer's data and store the result in dest
 	 * if weights == NULL or sub_weights == NULL, they should default to 1
 	 *
@@ -98,18 +102,24 @@
 	 * sub_weights gives the sub-element weights for each element in sources
 	 *    (there should be (sub element count)^2 weights per element)
 	 * count gives the number of elements in sources
+	 *
+	 * \note in some cases \a dest pointer is in \a sources
+	 *       so all functions have to take this into account and delay
+	 *       applying changes while reading from sources.
+	 *       See bug [#32395] - Campbell.
 	 */
 	void (*interp)(void **sources, const float *weights, const float *sub_weights,
 	               int count, void *dest);
 
-	/* a function to swap the data in corners of the element */
+	/** a function to swap the data in corners of the element */
 	void (*swap)(void *data, const int *corner_indices);
 
-	/* a function to set a layer's data to default values. if NULL, the
+	/**
+	 * a function to set a layer's data to default values. if NULL, the
 	 * default is assumed to be all zeros */
 	void (*set_default)(void *data, int count);
 
-	/* functions necessary for geometry collapse*/
+	/** functions necessary for geometry collapse */
 	int (*equal)(void *data1, void *data2);
 	void (*multiply)(void *data, float fac);
 	void (*initminmax)(void *min, void *max);
@@ -117,13 +127,13 @@
 	void (*dominmax)(void *data1, void *min, void *max);
 	void (*copyvalue)(void *source, void *dest);
 
-	/* a function to read data from a cdf file */
+	/** a function to read data from a cdf file */
 	int (*read)(CDataFile *cdf, void *data, int count);
 
-	/* a function to write data to a cdf file */
+	/** a function to write data to a cdf file */
 	int (*write)(CDataFile *cdf, void *data, int count);
 
-	/* a function to determine file size */
+	/** a function to determine file size */
 	size_t (*filesize)(CDataFile *cdf, void *data, int count);
 } LayerTypeInfo;
 
@@ -243,6 +253,8 @@
 		}
 	}
 
+	/* delay writing to the destination incase dest is in sources */
+
 	/* now we know how many unique deform weights there are, so realloc */
 	if (dvert->dw) MEM_freeN(dvert->dw);
 
@@ -276,6 +288,7 @@
 		madd_v2_v2fl(co, mst->co, w);
 	}
 
+	/* delay writing to the destination incase dest is in sources */
 	mst = (MSticky *)dest;
 	copy_v2_v2(mst->co, co);
 }
@@ -318,6 +331,7 @@
 		}
 	}
 
+	/* delay writing to the destination incase dest is in sources */
 	*tf = *(MTFace *)(*sources);
 	memcpy(tf->uv, uv, sizeof(tf->uv));
 }
@@ -419,6 +433,8 @@
 		}
 	}
 
+	/* delay writing to the destination incase dest is in sources */
+
 #if 0 /* no need, this ONLY contains UV's */
 	*osf = *(OrigSpaceFace *)(*sources);
 #endif
@@ -719,7 +735,8 @@
 	CLAMP(col.r, 0.0f, 255.0f);
 	CLAMP(col.g, 0.0f, 255.0f);
 	CLAMP(col.b, 0.0f, 255.0f);
-	
+
+	/* delay writing to the destination incase dest is in sources */
 	mc->r = (int)col.r;
 	mc->g = (int)col.g;
 	mc->b = (int)col.b;
@@ -771,8 +788,7 @@
 static void layerInterp_mloopuv(void **sources, const float *weights,
                                 const float *sub_weights, int count, void *dest)
 {
-	MLoopUV *mluv = dest;
-	float *uv = mluv->uv;
+	float uv[2];
 	int i;
 
 	zero_v2(uv);
@@ -793,6 +809,9 @@
 			madd_v2_v2fl(uv, src->uv, weight);
 		}
 	}
+
+	/* delay writing to the destination incase dest is in sources */
+	copy_v2_v2(((MLoopUV *)dest)->uv, uv);
 }
 
 /* origspace is almost exact copy of mloopuv's, keep in sync */
@@ -841,8 +860,7 @@
 static void layerInterp_mloop_origspace(void **sources, const float *weights,
                                         const float *sub_weights, int count, void *dest)
 {
-	OrigSpaceLoop *mluv = dest;
-	float *uv = mluv->uv;
+	float uv[2];
 	int i;
 
 	zero_v2(uv);
@@ -858,11 +876,14 @@
 	}
 	else {
 		for (i = 0; i < count; i++) {
-			float weight = weights ? weights[i] : 1;
+			float weight = weights ? weights[i] : 1.0f;
 			OrigSpaceLoop *src = sources[i];
 			madd_v2_v2fl(uv, src->uv, weight);
 		}
 	}
+
+	/* delay writing to the destination incase dest is in sources */
+	copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
 }
 /* --- end copy */
 
@@ -907,6 +928,7 @@
 		}
 	}
 
+	/* delay writing to the destination incase dest is in sources */
 	for (j = 0; j < 4; ++j) {
 		
 		/* Subdivide smooth or fractal can cause problems without clamping
@@ -949,30 +971,33 @@
 static void layerInterp_bweight(void **sources, const float *weights,
                                 const float *UNUSED(sub_weights), int count, void *dest)
 {
-	float *f = dest;
+	float f;
 	float **in = (float **)sources;
 	int i;
 	
 	if (count <= 0) return;
 
-	*f = 0.0f;
+	f = 0.0f;
 
 	if (weights) {
 		for (i = 0; i < count; ++i) {
-			*f += *in[i] * weights[i];
+			f += *in[i] * weights[i];
 		}
 	}
 	else {
 		for (i = 0; i < count; ++i) {
-			*f += *in[i];
+			f += *in[i];
 		}
 	}
+
+	/* delay writing to the destination incase dest is in sources */
+	*((float *)dest) = f;
 }
 
 static void layerInterp_shapekey(void **sources, const float *weights,
                                  const float *UNUSED(sub_weights), int count, void *dest)
 {
-	float *co = dest;
+	float co[3];
 	float **in = (float **)sources;
 	int i;
 
@@ -990,6 +1015,9 @@
 			add_v3_v3(co, in[i]);
 		}
 	}
+
+	/* delay writing to the destination incase dest is in sources */
+	copy_v3_v3((float *)dest, co);
 }
 
 static void layerDefault_mvert_skin(void *data, int count)
@@ -1019,6 +1047,7 @@
 		madd_v3_v3fl(radius, vs->radius, w);
 	}
 
+	/* delay writing to the destination incase dest is in sources */
 	vs = dest;
 	copy_v3_v3(vs->radius, radius);
 	vs->flag &= ~MVERT_SKIN_ROOT;
@@ -1962,23 +1991,6 @@
 
 #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)
@@ -2017,9 +2029,6 @@
 			void *src_data = source->layers[src_i].data;
 
 			for (j = 0; j < count; ++j) {
-				/* if this happens we need to do a temp copy, see: USE_INTERP_OVERLAP_FIX */
-				BLI_assert(((source == dest) && (dest_index == src_indices[j])) == FALSE);
-
 				sources[j] = (char *)src_data + typeInfo->size * src_indices[j];
 			}
 
@@ -2599,11 +2608,6 @@
 	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
 	 */
@@ -2617,21 +2621,7 @@
 		const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
 		if (typeInfo->interp) {
 			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,
@@ -2639,12 +2629,6 @@
 		}
 	}
 
-#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