Sculpt mode Gravity feature from GSOC 2010 by Jason Wilkins.

Reviewers: sergey, brecht, campbellbarton, jwilkins

Differential Revision: http://developer.blender.org/D89
This commit is contained in:
Antonis Ryakiotakis 2013-12-12 19:01:11 +02:00
parent 400fc9f86f
commit c740f1a792
6 changed files with 104 additions and 0 deletions

View File

@ -1023,8 +1023,16 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
capabilities = sculpt.brush.sculpt_capabilities
col = layout.column(align=True)
col.active = capabilities.has_gravity
col.label(text="Gravity:")
col.prop(sculpt, "gravity", slider=True, text="Factor")
col.prop(sculpt, "gravity_object")
layout.label(text="Lock:")
row = layout.row(align=True)
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)

View File

@ -5119,6 +5119,11 @@ static void lib_link_scene(FileData *fd, Main *main)
link_paint(fd, sce, &sce->toolsettings->wpaint->paint);
link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
link_paint(fd, sce, &sce->toolsettings->uvsculpt->paint);
if (sce->toolsettings->sculpt)
sce->toolsettings->sculpt->gravity_object =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->sculpt->gravity_object);
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base = sce->base.first; base; base = next) {

View File

@ -317,6 +317,7 @@ typedef struct StrokeCache {
int alt_smooth;
float plane_trim_squared;
float gravity_direction[3];
rcti previous_r; /* previous redraw rectangle */
} StrokeCache;
@ -2997,6 +2998,49 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
}
}
static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
float offset[3]/*, an[3]*/;
int n;
float gravity_vector[3];
mul_v3_v3fl(gravity_vector, ss->cache->gravity_direction, -ss->cache->radius_squared);
/* offset with as much as possible factored in already */
mul_v3_v3v3(offset, gravity_vector, ss->cache->scale);
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for(n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
float (*proxy)[3];
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
if (sculpt_brush_test_sq(&test, vd.co)) {
const float fade = tex_strength(ss, brush, vd.co, sqrt(test.dist),
ss->cache->sculpt_normal_symm, vd.no,
vd.fno, vd.mask ? *vd.mask : 0.0f);
mul_v3_v3fl(proxy[vd.i], offset, fade);
if(vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
BKE_pbvh_vertex_iter_end;
}
}
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
Mesh *me = (Mesh *)ob->data;
@ -3223,6 +3267,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
}
}
if (brush->sculpt_tool != SCULPT_TOOL_MASK && sd->gravity_factor > 0.0f)
do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
MEM_freeN(nodes);
/* update average stroke position */
@ -3826,6 +3873,24 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
cache->scale[1] = max_scale / ob->size[1];
cache->scale[2] = max_scale / ob->size[2];
if (sd->gravity_object) {
Object *gravity_object = sd->gravity_object;
float rmat[3][3], loc[3], size[3];
/* get gravity vector in world space */
copy_v3_v3(cache->gravity_direction, gravity_object->obmat[2]);
normalize_v3(cache->gravity_direction);
/* transform to sculpted object space by inverting object rotation matrix */
mat4_to_loc_rot_size(loc, rmat, size, ob->obmat);
/* transposition of orthogonal matrix (rotation), inverts */
transpose_m3(rmat);
mul_m3_v3(rmat, cache->gravity_direction);
}
else {
cache->gravity_direction[0] = cache->gravity_direction[1] = 0.0;
cache->gravity_direction[2] = sd->gravity_factor;
}
cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;

View File

@ -850,6 +850,13 @@ typedef struct Sculpt {
/* Direction used for SCULPT_OT_symmetrize operator */
int symmetrize_direction;
/* gravity factor for sculpting */
float gravity_factor;
int pad;
struct Object *gravity_object;
void *pad2;
} Sculpt;
typedef struct UvSculpt {

View File

@ -248,6 +248,12 @@ static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
MTEX_MAP_MODE_RANDOM);
}
static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return br->sculpt_tool != SCULPT_TOOL_MASK;
}
static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@ -556,6 +562,7 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna)
SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength");
SCULPT_TOOL_CAPABILITY(has_gravity, "Has Gravity");
#undef SCULPT_CAPABILITY
}

View File

@ -427,6 +427,18 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Detail Refine Method",
"In dynamic-topology mode, how to add or remove mesh detail");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "gravity_factor");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
RNA_def_property_ui_text(prop, "Gravity", "Amount of gravity after each dab");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "gravity_object", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Orientation", "Object whose Z axis defines orientation of gravity");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}