Vector displacement for the sculpting draw brush #104481

Merged
Jeroen Bakker merged 18 commits from robin.hohni/blender:sculpt-vector-displacement into main 2023-02-14 15:29:40 +01:00
7 changed files with 53 additions and 30 deletions
Showing only changes of commit cf6502f04c - Show all commits

View File

@ -37,6 +37,7 @@
#include "WM_api.h"
#include "wm_cursors.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "ED_image.h"
@ -56,7 +57,6 @@
/* still needed for sculpt_stroke_get_location, should be
* removed eventually (TODO) */
#include "sculpt_intern.h"
#include "IMB_colormanagement.h"
/* TODOs:
*

View File

@ -356,8 +356,13 @@ float paint_calc_object_space_radius(struct ViewContext *vc,
/**
* Returns true when a color was sampled and false when a value was sampled.
*/
bool paint_get_tex_pixel(
const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread, float *r_intensity, float r_rgba[4]);
bool paint_get_tex_pixel(const struct MTex *mtex,
float u,
float v,
struct ImagePool *pool,
int thread,
float *r_intensity,
float r_rgba[4]);
/**
* Used for both 3D view and image window.

View File

@ -157,7 +157,8 @@ bool paint_get_tex_pixel(const MTex *mtex,
{
const float co[3] = {u, v, 0.0f};
float intensity;
const bool has_rgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, r_rgba);
const bool has_rgb = RE_texture_evaluate(
mtex, co, thread, pool, false, false, &intensity, r_rgba);
*r_intensity = intensity;
if (!has_rgb) {

View File

@ -2630,12 +2630,13 @@ static void sculpt_apply_texture(const SculptSession *ss,
paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id, r_value, r_rgba);
add_v3_fl(r_rgba, brush->texture_sample_bias); // v3 -> Ignore alpha
add_v3_fl(r_rgba, brush->texture_sample_bias); // v3 -> Ignore alpha
*r_value -= brush->texture_sample_bias;
}
else {
float point_2d[2];
ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat);
ED_view3d_project_float_v2_m4(
cache->vc->region, symm_point, point_2d, cache->projection_mat);
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point_3d, r_rgba, 0, ss->tex_pool);
}
@ -2696,38 +2697,45 @@ void SCULPT_brush_strength_color(struct SculptSession *ss,
const float final_len = sculpt_apply_hardness(ss, len);
/* Falloff curve. */
const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius)
* frontface(brush, cache->view_normal, vno, fno);
const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius) *
frontface(brush, cache->view_normal, vno, fno);
/* Paint mask. */
const float paint_mask = 1.0f - mask;
/* Auto-masking. */
const float automasking_factor = SCULPT_automasking_factor_get(cache->automasking, ss, vertex, automask_data);
const float automasking_factor = SCULPT_automasking_factor_get(
cache->automasking, ss, vertex, automask_data);
const float masks_combined = falloff * paint_mask * automasking_factor;
mul_v4_fl(r_rgba, masks_combined);
}
void SCULPT_calc_vertex_displacement(SculptSession *ss, const struct Brush *brush, float rgba[4], float out_offset[3])
void SCULPT_calc_vertex_displacement(SculptSession *ss,
const struct Brush *brush,
float rgba[4],
float out_offset[3])
{
mul_v3_fl(rgba, ss->cache->bstrength);
if(ss->cache->bstrength < 0) {
rgba[0] *= -1;
rgba[1] *= -1;
}
mul_v3_fl(rgba, ss->cache->bstrength);
if (ss->cache->bstrength < 0) {
rgba[0] *= -1;
rgba[1] *= -1;
}
rgba[0] *= 1.0f / (brush->mtex.size[0] == 0.0f ? 1.0f : brush->mtex.size[0] * brush->mtex.size[0]);
rgba[1] *= 1.0f / (brush->mtex.size[1] == 0.0f ? 1.0f : brush->mtex.size[1] * brush->mtex.size[1]);
rgba[2] *= 1.0f / (brush->mtex.size[2] == 0.0f ? 1.0f : brush->mtex.size[2] * brush->mtex.size[2]);
rgba[0] *= 1.0f /
robin.hohni marked this conversation as resolved
Review

For readability would suggest to first square the size, and then do the inf check using math::safe_divide. Seems we currently don't have a safe divide in math for 2 vector types.

rgba[i] *= math::safe_divide(1.0f, POW2(brush->mtex.size[i])); perhaps?

For readability would suggest to first square the size, and then do the inf check using `math::safe_divide`. Seems we currently don't have a safe divide in math for 2 vector types. `rgba[i] *= math::safe_divide(1.0f, POW2(brush->mtex.size[i]));` perhaps?
Review

Thanks for the hint! Made a commit :)

Thanks for the hint! Made a commit :)
(brush->mtex.size[0] == 0.0f ? 1.0f : brush->mtex.size[0] * brush->mtex.size[0]);
rgba[1] *= 1.0f /
(brush->mtex.size[1] == 0.0f ? 1.0f : brush->mtex.size[1] * brush->mtex.size[1]);
rgba[2] *= 1.0f /
(brush->mtex.size[2] == 0.0f ? 1.0f : brush->mtex.size[2] * brush->mtex.size[2]);
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba);
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba);
if (ss->cache->radial_symmetry_pass) {
mul_m4_v3(ss->cache->symm_rot_mat, rgba);
}
flip_v3_v3(out_offset, rgba, ss->cache->mirror_symmetry_pass);
if (ss->cache->radial_symmetry_pass) {
mul_m4_v3(ss->cache->symm_rot_mat, rgba);
}
flip_v3_v3(out_offset, rgba, ss->cache->mirror_symmetry_pass);
}
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
@ -2997,7 +3005,10 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
mul_m4_v3(ob->world_to_object, y);
}
static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4][4], float local_mat_inv[4][4])
static void calc_brush_local_mat(const MTex *mtex,
Object *ob,
float local_mat[4][4],
float local_mat_inv[4][4])
{
const StrokeCache *cache = ob->sculpt->cache;
float tmat[4][4];

View File

@ -265,8 +265,8 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
/* Offset vertex. */
if(ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT
&& (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) {
if (ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT &&
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) {
float r_rgba[4];
SCULPT_brush_strength_color(ss,
brush,

View File

@ -1274,9 +1274,13 @@ void SCULPT_brush_strength_color(struct SculptSession *ss,
float r_rgba[4]);
/**
* Calculates the vertex offset for a single vertex depending on the brush setting rgb as vector displacement.
* Calculates the vertex offset for a single vertex depending on the brush setting rgb as vector
* displacement.
*/
void SCULPT_calc_vertex_displacement(SculptSession *ss, const struct Brush *brush, float rgba[3], float out_offset[3]);
void SCULPT_calc_vertex_displacement(SculptSession *ss,
const struct Brush *brush,
float rgba[3],
float out_offset[3]);
/**
* Tilts a normal by the x and y tilt values using the view axis.

View File

@ -2901,8 +2901,10 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_color_as_displacement", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_USE_COLOR_AS_DISPLACEMENT);
RNA_def_property_ui_text(prop, "Vector Displacement",
"Handles each pixel color as individual vector for displacement. Works only with area plane mapping");
RNA_def_property_ui_text(prop,
"Vector Displacement",
robin.hohni marked this conversation as resolved
Review

Can you ensure that you use the correct code formatting. You can install clang-format or run make format in the source folder.

Can you ensure that you use the correct code formatting. You can install clang-format or run `make format` in the source folder.
"Handles each pixel color as individual vector for displacement. Works "
"only with area plane mapping");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR);