diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 978 |
1 files changed, 254 insertions, 724 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 0ae39a661c1..f3108e02159 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1,5 +1,5 @@ /* - * $Id: sculptmode.c 18309 2009-01-04 07:47:11Z nicholasbishop $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -148,6 +148,7 @@ typedef struct StrokeCache { float *layer_disps; /* Displacements for each vertex */ float (*mesh_store)[3]; /* Copy of the mesh vertices' locations */ short (*orig_norms)[3]; /* Copy of the mesh vertices' normals */ + float (*face_norms)[3]; /* Copy of the mesh faces' normals */ float rotation; /* Texture rotation (radians) for anchored and rake modes */ int pixel_radius, previous_pixel_radius; ListBase grab_active_verts[8]; /* The same list of verts is used throught grab stroke */ @@ -155,7 +156,6 @@ typedef struct StrokeCache { float old_grab_location[3]; int symmetry; /* Symmetry index between 0 and 7 */ float view_normal[3], view_normal_symmetry[3]; - int last_dot[2]; /* Last location of stroke application */ int last_rake[2]; /* Last location of updating rake rotation */ } StrokeCache; @@ -234,66 +234,50 @@ static char brush_size(Sculpt *sd) special multiplier found experimentally to scale the strength factor. */ static float brush_strength(Sculpt *sd, StrokeCache *cache) { + /* Primary strength input; square it to make lower values more sensitive */ + float alpha = sd->brush->alpha * sd->brush->alpha; + float dir= sd->brush->flag & BRUSH_DIR_IN ? -1 : 1; float pressure= 1; float flip= cache->flip ? -1:1; - float anchored = sd->brush->flag & BRUSH_ANCHORED ? 25 : 1; if(sd->brush->flag & BRUSH_ALPHA_PRESSURE) pressure *= cache->pressure; switch(sd->brush->sculpt_tool){ case SCULPT_TOOL_DRAW: + case SCULPT_TOOL_INFLATE: + case SCULPT_TOOL_CLAY: + case SCULPT_TOOL_FLATTEN: case SCULPT_TOOL_LAYER: - return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */; + return alpha * dir * pressure * flip; /*XXX: not sure why? was multiplied by G.vd->grid */; case SCULPT_TOOL_SMOOTH: - return sd->brush->alpha / .5 * pressure * anchored; + return alpha * 4 * pressure; case SCULPT_TOOL_PINCH: - return sd->brush->alpha / 10.0f * dir * pressure * flip * anchored; + return alpha / 2 * dir * pressure * flip; case SCULPT_TOOL_GRAB: return 1; - case SCULPT_TOOL_INFLATE: - return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; - case SCULPT_TOOL_FLATTEN: - return sd->brush->alpha / 5.0f * pressure * anchored; default: return 0; } } -/* For clipping against a mirror modifier */ -static void sculpt_clip(StrokeCache *cache, float *co, const float val[3]) +/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */ +static void sculpt_clip(Sculpt *sd, float *co, const float val[3]) { int i; + for(i=0; i<3; ++i) { - if((cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= cache->clip_tolerance[i])) + if(sd->flags & (SCULPT_LOCK_X << i)) + continue; + + if((sd->session->cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= sd->session->cache->clip_tolerance[i])) co[i]= 0.0f; else co[i]= val[i]; } } -static void sculpt_axislock(Sculpt *sd, float *co) -{ - if(sd->flags == (SCULPT_LOCK_X|SCULPT_LOCK_Y|SCULPT_LOCK_Z)) - return; - - if(sd->session->cache->vc.v3d->twmode == V3D_MANIP_LOCAL) { - float mat[3][3], imat[3][3]; - Mat3CpyMat4(mat, sd->session->cache->vc.obact->obmat); - Mat3Inv(imat, mat); - Mat3MulVecfl(mat, co); - if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0; - if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0; - if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0; - Mat3MulVecfl(imat, co); - } else { - if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0; - if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0; - if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0; - } -} - static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], const short no[3]) { float fno[3] = {no[0], no[1], no[2]}; @@ -350,16 +334,14 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_ calc_area_normal(sd, area_normal, active_verts); - sculpt_axislock(sd, area_normal); - while(node){ float *co= ss->mvert[node->Index].co; - - const float val[3]= {co[0]+area_normal[0]*node->Fade*ss->cache->scale[0], - co[1]+area_normal[1]*node->Fade*ss->cache->scale[1], - co[2]+area_normal[2]*node->Fade*ss->cache->scale[2]}; + + const float val[3]= {co[0]+area_normal[0]*ss->cache->radius*node->Fade*ss->cache->scale[0], + co[1]+area_normal[1]*ss->cache->radius*node->Fade*ss->cache->scale[1], + co[2]+area_normal[2]*ss->cache->radius*node->Fade*ss->cache->scale[2]}; - sculpt_clip(ss->cache, co, val); + sculpt_clip(sd, co, val); node= node->next; } @@ -409,34 +391,37 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert) VecCopyf(avg, ss->mvert[vert].co); } -static void do_smooth_brush(SculptSession *ss, const ListBase* active_verts) +static void do_smooth_brush(Sculpt *s, const ListBase* active_verts) { ActiveData *node= active_verts->first; - - while(node){ - float *co= ss->mvert[node->Index].co; - float avg[3], val[3]; - - neighbor_average(ss, avg, node->Index); - val[0] = co[0]+(avg[0]-co[0])*node->Fade; - val[1] = co[1]+(avg[1]-co[1])*node->Fade; - val[2] = co[2]+(avg[2]-co[2])*node->Fade; - - sculpt_clip(ss->cache, co, val); - node= node->next; + int i; + + for(i = 0; i < 2; ++i) { + while(node){ + float *co= s->session->mvert[node->Index].co; + float avg[3], val[3]; + + neighbor_average(s->session, avg, node->Index); + val[0] = co[0]+(avg[0]-co[0])*node->Fade; + val[1] = co[1]+(avg[1]-co[1])*node->Fade; + val[2] = co[2]+(avg[2]-co[2])*node->Fade; + + sculpt_clip(s, co, val); + node= node->next; + } } } -static void do_pinch_brush(SculptSession *ss, const ListBase* active_verts) +static void do_pinch_brush(Sculpt *s, const ListBase* active_verts) { ActiveData *node= active_verts->first; while(node) { - float *co= ss->mvert[node->Index].co; - const float val[3]= {co[0]+(ss->cache->location[0]-co[0])*node->Fade, - co[1]+(ss->cache->location[1]-co[1])*node->Fade, - co[2]+(ss->cache->location[2]-co[2])*node->Fade}; - sculpt_clip(ss->cache, co, val); + float *co= s->session->mvert[node->Index].co; + const float val[3]= {co[0]+(s->session->cache->location[0]-co[0])*node->Fade, + co[1]+(s->session->cache->location[1]-co[1])*node->Fade, + co[2]+(s->session->cache->location[2]-co[2])*node->Fade}; + sculpt_clip(s, co, val); node= node->next; } } @@ -448,7 +433,6 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss) float grab_delta[3]; VecCopyf(grab_delta, ss->cache->grab_delta_symmetry); - sculpt_axislock(sd, grab_delta); while(node) { float *co= ss->mvert[node->Index].co; @@ -456,7 +440,7 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss) VecCopyf(add, grab_delta); VecMulf(add, node->Fade); VecAddf(add, add, co); - sculpt_clip(ss->cache, co, add); + sculpt_clip(sd, co, add); node= node->next; } @@ -467,42 +451,38 @@ static void do_layer_brush(Sculpt *sd, SculptSession *ss, const ListBase *active { float area_normal[3]; ActiveData *node= active_verts->first; - const float bstr= brush_strength(sd, ss->cache); + float lim= ss->cache->radius / 4; + + if(ss->cache->flip) + lim = -lim; calc_area_normal(sd, area_normal, active_verts); while(node){ float *disp= &ss->cache->layer_disps[node->Index]; + float *co= ss->mvert[node->Index].co; + float val[3]; - if((bstr > 0 && *disp < bstr) || - (bstr < 0 && *disp > bstr)) { - float *co= ss->mvert[node->Index].co; - - *disp+= node->Fade; - - if(bstr < 0) { - if(*disp < bstr) - *disp = bstr; - } else { - if(*disp > bstr) - *disp = bstr; - } + *disp+= node->Fade; + + /* Don't let the displacement go past the limit */ + if((lim < 0 && *disp < lim) || (lim > 0 && *disp > lim)) + *disp = lim; + + val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0]; + val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1]; + val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2]; - { - const float val[3]= {ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0], - ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1], - ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2]}; - sculpt_clip(ss->cache, co, val); - } - } + sculpt_clip(sd, co, val); node= node->next; } } -static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts) +static void do_inflate_brush(Sculpt *s, const ListBase *active_verts) { ActiveData *node= active_verts->first; + SculptSession *ss = s->session; float add[3]; while(node) { @@ -512,13 +492,13 @@ static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts) add[0]= no[0]/ 32767.0f; add[1]= no[1]/ 32767.0f; add[2]= no[2]/ 32767.0f; - VecMulf(add, node->Fade); + VecMulf(add, node->Fade * ss->cache->radius); add[0]*= ss->cache->scale[0]; add[1]*= ss->cache->scale[1]; add[2]*= ss->cache->scale[2]; VecAddf(add, add, co); - sculpt_clip(ss->cache, co, add); + sculpt_clip(s, co, add); node= node->next; } @@ -547,7 +527,7 @@ static void calc_flatten_center(SculptSession *ss, ActiveData *node, float co[3] VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE); } -static void do_flatten_brush(Sculpt *sd, SculptSession *ss, const ListBase *active_verts) +static void do_flatten_clay_brush(Sculpt *sd, SculptSession *ss, const ListBase *active_verts, int clay) { ActiveData *node= active_verts->first; /* area_normal and cntr define the plane towards which vertices are squashed */ @@ -570,16 +550,23 @@ static void do_flatten_brush(Sculpt *sd, SculptSession *ss, const ListBase *acti VecAddf(intr, intr, p1); VecSubf(val, intr, co); - VecMulf(val, node->Fade); + VecMulf(val, fabs(node->Fade)); VecAddf(val, val, co); - sculpt_clip(ss->cache, co, val); + if(clay) { + /* Clay brush displaces after flattening */ + float tmp[3]; + VecCopyf(tmp, area_normal); + VecMulf(tmp, ss->cache->radius * node->Fade * 0.1); + VecAddf(val, val, tmp); + } + + sculpt_clip(sd, co, val); node= node->next; } } - - + /* Uses symm to selectively flip any axis of a coordinate. */ static void flip_coord(float out[3], float in[3], const char symm) { @@ -750,37 +737,6 @@ static void sculpt_add_damaged_rect(SculptSession *ss) } } -/* Clears the depth buffer in each modified area. */ -#if 0 -static void sculpt_clear_damaged_areas(SculptSession *ss) -{ - RectNode *rn= NULL; - - for(rn = ss->damaged_rects.first; rn; rn = rn->next) { - rcti clp = rn->r; - rcti *win = NULL; /*XXX: &curarea->winrct; */ - - clp.xmin += win->xmin; - clp.xmax += win->xmin; - clp.ymin += win->ymin; - clp.ymax += win->ymin; - - if(clp.xmin < win->xmax && clp.xmax > win->xmin && - clp.ymin < win->ymax && clp.ymax > win->ymin) { - if(clp.xmin < win->xmin) clp.xmin = win->xmin; - if(clp.ymin < win->ymin) clp.ymin = win->ymin; - if(clp.xmax > win->xmax) clp.xmax = win->xmax; - if(clp.ymax > win->ymax) clp.ymax = win->ymax; - - glScissor(clp.xmin + 1, clp.ymin + 1, - clp.xmax - clp.xmin - 2, - clp.ymax - clp.ymin - 2); - } - - glClear(GL_DEPTH_BUFFER_BIT); - } -} -#endif static void do_brush_action(Sculpt *sd, StrokeCache *cache) { SculptSession *ss = sd->session; @@ -832,13 +788,13 @@ static void do_brush_action(Sculpt *sd, StrokeCache *cache) do_draw_brush(sd, ss, &active_verts); break; case SCULPT_TOOL_SMOOTH: - do_smooth_brush(ss, &active_verts); + do_smooth_brush(sd, &active_verts); break; case SCULPT_TOOL_PINCH: - do_pinch_brush(ss, &active_verts); + do_pinch_brush(sd, &active_verts); break; case SCULPT_TOOL_INFLATE: - do_inflate_brush(ss, &active_verts); + do_inflate_brush(sd, &active_verts); break; case SCULPT_TOOL_GRAB: do_grab_brush(sd, ss); @@ -847,8 +803,10 @@ static void do_brush_action(Sculpt *sd, StrokeCache *cache) do_layer_brush(sd, ss, &active_verts); break; case SCULPT_TOOL_FLATTEN: - do_flatten_brush(sd, ss, &active_verts); + do_flatten_clay_brush(sd, ss, &active_verts, 0); break; + case SCULPT_TOOL_CLAY: + do_flatten_clay_brush(sd, ss, &active_verts, 1); } /* Copy the modified vertices from mesh to the active key */ @@ -890,15 +848,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, StrokeCache *cache) const char symm = sd->flags & 7; int i; - /* Brush spacing: only apply dot if next dot is far enough away */ - if((sd->brush->flag & BRUSH_SPACE) && !(sd->brush->flag & BRUSH_ANCHORED) && !cache->first_time) { - int dx = cache->last_dot[0] - cache->mouse[0]; - int dy = cache->last_dot[1] - cache->mouse[1]; - if(sqrt(dx*dx+dy*dy) < sd->brush->spacing) - return; - } - memcpy(cache->last_dot, cache->mouse, sizeof(int) * 2); - VecCopyf(cache->location, cache->true_location); VecCopyf(cache->grab_delta_symmetry, cache->grab_delta); cache->symmetry = 0; @@ -997,25 +946,6 @@ static void sculpt_update_tex(Sculpt *sd) } } -void sculptmode_selectbrush_menu(void) -{ - /* XXX: I guess menus belong elsewhere too? - - Sculpt *sd= sculpt_data(); - int val; - - pupmenu_set_active(sd->brush_type); - - val= pupmenu("Select Brush%t|Draw|Smooth|Pinch|Inflate|Grab|Layer|Flatten"); - - if(val>0) { - sd->brush_type= val; - - allqueue(REDRAWVIEW3D, 1); - allqueue(REDRAWBUTSEDIT, 1); - }*/ -} - static void sculptmode_update_all_projverts(SculptSession *ss) { unsigned i; @@ -1069,7 +999,7 @@ static void sculpt_update_mesh_elements(bContext *C) if((ss->multires = sculpt_multires_active(ob))) { DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH); ss->totvert = dm->getNumVerts(dm); - ss->totface = dm->getNumTessFaces(dm); + ss->totface = dm->getNumFaces(dm); ss->mvert = dm->getVertDataArray(dm, CD_MVERT); ss->mface = dm->getTessFaceDataArray(dm, CD_MFACE); ss->face_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); @@ -1094,89 +1024,11 @@ static void sculpt_update_mesh_elements(bContext *C) } } -/* XXX: lots of drawing code (partial redraw), has to go elsewhere */ -#if 0 -void sculptmode_draw_wires(SculptSession *ss, int only_damaged) +static int sculpt_mode_poll(bContext *C) { - Mesh *me = get_mesh(OBACT); - int i; - - bglPolygonOffset(1.0); - glDepthMask(0); - BIF_ThemeColor((OBACT==OBACT)?TH_ACTIVE:TH_SELECT); - - for(i=0; i<me->totedge; i++) { - MEdge *med= &me->medge[i]; - - if((!only_damaged || (ss->projverts[med->v1].inside || ss->projverts[med->v2].inside)) && - (med->flag & ME_EDGEDRAW)) { - glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, &med->v1); - } - } - - glDepthMask(1); - bglPolygonOffset(0.0); + return G.f & G_SCULPTMODE; } -void sculptmode_draw_mesh(int only_damaged) -{ - int i, j, dt, drawCurrentMat = 1, matnr= -1; - SculptSession *ss = sculpt_session(); - - sculpt_update_mesh_elements(ss, OBACT); - - persp(PERSP_VIEW); - mymultmatrix(OBACT->obmat); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - /* XXX: GPU_set_object_materials(G.scene, OBACT, 0, NULL); */ - glEnable(GL_CULL_FACE); - - glShadeModel(GL_SMOOTH); - - glVertexPointer(3, GL_FLOAT, sizeof(MVert), &cache->mvert[0].co); - glNormalPointer(GL_SHORT, sizeof(MVert), &cache->mvert[0].no); - - dt= MIN2(G.vd->drawtype, OBACT->dt); - if(dt==OB_WIRE) - glColorMask(0,0,0,0); - - for(i=0; i<ss->totface; ++i) { - MFace *f= &ss->mface[i]; - char inside= 0; - int new_matnr= f->mat_nr + 1; - - if(new_matnr != matnr) - drawCurrentMat= GPU_enable_material(matnr = new_matnr, NULL); - - /* If only_damaged!=0, only draw faces that are partially - inside the area(s) modified by the brush */ - if(only_damaged) { - for(j=0; j<(f->v4?4:3); ++j) { - if(ss->projverts[*((&f->v1)+j)].inside) { - inside= 1; - break; - } - } - } - else - inside= 1; - - if(inside && drawCurrentMat) - glDrawElements(f->v4?GL_QUADS:GL_TRIANGLES, f->v4?4:3, GL_UNSIGNED_INT, &f->v1); - } - - glDisable(GL_CULL_FACE); - glDisable(GL_LIGHTING); - glColorMask(1,1,1,1); - - if(dt==OB_WIRE || (OBACT->dtx & OB_DRAWWIRE)) - sculptmode_draw_wires(ss, only_damaged); - - glDisable(GL_DEPTH_TEST); -} -#endif - static int sculpt_poll(bContext *C) { return G.f & G_SCULPTMODE && CTX_wm_area(C)->spacetype == SPACE_VIEW3D && @@ -1188,16 +1040,21 @@ static void draw_paint_cursor(bContext *C, int x, int y, void *customdata) { Sculpt *sd= CTX_data_tool_settings(C)->sculpt; - glTranslatef((float)x, (float)y, 0.0f); - glColor4ub(255, 100, 100, 128); glEnable( GL_LINE_SMOOTH ); glEnable(GL_BLEND); + + glTranslatef((float)x, (float)y, 0.0f); glutil_draw_lined_arc(0.0, M_PI*2.0, sd->brush->size, 40); + glTranslatef((float)-x, (float)-y, 0.0f); + + if(sd->session && sd->session->cache && sd->brush && (sd->brush->flag & BRUSH_SMOOTH_STROKE)) { + ARegion *ar = CTX_wm_region(C); + sdrawline(x, y, sd->session->cache->mouse[0] - ar->winrct.xmin, sd->session->cache->mouse[1] - ar->winrct.ymin); + } + glDisable(GL_BLEND); glDisable( GL_LINE_SMOOTH ); - - glTranslatef((float)-x, (float)-y, 0.0f); } static void toggle_paint_cursor(bContext *C) @@ -1245,16 +1102,16 @@ static int sculpt_brush_curve_preset_exec(bContext *C, wmOperator *op) static void SCULPT_OT_brush_curve_preset(wmOperatorType *ot) { static EnumPropertyItem prop_mode_items[] = { - {BRUSH_PRESET_SHARP, "SHARP", "Sharp Curve", ""}, - {BRUSH_PRESET_SMOOTH, "SMOOTH", "Smooth Curve", ""}, - {BRUSH_PRESET_MAX, "MAX", "Max Curve", ""}, - {0, NULL, NULL, NULL}}; + {BRUSH_PRESET_SHARP, "SHARP", 0, "Sharp Curve", ""}, + {BRUSH_PRESET_SMOOTH, "SMOOTH", 0, "Smooth Curve", ""}, + {BRUSH_PRESET_MAX, "MAX", 0, "Max Curve", ""}, + {0, NULL, 0, NULL, NULL}}; ot->name= "Preset"; ot->idname= "SCULPT_OT_brush_curve_preset"; ot->exec= sculpt_brush_curve_preset_exec; - ot->poll= sculpt_poll; + ot->poll= sculpt_mode_poll; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1294,7 +1151,7 @@ static void SCULPT_OT_radial_control(wmOperatorType *ot) ot->exec= sculpt_radial_control_exec; ot->poll= sculpt_poll; - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; } /**** Operator for applying a stroke (various attributes including mouse path) @@ -1319,6 +1176,8 @@ static void sculpt_cache_free(StrokeCache *cache) MEM_freeN(cache->mesh_store); if(cache->orig_norms) MEM_freeN(cache->orig_norms); + if(cache->face_norms) + MEM_freeN(cache->face_norms); if(cache->mats) MEM_freeN(cache->mats); MEM_freeN(cache); @@ -1338,6 +1197,9 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator * RNA_int_get_array(op->ptr, "initial_mouse", cache->initial_mouse); cache->depth = RNA_float_get(op->ptr, "depth"); + cache->mouse[0] = cache->initial_mouse[0]; + cache->mouse[1] = cache->initial_mouse[1]; + /* Truly temporary data that isn't stored in properties */ view3d_set_viewcontext(C, &cache->vc); @@ -1347,9 +1209,11 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator * sculpt_update_mesh_elements(C); + if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER) + cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements"); + /* Make copies of the mesh vertex locations and normals for some tools */ if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER || (sd->brush->flag & BRUSH_ANCHORED)) { - cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements"); cache->mesh_store= MEM_mallocN(sizeof(float) * 3 * sd->session->totvert, "sculpt mesh vertices copy"); for(i = 0; i < sd->session->totvert; ++i) VecCopyf(cache->mesh_store[i], sd->session->mvert[i].co); @@ -1361,6 +1225,13 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator * cache->orig_norms[i][1] = sd->session->mvert[i].no[1]; cache->orig_norms[i][2] = sd->session->mvert[i].no[2]; } + + if(sd->session->face_normals) { + float *fn = sd->session->face_normals; + cache->face_norms= MEM_mallocN(sizeof(float) * 3 * sd->session->totface, "Sculpt face norms"); + for(i = 0; i < sd->session->totface; ++i, fn += 3) + VecCopyf(cache->face_norms[i], fn); + } } } @@ -1470,9 +1341,6 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even Sculpt *sd = CTX_data_tool_settings(C)->sculpt; view3d_operator_needs_opengl(C); - sculpt_brush_stroke_init_properties(C, op, event, sd->session); - - sculptmode_update_all_projverts(sd->session); /* TODO: Shouldn't really have to do this at the start of every stroke, but sculpt would need some sort of notification when @@ -1487,17 +1355,27 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even static void sculpt_restore_mesh(Sculpt *sd) { - StrokeCache *cache = sd->session->cache; + SculptSession *ss = sd->session; + StrokeCache *cache = ss->cache; int i; /* Restore the mesh before continuing with anchored stroke */ if((sd->brush->flag & BRUSH_ANCHORED) && cache->mesh_store) { - for(i = 0; i < sd->session->totvert; ++i) { - VecCopyf(sd->session->mvert[i].co, cache->mesh_store[i]); - sd->session->mvert[i].no[0] = cache->orig_norms[i][0]; - sd->session->mvert[i].no[1] = cache->orig_norms[i][1]; - sd->session->mvert[i].no[2] = cache->orig_norms[i][2]; + for(i = 0; i < ss->totvert; ++i) { + VecCopyf(ss->mvert[i].co, cache->mesh_store[i]); + ss->mvert[i].no[0] = cache->orig_norms[i][0]; + ss->mvert[i].no[1] = cache->orig_norms[i][1]; + ss->mvert[i].no[2] = cache->orig_norms[i][2]; + } + + if(ss->face_normals) { + float *fn = ss->face_normals; + for(i = 0; i < ss->totface; ++i, fn += 3) + VecCopyf(fn, cache->face_norms[i]); } + + if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER) + memset(cache->layer_disps, 0, sizeof(float) * ss->totvert); } } @@ -1527,38 +1405,141 @@ static void sculpt_flush_update(bContext *C) ED_region_tag_redraw(ar); } -static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) +/* Returns zero if no sculpt changes should be made, non-zero otherwise */ +static int sculpt_smooth_stroke(Sculpt *s, int output[2], wmEvent *event) { - PointerRNA itemptr; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - float center[3]; - int mouse[2] = {event->x, event->y}; + output[0] = event->x; + output[1] = event->y; - sculpt_update_mesh_elements(C); + if(s->brush->flag & BRUSH_SMOOTH_STROKE && s->brush->sculpt_tool != SCULPT_TOOL_GRAB) { + StrokeCache *cache = s->session->cache; + float u = .9, v = 1.0 - u; + int dx = cache->mouse[0] - event->x, dy = cache->mouse[1] - event->y; + int radius = 50; + + /* If the mouse is moving within the radius of the last move, + don't update the mouse position. This allows sharp turns. */ + if(dx*dx + dy*dy < radius*radius) + return 0; - unproject(sd->session->cache->mats, center, event->x, event->y, - read_cached_depth(&sd->session->cache->vc, event->x, event->y)); + output[0] = event->x * v + cache->mouse[0] * u; + output[1] = event->y * v + cache->mouse[1] * u; + } + return 1; +} + +/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ +int sculpt_space_stroke_enabled(Sculpt *s) +{ + Brush *br = s->brush; + return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB); +} + +/* Put the location of the next sculpt stroke dot into the stroke RNA and apply it to the mesh */ +static void sculpt_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, int mouse[2]) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + StrokeCache *cache = sd->session->cache; + PointerRNA itemptr; + float cur_depth; + float center[3]; + + cur_depth = read_cached_depth(&cache->vc, mouse[0], mouse[1]); + unproject(sd->session->cache->mats, center, mouse[0], mouse[1], cur_depth); + /* Add to stroke */ RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "location", center); RNA_int_set_array(&itemptr, "mouse", mouse); RNA_boolean_set(&itemptr, "flip", event->shift); sculpt_update_cache_variants(sd, &itemptr); - + sculpt_restore_mesh(sd); - do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache); + do_symmetrical_brush_actions(sd, cache); +} - sculpt_flush_update(C); - sculpt_post_stroke_free(sd->session); +/* For brushes with stroke spacing enabled, moves mouse in steps + towards the final mouse location. */ +static int sculpt_space_stroke(bContext *C, wmOperator *op, wmEvent *event, Sculpt *s, const int final_mouse[2]) +{ + StrokeCache *cache = s->session->cache; + int cnt = 0; - /* Finished */ - if(event->type == LEFTMOUSE && event->val == 0) { - request_depth_update(sd->session->cache->vc.rv3d); + if(sculpt_space_stroke_enabled(s)) { + float vec[2] = {final_mouse[0] - cache->mouse[0], final_mouse[1] - cache->mouse[1]}; + int mouse[2] = {cache->mouse[0], cache->mouse[1]}; + float length, scale; + int steps = 0, i; + + /* Normalize the vector between the last stroke dot and the goal */ + length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]); + + if(length > FLT_EPSILON) { + scale = s->brush->spacing / length; + vec[0] *= scale; + vec[1] *= scale; + + steps = (int)(length / s->brush->spacing); + for(i = 0; i < steps; ++i, ++cnt) { + mouse[0] += vec[0]; + mouse[1] += vec[1]; + sculpt_brush_stroke_add_step(C, op, event, mouse); + } + } + } + + return cnt; +} - sculpt_cache_free(sd->session->cache); +static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + ARegion *ar = CTX_wm_region(C); + float cur_depth; - sculpt_undo_push(C, sd); + sculpt_update_mesh_elements(C); + + if(!sd->session->cache) { + ViewContext vc; + view3d_set_viewcontext(C, &vc); + cur_depth = read_cached_depth(&vc, event->x, event->y); + + /* Don't start the stroke until a valid depth is found */ + if(cur_depth < 1.0 - FLT_EPSILON) { + sculpt_brush_stroke_init_properties(C, op, event, sd->session); + sculptmode_update_all_projverts(sd->session); + } + + ED_region_tag_redraw(ar); + } + + if(sd->session->cache) { + int mouse[2]; + + if(sculpt_smooth_stroke(sd, mouse, event)) { + if(sculpt_space_stroke_enabled(sd)) { + if(!sculpt_space_stroke(C, op, event, sd, mouse)) + ED_region_tag_redraw(ar); + } + else + sculpt_brush_stroke_add_step(C, op, event, mouse); + + sculpt_flush_update(C); + sculpt_post_stroke_free(sd->session); + } + else + ED_region_tag_redraw(ar); + } + + /* Finished */ + if(event->type == LEFTMOUSE && event->val == 0) { + if(sd->session->cache) { + request_depth_update(sd->session->cache->vc.rv3d); + sculpt_cache_free(sd->session->cache); + sd->session->cache = NULL; + sculpt_undo_push(C, sd); + } return OPERATOR_FINISHED; } @@ -1608,7 +1589,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot) ot->poll= sculpt_poll; /* flags (sculpt does own undo? (ton) */ - ot->flag= OPTYPE_REGISTER; + ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING; /* properties */ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); @@ -1702,454 +1683,3 @@ void ED_operatortypes_sculpt() WM_operatortype_append(SCULPT_OT_sculptmode_toggle); WM_operatortype_append(SCULPT_OT_brush_curve_preset); } - -void sculpt(Sculpt *sd) -{ -#if 0 - SculptSession *ss= sd->session; - Object *ob= NULL; /*XXX */ - Mesh *me; - MultiresModifierData *mmd = NULL; - /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */ - short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut; - short modifier_calculations= 0; - BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action"); - short spacing= 32000; - int scissor_box[4]; - float offsetRot; - int smooth_stroke = 0, i; - int anchored, rake = 0 /* XXX: rake = ? */; - - /* XXX: checking that sculpting is allowed - if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0)) - return; - if(!(ob->lay & G.vd->lay)) - error("Active object is not in this layer"); - if(ob_get_keyblock(ob)) { - if(!(ob->shapeflag & OB_SHAPE_LOCK)) { - error("Cannot sculpt on unlocked shape key"); - return; - } - }*/ - - anchored = sd->brush->flag & BRUSH_ANCHORED; - smooth_stroke = (sd->flags & SCULPT_INPUT_SMOOTH) && (sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && !anchored; - - if(smooth_stroke) - sculpt_stroke_new(256); - - ss->damaged_rects.first = ss->damaged_rects.last = NULL; - ss->damaged_verts.first = ss->damaged_verts.last = NULL; - ss->vertexcosnos = NULL; - - mmd = sculpt_multires_active(ob); - - /* Check that vertex users are up-to-date */ - if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != cache->totvert) { - sculpt_vertexusers_free(ss); - calc_vertex_users(ss); - if(ss->projverts) - MEM_freeN(ss->projverts); - ss->projverts = NULL; - active_ob= ob; - } - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - /*XXX: - persp(PERSP_VIEW); - getmouseco_areawin(mvalo);*/ - - /* Init texture - FIXME: Shouldn't be doing this every time! */ - if(sd->tex_mode!=SCULPTREPT_3D) - sculptmode_update_tex(sd); - - /*XXX: getmouseco_areawin(mouse); */ - mvalo[0]= mouse[0]; - mvalo[1]= mouse[1]; - lastSigMouse[0]=mouse[0]; - lastSigMouse[1]=mouse[1]; - mousebut = 0; /* XXX: L_MOUSE; */ - - /* If modifier_calculations is true, then extra time must be spent - updating the mesh. This takes a *lot* longer, so it's worth - skipping if the modifier stack is empty. */ - modifier_calculations= sculpt_modifiers_active(ob); - - if(modifier_calculations) - ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /* XXX: scene = ? */ - sculptmode_update_all_projverts(ss); - - /* Capture original copy */ - if(sd->flags & SCULPT_DRAW_FAST) - glAccum(GL_LOAD, 1); - - /* Get original scissor box */ - glGetIntegerv(GL_SCISSOR_BOX, scissor_box); - - /* For raking, get the original angle*/ - offsetRot=sculpt_tex_angle(sd); - - me = get_mesh(ob); - - while (/*XXX:get_mbut() & mousebut*/0) { - /* XXX: getmouseco_areawin(mouse); */ - /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */ - if (rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){ - /*Nasty looking, but just orig + new angle really*/ - set_tex_angle(sd, offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0])))); - lastSigMouse[0]=mouse[0]; - lastSigMouse[1]=mouse[1]; - } - - if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || - sd->brush->flag & BRUSH_AIRBRUSH) { - a->firsttime = firsttime; - firsttime= 0; - - if(smooth_stroke) - sculpt_stroke_add_point(ss->stroke, mouse[0], mouse[1]); - - spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2)); - - if(modifier_calculations && !ss->vertexcosnos) - ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /*XXX scene = ? */ - - if(sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) { - if(anchored) { - /* Restore the mesh before continuing with anchored stroke */ - /*if(a->mesh_store) { - for(i = 0; i < cache->totvert; ++i) { - VecCopyf(cache->mvert[i].co, &a->mesh_store[i].x); - cache->mvert[i].no[0] = a->orig_norms[i][0]; - cache->mvert[i].no[1] = a->orig_norms[i][1]; - cache->mvert[i].no[2] = a->orig_norms[i][2]; - } - }*/ - - //do_symmetrical_brush_actions(sd, a, mouse, NULL); - } - else { - if(smooth_stroke) { - sculpt_stroke_apply(sd, ss->stroke); - } - else if(sd->spacing==0 || spacing>sd->spacing) { - //do_symmetrical_brush_actions(sd, a, mouse, NULL); - spacing= 0; - } - } - } - else { - //do_symmetrical_brush_actions(sd, a, mouse, mvalo); - //unproject(ss, sd->pivot, mouse[0], mouse[1], a->depth); - } - - if((!ss->multires && modifier_calculations) || ob_get_keyblock(ob)) { - /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); */ } - - if(modifier_calculations || sd->brush->sculpt_tool == SCULPT_TOOL_GRAB || !(sd->flags & SCULPT_DRAW_FAST)) { - calc_damaged_verts(ss, a); - /*XXX: scrarea_do_windraw(curarea); - screen_swapbuffers(); */ - } else { /* Optimized drawing */ - calc_damaged_verts(ss, a); - - /* Draw the stored image to the screen */ - glAccum(GL_RETURN, 1); - - sculpt_clear_damaged_areas(ss); - - /* Draw all the polygons that are inside the modified area(s) */ - glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]); - /* XXX: sculptmode_draw_mesh(1); */ - glAccum(GL_LOAD, 1); - - projverts_clear_inside(ss); - - /* XXX: persp(PERSP_WIN); */ - glDisable(GL_DEPTH_TEST); - - /* Draw cursor */ - if(sd->flags & SCULPT_TOOL_DRAW) - fdrawXORcirc((float)mouse[0],(float)mouse[1],sd->brush->size); - /* XXX: if(smooth_stroke) - sculpt_stroke_draw(); - - myswapbuffers(); */ - } - - BLI_freelistN(&ss->damaged_rects); - ss->damaged_rects.first = ss->damaged_rects.last = NULL; - - mvalo[0]= mouse[0]; - mvalo[1]= mouse[1]; - - if(ss->vertexcosnos) { - MEM_freeN(ss->vertexcosnos); - ss->vertexcosnos= NULL; - } - - } - else { /*XXX:BIF_wait_for_statechange();*/ } - } - - /* Set the rotation of the brush back to what it was before any rake */ - set_tex_angle(sd, offsetRot); - - if(smooth_stroke) { - sculpt_stroke_apply_all(sd, ss->stroke); - calc_damaged_verts(ss, a); - BLI_freelistN(&ss->damaged_rects); - } - - //if(a->layer_disps) MEM_freeN(a->layer_disps); - //if(a->mesh_store) MEM_freeN(a->mesh_store); - //if(a->orig_norms) MEM_freeN(a->orig_norms); - for(i=0; i<8; ++i) - BLI_freelistN(&a->grab_active_verts[i]); - MEM_freeN(a); - sculpt_stroke_free(ss->stroke); - ss->stroke = NULL; - - if(mmd) { - if(mmd->undo_verts && mmd->undo_verts != cache->mvert) - MEM_freeN(mmd->undo_verts); - - mmd->undo_verts = cache->mvert; - mmd->undo_verts_tot = cache->totvert; - } - - //sculpt_undo_push(sd); - - /* XXX: if(G.vd->depths) G.vd->depths->damaged= 1; - allqueue(REDRAWVIEW3D, 0); */ -#endif -} - -/* Partial Mesh Visibility */ - -/* XXX: Partial vis. always was a mess, have to figure something out */ -#if 0 -/* mode: 0=hide outside selection, 1=hide inside selection */ -static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode) -{ - Mesh *me= get_mesh(ob); - float hidebox[6][3]; - vec3f plane_normals[4]; - float plane_ds[4]; - unsigned i, j; - unsigned ndx_show, ndx_hide; - MVert *nve; - unsigned face_cnt_show= 0, face_ndx_show= 0; - unsigned edge_cnt_show= 0, edge_ndx_show= 0; - unsigned *old_map= NULL; - const unsigned SHOW= 0, HIDE=1; - - /* Convert hide box from 2D to 3D */ - unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1); - unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1); - unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1); - unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1); - unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0); - unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0); - - /* Calculate normals for each side of hide box */ - CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x); - CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x); - CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x); - CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x); - - /* Calculate D for each side of hide box */ - for(i= 0; i<4; ++i) - plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y + - hidebox[i][2]*plane_normals[i].z; - - /* Add partial visibility to mesh */ - if(!me->pv) { - me->pv= MEM_callocN(sizeof(PartialVisibility),"PartialVisibility"); - } else { - old_map= MEM_callocN(sizeof(unsigned)*me->pv->totvert,"PMV oldmap"); - for(i=0; i<me->pv->totvert; ++i) { - old_map[i]= me->pv->vert_map[i]<me->totvert?0:1; - } - mesh_pmv_revert(ob, me); - } - - /* Kill sculpt data */ - active_ob= NULL; - - /* Initalize map with which verts are to be hidden */ - me->pv->vert_map= MEM_mallocN(sizeof(unsigned)*me->totvert, "PMV vertmap"); - me->pv->totvert= me->totvert; - me->totvert= 0; - for(i=0; i<me->pv->totvert; ++i) { - me->pv->vert_map[i]= mode ? HIDE:SHOW; - for(j=0; j<4; ++j) { - if(me->mvert[i].co[0] * plane_normals[j].x + - me->mvert[i].co[1] * plane_normals[j].y + - me->mvert[i].co[2] * plane_normals[j].z < plane_ds[j] ) { - me->pv->vert_map[i]= mode ? SHOW:HIDE; /* Vert is outside the hide box */ - break; - } - } - if(old_map && old_map[i]) me->pv->vert_map[i]= 1; - if(!me->pv->vert_map[i]) ++me->totvert; - - } - if(old_map) MEM_freeN(old_map); - - /* Find out how many faces to show */ - for(i=0; i<me->totface; ++i) { - if(!me->pv->vert_map[me->mface[i].v1] && - !me->pv->vert_map[me->mface[i].v2] && - !me->pv->vert_map[me->mface[i].v3]) { - if(me->mface[i].v4) { - if(!me->pv->vert_map[me->mface[i].v4]) - ++face_cnt_show; - } - else ++face_cnt_show; - } - } - /* Find out how many edges to show */ - for(i=0; i<me->totedge; ++i) { - if(!me->pv->vert_map[me->medge[i].v1] && - !me->pv->vert_map[me->medge[i].v2]) - ++edge_cnt_show; - } - - /* Create new vert array and reset each vert's map with map[old]=new index */ - nve= MEM_mallocN(sizeof(MVert)*me->pv->totvert, "PMV verts"); - ndx_show= 0; ndx_hide= me->totvert; - for(i=0; i<me->pv->totvert; ++i) { - if(me->pv->vert_map[i]) { - me->pv->vert_map[i]= ndx_hide; - nve[me->pv->vert_map[i]]= me->mvert[i]; - ++ndx_hide; - } else { - me->pv->vert_map[i]= ndx_show; - nve[me->pv->vert_map[i]]= me->mvert[i]; - ++ndx_show; - } - } - CustomData_free_layer_active(&me->vdata, CD_MVERT, me->pv->totvert); - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, nve, me->totvert); - - /* Create new face array */ - me->pv->old_faces= me->mface; - me->pv->totface= me->totface; - me->mface= MEM_mallocN(sizeof(MFace)*face_cnt_show, "PMV faces"); - for(i=0; i<me->totface; ++i) { - MFace *pr_f= &me->pv->old_faces[i]; - char show= 0; - - if(me->pv->vert_map[pr_f->v1] < me->totvert && - me->pv->vert_map[pr_f->v2] < me->totvert && - me->pv->vert_map[pr_f->v3] < me->totvert) { - if(pr_f->v4) { - if(me->pv->vert_map[pr_f->v4] < me->totvert) - show= 1; - } - else show= 1; - } - - if(show) { - MFace *cr_f= &me->mface[face_ndx_show]; - *cr_f= *pr_f; - cr_f->v1= me->pv->vert_map[pr_f->v1]; - cr_f->v2= me->pv->vert_map[pr_f->v2]; - cr_f->v3= me->pv->vert_map[pr_f->v3]; - cr_f->v4= pr_f->v4 ? me->pv->vert_map[pr_f->v4] : 0; - test_index_face(cr_f,NULL,0,pr_f->v4?4:3); - ++face_ndx_show; - } - } - me->totface= face_cnt_show; - CustomData_set_layer(&me->fdata, CD_MFACE, me->mface); - - /* Create new edge array */ - me->pv->old_edges= me->medge; - me->pv->totedge= me->totedge; - me->medge= MEM_mallocN(sizeof(MEdge)*edge_cnt_show, "PMV edges"); - me->pv->edge_map= MEM_mallocN(sizeof(int)*me->pv->totedge,"PMV edgemap"); - for(i=0; i<me->totedge; ++i) { - if(me->pv->vert_map[me->pv->old_edges[i].v1] < me->totvert && - me->pv->vert_map[me->pv->old_edges[i].v2] < me->totvert) { - MEdge *cr_e= &me->medge[edge_ndx_show]; - me->pv->edge_map[i]= edge_ndx_show; - *cr_e= me->pv->old_edges[i]; - cr_e->v1= me->pv->vert_map[me->pv->old_edges[i].v1]; - cr_e->v2= me->pv->vert_map[me->pv->old_edges[i].v2]; - ++edge_ndx_show; - } - else me->pv->edge_map[i]= -1; - } - me->totedge= edge_cnt_show; - CustomData_set_layer(&me->edata, CD_MEDGE, me->medge); - - /* XXX: DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); */ -} - -static rcti sculptmode_pmv_box() -{ - /*XXX: short down[2], mouse[2]; - rcti ret; - - getmouseco_areawin(down); - - while((get_mbut()&L_MOUSE) || (get_mbut()&R_MOUSE)) { - getmouseco_areawin(mouse); - - scrarea_do_windraw(curarea); - - persp(PERSP_WIN); - glLineWidth(2); - setlinestyle(2); - sdrawXORline(down[0],down[1],mouse[0],down[1]); - sdrawXORline(mouse[0],down[1],mouse[0],mouse[1]); - sdrawXORline(mouse[0],mouse[1],down[0],mouse[1]); - sdrawXORline(down[0],mouse[1],down[0],down[1]); - setlinestyle(0); - glLineWidth(1); - persp(PERSP_VIEW); - - screen_swapbuffers(); - backdrawview3d(0); - } - - ret.xmin= down[0]<mouse[0]?down[0]:mouse[0]; - ret.ymin= down[1]<mouse[1]?down[1]:mouse[1]; - ret.xmax= down[0]>mouse[0]?down[0]:mouse[0]; - ret.ymax= down[1]>mouse[1]?down[1]:mouse[1]; - return ret;*/ -} - -void sculptmode_pmv(int mode) -{ - Object *ob= NULL; /*XXX: OBACT; */ - rcti hb_2d; - - if(ob_get_key(ob)) { - error("Cannot hide mesh with shape keys enabled"); - return; - } - - hb_2d= sculptmode_pmv_box(); /* Get 2D hide box */ - - sculptmode_correct_state(); - - waitcursor(1); - - if(hb_2d.xmax-hb_2d.xmin > 3 && hb_2d.ymax-hb_2d.ymin > 3) { - init_sculptmatrices(); - - sculptmode_do_pmv(ob,&hb_2d,mode); - } - else mesh_pmv_off(ob, get_mesh(ob)); - - /*XXX: scrarea_do_windraw(curarea); */ - - waitcursor(0); -} -#endif |