diff options
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_multires.h | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_sculpt.h | 12 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 42 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 36 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 18 | ||||
-rw-r--r-- | source/blender/editors/sculpt/sculpt.c | 75 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_brush_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_brush.c | 4 |
9 files changed, 95 insertions, 113 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 2ca4b3aa39a..f455b094f5d 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -109,6 +109,16 @@ UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v); void free_uv_vert_map(UvVertMap *vmap); +/* Connectivity data */ +typedef struct IndexNode { + struct IndexNode *next, *prev; + int index; +} IndexNode; +void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface, + const int totvert, const int totface); +void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge, + const int totvert, const int totedge); + /* Partial Mesh Visibility */ struct PartialVisibility *mesh_pmv_copy(struct PartialVisibility *); void mesh_pmv_free(struct PartialVisibility *); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8ee1d15d0f3..3b0ff2db6f4 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -38,16 +38,6 @@ typedef struct MultiresSubsurf { struct Mesh *me; } MultiresSubsurf; -typedef struct IndexNode { - struct IndexNode *next, *prev; - int index; -} IndexNode; - -void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface, - const int totvert, const int totface); -void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge, - const int totvert, const int totedge); - /* MultiresDM */ struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm); struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int); diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h index 54d750db3af..d0e28f3ae9a 100644 --- a/source/blender/blenkernel/BKE_sculpt.h +++ b/source/blender/blenkernel/BKE_sculpt.h @@ -40,13 +40,10 @@ struct StrokeCache; typedef struct SculptSession { struct ProjVert *projverts; - /* An array of lists; array is sized as - large as the number of verts in the mesh, - the list for each vert contains the index - for all the faces that use that vertex */ - struct ListBase *vertex_users; - struct IndexNode *vertex_users_mem; - int vertex_users_size; + /* Mesh connectivity */ + struct ListBase *fmap; + struct IndexNode *fmap_mem; + int fmap_size; /* Used temporarily per-stroke */ float *vertexcosnos; @@ -66,6 +63,5 @@ typedef struct SculptSession { } SculptSession; void sculptsession_free(struct Sculpt *sculpt); -void sculpt_vertexusers_free(struct SculptSession *ss); #endif diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 7ba8fb47740..b8d485065b1 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1149,6 +1149,48 @@ void free_uv_vert_map(UvVertMap *vmap) } } +/* Generates a map where the key is the vertex and the value is a list + of faces that use that vertex as a corner. The lists are allocated + from one memory pool. */ +void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface) +{ + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totface; ++i){ + for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); + } + } +} + +/* Generates a map where the key is the vertex and the value is a list + of edges that use that vertex as an endpoint. The lists are allocated + from one memory pool. */ +void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge) +{ + int i, j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totedge; ++i){ + for(j = 0; j < 2; ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node); + } + } +} + /* Partial Mesh Visibility */ PartialVisibility *mesh_pmv_copy(PartialVisibility *pmv) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 1227dcdded3..ec4b8eb6d03 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -54,42 +54,6 @@ #include <math.h> #include <string.h> -void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface) -{ - int i,j; - IndexNode *node = NULL; - - (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); - (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); - node = *mem; - - /* Find the users */ - for(i = 0; i < totface; ++i){ - for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) { - node->index = i; - BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); - } - } -} - -void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge) -{ - int i, j; - IndexNode *node = NULL; - - (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); - (*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem"); - node = *mem; - - /* Find the users */ - for(i = 0; i < totedge; ++i){ - for(j = 0; j < 2; ++j, ++node) { - node->index = i; - BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node); - } - } -} - /* MULTIRES MODIFIER */ static const int multires_max_levels = 13; static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3247c963644..0d036c924c5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -651,17 +651,6 @@ void scene_add_render_layer(Scene *sce) srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z; } -void sculpt_vertexusers_free(SculptSession *ss) -{ - if(ss && ss->vertex_users){ - MEM_freeN(ss->vertex_users); - MEM_freeN(ss->vertex_users_mem); - ss->vertex_users= NULL; - ss->vertex_users_mem= NULL; - ss->vertex_users_size= 0; - } -} - void sculptsession_free(Sculpt *sculpt) { SculptSession *ss= sculpt->session; @@ -672,7 +661,12 @@ void sculptsession_free(Sculpt *sculpt) if(ss->radialcontrol) MEM_freeN(ss->radialcontrol); - sculpt_vertexusers_free(ss); + if(ss->fmap) + MEM_freeN(ss->fmap); + + if(ss->fmap_mem) + MEM_freeN(ss->fmap_mem); + if(ss->texcache) MEM_freeN(ss->texcache); MEM_freeN(ss); diff --git a/source/blender/editors/sculpt/sculpt.c b/source/blender/editors/sculpt/sculpt.c index b84fa4d8795..989ff7ce700 100644 --- a/source/blender/editors/sculpt/sculpt.c +++ b/source/blender/editors/sculpt/sculpt.c @@ -181,32 +181,6 @@ typedef struct ProjVert { char inside; } ProjVert; -/* vertex_users is an array of Lists that store all the faces that use a - particular vertex. vertex_users is in the same order as mesh.mvert */ -static void calc_vertex_users(SculptSession *ss) -{ - int i,j; - IndexNode *node= NULL; - StrokeCache *cache = ss->cache; - - sculpt_vertexusers_free(ss); - - /* For efficiency, use vertex_users_mem as a memory pool (may be larger - than necessary if mesh has triangles, but only one alloc is needed.) */ - ss->vertex_users= MEM_callocN(sizeof(ListBase) * cache->totvert, "vertex_users"); - ss->vertex_users_size= cache->totvert; - ss->vertex_users_mem= MEM_callocN(sizeof(IndexNode)*cache->totface*4, "vertex_users_mem"); - node= ss->vertex_users_mem; - - /* Find the users */ - for(i=0; i<cache->totface; ++i){ - for(j=0; j<(cache->mface[i].v4?4:3); ++j, ++node) { - node->index=i; - BLI_addtail(&ss->vertex_users[((unsigned int*)(&cache->mface[i]))[j]], node); - } - } -} - /* ===== INTERFACE ===== */ @@ -326,7 +300,7 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache) case SCULPT_TOOL_LAYER: return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */; case SCULPT_TOOL_SMOOTH: - return sd->brush->alpha / .5f * pressure * anchored; + return sd->brush->alpha / .5 * pressure * anchored; case SCULPT_TOOL_PINCH: return sd->brush->alpha / 10.0f * dir * pressure * flip * anchored; case SCULPT_TOOL_GRAB: @@ -449,8 +423,8 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_ static void neighbor_average(SculptSession *ss, float avg[3], const int vert) { int i, skip= -1, total=0; - IndexNode *node= ss->vertex_users[vert].first; - char ncount= BLI_countlist(&ss->vertex_users[vert]); + IndexNode *node= ss->fmap[vert].first; + char ncount= BLI_countlist(&ss->fmap[vert]); MFace *f; avg[0] = avg[1] = avg[2] = 0; @@ -472,7 +446,7 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert) } for(i=0; i<(f->v4?4:3); ++i) { - if(i != skip && (ncount!=2 || BLI_countlist(&ss->vertex_users[(&f->v1)[i]]) <= 2)) { + if(i != skip && (ncount!=2 || BLI_countlist(&ss->fmap[(&f->v1)[i]]) <= 2)) { VecAddf(avg, avg, ss->cache->mvert[(&f->v1)[i]].co); ++total; } @@ -1000,7 +974,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd, StrokeCache *cache) int i; /* Brush spacing: only apply dot if next dot is far enough away */ - if(sd->brush->spacing > 0 && !(sd->brush->flag & BRUSH_ANCHORED) && !cache->first_time) { + 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) @@ -1052,7 +1026,7 @@ static void update_damaged_vert(SculptSession *ss, ListBase *lb) for(vert= lb->first; vert; vert= vert->next) { vec3f norm= {0,0,0}; - IndexNode *face= ss->vertex_users[vert->Index].first; + IndexNode *face= ss->fmap[vert->Index].first; while(face){ float *fn = NULL; @@ -1419,8 +1393,10 @@ static struct MultiresModifierData *sculpt_multires_active(Object *ob) return NULL; } -static void sculpt_update_mesh_elements(StrokeCache *cache, Object *ob) +static void sculpt_update_mesh_elements(SculptSession *ss, Object *ob) { + StrokeCache *cache = ss->cache; + if(sculpt_multires_active(ob)) { DerivedMesh *dm = mesh_get_derived_final(NULL, ob, CD_MASK_BAREMESH); /* XXX scene=? */ cache->multires = 1; @@ -1439,6 +1415,11 @@ static void sculpt_update_mesh_elements(StrokeCache *cache, Object *ob) cache->mface = me->mface; cache->face_normals = NULL; } + + if(cache->totvert != ss->fmap_size) { + create_vert_face_map(&ss->fmap, &ss->fmap_mem, cache->mface, cache->totvert, cache->totface); + ss->fmap_size = cache->totvert; + } } /* XXX: lots of drawing code (partial redraw), has to go elsewhere */ @@ -1621,7 +1602,7 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator * cache->mats = MEM_callocN(sizeof(bglMats), "sculpt bglMats"); sculpt_load_mats(cache->mats, &cache->vc); - sculpt_update_mesh_elements(cache, cache->vc.obact); + sculpt_update_mesh_elements(sd->session, cache->vc.obact); /* 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)) { @@ -1906,13 +1887,6 @@ static void draw_paint_cursor(bContext *C, int x, int y) glTranslatef((float)-x, (float)-y, 0.0f); } -static void init_sculpt(ToolSettings *ts) -{ - ts->sculpt = MEM_callocN(sizeof(Sculpt), "sculpt mode data"); - - /* XXX: initialize persistent sculpt settings */ -} - static int sculpt_toggle_mode(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); @@ -1931,12 +1905,23 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op) /* Enter sculptmode */ G.f |= G_SCULPTMODE; - + + /* Create persistent sculpt mode data */ if(!ts->sculpt) - init_sculpt(ts); + ts->sculpt = MEM_callocN(sizeof(Sculpt), "sculpt mode data"); + /* Create sculpt mode session data */ + if(ts->sculpt->session) + MEM_freeN(ts->sculpt->session); ts->sculpt->session = MEM_callocN(sizeof(SculptSession), "sculpt session"); + /* Activate visible brush */ + ts->sculpt->session->cursor = + WM_paint_cursor_activate(CTX_wm_manager(C), sculpt_brush_stroke_poll, draw_paint_cursor); + + + + /* XXX: testing */ /* Needed for testing, if there's no brush then create one */ ts->sculpt->brush = add_brush("test brush"); /* Also for testing, set the brush texture to the first available one */ @@ -1947,10 +1932,6 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op) mtex->tex = G.main->tex.first; mtex->size[0] = mtex->size[1] = mtex->size[2] = 50; } - - /* Activate visible brush */ - ts->sculpt->session->cursor = - WM_paint_cursor_activate(CTX_wm_manager(C), sculpt_brush_stroke_poll, draw_paint_cursor); } return OPERATOR_FINISHED; diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 305571b36ad..3fe92feb139 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -79,6 +79,7 @@ typedef struct Brush { #define BRUSH_RAKE 128 #define BRUSH_ANCHORED 256 #define BRUSH_DIR_IN 512 +#define BRUSH_SPACE 1024 /* Brush.blend */ #define BRUSH_BLEND_MIX 0 diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 04c36fd4965..3dc4b9e6fa4 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -159,6 +159,10 @@ void rna_def_brush(BlenderRNA *brna) prop= RNA_def_property(srna, "flip_direction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_DIR_IN); RNA_def_property_ui_text(prop, "Flip Direction", "Move vertices in the opposite direction."); + + prop= RNA_def_property(srna, "space", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACE); + RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing."); /* not exposed in the interface yet prop= RNA_def_property(srna, "fixed_tex", PROP_BOOLEAN, PROP_NONE); |