[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15214] branches/apricot/source/blender: Topology Mirror.
Campbell Barton
ideasman42 at gmail.com
Fri Jun 13 14:34:26 CEST 2008
Revision: 15214
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15214
Author: campbellbarton
Date: 2008-06-13 14:33:35 +0200 (Fri, 13 Jun 2008)
Log Message:
-----------
Topology Mirror. Find mirror verts based on topology, ignoring vertex location,
Currently works with transform and weight painting.
Tested with 5 peach characters and Suzanne (without eyes), rely's on both verts being uniquely positioned in relation to the surrounding edge topology. useful when weight painting asymmetric characters.
Modified Paths:
--------------
branches/apricot/source/blender/include/BIF_meshtools.h
branches/apricot/source/blender/include/blendef.h
branches/apricot/source/blender/src/buttons_editing.c
branches/apricot/source/blender/src/editmesh.c
branches/apricot/source/blender/src/editmesh_mods.c
branches/apricot/source/blender/src/meshtools.c
branches/apricot/source/blender/src/transform_conversions.c
branches/apricot/source/blender/src/vpaint.c
Modified: branches/apricot/source/blender/include/BIF_meshtools.h
===================================================================
--- branches/apricot/source/blender/include/BIF_meshtools.h 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/include/BIF_meshtools.h 2008-06-13 12:33:35 UTC (rev 15214)
@@ -41,8 +41,9 @@
extern void objects_bake_render(short event, char **error_msg);
extern long mesh_octree_table(struct Object *ob, float *co, char mode);
+extern long mesh_mirrtopo_table(struct Object *ob, char mode);
extern int mesh_get_x_mirror_vert(struct Object *ob, int index);
-extern struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, float *co);
+extern struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditVert *eve);
extern float *editmesh_get_mirror_uv(int axis, float *co, float *mirrCent, float *face_cent);
extern int *mesh_get_x_mirror_faces(struct Object *ob);
Modified: branches/apricot/source/blender/include/blendef.h
===================================================================
--- branches/apricot/source/blender/include/blendef.h 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/include/blendef.h 2008-06-13 12:33:35 UTC (rev 15214)
@@ -446,7 +446,9 @@
#define B_JOINTRIA_VCOL 0X400
#define B_JOINTRIA_SHARP 0X800
#define B_JOINTRIA_MAT 0X1000
+#define B_MIRROR_TOPO 0X2000 /* Topology Mirroring, disabled by default */
+
/* DISPLAYMODE */
#define R_DISPLAYIMAGE 0
#define R_DISPLAYWIN 1
Modified: branches/apricot/source/blender/src/buttons_editing.c
===================================================================
--- branches/apricot/source/blender/src/buttons_editing.c 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/src/buttons_editing.c 2008-06-13 12:33:35 UTC (rev 15214)
@@ -5086,7 +5086,8 @@
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, G_ALLEDGES, 0, "All Edges", 1125, 22,150,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization");
- uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation");
+ uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-Axis Mirror",1125,0,80,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation");
+ uiDefButBitS(block, TOG, B_MIRROR_TOPO, B_DIFF, "Topology",1125+80,0,70,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Calculate mirror from mesh topology");
uiBlockEndAlign(block);
}
@@ -6077,7 +6078,8 @@
if(ob) {
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, VP_ONLYVGROUP, REDRAWVIEW3D, "Vgroup", 10,0,100,19, &Gwp.flag, 0, 0, 0, 0, "Only paint on vertices in the selected vertex group.");
- uiDefButBitS(block, TOG, VP_MIRROR_X, REDRAWVIEW3D, "X-Mirror", 110,0,100,19, &Gwp.flag, 0, 0, 0, 0, "Mirrored Paint, applying on mirrored Weight Group name");
+ uiDefButBitS(block, TOG, VP_MIRROR_X, REDRAWVIEW3D, "X-Mirror", 110,0,80,19, &Gwp.flag, 0, 0, 0, 0, "Mirrored Paint, applying on mirrored Weight Group name");
+ uiDefButBitS(block, TOG, B_MIRROR_TOPO, B_DIFF, "T",110+80,0,20,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Calculate mirror from mesh topology"); /* TODO - Put this in a nicer place */
uiDefBut(block, BUT, B_CLR_WPAINT, "Clear", 210,0,100,19, NULL, 0, 0, 0, 0, "Removes reference to this deform group from all vertices");
uiBlockEndAlign(block);
}
Modified: branches/apricot/source/blender/src/editmesh.c
===================================================================
--- branches/apricot/source/blender/src/editmesh.c 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/src/editmesh.c 2008-06-13 12:33:35 UTC (rev 15214)
@@ -627,6 +627,7 @@
em->allfaces= em->curface= NULL;
mesh_octree_table(NULL, NULL, 'e');
+ mesh_mirrtopo_table(NULL, 'e');
G.totvert= G.totface= 0;
Modified: branches/apricot/source/blender/src/editmesh_mods.c
===================================================================
--- branches/apricot/source/blender/src/editmesh_mods.c 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/src/editmesh_mods.c 2008-06-13 12:33:35 UTC (rev 15214)
@@ -120,7 +120,7 @@
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->f & SELECT) {
- v1= editmesh_get_x_mirror_vert(G.obedit, eve->co);
+ v1= editmesh_get_x_mirror_vert(G.obedit, eve);
if(v1) {
eve->f &= ~SELECT;
v1->f |= SELECT;
@@ -4249,7 +4249,7 @@
if(eve->f1) {
if (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) {
- eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve->co);
+ eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve);
}
adr = eve->tmp.p;
Modified: branches/apricot/source/blender/src/meshtools.c
===================================================================
--- branches/apricot/source/blender/src/meshtools.c 2008-06-13 02:20:09 UTC (rev 15213)
+++ branches/apricot/source/blender/src/meshtools.c 2008-06-13 12:33:35 UTC (rev 15214)
@@ -837,8 +837,192 @@
return 0;
}
-int mesh_get_x_mirror_vert(Object *ob, int index)
+
+/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */
+
+#define MIRRHASH_TYPE int
+
+typedef struct MirrTopoPair {
+ long hash;
+ int vIndex;
+} MirrTopoPair;
+
+/* sort faces on view axis */
+static int MirrTopo_long_sort(const void *l1, const void *l2)
+{
+ if( (MIRRHASH_TYPE)l1 > (MIRRHASH_TYPE)l2 ) return 1;
+ else if( (MIRRHASH_TYPE)l1 < (MIRRHASH_TYPE)l2 ) return -1;
+ return 0;
+}
+
+static int MirrTopo_item_sort(const void *v1, const void *v2)
{
+ if( ((MirrTopoPair *)v1)->hash > ((MirrTopoPair *)v2)->hash ) return 1;
+ else if( ((MirrTopoPair *)v1)->hash < ((MirrTopoPair *)v2)->hash ) return -1;
+ return 0;
+}
+
+static long *mesh_topo_lookup = NULL;
+static int mesh_topo_lookup_tot = -1;
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+long mesh_mirrtopo_table(Object *ob, char mode)
+{
+ if(mode=='u') { /* use table */
+ Mesh *me= ob->data;
+ if (!mesh_topo_lookup || (me->totvert != mesh_topo_lookup_tot)) {
+ mesh_mirrtopo_table(ob, 's');
+ }
+ } else if(mode=='s') { /* start table */
+ Mesh *me= ob->data;
+ MEdge *medge;
+
+ /* editmode*/
+ EditEdge *eed;
+
+ int a, last, totvert;
+ int totUnique= -1, totUniqueOld= -1;
+
+
+ MIRRHASH_TYPE *MirrTopoHash = NULL;
+ MIRRHASH_TYPE *MirrTopoHash_Prev = NULL;
+ MirrTopoPair *MirrTopoPairs;
+
+ /* reallocate if needed */
+ if (mesh_topo_lookup) {
+ MEM_freeN(mesh_topo_lookup);
+ mesh_topo_lookup = NULL;
+ }
+
+ if(ob==G.obedit) {
+ EditVert *eve;
+ totvert= 0;
+ for(eve= G.editMesh->verts.first; eve; eve= eve->next) {
+ eve->tmp.l = totvert++;
+ }
+ } else {
+ totvert = me->totvert;
+ }
+
+ MirrTopoHash = MEM_callocN( totvert * sizeof(MIRRHASH_TYPE), "TopoMirr" );
+
+ /* Initialize the vert-edge-user counts used to detect unique topology */
+ if(ob==G.obedit) {
+ for(eed=G.editMesh->edges.first; eed; eed= eed->next) {
+ MirrTopoHash[eed->v1->tmp.l]++;
+ MirrTopoHash[eed->v2->tmp.l]++;
+ }
+ } else {
+ for(a=0, medge=me->medge; a<me->totedge; a++, medge++) {
+ MirrTopoHash[medge->v1]++;
+ MirrTopoHash[medge->v2]++;
+ }
+ }
+
+ MirrTopoHash_Prev = MEM_dupallocN( MirrTopoHash );
+
+ totUniqueOld = -1;
+ while(1) {
+ /* use the number of edges per vert to give verts unique topology IDs */
+
+ if(ob==G.obedit) {
+ for(eed=G.editMesh->edges.first; eed; eed= eed->next) {
+ MirrTopoHash[eed->v1->tmp.l] += MirrTopoHash_Prev[eed->v2->tmp.l];
+ MirrTopoHash[eed->v2->tmp.l] += MirrTopoHash_Prev[eed->v1->tmp.l];
+ }
+ } else {
+ for(a=0, medge=me->medge; a<me->totedge; a++, medge++) {
+ /* This can make realy big numbers, wrapping around here is fine */
+ MirrTopoHash[medge->v1] += MirrTopoHash_Prev[medge->v2];
+ MirrTopoHash[medge->v2] += MirrTopoHash_Prev[medge->v1];
+ }
+ }
+ memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MIRRHASH_TYPE) * totvert);
+
+ /* sort so we can count unique values */
+ qsort(MirrTopoHash_Prev, totvert, sizeof(MIRRHASH_TYPE), MirrTopo_long_sort);
+
+ totUnique = 1; /* account for skiping the first value */
+ for(a=1; a<totvert; a++) {
+ if (MirrTopoHash_Prev[a-1] != MirrTopoHash_Prev[a]) {
+ totUnique++;
+ }
+ }
+
+ if (totUnique <= totUniqueOld) {
+ /* Finish searching for unique valus when 1 loop dosnt give a
+ * higher number of unique values compared to the previous loop */
+ break;
+ } else {
+ totUniqueOld = totUnique;
+ }
+ /* Copy the hash calculated this iter, so we can use them next time */
+ memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MIRRHASH_TYPE) * totvert);
+ }
+
+ /* Hash/Index pairs are needed for sorting to find index pairs */
+ MirrTopoPairs= MEM_callocN( sizeof(MirrTopoPair) * totvert, "MirrTopoPairs");
+
+ /* since we are looping through verts, initialize these values here too */
+ mesh_topo_lookup = MEM_mallocN( totvert * sizeof(long), "mesh_topo_lookup" );
+
+ if(ob==G.obedit) {
+ EM_init_index_arrays(1,0,0);
+ }
+
+
+ for(a=0; a<totvert; a++) {
+ MirrTopoPairs[a].hash= MirrTopoHash[a];
+ MirrTopoPairs[a].vIndex = a;
+
+ /* initialize lookup */
+ mesh_topo_lookup[a] = -1;
+ }
+
+ qsort(MirrTopoPairs, totvert, sizeof(MirrTopoPair), MirrTopo_item_sort);
+
+ /* Since the loop starts at 2, we must define the last index where the hash's differ */
+ last = ((totvert >= 2) && (MirrTopoPairs[0].hash == MirrTopoPairs[1].hash)) ? 0 : 1;
+
+ /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
+ * but you cant ever access the last 'a' index of MirrTopoPairs */
+ for(a=2; a < totvert+1; a++) {
+ /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].vIndex ); */
+ if ((a==totvert) || (MirrTopoPairs[a-1].hash != MirrTopoPairs[a].hash)) {
+ if (a-last==2) {
+ if(ob==G.obedit) {
+ mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = (long)EM_get_vert_for_index(MirrTopoPairs[a-2].vIndex);
+ mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = (long)EM_get_vert_for_index(MirrTopoPairs[a-1].vIndex);
+ } else {
+ mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = MirrTopoPairs[a-2].vIndex;
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list