static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], const int *selected, float scale) { /* Create vertex group weights from envelopes */ Bone *bone; bDeformGroup *dgroup; float distance; int i, iflip, j; bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0; bool use_mask = false; if ((ob->mode & OB_MODE_WEIGHT_PAINT) && (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL))) { use_mask = true; } /* for each vertex in the mesh */ for (i = 0; i < mesh->totvert; i++) { if (use_mask && !(mesh->mvert[i].flag & SELECT)) { continue; } iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1; /* for each skinnable bone */ for (j = 0; j < numbones; ++j) { if (!selected[j]) continue; bone = bonelist[j]; dgroup = dgrouplist[j]; /* store the distance-factor from the vertex to the bone */ distance = distfactor_to_bone(verts[i], root[j], tip[j], bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale); /* add the vert to the deform group if (weight != 0.0) */ if (distance != 0.0f) ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgroup, i); /* do same for mirror */ if (dgroupflip && dgroupflip[j] && iflip != -1) { if (distance != 0.0f) ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgroupflip[j], iflip); } } } }
/* removes from active defgroup, if allverts==0 only selected vertices */ static void vgroup_active_remove_verts(Object *ob, int allverts) { EditVert *eve; MDeformVert *dvert; MDeformWeight *newdw; bDeformGroup *dg, *eg; int i; dg=BLI_findlink(&ob->defbase, ob->actdef-1); if(!dg) return; if(ob->type == OB_MESH) { Mesh *me= ob->data; EditMesh *em = BKE_mesh_get_editmesh(me); for(eve=em->verts.first; eve; eve=eve->next){ dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); if(dvert && dvert->dw && ((eve->f & 1) || allverts)){ for(i=0; i<dvert->totweight; i++){ /* Find group */ eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr); if(eg == dg){ dvert->totweight--; if(dvert->totweight){ newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); if(dvert->dw){ memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i); memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); MEM_freeN(dvert->dw); } dvert->dw=newdw; } else{ MEM_freeN(dvert->dw); dvert->dw=NULL; break; } } } } } BKE_mesh_end_editmesh(me, em); } else if(ob->type == OB_LATTICE) { Lattice *lt= vgroup_edit_lattice(ob); if(lt->dvert) { BPoint *bp; int a, tot= lt->pntsu*lt->pntsv*lt->pntsw; for(a=0, bp= lt->def; a<tot; a++, bp++) { if(allverts || (bp->f1 & SELECT)) ED_vgroup_vert_remove(ob, dg, a); } } } }
static void vgroup_delete_object_mode(Object *ob) { bDeformGroup *dg; MDeformVert *dvert, *dvert_array=NULL; int i, e, dvert_tot=0; dg = BLI_findlink(&ob->defbase, (ob->actdef-1)); if(!dg) return; ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot); if(dvert_array) { for(i = 0; i < dvert_tot; i++) { dvert = dvert_array + i; if(dvert) { if(ED_vgroup_weight_get(dvert, (ob->actdef-1))) ED_vgroup_vert_remove(ob, dg, i); } } for(i = 0; i < dvert_tot; i++) { dvert = dvert_array+i; if(dvert) { for(e = 0; e < dvert->totweight; e++) { if(dvert->dw[e].def_nr > (ob->actdef-1)) dvert->dw[e].def_nr--; } } } } vgroup_delete_update_users(ob, ob->actdef); /* Update the active deform index if necessary */ if(ob->actdef == BLI_countlist(&ob->defbase)) ob->actdef--; /* Remove the group */ BLI_freelinkN(&ob->defbase, dg); }
void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str) { LaplacianSystem *sys; MLoopTri *mlooptri; MPoly *mp; MLoop *ml; float solution, weight; int *vertsflipped = NULL, *mask = NULL; int a, tottri, j, bbone, firstsegment, lastsegment; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; MVert *mvert = me->mvert; bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; *err_str = NULL; /* bone heat needs triangulated faces */ tottri = poly_to_tri_count(me->totpoly, me->totloop); /* count triangles and create mask */ if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) { mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask"); /* (added selectedVerts content for vertex mask, they used to just equal 1) */ if (use_vert_sel) { for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) { for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) { mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0; } } } else if (use_face_sel) { for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) { if (mp->flag & ME_FACE_SEL) { for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) { mask[ml->v] = 1; } } } } } /* create laplacian */ sys = laplacian_system_construct_begin(me->totvert, tottri, 1); sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop); mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__); BKE_mesh_recalc_looptri( me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri); sys->heat.mlooptri = mlooptri; sys->heat.mloop = me->mloop; sys->heat.totvert = me->totvert; sys->heat.verts = verts; sys->heat.root = root; sys->heat.tip = tip; sys->heat.numsource = numsource; heat_ray_tree_create(sys); heat_laplacian_create(sys); laplacian_system_construct_end(sys); if (dgroupflip) { vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped"); for (a = 0; a < me->totvert; a++) vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology); } /* compute weights per bone */ for (j = 0; j < numsource; j++) { if (!selected[j]) continue; firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]); lastsegment = (j == numsource - 1 || dgrouplist[j] != dgrouplist[j + 1]); bbone = !(firstsegment && lastsegment); /* clear weights */ if (bbone && firstsegment) { for (a = 0; a < me->totvert; a++) { if (mask && !mask[a]) continue; ED_vgroup_vert_remove(ob, dgrouplist[j], a); if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } /* fill right hand side */ laplacian_begin_solve(sys, -1); for (a = 0; a < me->totvert; a++) if (heat_source_closest(sys, a, j)) laplacian_add_right_hand_side(sys, a, sys->heat.H[a] * sys->heat.p[a]); /* solve */ if (laplacian_system_solve(sys)) { /* load solution into vertex groups */ for (a = 0; a < me->totvert; a++) { if (mask && !mask[a]) continue; solution = laplacian_system_get_solution(sys, a); if (bbone) { if (solution > 0.0f) ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD); } else { weight = heat_limit_weight(solution); if (weight > 0.0f) ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgrouplist[j], a); } /* do same for mirror */ if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) { if (bbone) { if (solution > 0.0f) ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD); } else { weight = heat_limit_weight(solution); if (weight > 0.0f) ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } } } else if (*err_str == NULL) { *err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones"); break; } /* remove too small vertex weights */ if (bbone && lastsegment) { for (a = 0; a < me->totvert; a++) { if (mask && !mask[a]) continue; weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a); weight = heat_limit_weight(weight); if (weight <= 0.0f) ED_vgroup_vert_remove(ob, dgrouplist[j], a); if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) { weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]); weight = heat_limit_weight(weight); if (weight <= 0.0f) ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } } } /* free */ if (vertsflipped) MEM_freeN(vertsflipped); if (mask) MEM_freeN(mask); heat_system_free(sys); laplacian_system_delete(sys); }
void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str) { LaplacianSystem *sys; MFace *mface; float solution, weight; int *vertsflipped = NULL, *mask= NULL; int a, totface, j, bbone, firstsegment, lastsegment; *err_str= NULL; /* count triangles and create mask */ if(me->editflag & ME_EDIT_PAINT_MASK) mask= MEM_callocN(sizeof(int)*me->totvert, "heat_bone_weighting mask"); for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) { totface++; if(mface->v4) totface++; if(mask && (mface->flag & ME_FACE_SEL)) { mask[mface->v1]= 1; mask[mface->v2]= 1; mask[mface->v3]= 1; if(mface->v4) mask[mface->v4]= 1; } } /* create laplacian */ sys = laplacian_system_construct_begin(me->totvert, totface, 1); sys->heat.mface= me->mface; sys->heat.totface= me->totface; sys->heat.totvert= me->totvert; sys->heat.verts= verts; sys->heat.root= root; sys->heat.tip= tip; sys->heat.numsource= numsource; heat_ray_tree_create(sys); heat_laplacian_create(sys); laplacian_system_construct_end(sys); if(dgroupflip) { vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped"); for(a=0; a<me->totvert; a++) vertsflipped[a] = mesh_get_x_mirror_vert(ob, a); } /* compute weights per bone */ for(j=0; j<numsource; j++) { if(!selected[j]) continue; firstsegment= (j == 0 || dgrouplist[j-1] != dgrouplist[j]); lastsegment= (j == numsource-1 || dgrouplist[j] != dgrouplist[j+1]); bbone= !(firstsegment && lastsegment); /* clear weights */ if(bbone && firstsegment) { for(a=0; a<me->totvert; a++) { if(mask && !mask[a]) continue; ED_vgroup_vert_remove(ob, dgrouplist[j], a); if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } /* fill right hand side */ laplacian_begin_solve(sys, -1); for(a=0; a<me->totvert; a++) if(heat_source_closest(sys, a, j)) laplacian_add_right_hand_side(sys, a, sys->heat.H[a]*sys->heat.p[a]); /* solve */ if(laplacian_system_solve(sys)) { /* load solution into vertex groups */ for(a=0; a<me->totvert; a++) { if(mask && !mask[a]) continue; solution= laplacian_system_get_solution(a); if(bbone) { if(solution > 0.0f) ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD); } else { weight= heat_limit_weight(solution); if(weight > 0.0f) ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgrouplist[j], a); } /* do same for mirror */ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) { if(bbone) { if(solution > 0.0f) ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD); } else { weight= heat_limit_weight(solution); if(weight > 0.0f) ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE); else ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } } } else if(*err_str == NULL) { *err_str= "Bone Heat Weighting: failed to find solution for one or more bones"; break; } /* remove too small vertex weights */ if(bbone && lastsegment) { for(a=0; a<me->totvert; a++) { if(mask && !mask[a]) continue; weight= ED_vgroup_vert_weight(ob, dgrouplist[j], a); weight= heat_limit_weight(weight); if(weight <= 0.0f) ED_vgroup_vert_remove(ob, dgrouplist[j], a); if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) { weight= ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]); weight= heat_limit_weight(weight); if(weight <= 0.0f) ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]); } } } } /* free */ if(vertsflipped) MEM_freeN(vertsflipped); if(mask) MEM_freeN(mask); heat_system_free(sys); laplacian_system_delete(sys); }
static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); // Object *obedit= CTX_data_edit_object(C); View3D *v3d= CTX_wm_view3d(C); // BoundBox *bb; Object *ob= OBACT; TransformProperties *tfp= v3d->properties_storage; switch(event) { case B_REDR: ED_area_tag_redraw(CTX_wm_area(C)); return; /* no notifier! */ case B_OBJECTPANEL: DAG_id_tag_update(&ob->id, OB_RECALC_OB); break; case B_OBJECTPANELMEDIAN: if(ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } break; /* note; this case also used for parbone */ case B_OBJECTPANELPARENT: if(ob) { if(ob->id.lib || test_parent_loop(ob->parent, ob) ) ob->parent= NULL; else { DAG_scene_sort(bmain, scene); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } break; case B_ARMATUREPANEL3: // rotate button on channel { bPoseChannel *pchan; float eul[3]; pchan= get_active_posechannel(ob); if (!pchan) return; /* make a copy to eul[3], to allow TAB on buttons to work */ eul[0]= (float)M_PI*tfp->ob_eul[0]/180.0f; eul[1]= (float)M_PI*tfp->ob_eul[1]/180.0f; eul[2]= (float)M_PI*tfp->ob_eul[2]/180.0f; if (pchan->rotmode == ROT_MODE_AXISANGLE) { float quat[4]; /* convert to axis-angle, passing through quats */ eul_to_quat( quat,eul); quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,quat); } else if (pchan->rotmode == ROT_MODE_QUAT) eul_to_quat( pchan->quat,eul); else copy_v3_v3(pchan->eul, eul); } /* no break, pass on */ case B_ARMATUREPANEL2: { ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } break; case B_TRANSFORMSPACEADD: { char names[sizeof(((TransformOrientation *)NULL)->name)]= ""; BIF_createTransformOrientation(C, NULL, names, 1, 0); break; } case B_TRANSFORMSPACECLEAR: BIF_clearTransformOrientation(C); break; #if 0 // XXX case B_WEIGHT0_0: wpaint->weight = 0.0f; break; case B_WEIGHT1_4: wpaint->weight = 0.25f; break; case B_WEIGHT1_2: wpaint->weight = 0.5f; break; case B_WEIGHT3_4: wpaint->weight = 0.75f; break; case B_WEIGHT1_0: wpaint->weight = 1.0f; break; case B_OPA1_8: wpaint->a = 0.125f; break; case B_OPA1_4: wpaint->a = 0.25f; break; case B_OPA1_2: wpaint->a = 0.5f; break; case B_OPA3_4: wpaint->a = 0.75f; break; case B_OPA1_0: wpaint->a = 1.0f; break; #endif case B_CLR_WPAINT: // if(!multires_level1_test()) { { bDeformGroup *defGroup = BLI_findlink(&ob->defbase, ob->actdef-1); if(defGroup) { Mesh *me= ob->data; int a; for(a=0; a<me->totvert; a++) ED_vgroup_vert_remove (ob, defGroup, a); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } break; case B_RV3D_LOCKED: case B_RV3D_BOXVIEW: case B_RV3D_BOXCLIP: { ScrArea *sa= CTX_wm_area(C); ARegion *ar= sa->regionbase.last; RegionView3D *rv3d; short viewlock; ar= ar->prev; rv3d= ar->regiondata; viewlock= rv3d->viewlock; if((viewlock & RV3D_LOCKED)==0) viewlock= 0; else if((viewlock & RV3D_BOXVIEW)==0) viewlock &= ~RV3D_BOXCLIP; for(; ar; ar= ar->prev) { if(ar->alignment==RGN_ALIGN_QSPLIT) { rv3d= ar->regiondata; rv3d->viewlock= viewlock; } } if(rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(sa, sa->regionbase.last); ED_area_tag_redraw(sa); } break; } /* default for now */ WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, ob); }