Compare commits
2 Commits
tmp-workbe
...
temp-texpa
Author | SHA1 | Date | |
---|---|---|---|
74bfcff02d | |||
3cae409b24 |
@@ -79,6 +79,7 @@ typedef enum {
|
|||||||
PBVH_UpdateTopology = 1 << 13,
|
PBVH_UpdateTopology = 1 << 13,
|
||||||
PBVH_UpdateColor = 1 << 14,
|
PBVH_UpdateColor = 1 << 14,
|
||||||
PBVH_RebuildPixels = 1 << 15,
|
PBVH_RebuildPixels = 1 << 15,
|
||||||
|
PBVH_RebuildAutomasking = 1 << 16,
|
||||||
|
|
||||||
} PBVHNodeFlags;
|
} PBVHNodeFlags;
|
||||||
|
|
||||||
@@ -413,7 +414,7 @@ typedef struct PBVHVertexIter {
|
|||||||
/* mesh */
|
/* mesh */
|
||||||
struct MVert *mverts;
|
struct MVert *mverts;
|
||||||
float (*vert_normals)[3];
|
float (*vert_normals)[3];
|
||||||
int totvert;
|
int totvert, unique_verts;
|
||||||
const int *vert_indices;
|
const int *vert_indices;
|
||||||
float *vmask;
|
float *vmask;
|
||||||
|
|
||||||
@@ -587,6 +588,23 @@ void BKE_pbvh_vertex_color_get(const PBVH *pbvh, int vertex, float r_color[4]);
|
|||||||
void BKE_pbvh_ensure_node_loops(PBVH *pbvh);
|
void BKE_pbvh_ensure_node_loops(PBVH *pbvh);
|
||||||
bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh);
|
bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh);
|
||||||
|
|
||||||
|
void BKE_pbvh_node_automasking_mark(PBVH *pbvh, PBVHNode *node);
|
||||||
|
void BKE_pbvh_node_automasking_unmark(PBVH *pbvh, PBVHNode *node);
|
||||||
|
bool BKE_pbvh_node_needs_automasking(PBVH *pbvh, PBVHNode *node);
|
||||||
|
void BKE_pbvh_node_automasking_mark_all(PBVH *pbvh);
|
||||||
|
|
||||||
|
/* XXX Temporary attribute for patch development; remove for final patch! */
|
||||||
|
#ifdef __clang__
|
||||||
|
# define ATTR_NO_OPT __attribute__((optnone))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define ATTR_NO_OPT __pragma(optimize("", off))
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define ATTR_NO_OPT __attribute__((optimize("O0")))
|
||||||
|
#else
|
||||||
|
# define ATTR_NO_OPT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -3126,6 +3126,9 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||||||
else {
|
else {
|
||||||
vi->totvert = uniq_verts;
|
vi->totvert = uniq_verts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vi->unique_verts = uniq_verts;
|
||||||
|
|
||||||
vi->vert_indices = vert_indices;
|
vi->vert_indices = vert_indices;
|
||||||
vi->mverts = verts;
|
vi->mverts = verts;
|
||||||
|
|
||||||
@@ -3320,3 +3323,27 @@ void BKE_pbvh_ensure_node_loops(PBVH *pbvh)
|
|||||||
|
|
||||||
MEM_SAFE_FREE(visit);
|
MEM_SAFE_FREE(visit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_pbvh_node_automasking_mark(PBVH *pbvh, PBVHNode *node)
|
||||||
|
{
|
||||||
|
node->flag |= PBVH_RebuildAutomasking;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_pbvh_node_automasking_unmark(PBVH *pbvh, PBVHNode *node)
|
||||||
|
{
|
||||||
|
node->flag &= ~PBVH_RebuildAutomasking;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BKE_pbvh_node_needs_automasking(PBVH *pbvh, PBVHNode *node)
|
||||||
|
{
|
||||||
|
return node->flag & PBVH_RebuildAutomasking;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_pbvh_node_automasking_mark_all(PBVH *pbvh)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pbvh->totnode; i++) {
|
||||||
|
if (pbvh->nodes[i].flag & PBVH_Leaf) {
|
||||||
|
pbvh->nodes[i].flag |= PBVH_RebuildAutomasking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -96,7 +96,7 @@ struct PBVHNode {
|
|||||||
|
|
||||||
/* Indicates whether this node is a leaf or not; also used for
|
/* Indicates whether this node is a leaf or not; also used for
|
||||||
* marking various updates that need to be applied. */
|
* marking various updates that need to be applied. */
|
||||||
PBVHNodeFlags flag : 16;
|
PBVHNodeFlags flag : 32;
|
||||||
|
|
||||||
/* Used for raycasting: how close bb is to the ray point. */
|
/* Used for raycasting: how close bb is to the ray point. */
|
||||||
float tmin;
|
float tmin;
|
||||||
|
@@ -1288,7 +1288,10 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node, SculptUndoType type)
|
void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
|
||||||
|
Object *ob,
|
||||||
|
PBVHNode *node,
|
||||||
|
SculptUndoType type)
|
||||||
{
|
{
|
||||||
SculptUndoNode *unode;
|
SculptUndoNode *unode;
|
||||||
unode = SCULPT_undo_push_node(ob, node, type);
|
unode = SCULPT_undo_push_node(ob, node, type);
|
||||||
@@ -2447,7 +2450,9 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||||||
avg *= 1.0f - mask;
|
avg *= 1.0f - mask;
|
||||||
|
|
||||||
/* Auto-masking. */
|
/* Auto-masking. */
|
||||||
|
if (vertex_index != -1) {
|
||||||
avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index);
|
avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index);
|
||||||
|
}
|
||||||
|
|
||||||
return avg;
|
return avg;
|
||||||
}
|
}
|
||||||
@@ -4173,6 +4178,7 @@ static void sculpt_update_cache_invariants(
|
|||||||
{
|
{
|
||||||
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
|
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
|
||||||
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
||||||
|
ToolSettings *tool_settings = CTX_data_tool_settings(C);
|
||||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||||
ViewContext *vc = paint_stroke_view_context(op->customdata);
|
ViewContext *vc = paint_stroke_view_context(op->customdata);
|
||||||
Object *ob = CTX_data_active_object(C);
|
Object *ob = CTX_data_active_object(C);
|
||||||
@@ -4183,6 +4189,8 @@ static void sculpt_update_cache_invariants(
|
|||||||
|
|
||||||
ss->cache = cache;
|
ss->cache = cache;
|
||||||
|
|
||||||
|
cache->use_pixels = sculpt_needs_pbvh_pixels(&tool_settings->paint_mode, brush, ob);
|
||||||
|
|
||||||
/* Set scaling adjustment. */
|
/* Set scaling adjustment. */
|
||||||
max_scale = 0.0f;
|
max_scale = 0.0f;
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
@@ -5334,6 +5342,11 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
|
|||||||
SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
|
SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark all pbvh nodes for update. */
|
||||||
|
if (ss->pbvh) {
|
||||||
|
BKE_pbvh_node_automasking_mark_all(ss->pbvh);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@@ -11,7 +11,10 @@
|
|||||||
#include "BLI_hash.h"
|
#include "BLI_hash.h"
|
||||||
#include "BLI_index_range.hh"
|
#include "BLI_index_range.hh"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_set.hh"
|
||||||
#include "BLI_task.h"
|
#include "BLI_task.h"
|
||||||
|
#include "BLI_task.hh"
|
||||||
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
@@ -48,6 +51,8 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
using blender::IndexRange;
|
using blender::IndexRange;
|
||||||
|
using blender::Set;
|
||||||
|
using blender::Vector;
|
||||||
|
|
||||||
AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
|
AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
|
||||||
{
|
{
|
||||||
@@ -114,18 +119,8 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
|
float sculpt_automasking_factor_calc(AutomaskingCache *automasking, SculptSession *ss, int vert)
|
||||||
{
|
{
|
||||||
if (!automasking) {
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
/* If the cache is initialized with valid info, use the cache. This is used when the
|
|
||||||
* automasking information can't be computed in real time per vertex and needs to be
|
|
||||||
* initialized for the whole mesh when the stroke starts. */
|
|
||||||
if (automasking->factor) {
|
|
||||||
return automasking->factor[vert];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
|
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
|
||||||
if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
|
if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
@@ -147,6 +142,21 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
|
||||||
|
{
|
||||||
|
if (!automasking) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
/* If the cache is initialized with valid info, use the cache. This is used when the
|
||||||
|
* automasking information can't be computed in real time per vertex and needs to be
|
||||||
|
* initialized for the whole mesh when the stroke starts. */
|
||||||
|
if (automasking->factor) {
|
||||||
|
return automasking->factor[vert];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sculpt_automasking_factor_calc(automasking, ss, vert);
|
||||||
|
}
|
||||||
|
|
||||||
void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
|
void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
|
||||||
{
|
{
|
||||||
if (!automasking) {
|
if (!automasking) {
|
||||||
@@ -335,11 +345,23 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
|
|||||||
SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
|
SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
|
||||||
SCULPT_boundary_info_ensure(ob);
|
SCULPT_boundary_info_ensure(ob);
|
||||||
|
|
||||||
|
if (!SCULPT_automasking_needs_factors_cache(sd, brush) && ss->cache && ss->cache->use_pixels) {
|
||||||
|
/*
|
||||||
|
* Allocate factor cache but don't initialize it.
|
||||||
|
* Will be filled in by SCULPT_automasking_cache_check.
|
||||||
|
*/
|
||||||
|
automasking->factor = (float *)MEM_calloc_arrayN(totvert, sizeof(float), "automask_factor");
|
||||||
|
|
||||||
|
return automasking;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
|
if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
|
||||||
return automasking;
|
return automasking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
automasking->has_full_factor_cache = true;
|
||||||
automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
|
automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
|
||||||
|
|
||||||
for (int i : IndexRange(totvert)) {
|
for (int i : IndexRange(totvert)) {
|
||||||
automasking->factor[i] = 1.0f;
|
automasking->factor[i] = 1.0f;
|
||||||
}
|
}
|
||||||
@@ -370,3 +392,71 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
|
|||||||
|
|
||||||
return automasking;
|
return automasking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SCULPT_automasking_cache_check(SculptSession *ss,
|
||||||
|
AutomaskingCache *automasking,
|
||||||
|
PBVHNode **nodes,
|
||||||
|
int totnode)
|
||||||
|
{
|
||||||
|
if (!automasking || automasking->has_full_factor_cache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cb = [&](PBVHNode *node) {
|
||||||
|
if (!BKE_pbvh_node_needs_automasking(ss->pbvh, node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_pbvh_node_automasking_unmark(ss->pbvh, node);
|
||||||
|
PBVHVertexIter vi;
|
||||||
|
|
||||||
|
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vi, PBVH_ITER_ALL) {
|
||||||
|
if (vi.i >= vi.unique_verts) {
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
automasking->factor[vi.index] = SCULPT_automasking_factor_get(
|
||||||
|
automasking, ss, ss->active_face_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BKE_pbvh_vertex_iter_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Vector<int>> node_other_verts;
|
||||||
|
node_other_verts.resize(totnode);
|
||||||
|
|
||||||
|
blender::threading::parallel_for(IndexRange(totnode), 2, [&](IndexRange range) {
|
||||||
|
for (int i : range) {
|
||||||
|
PBVHNode *node = nodes[i];
|
||||||
|
|
||||||
|
if (!BKE_pbvh_node_needs_automasking(ss->pbvh, node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_pbvh_node_automasking_unmark(ss->pbvh, node);
|
||||||
|
PBVHVertexIter vi;
|
||||||
|
|
||||||
|
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vi, PBVH_ITER_ALL) {
|
||||||
|
if (vi.i >= vi.unique_verts) {
|
||||||
|
node_other_verts[i].append(vi.index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
automasking->factor[vi.index] = sculpt_automasking_factor_calc(
|
||||||
|
automasking, ss, vi.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BKE_pbvh_vertex_iter_end;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<int> done_set;
|
||||||
|
|
||||||
|
for (int i : IndexRange(totnode)) {
|
||||||
|
for (int vertex : node_other_verts[i]) {
|
||||||
|
if (!done_set.contains(vertex)) {
|
||||||
|
done_set.add(vertex);
|
||||||
|
|
||||||
|
automasking->factor[vertex] = sculpt_automasking_factor_calc(automasking, ss, vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -401,6 +401,7 @@ typedef struct AutomaskingCache {
|
|||||||
/* Precomputed auto-mask factor indexed by vertex, owned by the auto-masking system and
|
/* Precomputed auto-mask factor indexed by vertex, owned by the auto-masking system and
|
||||||
* initialized in #SCULPT_automasking_cache_init when needed. */
|
* initialized in #SCULPT_automasking_cache_init when needed. */
|
||||||
float *factor;
|
float *factor;
|
||||||
|
bool has_full_factor_cache; /* Cache was built for entire mesh at once. */
|
||||||
} AutomaskingCache;
|
} AutomaskingCache;
|
||||||
|
|
||||||
typedef struct FilterCache {
|
typedef struct FilterCache {
|
||||||
@@ -631,6 +632,7 @@ typedef struct StrokeCache {
|
|||||||
rcti previous_r; /* previous redraw rectangle */
|
rcti previous_r; /* previous redraw rectangle */
|
||||||
rcti current_r; /* current redraw rectangle */
|
rcti current_r; /* current redraw rectangle */
|
||||||
|
|
||||||
|
bool use_pixels;
|
||||||
} StrokeCache;
|
} StrokeCache;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@@ -1288,6 +1290,10 @@ float *SCULPT_boundary_automasking_init(Object *ob,
|
|||||||
eBoundaryAutomaskMode mode,
|
eBoundaryAutomaskMode mode,
|
||||||
int propagation_steps,
|
int propagation_steps,
|
||||||
float *automask_factor);
|
float *automask_factor);
|
||||||
|
|
||||||
|
bool SCULPT_automasking_needs_normal(const SculptSession *ss,
|
||||||
|
const Sculpt *sculpt,
|
||||||
|
const Brush *brush);
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@@ -1805,6 +1811,11 @@ void SCULPT_OT_brush_stroke(struct wmOperatorType *ot);
|
|||||||
|
|
||||||
/* end sculpt_ops.c */
|
/* end sculpt_ops.c */
|
||||||
|
|
||||||
|
void SCULPT_automasking_cache_check(struct SculptSession *ss,
|
||||||
|
struct AutomaskingCache *automasking,
|
||||||
|
struct PBVHNode **nodes,
|
||||||
|
int totnode);
|
||||||
|
|
||||||
#define SCULPT_TOOL_NEEDS_COLOR(tool) ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)
|
#define SCULPT_TOOL_NEEDS_COLOR(tool) ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -125,6 +125,21 @@ class ImageBufferByte4 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static float paint_automasking_interp(SculptSession *ss,
|
||||||
|
const TrianglePaintInput &triangle,
|
||||||
|
const float2 uv)
|
||||||
|
{
|
||||||
|
if (!ss->cache->automasking) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float a = SCULPT_automasking_factor_get(ss->cache->automasking, ss, triangle.vert_indices[0]);
|
||||||
|
float b = SCULPT_automasking_factor_get(ss->cache->automasking, ss, triangle.vert_indices[1]);
|
||||||
|
float c = SCULPT_automasking_factor_get(ss->cache->automasking, ss, triangle.vert_indices[2]);
|
||||||
|
|
||||||
|
return a * uv[0] + b * uv[1] + c * (1.0 - uv[0] - uv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ImageBuffer> class PaintingKernel {
|
template<typename ImageBuffer> class PaintingKernel {
|
||||||
ImageBuffer image_accessor;
|
ImageBuffer image_accessor;
|
||||||
|
|
||||||
@@ -160,9 +175,13 @@ template<typename ImageBuffer> class PaintingKernel {
|
|||||||
float3 pixel_pos = get_start_pixel_pos(triangle, pixel_row);
|
float3 pixel_pos = get_start_pixel_pos(triangle, pixel_row);
|
||||||
const float3 delta_pixel_pos = get_delta_pixel_pos(triangle, pixel_row, pixel_pos);
|
const float3 delta_pixel_pos = get_delta_pixel_pos(triangle, pixel_row, pixel_pos);
|
||||||
bool pixels_painted = false;
|
bool pixels_painted = false;
|
||||||
|
|
||||||
|
float2 uv = pixel_row.start_barycentric_coord;
|
||||||
|
|
||||||
for (int x = 0; x < pixel_row.num_pixels; x++) {
|
for (int x = 0; x < pixel_row.num_pixels; x++) {
|
||||||
if (!brush_test_fn(&test, pixel_pos)) {
|
if (!brush_test_fn(&test, pixel_pos)) {
|
||||||
pixel_pos += delta_pixel_pos;
|
pixel_pos += delta_pixel_pos;
|
||||||
|
uv += triangle.delta_barycentric_coord_u;
|
||||||
image_accessor.next_pixel();
|
image_accessor.next_pixel();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -171,8 +190,11 @@ template<typename ImageBuffer> class PaintingKernel {
|
|||||||
const float3 normal(0.0f, 0.0f, 0.0f);
|
const float3 normal(0.0f, 0.0f, 0.0f);
|
||||||
const float3 face_normal(0.0f, 0.0f, 0.0f);
|
const float3 face_normal(0.0f, 0.0f, 0.0f);
|
||||||
const float mask = 0.0f;
|
const float mask = 0.0f;
|
||||||
const float falloff_strength = SCULPT_brush_strength_factor(
|
float falloff_strength = SCULPT_brush_strength_factor(
|
||||||
ss, brush, pixel_pos, sqrtf(test.dist), normal, face_normal, mask, 0, thread_id);
|
ss, brush, pixel_pos, sqrtf(test.dist), normal, face_normal, mask, -1, thread_id);
|
||||||
|
|
||||||
|
falloff_strength *= paint_automasking_interp(ss, triangle, uv);
|
||||||
|
|
||||||
float4 paint_color = brush_color * falloff_strength * brush_strength;
|
float4 paint_color = brush_color * falloff_strength * brush_strength;
|
||||||
float4 buffer_color;
|
float4 buffer_color;
|
||||||
blend_color_mix_float(buffer_color, color, paint_color);
|
blend_color_mix_float(buffer_color, color, paint_color);
|
||||||
@@ -183,6 +205,7 @@ template<typename ImageBuffer> class PaintingKernel {
|
|||||||
|
|
||||||
image_accessor.next_pixel();
|
image_accessor.next_pixel();
|
||||||
pixel_pos += delta_pixel_pos;
|
pixel_pos += delta_pixel_pos;
|
||||||
|
uv += triangle.delta_barycentric_coord_u;
|
||||||
}
|
}
|
||||||
return pixels_painted;
|
return pixels_painted;
|
||||||
}
|
}
|
||||||
@@ -500,6 +523,8 @@ void SCULPT_do_paint_brush_image(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCULPT_automasking_cache_check(ob->sculpt, ob->sculpt->cache->automasking, nodes, totnode);
|
||||||
|
|
||||||
TaskParallelSettings settings;
|
TaskParallelSettings settings;
|
||||||
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
||||||
BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings);
|
BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings);
|
||||||
|
Reference in New Issue
Block a user