svn merge ^/trunk/blender -r46559:HEAD
authorOve Murberg Henriksen <sorayasilvermoon@hotmail.com>
Tue, 15 May 2012 01:28:12 +0000 (01:28 +0000)
committerOve Murberg Henriksen <sorayasilvermoon@hotmail.com>
Tue, 15 May 2012 01:28:12 +0000 (01:28 +0000)
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_vgroup.c

index f3fa1585d562c15bce98390985918e089da5e352..729380a04339dbf461bb099d5db4516f58596851 100644 (file)
@@ -986,6 +986,8 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
 
         col = layout.column()
         col.active = ob.vertex_groups.active is not None
+        col.operator("object.vertex_group_copy_to_selected", text="Transfer weight All")
+        col.operator("object.vertex_group_copy_to_selected_single", text="Transfer weight")
         col.operator("object.vertex_group_normalize_all", text="Normalize All")
         col.operator("object.vertex_group_normalize", text="Normalize")
         col.operator("object.vertex_group_mirror", text="Mirror")
index e834c93b0d86c4eb1a9f255f08a11decee9c914c..e29ab687fffb29021f961c1fcda81fdfc1fdcb4d 100644 (file)
@@ -197,6 +197,7 @@ void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_copy_to_selected_single(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
 void OBJECT_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
index b7dc3fd7bea4ac2a8cd196b7bc0107d7b9c33419..9f5ae7e255f972c0f547d329c1cf08434e49bed5 100644 (file)
@@ -171,6 +171,7 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
        WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
        WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
+       WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected_single);
        WM_operatortype_append(OBJECT_OT_vertex_group_copy);
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
index 0c0611d3d33e8771e80709796a2e7a49b0be1078..855230c54f348648d953c591593847c8815c1fe2 100644 (file)
@@ -376,6 +376,360 @@ int ED_vgroup_copy_array(Object *ob, Object *ob_from)
        return 1;
 }
 
+/*Copy a single vertex group from source to destination with weights by identical meshes*/
+int ED_vgroup_copy_single(Object *ob_dst, const Object *ob_src)
+{
+       MDeformVert **dv_array_src;
+       MDeformVert **dv_array_dst;
+       MDeformWeight *dw_dst, *dw_src;
+       int dv_tot_src, dv_tot_dst;
+       int i, index_src, index_dst;
+       bDeformGroup *dg_src, *dg_dst;
+
+       /*get source deform group*/
+       dg_src= BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
+
+       /*create new and overwrite vertex group on destination without data*/
+       ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
+       ED_vgroup_add_name(ob_dst, dg_src->name);
+
+       /*get destination deformgroup*/
+       dg_dst= defgroup_find_name(ob_dst, dg_src->name);
+
+       /*get vertex group arrays*/
+       ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
+       ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
+
+       /*get indexes of vertex groups*/
+       index_src= BLI_findindex(&ob_src->defbase, dg_src);
+       index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
+
+       /*check if indices are matching, delete and return if not*/
+       if (ob_dst == ob_src || dv_tot_dst == 0 || (dv_tot_dst != dv_tot_src) || dv_array_src == NULL || dv_array_dst == NULL) {
+               ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_dst->name));
+               return 0;
+       }
+
+       /* loop through the vertices and copy weight*/
+       for(i=0; i<dv_tot_dst; i++, dv_array_src++, dv_array_dst++) {
+               dw_src= defvert_verify_index(*dv_array_src, index_src);
+               dw_dst= defvert_verify_index(*dv_array_dst, index_dst);
+               dw_dst->weight= dw_src->weight;
+       }
+
+       return 1;
+}
+
+/*Copy a single vertex group from source to destination with weights by nearest weight*/
+int ED_vgroup_copy_by_nearest_vertex_single(Object *ob_dst, Object *ob_src)
+{
+       bDeformGroup *dg_src, *dg_dst;
+       MDeformVert **dv_array_src, **dv_array_dst;
+       MDeformWeight *dw_dst, *dw_src;
+       MVert *mv_dst;
+       Mesh *me_dst;
+       BVHTreeFromMesh tree_mesh_src;
+       BVHTreeNearest nearest;
+       DerivedMesh *dmesh_src;
+       int dv_tot_src, dv_tot_dst, i, index_dst, index_src;
+       float tmp_co[3], tmp_mat[4][4];
+
+       /*get source deform group*/
+       dg_src= BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
+
+       /*create new and overwrite vertex group on destination without data*/
+       ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
+       ED_vgroup_add_name(ob_dst, dg_src->name);
+
+       /*get destination deformgroup*/
+       dg_dst= defgroup_find_name(ob_dst, dg_src->name);
+
+       /*get meshes*/
+       me_dst= ob_dst->data;
+       dmesh_src= ob_src->derivedDeform;
+
+       /*make node tree*/
+       bvhtree_from_mesh_verts(&tree_mesh_src, dmesh_src, 0.0, 2, 6);
+
+       /*get vertex group arrays*/
+       ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
+       ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
+
+       /*get indexes of vertex groups*/
+       index_src= BLI_findindex(&ob_src->defbase, dg_src);
+       index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
+
+       /*get vertices*/
+       mv_dst= me_dst->mvert;
+
+       /*prepare transformation matrix*/
+       /*this can be excluded to make a lazy feature that works better when object centers relative to mesh is the same*/
+       invert_m4_m4(ob_src->imat, ob_src->obmat);
+       mult_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat);
+
+       /* loop through the vertices and copy weight from nearest weight*/
+       for(i=0; i < me_dst->totvert; i++, mv_dst++, dv_array_dst++){
+
+               /*reset nearest*/
+               nearest.index= -1;
+               nearest.dist= FLT_MAX;
+
+               /*transform into target space*/
+               mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
+
+               /*node tree accelerated search for closest vetex*/
+               BLI_bvhtree_find_nearest(tree_mesh_src.tree, tmp_co, &nearest, tree_mesh_src.nearest_callback, &tree_mesh_src);
+
+               /*copy weight*/
+               dw_src= defvert_verify_index(dv_array_src[nearest.index], index_src);
+               dw_dst= defvert_verify_index(*dv_array_dst, index_dst);
+               dw_dst->weight= dw_src->weight;
+       }
+
+       /*free memory and return*/
+       free_bvhtree_from_mesh(&tree_mesh_src);
+       return 1;
+}
+
+/*Copy a single vertex group from source to destination with weights by nearest weight in face*/
+int ED_vgroup_copy_by_nearest_vertex_in_face_single(Object *ob_dst, Object *ob_src)
+{
+       bDeformGroup *dg_src, *dg_dst;
+       Mesh *me_dst;
+       DerivedMesh *dmesh_src;
+       BVHTreeFromMesh tree_mesh_faces_src = {NULL};
+       MDeformVert **dv_array_src, **dv_array_dst;
+       MVert *mv_dst, *mv_src;
+       MFace *mface_src;
+       BVHTreeNearest nearest;
+       MDeformWeight *dw_dst, *dw_src;
+       int dv_tot_src, dv_tot_dst, i, index_dst, index_src;
+       float dist_v1, dist_v2, dist_v3, dist_v4, tmp_co[3], tmp_mat[4][4];
+
+       /*get source deform group*/
+       dg_src= BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
+
+       /*create new and overwrite vertex group on destination without data*/
+       ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
+       ED_vgroup_add_name(ob_dst, dg_src->name);
+
+       /*get destination deformgroup*/
+       dg_dst= defgroup_find_name(ob_dst, dg_src->name);
+
+       /*get meshes*/
+       me_dst= ob_dst->data;
+       dmesh_src= ob_src->derivedDeform;
+
+       /*make node tree*/
+       DM_ensure_tessface(dmesh_src);
+       bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, 0.0, 2, 6);
+
+       /*get vertex group arrays*/
+       ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
+       ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
+
+       /*get indexes of vertex groups*/
+       index_src= BLI_findindex(&ob_src->defbase, dg_src);
+       index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
+
+       /*get vertices*/
+       mv_dst= me_dst->mvert;
+       mv_src= dmesh_src->getVertArray(dmesh_src);
+
+       /*get faces*/
+       mface_src= dmesh_src->getTessFaceArray(dmesh_src);
+
+       /*prepare transformation matrix*/
+       invert_m4_m4(ob_src->imat, ob_src->obmat);
+       mult_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat);
+
+       /* loop through the vertices and copy weight from nearest weight*/
+       for(i=0; i < me_dst->totvert; i++, mv_dst++, dv_array_dst++){
+
+               /*reset nearest*/
+               nearest.index= -1;
+               nearest.dist= FLT_MAX;
+
+               /*transform into target space*/
+               mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
+
+               /*node tree accelerated search for closest face*/
+               BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
+
+               /*get distances*/
+               dist_v1= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v1].co);
+               dist_v2= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v2].co);
+               dist_v3= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v3].co);
+
+               /*get weight from triangle*/
+               if(dist_v1<dist_v2 && dist_v1<dist_v3){
+                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v1], index_src);
+               }
+               else if(dist_v2<dist_v3){
+                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v2], index_src);
+               }
+               else{
+                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v3], index_src);
+               }
+               /*check for and get weight from quad*/
+               if(mface_src[nearest.index].v4){
+                       dist_v4= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v4].co);
+                       if(dist_v4<dist_v1 && dist_v4<dist_v2 && dist_v4<dist_v3){
+                               dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v4], index_src);
+                       }
+               }
+
+               /*copy weight*/
+               dw_dst= defvert_verify_index(*dv_array_dst, index_dst);
+               dw_dst->weight= dw_src->weight;
+       }
+
+       /*free memory and return*/
+       free_bvhtree_from_mesh(&tree_mesh_faces_src);
+       return 1;
+}
+
+/*Copy a single vertex group from source to destination with weights interpolated over nearest face*/
+/*TODO: transform into target space as in by_vertex function. postphoned due to easier testing during development*/
+int ED_vgroup_copy_by_nearest_face_single(Object *ob_dst, Object *ob_src)
+{
+       bDeformGroup *dg_src, *dg_dst;
+       Mesh *me_dst;
+       DerivedMesh *dmesh_src;
+       BVHTreeFromMesh tree_mesh_faces_src = {NULL};
+       MDeformVert **dv_array_src, **dv_array_dst;
+       MVert *mv_dst, *mv_src;
+       MFace *mface_src;
+       BVHTreeNearest nearest;
+       MDeformWeight *dw_dst, *dw_src;
+       int dv_tot_src, dv_tot_dst, i, index_dst, index_src;
+       float weight, tot_distribution, distribution_v1, distribution_v2, distribution_v3, distribution_v4, tmp_co[3], tmp_co_v4[3], normal[3];
+
+       /*get source deform group*/
+       dg_src= BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
+
+       /*create new and overwrite vertex group on destination without data*/
+       ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
+       ED_vgroup_add_name(ob_dst, dg_src->name);
+
+       /*get destination deformgroup*/
+       dg_dst= defgroup_find_name(ob_dst, dg_src->name);
+
+       /*get meshes*/
+       me_dst= ob_dst->data;
+       dmesh_src= ob_src->derivedDeform;
+
+       /*make node tree*/
+       DM_ensure_tessface(dmesh_src);
+       bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, 0.0, 2, 6);
+
+       /*get vertex group arrays*/
+       ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
+       ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
+
+       /*get indexes of vertex groups*/
+       index_src= BLI_findindex(&ob_src->defbase, dg_src);
+       index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
+
+       /*get vertices*/
+       mv_dst= me_dst->mvert;
+       mv_src= dmesh_src->getVertArray(dmesh_src);
+
+       /*get faces*/
+       mface_src= dmesh_src->getTessFaceArray(dmesh_src);
+
+       /* loop through the vertices and copy weight from nearest weight*/
+       for(i=0; i < me_dst->totvert; i++, mv_dst++, dv_array_dst++){
+
+               /*reset nearest*/
+               nearest.index= -1;
+               nearest.dist= FLT_MAX;
+
+               /*set destination coordinate*/
+               copy_v3_v3(tmp_co, mv_dst->co);
+
+               /*node tree accelerated search for closest face*/
+               BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src);
+
+               /*project destination coordinate onto face*/
+               normal_tri_v3(normal, mv_src[mface_src[nearest.index].v1].co, mv_src[mface_src[nearest.index].v2].co, mv_src[mface_src[nearest.index].v3].co);
+               project_v3_plane(tmp_co, normal, mv_src[mface_src[nearest.index].v1].co);
+
+               /*get distances*/
+               distribution_v1= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v1].co);
+               distribution_v2= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v2].co);
+               distribution_v3= len_squared_v3v3(tmp_co, mv_src[mface_src[nearest.index].v3].co);
+
+               /*get weight from overlapping vert if any*/
+               if(distribution_v1 == 0) weight= defvert_verify_index(dv_array_src[mface_src[nearest.index].v1], index_src)->weight;
+               if(distribution_v2 == 0) weight= defvert_verify_index(dv_array_src[mface_src[nearest.index].v2], index_src)->weight;
+               if(distribution_v3 == 0) weight= defvert_verify_index(dv_array_src[mface_src[nearest.index].v3], index_src)->weight;
+               else{
+                       /*invert distribution*/
+                       distribution_v1= 1/distribution_v1;
+                       distribution_v2= 1/distribution_v2;
+                       distribution_v3= 1/distribution_v3;
+
+                       /*set total distribution*/
+                       tot_distribution= distribution_v1 + distribution_v2 + distribution_v3;
+
+                       /*check for quad*/
+                       if(mface_src[nearest.index].v4){
+                               /*project vertex nr4 coordinate onto face and distribute*/
+                               copy_v3_v3(tmp_co_v4, mv_src[mface_src[nearest.index].v4].co);
+                               project_v3_plane(tmp_co_v4, normal, mv_src[mface_src[nearest.index].v1].co);
+                               distribution_v4= len_squared_v3v3(tmp_co, tmp_co_v4);
+                               if(distribution_v4 == 0) weight= defvert_verify_index(dv_array_src[mface_src[nearest.index].v4], index_src)->weight;
+                               else{
+                                       distribution_v4= 1/distribution_v4;
+                                       tot_distribution+= distribution_v4;
+
+                                       /*get weight from quad*/
+                                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v1], index_src);
+                                       weight= dw_src->weight * distribution_v1 / tot_distribution;
+                                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v2], index_src);
+                                       weight+= dw_src->weight * distribution_v2 / tot_distribution;
+                                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v3], index_src);
+                                       weight+= dw_src->weight * distribution_v3 / tot_distribution;
+                                       dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v4], index_src);
+                                       weight+= dw_src->weight * distribution_v4 / tot_distribution;
+                               }
+                       }
+                       else{
+                               /*get weight from triangle*/
+                               dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v1], index_src);
+                               weight= dw_src->weight * distribution_v1 / tot_distribution;
+                               dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v2], index_src);
+                               weight+= dw_src->weight * distribution_v2 / tot_distribution;
+                               dw_src= defvert_verify_index(dv_array_src[mface_src[nearest.index].v3], index_src);
+                               weight+= dw_src->weight * distribution_v3 / tot_distribution;
+                       }
+               }
+
+               /*dist_to_line_segment_v3()*/
+               /*There is probably something fundamentaly wrong about the interpolation.
+               When a vertex is on an edge, it should get no weight from the vertex not connected to the edge...
+               Projected onto edge it should get linar interpolation from two vertices.
+               so it should get the interpolated weight from the third vertex based on the inverted distance from edge along normal to edge!
+               if I got this right! :P
+               */
+               /*snap to valid number, for testing. This should not be nessecary if interpolation works as its supposed to! or is my logick wrong???*//*
+               weight*= 1000;
+               weight+= 0.5;
+               weight= (int)weight;
+               weight/=1000;
+               if(weight>1)weight= 1;*/
+
+               /*copy weight*/
+               dw_dst= defvert_verify_index(*dv_array_dst, index_dst);
+               dw_dst->weight= weight;
+       }
+
+       /*free memory and return*/
+       free_bvhtree_from_mesh(&tree_mesh_faces_src);
+       return 1;
+}
+
 
 /* for Mesh in Object mode */
 /* allows editmode for Lattice */
@@ -2760,6 +3114,58 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+static int vertex_group_copy_to_selected_single_exec(bContext *C, wmOperator *op)
+{
+       Object *obact= CTX_data_active_object(C);
+       int change= 0;
+       int fail= 0;
+
+       /*Macro to loop through selected objects and perform operation*/
+       CTX_DATA_BEGIN(C, Object*, obslc, selected_editable_objects)
+       {
+               if(obact != obslc) {
+                       /*Try function for matching number of vertices*/
+                       if(ED_vgroup_copy_single(obslc, obact)) change++;
+                       /*Try function for get weight from closest vertex*/
+                       /*TODO: try this function*/
+                       /*Try function for get weight from closest face*/
+                       else if(ED_vgroup_copy_by_nearest_face_single(obslc, obact)) change++;
+                       /*Trigger error message*/
+                       else fail++;
+                       /*Event notifiers for correct display of data*/
+                       DAG_id_tag_update(&obslc->id, OB_RECALC_DATA);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obslc);
+                       WM_event_add_notifier(C, NC_GEOM|ND_DATA, obslc->data);
+               }
+       }
+       CTX_DATA_END;
+
+       /*Report error when task can not be completed with available functions.*/
+       if((change == 0 && fail == 0) || fail) {
+               BKE_reportf(op->reports, RPT_ERROR,
+                           "Copy to VGroups to Selected warning done %d, failed %d, All functions failed!",
+                           change, fail);
+       }
+
+       return OPERATOR_FINISHED;
+}
+
+/*Transfer vertex group with weight to selected*/
+void OBJECT_OT_vertex_group_copy_to_selected_single(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Copy a Vertex Group to Selected";
+       ot->idname= "OBJECT_OT_vertex_group_copy_to_selected_single";
+       ot->description= "Copy a vertex group to other selected objects with matching indices";
+
+       /* api callbacks */
+       ot->poll= vertex_group_poll;
+       ot->exec= vertex_group_copy_to_selected_single_exec;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 static EnumPropertyItem vgroup_items[] = {
        {0, NULL, 0, NULL, NULL}
 };