[Bf-committers] editmesh.c: New User Iterative Smoothing, New Mesh Wrinkle Specials Function

Robert Tiess bf-committers@blender.org
Thu, 19 Feb 2004 01:01:42 -0500


Part One:  Improved Mesh Smoothing

I have added a user adjustable menu to perform one or more smoothing
passes on a mesh in edit mode.  This not only saves time from a user having
to click Smooth multiple times to tame a mesh after a fractal subdivision
(or the new wrinkle function I proprose below), it also saves undo levels
by containing the iterations (ranging from 1 to 10) in one undo level -- 
that
is, each smooth pass is not passed to undo, only the aftereffect of the
smoothing pass(es).  The submenu appears after selecting Smooth from
the Specials menu or by clicking the Smooth button in the edit window,
at which point a user selects an Amount to smooth by.


Part Two:  New Wrinkle Function in Specials Menu

You may have seen my "Crinkle" Python script posted at Elysiun and
Blender.org.  That script was created to help users easily achieve irregular
and complex shapes which have possibilities in organic modeling as well
as for terrain/environment creation, among other things.  While presently
in Blender a user can attain irregular shapes through Fractal Subdivision,
such subdivision introduce additional vertices/faces into a mesh.  The
Crinkle script did not do that:  it worked on the existing vertices 
themselves.
The Wrinkle function, which I found I could not simply rewrite from my
Python code, achieves superior results from a number of tests I've run
because it can function at a very small or very dramatic level, occurs very
quickly, and doesn't suffer from the screen/mesh update glitches the Python
script suffered from.  "Wrinkling a mesh" entails moving vertices from their
existing coordinates in small and random distances, so as to introduce
irregularity into the mesh.  Yet another benefit of the Wrinkle code in
Blender as compared to my older Python script is that it can function
either on the entire mesh (all vertices selected in edit mode) or only those
vertices currently selected.  This can be especially useful, since the user
may not always want to deform the entire mesh but only a part of it.

The editobject.c file would necessarily be updated via the enclosed
patch as well to accommodate the new Specials popup menu function.


My proposed patch code is included below and contains references
to my previously posted proposed loopcut operation enhancements
(as revised according to Martin's requests).

Thank you very much for considering these enhancements.

Robert

patch.txt begins with next line:
Index: editmesh.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/editmesh.c,v
retrieving revision 1.72
diff -r1.72 editmesh.c
2993,2994c2993,3007
<         if (G.qual & LR_CTRLKEY)
<             percentcut = (int)(percentcut*100.0)/100.0;       
---
 >         /* 10% loop cut with CTRL KEY */
 >         if (G.qual & LR_CTRLKEY && !(G.qual & LR_SHIFTKEY)) {
 >             percentcut = (int)(percentcut*10.0)/10.0;
 >         }
 >
 >         /* 1% loop cut with SHIFT KEY */
 >         if (G.qual & LR_SHIFTKEY && !(G.qual & LR_CTRLKEY)) {
 >             percentcut = (int)(percentcut*100.0)/100.0;
 >         }
 >
 >         /* 50% loop cut with MIDDLE MOUSE BUTTON */
 >         if (get_mbut()&M_MOUSE) {
 >             percentcut = 0.50;   
 >             searching=0;
 >         }
6011c6024,6027
<     int teller=0;
---
 >     int smoothLoop, teller=0;
 >     short smoothingAmount = 1;
 >
 >     if (button(&smoothingAmount, 1, 10, "Amount: ")==0) return;
6025,6031c6041,6050
<     adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, 
"vertsmooth");
<     eve= G.edve.first;
<     while(eve) {
<         if(eve->f & 1) {
<             eve->vn= (EditVert *)adr;
<             eve->f1= 0;
<             adr+= 3;
---
 >     for (smoothLoop=0; smoothLoop<smoothingAmount; smoothLoop++) {
 >         adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, 
"vertsmooth");
 >         eve= G.edve.first;
 >         while(eve) {
 >             if(eve->f & 1) {
 >                 eve->vn= (EditVert *)adr;
 >                 eve->f1= 0;
 >                 adr+= 3;
 >             }
 >             eve= eve->next;
6033,6034d6051
<         eve= eve->next;
<     }
6036,6049c6053,6067
<     eed= G.eded.first;
<     while(eed) {
<         if( (eed->v1->f & 1) || (eed->v2->f & 1) ) {
<             fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
<             fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
<             fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
<            
<             if((eed->v1->f & 1) && eed->v1->f1<255) {
<                 eed->v1->f1++;
<                 VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
<             }
<             if((eed->v2->f & 1) && eed->v2->f1<255) {
<                 eed->v2->f1++;
<                 VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
---
 >         eed= G.eded.first;
 >         while(eed) {
 >             if( (eed->v1->f & 1) || (eed->v2->f & 1) ) {
 >                 fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
 >                 fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
 >                 fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
 >    
 >                 if((eed->v1->f & 1) && eed->v1->f1<255) {
 >                     eed->v1->f1++;
 >                     VecAddf((float *)eed->v1->vn, (float 
*)eed->v1->vn, fvec);
 >                 }
 >                 if((eed->v2->f & 1) && eed->v2->f1<255) {
 >                     eed->v2->f1++;
 >                     VecAddf((float *)eed->v2->vn, (float 
*)eed->v2->vn, fvec);
 >                 }
6050a6069
 >             eed= eed->next;
6052c6071,6087
<         eed= eed->next;
---
 >
 >         eve= G.edve.first;
 >         while(eve) {
 >             if(eve->f & 1) {
 >                 if(eve->f1) {
 >                     adr= (float *)eve->vn;
 >                     fac= 0.5/(float)eve->f1;
 >                
 >                     eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
 >                     eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
 >                     eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
 >                 }
 >                 eve->vn= 0;
 >             }
 >             eve= eve->next;
 >         }
 >         MEM_freeN(adror);
6053a6089,6091
 >     allqueue(REDRAWVIEW3D, 0);
 >     makeDispList(G.obedit);
 > }
6055c6093,6109
<     eve= G.edve.first;
---
 > void vertexwrinkle(void)
 > {
 >     Tex *tex;
 >     EditVert *eve;
 >     float vec[3];
 >     float wf = 1.0;
 >
 >     if (fbutton(&wf,1.0,100.0,"Intensity")==0) return;
 >
 >     wf *= .01;
 >
 >     if(G.obedit==0) return;
 >    
 >     undo_push_mesh("VertexWrinkle");
 >    
 >    
 >     eve= (struct EditVert *)G.edve.first;
6058,6066c6112,6116
<             if(eve->f1) {
<                 adr= (float *)eve->vn;
<                 fac= 0.5/(float)eve->f1;
<                
<                 eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
<                 eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
<                 eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
<             }
<             eve->vn= 0;
---
 >             BLI_srand(BLI_rand());
 >             vec[0]= BLI_frand()*wf;
 >             vec[1]= BLI_frand()*wf;
 >             vec[2]= BLI_frand()*wf;
 >             VecAddf(eve->co, eve->co, vec);
6070d6119
<     MEM_freeN(adror);
6075d6123
<
Index: editobject.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/src/editobject.c,v
retrieving revision 1.71
diff -r1.71 editobject.c
1567c1567
<         nr= pupmenu("Specials%t|Subdivide%x1|Subdivide 
Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove 
Doubles%x5|Hide%x6|Reveal%x7|Select swap%x8|Flip Normals %x9|Smooth 
%x10|Bevel %x11");
---
 >         nr= pupmenu("Specials%t|Subdivide%x1|Subdivide 
Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove 
Doubles%x5|Hide%x6|Reveal%x7|Select swap%x8|Flip Normals %x9|Smooth 
%x10|Bevel %x11|Wrinkle %x12");
1611a1612,1615
 >             break;
 >         case 12:
 >             undo_push_mesh("Wrinkle");
 >             vertexwrinkle();