New: X-axis mirror weightpainting.

- Set the button in Paint Panel, Edit buttons context
- It assumes the mesh to be near-perfectly mirrored. Current threshold is
  set to 0.0001 (maximum difference allowed).
  In order to evaluate proper mirroring, a new option will be added in
  Mesh editmode later.
- When the flipped group doesn't exist yet, it creates the group
- Of course this doesn't work for mirror modifier!

New: Select/activate flipped bone or vertex group
- Press SHIFT+F in PoseMode or WeightPaint mode to get the flipped bone.
  Is especially to see while painting if the mirror copying works OK.

New: "Apply Envelope to VertexGroup" uses X-mirror option too.

Todo; check on mirror vertex painting, and mirror Mesh editmode....

The implementation is based on a 8x8x8 Octree, where vertex locations are
stored. Vertices on the threshold boundary of an Octree node are filled in
the neighbour nodes as well, ensuring that the lookup works with threshold.
The current size of the Octree gives good speedup, even for 128k vertices
it only needs 256 lookup cycles per checked vertex.
Same code could be used for the bevel tool for example.

src/meshtools.c:
int mesh_octree_table(Object *ob, float *co, char mode)

- mode 's' or 'e' is "start octree" or "end octree"
- mode 'u' is "use", it then returns an index nr of the found vertex.
  (return -1 if not found)
This commit is contained in:
2005-10-22 14:05:25 +00:00
parent ed7fb486a1
commit 5e8131309e
11 changed files with 363 additions and 32 deletions

View File

@@ -65,6 +65,7 @@
#include "BIF_graphics.h"
#include "BIF_interface.h"
#include "BIF_poseobject.h"
#include "BIF_meshtools.h"
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BIF_screen.h"
@@ -73,6 +74,7 @@
#include "BSE_edit.h"
#include "BSE_editipo.h"
#include "BSE_trans_types.h"
#include "mydevice.h"
#include "blendef.h"
@@ -582,7 +584,7 @@ void paste_posebuf (int flip)
struct vgroup_map {
float head[3], tail[3];
Bone *bone;
bDeformGroup *dg;
bDeformGroup *dg, *dgflip;
Object *meshobj;
};
@@ -591,7 +593,6 @@ static void pose_adds_vgroups__mapFunc(void *userData, int index, float *co, flo
struct vgroup_map *map= userData;
float vec[3], fac;
VECCOPY(vec, co);
Mat4MulVecfl(map->meshobj->obmat, vec);
@@ -604,17 +605,27 @@ static void pose_adds_vgroups__mapFunc(void *userData, int index, float *co, flo
else
remove_vert_defgroup (map->meshobj, map->dg, index);
if(map->dgflip) {
int j= mesh_get_x_mirror_vert(map->meshobj, index);
if(j>=0) {
if(fac!=0.0f)
add_vert_to_defgroup (map->meshobj, map->dgflip, j, fac, WEIGHT_REPLACE);
else
remove_vert_defgroup (map->meshobj, map->dgflip, j);
}
}
}
/* context weightpaint and deformer in posemode */
void pose_adds_vgroups(Object *meshobj)
{
extern VPaint Gwp; /* from vpaint */
struct vgroup_map map;
DerivedMesh *dm;
Object *poseobj= modifiers_isDeformedByArmature(meshobj);
bPoseChannel *pchan;
Bone *bone;
bDeformGroup *dg;
bDeformGroup *dg, *curdef;
int DMneedsFree;
if(poseobj==NULL || (poseobj->flag & OB_POSEMODE)==0) return;
@@ -632,6 +643,20 @@ void pose_adds_vgroups(Object *meshobj)
if(dg==NULL)
dg= add_defgroup_name(meshobj, bone->name);
/* flipped bone */
if(Gwp.flag & VP_MIRROR_X) {
char name[32];
BLI_strncpy(name, dg->name, 32);
bone_flip_name(name, 0); // 0 = don't strip off number extensions
for (curdef = meshobj->defbase.first; curdef; curdef=curdef->next)
if (!strcmp(curdef->name, name))
break;
map.dgflip= curdef;
}
else map.dgflip= NULL;
/* get the root of the bone in global coords */
VECCOPY(map.head, bone->arm_head);
Mat4MulVecfl(poseobj->obmat, map.head);
@@ -693,3 +718,52 @@ void pose_flip_names(void)
BIF_undo_push("Flip names");
}
/* context active object, or weightpainted object with armature in posemode */
void pose_activate_flipped_bone(void)
{
Object *ob= OBACT;
if(ob==NULL) return;
if(G.f & G_WEIGHTPAINT) {
ob= modifiers_isDeformedByArmature(ob);
}
if(ob && (ob->flag & OB_POSEMODE)) {
bPoseChannel *pchan, *pchanf;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->bone->flag & BONE_ACTIVE) {
break;
}
}
if(pchan) {
char name[32];
BLI_strncpy(name, pchan->name, 32);
bone_flip_name(name, 1); // 0 = do not strip off number extensions
pchanf= get_pose_channel(ob->pose, name);
if(pchanf && pchanf!=pchan) {
pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
pchanf->bone->flag |= (BONE_SELECTED|BONE_ACTIVE);
/* in weightpaint we select the associated vertex group too */
if(G.f & G_WEIGHTPAINT) {
vertexgroup_select_by_name(OBACT, name);
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
}
select_actionchannel_by_name(ob->action, name, 1);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0); /* To force action/constraint ipo update */
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWOOPS, 0);
}
}
}
}