== Sculpt Mode ==
authorNicholas Bishop <nicholasbishop@gmail.com>
Thu, 20 Dec 2007 19:07:47 +0000 (19:07 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Thu, 20 Dec 2007 19:07:47 +0000 (19:07 +0000)
Applying Stephan Kassemeyer's patch (#6750) to add a curve modifier for sculpting.

A few changes from the patch:
* The default curve is closer to the old behavior
* Fixed loading files already saved in sculpt mode
* Changed the interface; split the brush texture controls off into a third sculpt tab, and put the curve (and curve reset) into the Brush tab.

source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BDR_sculptmode.h
source/blender/makesdna/DNA_scene_types.h
source/blender/src/buttons_editing.c
source/blender/src/drawview.c
source/blender/src/sculptmode.c

index 8b9454f1a9d9e54deaa44b2b8ba0bb0e34c0b28a..02e2f799103bdb98115d3e898e31354d50f8f0e4 100644 (file)
@@ -217,6 +217,8 @@ void multires_update_levels(struct Mesh *me, const int render);
 void multires_calc_level_maps(struct MultiresLevel *lvl);
 struct Multires *multires_copy(struct Multires *orig);
 /* sculptmode.c */
+struct SculptData;
+void sculpt_reset_curve(struct SculptData *sd);
 void sculptmode_free_all(struct Scene *sce);
 void sculptmode_init(struct Scene *sce);
 
index 55931b50462ae97a51aebb0e089edd1f3da80cc8..e0aa288c7b207eb08448700c6b38b19dfb6aac84 100644 (file)
@@ -317,6 +317,7 @@ void multires_set_level(struct Object *ob, struct Mesh *me, const int render) {}
 void multires_update_levels(struct Mesh *me, const int render) {}
 void multires_calc_level_maps(struct MultiresLevel *lvl) {}
 struct Multires *multires_copy(struct Multires *orig) {return NULL;}
+void sculpt_reset_curve(struct SculptData *sd) {}
 void sculptmode_init(struct Scene *sce) {}
 void sculptmode_free_all(struct Scene *sce) {}
 
index 8bbcc7016c14b2a072133deb870f7372909ac633..553ab0eb168ad1c21a0cfec02770f98f58330f7c 100644 (file)
@@ -3323,6 +3323,12 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        /* SculptData textures */
        for(a=0; a<MAX_MTEX; ++a)
                sce->sculptdata.mtex[a]= newdataadr(fd,sce->sculptdata.mtex[a]);
+       /* Sculpt intensity curve */
+       sce->sculptdata.cumap= newdataadr(fd, sce->sculptdata.cumap);
+       if(sce->sculptdata.cumap)
+               direct_link_curvemapping(fd, sce->sculptdata.cumap);
+       else
+               sculpt_reset_curve(&sce->sculptdata);
 
        if(sce->ed) {
                ListBase *old_seqbasep= &((Editing *)sce->ed)->seqbase;
index cfaae977bddd574d040d7c9cfad26b9d67e74696..d19c634e610d4a0fc453d2caa473fcb877bb24a3 100644 (file)
@@ -1422,6 +1422,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
 
                for(a=0; a<MAX_MTEX; ++a)
                        writestruct(wd, DATA, "MTex", 1, sce->sculptdata.mtex[a]);
+               if(sce->sculptdata.cumap)
+                       write_curvemapping(wd, sce->sculptdata.cumap);
 
                ed= sce->ed;
                if(ed) {
index c80f9ea86265e3508c6c0500617343822f496dbc..abbb17ac42b45a885b2c1ea60a4197f51016b7f8 100644 (file)
@@ -99,12 +99,14 @@ SculptSession *sculpt_session(void);
 struct SculptData *sculpt_data(void);
 
 /* Memory */
+void sculpt_reset_curve(struct SculptData *sd);
 void sculptmode_init(struct Scene *);
 void sculptmode_free_all(struct Scene *);
 void sculptmode_correct_state(void);
 
 /* Interface */
 void sculptmode_draw_interface_tools(struct uiBlock *block,unsigned short cx, unsigned short cy);
+void sculptmode_draw_interface_brush(struct uiBlock *block,unsigned short cx, unsigned short cy);
 void sculptmode_draw_interface_textures(struct uiBlock *block,unsigned short cx, unsigned short cy);
 void sculptmode_rem_tex(void*,void*);
 void sculptmode_propset_init(PropsetMode mode);
index 412c40c7eb03bb0d5e18c0b56778e14a2412fe1c..c82a1f9e510368455391b63a7716b9278175c6b5 100644 (file)
@@ -424,6 +424,9 @@ typedef struct SculptData
        /* Pointers to all of sculptmodes's textures */
        struct MTex *mtex[10];
 
+       /* Editable brush shape */
+       struct CurveMapping *cumap;
+
        /* Settings for each brush */
        BrushData drawbrush, smoothbrush, pinchbrush, inflatebrush, grabbrush, layerbrush, flattenbrush;
        short brush_type;
index 83139fcfb0af3a3ea9a2aa194c4919008ec367f9..ca87893349935834ce33b4348cae37d3c3a6c895 100644 (file)
@@ -5046,22 +5046,29 @@ void editing_panel_sculpting_tools()
        sculptmode_draw_interface_tools(block,0,200);
 }
 
-void editing_panel_sculpting_textures()
+void editing_panel_sculpting_brush()
 {
-       uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_textures", UI_EMBOSS, UI_HELV, curarea->win);
+       uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_brush", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Brush", "Editing", 300, 0, 318, 204)==0) return;
 
+       sculptmode_draw_interface_brush(block,0,200);
+}
+
+void editing_panel_sculpting_textures()
+{
+       uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_texture", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Texture", "Editing", 300, 0, 318, 204)==0) return;
+
        sculptmode_draw_interface_textures(block,0,200);
 }
 
 void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned short cy)
 {
        SculptData *sd;
-       uiBut *but;
 
        if(!G.scene) return;
        sd= &G.scene->sculptdata;
-       
+
        uiBlockBeginAlign(block);
 
        uiDefBut(block,LABEL,B_NOP,"Brush",cx,cy,90,19,NULL,0,0,0,0,"");
@@ -5090,7 +5097,7 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned
        if(sd->brush_type!=GRAB_BRUSH)
                uiDefButC(block,TOG,B_NOP,"Airbrush",cx+178,cy,89,19,&sculptmode_brush()->airbrush,0,0,0,0,"Brush makes changes without waiting for the mouse to move");
        cy-= 20;
-       but= uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels");
+       uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels");
        cy-= 20;
        if(sd->brush_type!=GRAB_BRUSH)
                uiDefButC(block,NUMSLI,B_NOP,"Strength: ",cx,cy,268,19,&sculptmode_brush()->strength,1.0,100.0,0,0,"Set brush strength");
@@ -5109,34 +5116,57 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned
        cx+= 210;
 }
 
-void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsigned short cy)
+static void sculptmode_curves_reset(void *sd_v, void *j)
+{
+       SculptData *sd = sd_v;
+       sculpt_reset_curve(sd);
+       curvemapping_changed(sd->cumap, 0);
+}
+
+void sculptmode_draw_interface_brush(uiBlock *block, unsigned short cx, unsigned short cy)
 {
        SculptData *sd= sculpt_data();
-       MTex *mtex;
-       int i;
-       int orig_y= cy;
-       char *strp;
+       int orig_y = cy;
+       rctf rect;
        uiBut *but;
 
        uiBlockBeginAlign(block);
-       uiDefBut(block,LABEL,B_NOP,"Common",cx,cy,80,20,0,0,0,0,0,"");
        cy-= 20;
-       
-       uiBlockBeginAlign(block);
-       uiDefButC(block,TOG,B_NOP, "Fade", cx,cy,80,19, &sd->texfade, 0,0,0,0,"Smooth the edges of the texture");
+       uiDefButC(block,TOG,REDRAWBUTSEDIT, "Curve", cx,cy,80,19, &sd->texfade, 0,0,0,0,"Use curve control for radial brush intensity");
        cy-= 20;
+       but= uiDefBut(block, BUT, REDRAWBUTSEDIT, "Reset",cx,cy,80,19, NULL, 0,0,0,0, "Default curve preset");
+       uiButSetFunc(but, sculptmode_curves_reset, sd, NULL);
+       cy-= 25;
+       uiBlockEndAlign(block); 
+
+       uiBlockBeginAlign(block);
        uiDefButS(block,NUM,B_NOP, "Space", cx,cy,80,19, &sd->spacing, 0,500,20,0,"Non-zero inserts N pixels between dots");
        cy-= 20;
        if(sd->brush_type == DRAW_BRUSH)
                uiDefButC(block,NUM,B_NOP, "View", cx,cy,80,19, &sculptmode_brush()->view, 0,10,20,0,"Pulls brush direction towards view");
        uiBlockEndAlign(block);
-       
-       cy= orig_y;
-       cx+= 85;
+
+       /* Draw curve */
+       cx += 90;
+       cy = orig_y;
+       rect.xmin= cx; rect.xmax= cx + 178;
+       rect.ymin= cy - 160; rect.ymax= cy + 20;
        uiBlockBeginAlign(block);
-       uiDefBut(block,LABEL,B_NOP,"Texture",cx,cy,80,20,0,0,0,0,0,"");
-       cy-= 20;
+       curvemap_buttons(block, sd->cumap, (char)0, B_NOP, 0, &rect);
+       uiBlockEndAlign(block);
+}
+
+void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsigned short cy)
+{
+       SculptData *sd= sculpt_data();
+       MTex *mtex;
+       int i;
+       int orig_y= cy;
+       char *strp;
+       uiBut *but;
 
+       uiBlockBeginAlign(block);
+       cy-= 20;
        /* TEX CHANNELS */
        uiBlockBeginAlign(block);
        uiBlockSetCol(block, TH_BUT_NEUTRAL);
@@ -6034,6 +6064,8 @@ void editing_panels()
                        uiNewPanelTabbed("Multires", "Editing");
                        editing_panel_sculpting_tools();
                        uiNewPanelTabbed("Multires", "Editing");
+                       editing_panel_sculpting_brush();
+                       uiNewPanelTabbed("Multires", "Editing");
                        editing_panel_sculpting_textures();
                } else {
                        if(G.f & (G_VERTEXPAINT | G_TEXTUREPAINT | G_WEIGHTPAINT) ) {
index b3ffd1263ad2f99c6a3785cc4cda6dbfbf4b163d..5df1448ebc162937981f8142534502c70e09e90e 100644 (file)
@@ -2252,7 +2252,7 @@ static void view3d_panel_object(short cntrl)      // VIEW3D_HANDLER_OBJECT
        uiSetPanelHandler(VIEW3D_HANDLER_OBJECT);  // for close and esc
 
        if((G.f & G_SCULPTMODE) && !G.obedit) {
-               if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 425, 234))
+               if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234))
                        return;
        } else if(G.f & G_PARTICLEEDIT && !G.obedit){
                if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234))
index 7dd668e1acb3c8b01fb40cce07f1143d138306c5..010bf6f746cbc145cd1fcad3b680490f87f31cad 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_texture_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_userdef_types.h"
+#include "DNA_color_types.h"
 
 #include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
@@ -66,6 +67,7 @@
 #include "BKE_modifier.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
+#include "BKE_colortools.h"
 
 #include "BIF_editkey.h"
 #include "BIF_editview.h"
@@ -190,6 +192,35 @@ SculptSession *sculpt_session(void)
  * Allocate/initialize/free data
  */
 
+// Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1;
+void sculpt_reset_curve(SculptData *sd)
+{
+       CurveMap *cm = NULL;
+
+       if(!sd->cumap)
+               sd->cumap = curvemapping_add(1, 0, 0, 1, 1);
+
+       cm = sd->cumap->cm;
+
+       if(cm->curve)
+               MEM_freeN(cm->curve);
+       cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points");
+       cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+       cm->totpoint= 6;
+       cm->curve[0].x= 0;
+       cm->curve[0].y= 1;
+       cm->curve[1].x= 0.1;
+       cm->curve[1].y= 0.97553;
+       cm->curve[2].x= 0.3;
+       cm->curve[2].y= 0.79389;
+       cm->curve[3].x= 0.9;
+       cm->curve[3].y= 0.02447;
+       cm->curve[4].x= 0.7;
+       cm->curve[4].y= 0.20611;
+       cm->curve[5].x= 1;
+       cm->curve[5].y= 0;
+}
+
 /* Initialize 'permanent' sculpt data that is saved with file kept after
    switching out of sculptmode. */
 void sculptmode_init(Scene *sce)
@@ -203,6 +234,9 @@ void sculptmode_init(Scene *sce)
 
        sd= &sce->sculptdata;
 
+       if(sd->cumap)
+               curvemapping_free(sd->cumap);
+
        memset(sd, 0, sizeof(SculptData));
 
        sd->drawbrush.size = sd->smoothbrush.size = sd->pinchbrush.size =
@@ -227,6 +261,7 @@ void sculptmode_init(Scene *sce)
        sd->tablet_size=3;
        sd->tablet_strength=10;
        sd->rake=0;
+       sculpt_reset_curve(sd);
 }
 
 void sculptmode_free_session(Scene *);
@@ -281,6 +316,9 @@ void sculptmode_free_all(Scene *sce)
                        MEM_freeN(mtex);
                }
        }
+
+       curvemapping_free(sd->cumap);
+       sd->cumap = NULL;
 }
 
 /* vertex_users is an array of Lists that store all the faces that use a
@@ -735,12 +773,11 @@ void do_flatten_brush(const EditData *e, const ListBase *active_verts)
        }
 }
 
-/* Creates a smooth curve for the brush shape. This is the cos(x) curve from
-   [0,PI] scaled to [0,len]. The range is scaled to [0,1]. */
-float simple_strength(float p, const float len)
+/* Uses the brush curve control to find a strength value between 0 and 1 */
+float curve_strength(float p, const float len)
 {
        if(p > len) p= len;
-       return 0.5f * (cos(M_PI*p/len) + 1);
+       return curvemapping_evaluateF(G.scene->sculptdata.cumap, 0, p/len);
 }
 
 /* Uses symm to selectively flip any axis of a coordinate. */
@@ -883,7 +920,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin
        }
 
        if(sd->texfade)
-               avg*= simple_strength(len,e->size); /* Smooth curve */
+               avg*= curve_strength(len,e->size); /* Smooth curve */
 
        return avg;
 }
@@ -1323,7 +1360,7 @@ void sculptmode_propset_calctex()
                                for(j=0; j<tsz; ++j) {
                                        float magn= sqrt(pow(i-tsz/2,2)+pow(j-tsz/2,2));
                                        if(sd->texfade)
-                                               pd->texdata[i*tsz+j]= simple_strength(magn,tsz/2);
+                                               pd->texdata[i*tsz+j]= curve_strength(magn,tsz/2);
                                        else
                                                pd->texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0;
                                }