[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58230] branches/ soc-2013-meshdata_transfer: Adding the Shapekey transfer algorithm

Walid Shouman eng.walidshouman at gmail.com
Sun Jul 14 10:13:03 CEST 2013


Revision: 58230
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58230
Author:   walid
Date:     2013-07-14 08:13:02 +0000 (Sun, 14 Jul 2013)
Log Message:
-----------
Adding the Shapekey transfer algorithm

Modified Paths:
--------------
    branches/soc-2013-meshdata_transfer/release/scripts/startup/bl_ui/space_view3d_toolbar.py
    branches/soc-2013-meshdata_transfer/source/blender/bmesh/CMakeLists.txt
    branches/soc-2013-meshdata_transfer/source/blender/bmesh/bmesh.h
    branches/soc-2013-meshdata_transfer/source/blender/editors/object/object_intern.h
    branches/soc-2013-meshdata_transfer/source/blender/editors/object/object_ops.c
    branches/soc-2013-meshdata_transfer/source/blender/editors/object/object_shapekey.c

Added Paths:
-----------
    branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
    branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.h

Modified: branches/soc-2013-meshdata_transfer/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- branches/soc-2013-meshdata_transfer/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2013-07-14 07:27:44 UTC (rev 58229)
+++ branches/soc-2013-meshdata_transfer/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2013-07-14 08:13:02 UTC (rev 58230)
@@ -114,7 +114,9 @@
         draw_gpencil_tools(context, layout)
         col = layout.column(align=True)
 
+        col.operator("object.shape_key_transfer_new", text="Transfer Shapekeys (new)")
 
+
 class VIEW3D_PT_tools_rigidbody(View3DPanel, Panel):
     bl_context = "objectmode"
     bl_label = "Rigid Body Tools"

Modified: branches/soc-2013-meshdata_transfer/source/blender/bmesh/CMakeLists.txt
===================================================================
--- branches/soc-2013-meshdata_transfer/source/blender/bmesh/CMakeLists.txt	2013-07-14 07:27:44 UTC (rev 58229)
+++ branches/soc-2013-meshdata_transfer/source/blender/bmesh/CMakeLists.txt	2013-07-14 08:13:02 UTC (rev 58230)
@@ -128,6 +128,8 @@
 	tools/bmesh_path.h
 	tools/bmesh_triangulate.c
 	tools/bmesh_triangulate.h
+	tools/bmesh_data_transfer.c
+	tools/bmesh_data_transfer.h
 
 	bmesh.h
 	bmesh_class.h

Modified: branches/soc-2013-meshdata_transfer/source/blender/bmesh/bmesh.h
===================================================================
--- branches/soc-2013-meshdata_transfer/source/blender/bmesh/bmesh.h	2013-07-14 07:27:44 UTC (rev 58229)
+++ branches/soc-2013-meshdata_transfer/source/blender/bmesh/bmesh.h	2013-07-14 08:13:02 UTC (rev 58230)
@@ -273,6 +273,7 @@
 #include "tools/bmesh_decimate.h"
 #include "tools/bmesh_path.h"
 #include "tools/bmesh_triangulate.h"
+#include "tools/bmesh_data_transfer.h"
 
 #ifdef __cplusplus
 }

Added: branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
===================================================================
--- branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c	                        (rev 0)
+++ branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c	2013-07-14 08:13:02 UTC (rev 58230)
@@ -0,0 +1,409 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+
+#include "DNA_meshdata_types.h"
+#include "BKE_editmesh.h"
+
+#include "BKE_editmesh_bvh.h"		//to use bvh
+#include "bmesh_data_transfer.h"	//own include
+#include "BKE_customdata.h"			//Custom Data related
+#include "BLI_array.h"				//used for interpolation (reserving custom size)
+#include "DNA_key_types.h"			//used for dealing with keyblocks
+#include "BLI_math_vector.h"		//for copying vectors
+
+//should be replaced by the min_float and its inverse
+#ifndef MY_MIN_FLOAT
+#define MY_MIN_FLOAT .001
+#endif
+
+#ifndef MY_MAX_FLOAT
+#define MY_MAX_FLOAT 1000
+#endif
+
+bool BKE_bmesh_calc_relative_deform(
+		const int v_count,
+
+		const float (*vert_cos_src)[3],		//source	-- we should have the sources we'll work on layed down in a way compatible with the one we'll summon them for the barycentric transfromation
+											//so we've 2 issues. 1)getting the vertices we we'll inherit from!
+											//2)laying them in a contigeoeusly accessible order
+		const float (*vert_cos_dst)[3],		//dest is KNOWN bm_dst vertix/vertices
+
+		const float (*vert_cos_org)[3],		//source's offset
+			  float (*vert_cos_new)[3])		//The Unknown :D
+{
+	int i;
+
+	//allocate space for the total vertices count
+	int *vert_accum = MEM_callocN(sizeof(*vert_accum) * v_count, "vert_accum bmesh_data_transfer.c");
+
+	//set the new coordinates to \0!!!
+	memset(*vert_cos_new, '\0', sizeof(*vert_cos_new) * v_count);
+
+	for (i = 0; i < v_count; i++) {
+		//assignment here is useless!
+		int v_prev = (v_count + (i - 1)) % v_count;
+		int v_curr = i;
+		int v_next = (i + 1) % v_count;
+
+		float tvec[3];
+
+		//needed for line intersection check
+		float i1[3], i2[3];
+		bool colinear = true;
+
+		//skip duplicate vertices to capture the data From (extensible to capturing the data to ... but that won't be
+		//needed currently)
+		int j = 0, k = 0;
+		while(equals_v3v3(vert_cos_src[v_next], vert_cos_src[v_curr]) && j < v_count) {
+			j++;
+			v_next = (i + j) % v_count;
+		}
+
+
+		//we need to check that way the barycentric transformation that will give consistent results
+		//(by iterating the loops by their index only).
+		//we ensure here also that the prev isn't the same as the next to avoid stoping the while at a midpoint that will
+		//cause in transformation between 2 similar points!
+		while((equals_v3v3(vert_cos_src[v_prev], vert_cos_src[v_curr]) ||
+		      equals_v3v3(vert_cos_src[v_prev], vert_cos_src[v_next]) || colinear) && k < v_count) {
+			k++;
+			v_prev = (v_count + (i - k)) % v_count;
+
+			//barycentric transfromation will fail if the 3 -or more- given points were on the same line
+			//thus, if we have the third point  (v_prev) colinear with the previous 2 ones, we'll have a tvec[] = NAN
+			colinear = !isect_line_line_v3(vert_cos_src[v_prev], vert_cos_src[v_curr],
+			                              vert_cos_src[v_curr], vert_cos_src[v_next], i1, i2);
+
+			//this shall be used in case of return values got changed (Currently it's in the todo list of math_geom.c)
+/*			if(!isect_line_line_v3(vert_cos_src[v_prev], vert_cos_src[v_curr],
+			                      vert_cos_src[v_curr], vert_cos_src[v_next], i1, i2))
+			{
+				colinear = true;
+			}
+			else
+			{
+				colinear = false;
+			}
+*/
+		}
+		//k or j will reach v_count if there was less than 3 different coordinates that aren't on the same line!
+		if ((k == v_count) || (j == v_count)) {
+			//CANCEL the operation!
+			return false;
+		}
+
+		//outputs the relative position of the new coordinates and stores it in a temp tvec
+		barycentric_transform(
+					tvec, vert_cos_dst[v_curr],						//the difference, and the des
+					vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],	//3 org vertices
+					vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]	//3 source vertices
+					);
+
+		//get the new position by accumelating the difference
+		//note: if we passed by a vertex twice vert_cos_new would hold the sum of both the differences
+		//		used as an accum. to be averaged later
+		add_v3_v3(vert_cos_new[v_curr], tvec);
+		vert_accum[v_curr] += 1;	//each time we calc for a vertex, we increase its value in the ver_accum table
+	}
+
+	for (i = 0; i < v_count; i++) {
+		if (vert_accum[i]) {			//if we ever passed by the vertex
+			mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]);	//get its average
+		}
+
+		else {							//if we didn't pass by this vertex .. assume it inherits the pos of it's org
+			copy_v3_v3(vert_cos_new[i], vert_cos_org[i]);
+		}
+	}
+
+	MEM_freeN(vert_accum);
+	return true;
+}
+
+/**
+ * @brief inherit vertices' offset from the source, then interpolate within the destination by using distance from
+ * vertices that inherited And normals from those vertices
+ * @param bm_src: the source bmesh
+ * @param bm_dst: the destination bmesh
+ * @param tolerance: how far the dst vertices should look within for src vertices to inherit from
+ * @param radius_interp: how far vertices that didn't inherit should search within for already inherited vertices
+ * to interpolate from
+ * @param dist_pow: multiplying the distance weights to have a stronger effect from near vertices
+ * @param no_pow: multiplying the normals effect to have a stronger effect from vertices with the same normal
+ * @param USE_NORMALS: use/don't use normals in interpolation
+ * @param replace_mode: how should we treat the destination shapekey groups
+ * @param act_shapekey_lay: get the active layer within the source and destination
+ * @return true if success, false if failure (currently failure would happen if less than 3 non-colinear vertices
+ * inherit from the source)
+ */
+
+bool BM_mesh_shapekey_copy(BMesh *bm_src, BMesh *bm_dst, float tolerance, float radius_interp, int dist_pow, int no_pow,
+                           bool USE_NORMALS, ST_ShapekeyGroupMode replace_mode, int *act_shapekey_lay)
+{
+	int CD_offset_src, CD_offset_dst;
+	int CD_basis_src, CD_basis_dst;
+
+	//used for iterating the destination's verts
+	BMVert *v;
+	//iter => vertex iterator
+	BMIter iter, iter2;
+	int tot_layer_src,tot_layer_dst;
+	int src_lay_iter, dst_lay_iter;
+
+	//tree variables
+	struct BMBVHTree *bmtree = NULL;
+	BMEditMesh *em_src;
+
+	float (*vertexCos_src_basis)[3];
+	float (*vertexCos_src_offset)[3];
+	float (*vertexCos_dst_basis)[3];
+	float (*vertexCos_dst_offset)[3];
+
+	int num_vert = bm_dst->totvert;
+
+	//replace mode variables
+	int src_lay_start, src_lay_end;
+	int dst_lay_start, dst_lay_end;	//dst_lay_end currently isn't being used
+
+
+	//Is that good to support edit mesh mode at the cost of receiving me_src too ?
+	//if (me_src->edit_btmesh != NULL) em_src = me_src->edit_btmesh;	//edit mesh mode
+	//else
+	em_src = BKE_editmesh_create(bm_src, true);	//create editmesh data from bm WITH tess.
+													//if it was false ... data other than
+													//em->bm won't be copied
+
+	tot_layer_src = CustomData_number_of_layers(&bm_src->vdata, CD_SHAPEKEY);//to change the last one
+	tot_layer_dst = CustomData_number_of_layers(&bm_dst->vdata, CD_SHAPEKEY);	//get the number of Shapekey layers
+																				//within the target
+
+	vertexCos_src_basis = MEM_mallocN(sizeof(*vertexCos_src_basis), "vertexCos_src_basis bmesh_data_transfer.c");
+	vertexCos_src_offset = MEM_mallocN(sizeof(*vertexCos_src_offset), "vertexCos_src_offset bmesh_data_transfer.c");
+	vertexCos_dst_basis = MEM_mallocN(sizeof(*vertexCos_dst_basis), "vertexCos_dst_basis bmesh_data_transfer.c");
+
+	CD_basis_src = CustomData_get_n_offset(&bm_src->vdata, CD_SHAPEKEY, 0);	//get the offset of the basis
+	CD_basis_dst = CustomData_get_n_offset(&bm_dst->vdata, CD_SHAPEKEY, 0);
+
+	if (replace_mode == ST_APPEND_SHAPEKEY_GROUPS) {
+		//add 1 to skip the basis
+		src_lay_start = 1;
+		src_lay_end = tot_layer_src;
+		dst_lay_start = tot_layer_dst - tot_layer_src + 1;
+		dst_lay_end = tot_layer_dst;
+	}
+
+	else if ((replace_mode == ST_REPLACE_ENOUGH_SHAPEKEY_GROUPS) || (replace_mode == ST_REPLACE_ALL_SHAPEKEY_GROUPS)) {
+		src_lay_start = 1;
+		src_lay_end = tot_layer_src;
+		dst_lay_start = 1;
+		dst_lay_end = tot_layer_src;
+	}
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list