forked from blender/blender
WIP: uv-simple-select #1
@ -1141,6 +1141,11 @@ def brush_texture_settings(layout, brush, sculpt):
|
|||||||
# texture_sample_bias
|
# texture_sample_bias
|
||||||
layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias")
|
layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias")
|
||||||
|
|
||||||
|
if brush.sculpt_tool == 'DRAW':
|
||||||
|
col = layout.column()
|
||||||
|
col.active = tex_slot.map_mode == 'AREA_PLANE'
|
||||||
|
col.prop(brush, "use_color_as_displacement", text="Vector Displacement")
|
||||||
|
|
||||||
|
|
||||||
def brush_mask_texture_settings(layout, brush):
|
def brush_mask_texture_settings(layout, brush):
|
||||||
mask_tex_slot = brush.mask_texture_slot
|
mask_tex_slot = brush.mask_texture_slot
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
#include "wm_cursors.h"
|
#include "wm_cursors.h"
|
||||||
|
|
||||||
|
#include "IMB_colormanagement.h"
|
||||||
#include "IMB_imbuf_types.h"
|
#include "IMB_imbuf_types.h"
|
||||||
|
|
||||||
#include "ED_image.h"
|
#include "ED_image.h"
|
||||||
@ -200,10 +201,18 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
|
|||||||
y = len * sinf(angle);
|
y = len * sinf(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col) {
|
float avg;
|
||||||
float rgba[4];
|
float rgba[4];
|
||||||
|
paint_get_tex_pixel(mtex, x, y, pool, thread_id, &avg, rgba);
|
||||||
|
|
||||||
paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace);
|
if (col) {
|
||||||
|
if (convert_to_linear) {
|
||||||
|
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
linearrgb_to_srgb_v3_v3(rgba, rgba);
|
||||||
|
|
||||||
|
clamp_v4(rgba, 0.0f, 1.0f);
|
||||||
|
|
||||||
buffer[index * 4] = rgba[0] * 255;
|
buffer[index * 4] = rgba[0] * 255;
|
||||||
buffer[index * 4 + 1] = rgba[1] * 255;
|
buffer[index * 4 + 1] = rgba[1] * 255;
|
||||||
@ -211,8 +220,6 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
|
|||||||
buffer[index * 4 + 3] = rgba[3] * 255;
|
buffer[index * 4 + 3] = rgba[3] * 255;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id);
|
|
||||||
|
|
||||||
avg += br->texture_sample_bias;
|
avg += br->texture_sample_bias;
|
||||||
|
|
||||||
/* Clamp to avoid precision overflow. */
|
/* Clamp to avoid precision overflow. */
|
||||||
|
@ -352,16 +352,17 @@ void paint_calc_redraw_planes(float planes[4][4],
|
|||||||
float paint_calc_object_space_radius(struct ViewContext *vc,
|
float paint_calc_object_space_radius(struct ViewContext *vc,
|
||||||
const float center[3],
|
const float center[3],
|
||||||
float pixel_radius);
|
float pixel_radius);
|
||||||
float paint_get_tex_pixel(
|
|
||||||
const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
|
/**
|
||||||
void paint_get_tex_pixel_col(const struct MTex *mtex,
|
* Returns true when a color was sampled and false when a value was sampled.
|
||||||
float u,
|
*/
|
||||||
float v,
|
bool paint_get_tex_pixel(const struct MTex *mtex,
|
||||||
float rgba[4],
|
float u,
|
||||||
struct ImagePool *pool,
|
float v,
|
||||||
int thread,
|
struct ImagePool *pool,
|
||||||
bool convert,
|
int thread,
|
||||||
struct ColorSpace *colorspace);
|
float *r_intensity,
|
||||||
|
float r_rgba[4]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for both 3D view and image window.
|
* Used for both 3D view and image window.
|
||||||
|
@ -146,45 +146,29 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
|
|||||||
return len_v3(delta) / scale;
|
return len_v3(delta) / scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread)
|
bool paint_get_tex_pixel(const MTex *mtex,
|
||||||
{
|
float u,
|
||||||
float intensity;
|
float v,
|
||||||
float rgba_dummy[4];
|
struct ImagePool *pool,
|
||||||
const float co[3] = {u, v, 0.0f};
|
int thread,
|
||||||
|
/* Return arguments. */
|
||||||
RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy);
|
float *r_intensity,
|
||||||
|
float r_rgba[4])
|
||||||
return intensity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void paint_get_tex_pixel_col(const MTex *mtex,
|
|
||||||
float u,
|
|
||||||
float v,
|
|
||||||
float rgba[4],
|
|
||||||
struct ImagePool *pool,
|
|
||||||
int thread,
|
|
||||||
bool convert_to_linear,
|
|
||||||
struct ColorSpace *colorspace)
|
|
||||||
{
|
{
|
||||||
const float co[3] = {u, v, 0.0f};
|
const float co[3] = {u, v, 0.0f};
|
||||||
float intensity;
|
float intensity;
|
||||||
|
const bool has_rgb = RE_texture_evaluate(
|
||||||
|
mtex, co, thread, pool, false, false, &intensity, r_rgba);
|
||||||
|
*r_intensity = intensity;
|
||||||
|
|
||||||
const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
|
if (!has_rgb) {
|
||||||
|
r_rgba[0] = intensity;
|
||||||
if (!hasrgb) {
|
r_rgba[1] = intensity;
|
||||||
rgba[0] = intensity;
|
r_rgba[2] = intensity;
|
||||||
rgba[1] = intensity;
|
r_rgba[3] = 1.0f;
|
||||||
rgba[2] = intensity;
|
|
||||||
rgba[3] = 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convert_to_linear) {
|
return has_rgb;
|
||||||
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
linearrgb_to_srgb_v3_v3(rgba, rgba);
|
|
||||||
|
|
||||||
clamp_v4(rgba, 0.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void paint_stroke_operator_properties(wmOperatorType *ot)
|
void paint_stroke_operator_properties(wmOperatorType *ot)
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
#include "BKE_subdiv_ccg.h"
|
#include "BKE_subdiv_ccg.h"
|
||||||
#include "BKE_subsurf.h"
|
#include "BKE_subsurf.h"
|
||||||
|
#include "BLI_math_vector.hh"
|
||||||
|
|
||||||
#include "NOD_texture.h"
|
#include "NOD_texture.h"
|
||||||
|
|
||||||
@ -2555,80 +2556,12 @@ static float brush_strength(const Sculpt *sd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float SCULPT_brush_strength_factor(SculptSession *ss,
|
static float sculpt_apply_hardness(const SculptSession *ss, const float input_len)
|
||||||
const Brush *br,
|
|
||||||
const float brush_point[3],
|
|
||||||
float len,
|
|
||||||
const float vno[3],
|
|
||||||
const float fno[3],
|
|
||||||
float mask,
|
|
||||||
const PBVHVertRef vertex,
|
|
||||||
const int thread_id,
|
|
||||||
AutomaskingNodeData *automask_data)
|
|
||||||
{
|
{
|
||||||
StrokeCache *cache = ss->cache;
|
const StrokeCache *cache = ss->cache;
|
||||||
const Scene *scene = cache->vc->scene;
|
float final_len = input_len;
|
||||||
const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT);
|
|
||||||
float avg = 1.0f;
|
|
||||||
float rgba[4];
|
|
||||||
float point[3];
|
|
||||||
|
|
||||||
sub_v3_v3v3(point, brush_point, cache->plane_offset);
|
|
||||||
|
|
||||||
if (!mtex->tex) {
|
|
||||||
avg = 1.0f;
|
|
||||||
}
|
|
||||||
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
|
|
||||||
/* Get strength by feeding the vertex location directly into a texture. */
|
|
||||||
avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float symm_point[3], point_2d[2];
|
|
||||||
/* Quite warnings. */
|
|
||||||
float x = 0.0f, y = 0.0f;
|
|
||||||
|
|
||||||
/* If the active area is being applied for symmetry, flip it
|
|
||||||
* across the symmetry axis and rotate it back to the original
|
|
||||||
* position in order to project it. This insures that the
|
|
||||||
* brush texture will be oriented correctly. */
|
|
||||||
if (cache->radial_symmetry_pass) {
|
|
||||||
mul_m4_v3(cache->symm_rot_mat_inv, point);
|
|
||||||
}
|
|
||||||
flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
|
|
||||||
|
|
||||||
ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat);
|
|
||||||
|
|
||||||
/* Still no symmetry supported for other paint modes.
|
|
||||||
* Sculpt does it DIY. */
|
|
||||||
if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
|
|
||||||
/* Similar to fixed mode, but projects from brush angle
|
|
||||||
* rather than view direction. */
|
|
||||||
|
|
||||||
mul_m4_v3(cache->brush_local_mat, symm_point);
|
|
||||||
|
|
||||||
x = symm_point[0];
|
|
||||||
y = symm_point[1];
|
|
||||||
|
|
||||||
x *= mtex->size[0];
|
|
||||||
y *= mtex->size[1];
|
|
||||||
|
|
||||||
x += mtex->ofs[0];
|
|
||||||
y += mtex->ofs[1];
|
|
||||||
|
|
||||||
avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id);
|
|
||||||
|
|
||||||
avg += br->texture_sample_bias;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
|
|
||||||
avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hardness. */
|
|
||||||
float final_len = len;
|
|
||||||
const float hardness = cache->paint_brush.hardness;
|
const float hardness = cache->paint_brush.hardness;
|
||||||
float p = len / cache->radius;
|
float p = input_len / cache->radius;
|
||||||
if (p < hardness) {
|
if (p < hardness) {
|
||||||
final_len = 0.0f;
|
final_len = 0.0f;
|
||||||
}
|
}
|
||||||
@ -2640,9 +2573,100 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||||||
final_len = p * cache->radius;
|
final_len = p * cache->radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return final_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sculpt_apply_texture(const SculptSession *ss,
|
||||||
|
const Brush *brush,
|
||||||
|
const float brush_point[3],
|
||||||
|
const int thread_id,
|
||||||
|
float *r_value,
|
||||||
|
float r_rgba[4])
|
||||||
|
{
|
||||||
|
StrokeCache *cache = ss->cache;
|
||||||
|
const Scene *scene = cache->vc->scene;
|
||||||
|
const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
|
||||||
|
|
||||||
|
if (!mtex->tex) {
|
||||||
|
*r_value = 1.0f;
|
||||||
|
copy_v4_fl(r_rgba, 1.0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float point[3];
|
||||||
|
sub_v3_v3v3(point, brush_point, cache->plane_offset);
|
||||||
|
|
||||||
|
if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
|
||||||
|
/* Get strength by feeding the vertex location directly into a texture. */
|
||||||
|
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point, r_rgba, 0, ss->tex_pool);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float symm_point[3];
|
||||||
|
|
||||||
|
/* If the active area is being applied for symmetry, flip it
|
||||||
|
* across the symmetry axis and rotate it back to the original
|
||||||
|
* position in order to project it. This insures that the
|
||||||
|
* brush texture will be oriented correctly. */
|
||||||
|
if (cache->radial_symmetry_pass) {
|
||||||
|
mul_m4_v3(cache->symm_rot_mat_inv, point);
|
||||||
|
}
|
||||||
|
flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
|
||||||
|
|
||||||
|
/* Still no symmetry supported for other paint modes.
|
||||||
|
* Sculpt does it DIY. */
|
||||||
|
if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
|
||||||
|
/* Similar to fixed mode, but projects from brush angle
|
||||||
|
* rather than view direction. */
|
||||||
|
|
||||||
|
mul_m4_v3(cache->brush_local_mat, symm_point);
|
||||||
|
|
||||||
|
float x = symm_point[0];
|
||||||
|
float y = symm_point[1];
|
||||||
|
|
||||||
|
x *= mtex->size[0];
|
||||||
|
y *= mtex->size[1];
|
||||||
|
|
||||||
|
x += mtex->ofs[0];
|
||||||
|
y += mtex->ofs[1];
|
||||||
|
|
||||||
|
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
|
||||||
|
*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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float SCULPT_brush_strength_factor(SculptSession *ss,
|
||||||
|
const Brush *brush,
|
||||||
|
const float brush_point[3],
|
||||||
|
float len,
|
||||||
|
const float vno[3],
|
||||||
|
const float fno[3],
|
||||||
|
float mask,
|
||||||
|
const PBVHVertRef vertex,
|
||||||
|
int thread_id,
|
||||||
|
AutomaskingNodeData *automask_data)
|
||||||
|
{
|
||||||
|
StrokeCache *cache = ss->cache;
|
||||||
|
|
||||||
|
float avg = 1.0f;
|
||||||
|
float rgba[4];
|
||||||
|
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, rgba);
|
||||||
|
|
||||||
|
/* Hardness. */
|
||||||
|
const float final_len = sculpt_apply_hardness(ss, len);
|
||||||
|
|
||||||
/* Falloff curve. */
|
/* Falloff curve. */
|
||||||
avg *= BKE_brush_curve_strength(br, final_len, cache->radius);
|
avg *= BKE_brush_curve_strength(brush, final_len, cache->radius);
|
||||||
avg *= frontface(br, cache->view_normal, vno, fno);
|
avg *= frontface(brush, cache->view_normal, vno, fno);
|
||||||
|
|
||||||
/* Paint mask. */
|
/* Paint mask. */
|
||||||
avg *= 1.0f - mask;
|
avg *= 1.0f - mask;
|
||||||
@ -2653,6 +2677,69 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||||||
return avg;
|
return avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SCULPT_brush_strength_color(SculptSession *ss,
|
||||||
|
const Brush *brush,
|
||||||
|
const float brush_point[3],
|
||||||
|
float len,
|
||||||
|
const float vno[3],
|
||||||
|
const float fno[3],
|
||||||
|
float mask,
|
||||||
|
const PBVHVertRef vertex,
|
||||||
|
int thread_id,
|
||||||
|
AutomaskingNodeData *automask_data,
|
||||||
|
float r_rgba[4])
|
||||||
|
{
|
||||||
|
StrokeCache *cache = ss->cache;
|
||||||
|
|
||||||
|
float avg = 1.0f;
|
||||||
|
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, r_rgba);
|
||||||
|
|
||||||
|
/* Hardness. */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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 masks_combined = falloff * paint_mask * automasking_factor;
|
||||||
|
|
||||||
|
mul_v4_fl(r_rgba, masks_combined);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCULPT_calc_vertex_displacement(SculptSession *ss,
|
||||||
|
const Brush *brush,
|
||||||
|
float rgba[4],
|
||||||
|
float out_offset[3])
|
||||||
|
{
|
||||||
|
mul_v3_fl(rgba, ss->cache->bstrength);
|
||||||
|
/* Handle brush inversion */
|
||||||
|
if (ss->cache->bstrength < 0) {
|
||||||
|
rgba[0] *= -1;
|
||||||
|
rgba[1] *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply texture size */
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
rgba[i] *= blender::math::safe_divide(1.0f, pow2f(brush->mtex.size[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transform vector to object space */
|
||||||
|
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba);
|
||||||
|
|
||||||
|
/* Handle symmetry */
|
||||||
|
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)
|
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
|
||||||
{
|
{
|
||||||
SculptSearchSphereData *data = static_cast<SculptSearchSphereData *>(data_v);
|
SculptSearchSphereData *data = static_cast<SculptSearchSphereData *>(data_v);
|
||||||
@ -2920,7 +3007,10 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
|
|||||||
mul_m4_v3(ob->world_to_object, y);
|
mul_m4_v3(ob->world_to_object, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[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;
|
const StrokeCache *cache = ob->sculpt->cache;
|
||||||
float tmat[4][4];
|
float tmat[4][4];
|
||||||
@ -2966,6 +3056,8 @@ static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4
|
|||||||
scale_m4_fl(scale, radius);
|
scale_m4_fl(scale, radius);
|
||||||
mul_m4_m4m4(tmat, mat, scale);
|
mul_m4_m4m4(tmat, mat, scale);
|
||||||
|
|
||||||
|
/* Return tmat as is (for converting from local area coords to model-space coords). */
|
||||||
|
copy_m4_m4(local_mat_inv, tmat);
|
||||||
/* Return inverse (for converting from model-space coords to local area coords). */
|
/* Return inverse (for converting from model-space coords to local area coords). */
|
||||||
invert_m4_m4(local_mat, tmat);
|
invert_m4_m4(local_mat, tmat);
|
||||||
}
|
}
|
||||||
@ -3000,7 +3092,7 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
|
|||||||
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) {
|
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) {
|
||||||
const Brush *brush = BKE_paint_brush(&sd->paint);
|
const Brush *brush = BKE_paint_brush(&sd->paint);
|
||||||
const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
|
const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
|
||||||
calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat);
|
calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat, cache->brush_local_mat_inv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,18 +265,35 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
|
|||||||
SCULPT_automasking_node_update(ss, &automask_data, &vd);
|
SCULPT_automasking_node_update(ss, &automask_data, &vd);
|
||||||
|
|
||||||
/* Offset vertex. */
|
/* Offset vertex. */
|
||||||
const float fade = SCULPT_brush_strength_factor(ss,
|
if (ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT &&
|
||||||
brush,
|
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) {
|
||||||
vd.co,
|
float r_rgba[4];
|
||||||
sqrtf(test.dist),
|
SCULPT_brush_strength_color(ss,
|
||||||
vd.no,
|
brush,
|
||||||
vd.fno,
|
vd.co,
|
||||||
vd.mask ? *vd.mask : 0.0f,
|
sqrtf(test.dist),
|
||||||
vd.vertex,
|
vd.no,
|
||||||
thread_id,
|
vd.fno,
|
||||||
&automask_data);
|
vd.mask ? *vd.mask : 0.0f,
|
||||||
|
vd.vertex,
|
||||||
mul_v3_v3fl(proxy[vd.i], offset, fade);
|
thread_id,
|
||||||
|
&automask_data,
|
||||||
|
r_rgba);
|
||||||
|
SCULPT_calc_vertex_displacement(ss, brush, r_rgba, proxy[vd.i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float fade = SCULPT_brush_strength_factor(ss,
|
||||||
|
brush,
|
||||||
|
vd.co,
|
||||||
|
sqrtf(test.dist),
|
||||||
|
vd.no,
|
||||||
|
vd.fno,
|
||||||
|
vd.mask ? *vd.mask : 0.0f,
|
||||||
|
vd.vertex,
|
||||||
|
thread_id,
|
||||||
|
&automask_data);
|
||||||
|
mul_v3_v3fl(proxy[vd.i], offset, fade);
|
||||||
|
}
|
||||||
|
|
||||||
if (vd.is_mesh) {
|
if (vd.is_mesh) {
|
||||||
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);
|
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);
|
||||||
|
@ -586,8 +586,13 @@ struct StrokeCache {
|
|||||||
float sculpt_normal_symm[3];
|
float sculpt_normal_symm[3];
|
||||||
|
|
||||||
/* Used for area texture mode, local_mat gets calculated by
|
/* Used for area texture mode, local_mat gets calculated by
|
||||||
* calc_brush_local_mat() and used in tex_strength(). */
|
* calc_brush_local_mat() and used in sculpt_apply_texture().
|
||||||
|
* Transforms from model-space coords to local area coords.
|
||||||
|
*/
|
||||||
float brush_local_mat[4][4];
|
float brush_local_mat[4][4];
|
||||||
|
/* The matrix from local area coords to model-space coords is used to calculate the vector
|
||||||
|
* displacement in area plane mode. */
|
||||||
|
float brush_local_mat_inv[4][4];
|
||||||
|
|
||||||
float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
|
float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
|
||||||
int tile_pass;
|
int tile_pass;
|
||||||
@ -1241,6 +1246,30 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||||||
int thread_id,
|
int thread_id,
|
||||||
AutomaskingNodeData *automask_data);
|
AutomaskingNodeData *automask_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a color of a brush texture on a particular vertex multiplied by active masks.
|
||||||
|
*/
|
||||||
|
void SCULPT_brush_strength_color(SculptSession *ss,
|
||||||
|
const Brush *brush,
|
||||||
|
const float brush_point[3],
|
||||||
|
float len,
|
||||||
|
const float vno[3],
|
||||||
|
const float fno[3],
|
||||||
|
float mask,
|
||||||
|
const PBVHVertRef vertex,
|
||||||
|
int thread_id,
|
||||||
|
AutomaskingNodeData *automask_data,
|
||||||
|
float r_rgba[4]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Brush *brush,
|
||||||
|
float rgba[3],
|
||||||
|
float out_offset[3]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tilts a normal by the x and y tilt values using the view axis.
|
* Tilts a normal by the x and y tilt values using the view axis.
|
||||||
*/
|
*/
|
||||||
|
@ -412,6 +412,7 @@ typedef enum eBrushFlags2 {
|
|||||||
BRUSH_CLOTH_USE_COLLISION = (1 << 6),
|
BRUSH_CLOTH_USE_COLLISION = (1 << 6),
|
||||||
BRUSH_AREA_RADIUS_PRESSURE = (1 << 7),
|
BRUSH_AREA_RADIUS_PRESSURE = (1 << 7),
|
||||||
BRUSH_GRAB_SILHOUETTE = (1 << 8),
|
BRUSH_GRAB_SILHOUETTE = (1 << 8),
|
||||||
|
BRUSH_USE_COLOR_AS_DISPLACEMENT = (1 << 9),
|
||||||
} eBrushFlags2;
|
} eBrushFlags2;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -2899,6 +2899,14 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Texture Sample Bias", "Value added to texture samples");
|
RNA_def_property_ui_text(prop, "Texture Sample Bias", "Value added to texture samples");
|
||||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
|
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_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR);
|
prop = RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR);
|
||||||
RNA_def_property_float_sdna(prop, NULL, "normal_weight");
|
RNA_def_property_float_sdna(prop, NULL, "normal_weight");
|
||||||
RNA_def_property_float_default(prop, 0);
|
RNA_def_property_float_default(prop, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user