Brought back sculpt smooth brush. Also added a new brush flag for setting whether to use brush spacing.

This commit is contained in:
2009-01-21 22:40:28 +00:00
parent e609d0cb25
commit faa871117f
9 changed files with 95 additions and 113 deletions

View File

@@ -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 *);

View File

@@ -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);

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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};

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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);