Sculpt-dev: Improve autosmooth performance
* PBVH_FACES now uses MDynTopoVert (have got to rename it) to store boundary/corner/visibility flags the same way PBVH_BMESH does. * Fixed brush add/sub buttons in header not working * Fixed inverted brushes feeding negative strength to sub commands (like autosmooth, which flips it to sharpen mode).
This commit is contained in:
parent
486627215c
commit
06e8cc0256
|
@ -794,7 +794,6 @@ void range_tree_uint_take(RangeTreeUInt *rt, const uint value)
|
|||
range_tree_uint_take_impl(rt, value, node);
|
||||
}
|
||||
|
||||
#pragma optimize("", off)
|
||||
bool range_tree_uint_retake(RangeTreeUInt *rt, const uint value)
|
||||
{
|
||||
Node *node = rt_find_node_from_value(rt, value);
|
||||
|
|
|
@ -300,6 +300,15 @@ class UnifiedPaintPanel:
|
|||
itemicon = "CHECKBOX_DEHLT"
|
||||
row3.prop_enum(finalch, typeprop, item.identifier, icon=itemicon)
|
||||
|
||||
elif header and ch.idname == "direction":
|
||||
row2 = row.row(align=True)
|
||||
row2.use_property_split = False
|
||||
row2.use_property_decorate = False
|
||||
|
||||
#replicate pre-existing functionality of direction showing up as +/- in the header
|
||||
row2.prop_enum(finalch, typeprop, "ADD", text="")
|
||||
row2.prop_enum(finalch, typeprop, "SUBTRACT", text="")
|
||||
pass
|
||||
elif expand is not None:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider, expand=expand)
|
||||
else:
|
||||
|
|
|
@ -274,7 +274,19 @@ class _draw_tool_settings_context_mode:
|
|||
|
||||
# direction
|
||||
if not capabilities.has_direction:
|
||||
layout.row().prop(brush, "direction", expand=True, text="")
|
||||
row = layout.row()
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"direction",
|
||||
pressure_name=pressure_name,
|
||||
unified_name="use_unified_strength",
|
||||
text="",
|
||||
header=True,
|
||||
expand=True
|
||||
)
|
||||
|
||||
if capabilities.has_color:
|
||||
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
|
||||
|
|
|
@ -538,7 +538,7 @@ typedef struct SculptArray {
|
|||
int *symmetry_pass;
|
||||
|
||||
float *smooth_strength;
|
||||
|
||||
struct SculptCustomLayer *scl_inst, *scl_sym;
|
||||
} SculptArray;
|
||||
|
||||
typedef struct SculptFakeNeighbors {
|
||||
|
|
|
@ -110,6 +110,7 @@ struct BMVert;
|
|||
struct BMEdge;
|
||||
struct BMFace;
|
||||
struct CCGElem;
|
||||
struct MeshElemMap;
|
||||
struct CCGKey;
|
||||
struct CustomData;
|
||||
struct TableGSet;
|
||||
|
@ -913,6 +914,15 @@ typedef struct SculptLayerEntry {
|
|||
int BKE_pbvh_do_fset_symmetry(int fset, const int symflag, const float *co);
|
||||
bool BKE_pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v);
|
||||
|
||||
void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
|
||||
struct MVert *mvert,
|
||||
struct MEdge *medge,
|
||||
struct MLoop *mloop,
|
||||
struct MPoly *mpoly,
|
||||
struct MDynTopoVert *mdyntopo_verts,
|
||||
struct MeshElemMap *pmap,
|
||||
SculptVertRef vertex);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -441,6 +441,7 @@ MAKE_ENUM(elastic_deform_type, "Deformation", "Deformation type that is used in
|
|||
{BRUSH_ELASTIC_DEFORM_TWIST, "TWIST", "NONE", "Twist", ""},
|
||||
{-1}
|
||||
})
|
||||
MAKE_BOOL(use_ctrl_invert, "Use Ctrl Invert", "Take brush addition or subtraction mode into account", true)
|
||||
|
||||
//MAKE_FLOAT3_EX
|
||||
/* clang-format on */
|
||||
|
|
|
@ -1397,6 +1397,9 @@ BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool)
|
|||
#define float_set_uninherit(chset, channel, val) \
|
||||
_float_set_uninherit(chset, MAKE_BUILTIN_CH_NAME(channel), val)
|
||||
|
||||
#define int_set_uninherit(chset, channel, val) \
|
||||
_int_set_uninherit(chset, MAKE_BUILTIN_CH_NAME(channel), val)
|
||||
|
||||
static void _float_set_uninherit(BrushChannelSet *chset, const char *channel, float val)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, channel);
|
||||
|
@ -1410,6 +1413,19 @@ static void _float_set_uninherit(BrushChannelSet *chset, const char *channel, fl
|
|||
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
static void _int_set_uninherit(BrushChannelSet *chset, const char *channel, int val)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, channel);
|
||||
|
||||
if (!ch) {
|
||||
printf("%s: unknown channel %s\n", __func__, channel);
|
||||
return;
|
||||
}
|
||||
|
||||
ch->ivalue = val;
|
||||
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
/*flag all mappings to use inherited curves even if owning channel
|
||||
is not set to inherit.*/
|
||||
void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chset)
|
||||
|
@ -1463,6 +1479,7 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, strength, autosmooth);
|
||||
float_set_uninherit(cmd->params, radius, radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, projection, autosmooth_projection);
|
||||
|
@ -1580,6 +1597,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, strength, autosmooth);
|
||||
float_set_uninherit(cmd->params, radius, radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, projection, autosmooth_projection);
|
||||
|
@ -1620,6 +1638,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
ch->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
}
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, strength, topology_rake);
|
||||
float_set_uninherit(cmd->params, radius, radius * topology_rake_scale);
|
||||
float_set_uninherit(cmd->params, projection, topology_rake_projection);
|
||||
|
@ -1637,6 +1656,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
|
||||
radius2 *= radius;
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, spacing, spacing);
|
||||
float_set_uninherit(cmd->params, radius, radius2);
|
||||
}
|
||||
|
|
|
@ -807,6 +807,7 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH(radius_unit);
|
||||
ADDCH(unprojected_radius);
|
||||
|
||||
ADDCH(use_ctrl_invert);
|
||||
ADDCH(tilt_strength_factor);
|
||||
|
||||
ADDCH(autosmooth);
|
||||
|
|
|
@ -2203,6 +2203,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
|||
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
|
@ -2214,6 +2215,19 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
|||
|
||||
BKE_sculpt_sync_face_set_visibility(me, NULL);
|
||||
|
||||
if (!ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(&ss->pmap,
|
||||
&ss->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop,
|
||||
false);
|
||||
}
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh,
|
||||
|
@ -2294,6 +2308,16 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
|
|||
for (int i = 0; i < totvert; i++, mv++) {
|
||||
mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
|
||||
mv->stroke_id = -1;
|
||||
|
||||
SculptVertRef vertex = {.i = i};
|
||||
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
|
||||
ss->mvert,
|
||||
ss->medge,
|
||||
ss->mloop,
|
||||
ss->mpoly,
|
||||
ss->mdyntopo_verts,
|
||||
ss->pmap,
|
||||
vertex);
|
||||
}
|
||||
}
|
||||
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_subdiv_ccg.h"
|
||||
|
@ -4125,3 +4126,88 @@ void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
|
||||
MVert *mvert,
|
||||
MEdge *medge,
|
||||
MLoop *mloop,
|
||||
MPoly *mpoly,
|
||||
MDynTopoVert *mdyntopo_verts,
|
||||
MeshElemMap *pmap,
|
||||
SculptVertRef vertex)
|
||||
{
|
||||
MDynTopoVert *mv = mdyntopo_verts + vertex.i;
|
||||
MeshElemMap *vert_map = &pmap[vertex.i];
|
||||
|
||||
int last_fset = 0;
|
||||
int last_fset2 = 0;
|
||||
|
||||
mv->flag &= ~(DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY | DYNVERT_NEED_BOUNDARY |
|
||||
DYNVERT_FSET_CORNER | DYNVERT_CORNER | DYNVERT_SEAM_BOUNDARY |
|
||||
DYNVERT_SHARP_BOUNDARY | DYNVERT_SEAM_CORNER | DYNVERT_SHARP_CORNER);
|
||||
|
||||
int totsharp = 0, totseam = 0;
|
||||
int visible = false;
|
||||
|
||||
for (int i = 0; i < vert_map->count; i++) {
|
||||
int f_i = vert_map->indices[i];
|
||||
|
||||
MPoly *mp = mpoly + f_i;
|
||||
MLoop *ml = mloop + mp->loopstart;
|
||||
int j = 0;
|
||||
|
||||
for (j = 0; j < mp->totloop; j++, ml++) {
|
||||
if (ml->v == (int)vertex.i) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < mp->totloop) {
|
||||
MEdge *me = medge + ml->e;
|
||||
if (me->flag & ME_SHARP) {
|
||||
mv->flag |= DYNVERT_SHARP_BOUNDARY;
|
||||
totsharp++;
|
||||
}
|
||||
|
||||
if (me->flag & ME_SEAM) {
|
||||
mv->flag |= DYNVERT_SEAM_BOUNDARY;
|
||||
totseam++;
|
||||
}
|
||||
}
|
||||
|
||||
int fset = face_sets[f_i];
|
||||
|
||||
if (fset > 0) {
|
||||
visible = true;
|
||||
}
|
||||
else {
|
||||
fset = -fset;
|
||||
}
|
||||
|
||||
if (i > 0 && fset != last_fset) {
|
||||
mv->flag |= DYNVERT_FSET_BOUNDARY;
|
||||
|
||||
if (i > 1 && last_fset2 != last_fset) {
|
||||
mv->flag |= DYNVERT_FSET_CORNER;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0 && last_fset != fset) {
|
||||
last_fset2 = last_fset;
|
||||
}
|
||||
|
||||
last_fset = fset;
|
||||
}
|
||||
|
||||
if (!visible) {
|
||||
mv->flag |= DYNVERT_VERT_FSET_HIDDEN;
|
||||
}
|
||||
|
||||
if (totsharp > 2) {
|
||||
mv->flag |= DYNVERT_SHARP_CORNER;
|
||||
}
|
||||
|
||||
if (totseam > 2) {
|
||||
mv->flag |= DYNVERT_SEAM_CORNER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ struct PBVH {
|
|||
MVert *verts;
|
||||
const MPoly *mpoly;
|
||||
const MLoop *mloop;
|
||||
struct MDynTopoVert *mdyntopo_verts;
|
||||
const MLoopTri *looptri;
|
||||
CustomData *vdata;
|
||||
CustomData *ldata;
|
||||
|
@ -218,7 +219,6 @@ struct PBVH {
|
|||
|
||||
int balance_counter;
|
||||
int stroke_id; // used to keep origdata up to date in PBVH_BMESH
|
||||
struct MDynTopoVert *mdyntopo_verts;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
|
|
|
@ -921,13 +921,15 @@ void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTem
|
|||
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
|
||||
|
||||
// flag mesh id layer as temporary
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CustomData *cdata = dstdatas[i];
|
||||
if (!(bm_dst->idmap.flag & BM_PERMANENT_IDS)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CustomData *cdata = dstdatas[i];
|
||||
|
||||
if (CustomData_has_layer(cdata, CD_MESH_ID)) {
|
||||
int idx = CustomData_get_layer_index(cdata, CD_MESH_ID);
|
||||
if (CustomData_has_layer(cdata, CD_MESH_ID)) {
|
||||
int idx = CustomData_get_layer_index(cdata, CD_MESH_ID);
|
||||
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_ELEM_NOCOPY;
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_ELEM_NOCOPY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -976,7 +978,7 @@ void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
|
|||
bm_update_idmap_cdlayers(bm_dst);
|
||||
}
|
||||
|
||||
BMesh *BM_mesh_copy(BMesh *bm_old)
|
||||
BMesh *BM_mesh_copy_ex(BMesh *bm_old, struct BMeshCreateParams *params)
|
||||
{
|
||||
BMesh *bm_new;
|
||||
BMVert *v, *v_new, **vtable = NULL;
|
||||
|
@ -987,19 +989,29 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||
BMIter iter;
|
||||
int i;
|
||||
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
|
||||
struct BMeshCreateParams _params;
|
||||
|
||||
if (!params) {
|
||||
_params = ((struct BMeshCreateParams){
|
||||
.use_toolflags = bm_old->use_toolflags,
|
||||
.id_elem_mask = bm_old->idmap.flag & (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE),
|
||||
.create_unique_ids = !!(bm_old->idmap.flag & BM_HAS_IDS),
|
||||
.id_map = !!(bm_old->idmap.flag & BM_HAS_ID_MAP),
|
||||
.temporary_ids = !(bm_old->idmap.flag & BM_PERMANENT_IDS),
|
||||
.no_reuse_ids = !!(bm_old->idmap.flag & BM_NO_REUSE_IDS)});
|
||||
params = &_params;
|
||||
}
|
||||
|
||||
/* allocate a bmesh */
|
||||
bm_new = BM_mesh_create(
|
||||
&allocsize,
|
||||
&((struct BMeshCreateParams){.use_toolflags = bm_old->use_toolflags,
|
||||
.id_elem_mask = bm_old->idmap.flag &
|
||||
(BM_VERT | BM_EDGE | BM_LOOP | BM_FACE),
|
||||
.create_unique_ids = !!(bm_old->idmap.flag & BM_HAS_IDS),
|
||||
.id_map = !!(bm_old->idmap.flag & BM_HAS_ID_MAP),
|
||||
.temporary_ids = !(bm_old->idmap.flag & BM_PERMANENT_IDS),
|
||||
.no_reuse_ids = !!(bm_old->idmap.flag & BM_NO_REUSE_IDS)}));
|
||||
bm_new = BM_mesh_create(&allocsize, params);
|
||||
|
||||
BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
|
||||
if (params->copy_all_layers) {
|
||||
BM_mesh_copy_init_customdata_all_layers(
|
||||
bm_new, bm_old, BM_VERT | BM_EDGE | BM_LOOP | BM_FACE, &allocsize);
|
||||
}
|
||||
else {
|
||||
BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
|
||||
}
|
||||
|
||||
if (bm_old->idmap.flag & BM_HAS_IDS) {
|
||||
MEM_SAFE_FREE(bm_new->idmap.map);
|
||||
|
@ -1139,6 +1151,11 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||
return bm_new;
|
||||
}
|
||||
|
||||
BMesh *BM_mesh_copy(BMesh *bm_old)
|
||||
{
|
||||
return BM_mesh_copy_ex(bm_old, NULL);
|
||||
}
|
||||
|
||||
/* ME -> BM */
|
||||
char BM_vert_flag_from_mflag(const char mflag)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@ struct BMeshCreateParams {
|
|||
uint no_reuse_ids : 1; // do not reuse IDs; a GHash will be used internally instead of a lookup
|
||||
// array
|
||||
uint temporary_ids : 1;
|
||||
uint copy_all_layers : 1; // used by BM_mesh_copy_ex
|
||||
};
|
||||
|
||||
// used to temporary save/restore element IDs
|
||||
|
|
|
@ -1796,6 +1796,7 @@ static void sculpt_vertex_neighbors_get_bmesh(const SculptSession *ss,
|
|||
iter->is_duplicate = false;
|
||||
iter->size = 0;
|
||||
iter->num_duplicates = 0;
|
||||
iter->has_edge = true;
|
||||
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
|
||||
iter->neighbors = iter->neighbors_fixed;
|
||||
iter->neighbor_indices = iter->neighbor_indices_fixed;
|
||||
|
@ -1851,6 +1852,7 @@ static void sculpt_vertex_neighbors_get_faces(const SculptSession *ss,
|
|||
iter->neighbors = iter->neighbors_fixed;
|
||||
iter->neighbor_indices = iter->neighbor_indices_fixed;
|
||||
iter->is_duplicate = false;
|
||||
iter->has_edge = true;
|
||||
|
||||
for (int i = 0; i < ss->pmap[index].count; i++) {
|
||||
if (ss->face_sets[vert_map->indices[i]] < 0) {
|
||||
|
@ -1859,23 +1861,31 @@ static void sculpt_vertex_neighbors_get_faces(const SculptSession *ss,
|
|||
}
|
||||
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
|
||||
uint f_adj_v[2];
|
||||
if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) {
|
||||
for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
|
||||
|
||||
MLoop *l = &ss->mloop[p->loopstart];
|
||||
int e1, e2;
|
||||
|
||||
bool ok = false;
|
||||
|
||||
for (int j = 0; j < p->totloop; j++, l++) {
|
||||
if (l->v == index) {
|
||||
f_adj_v[0] = ME_POLY_LOOP_PREV(ss->mloop, p, j)->v;
|
||||
f_adj_v[1] = ME_POLY_LOOP_NEXT(ss->mloop, p, j)->v;
|
||||
|
||||
e1 = ME_POLY_LOOP_PREV(ss->mloop, p, j)->e;
|
||||
e2 = l->e;
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
for (int j = 0; j < 2; j += 1) {
|
||||
int e = 0;
|
||||
|
||||
if (f_adj_v[j] != index) {
|
||||
int loopidx = p->loopstart;
|
||||
|
||||
for (int k = 0; k < p->totloop; k++, loopidx++) {
|
||||
const MEdge *e2 = &ss->medge[ss->mloop[loopidx].e];
|
||||
if ((e2->v1 == index && e2->v2 == f_adj_v[j]) ||
|
||||
(e2->v2 == index && e2->v1 == f_adj_v[j])) {
|
||||
e = e2 - ss->medge;
|
||||
}
|
||||
}
|
||||
|
||||
sculpt_vertex_neighbor_add(
|
||||
iter, BKE_pbvh_make_vref(f_adj_v[j]), BKE_pbvh_make_eref(e), f_adj_v[j]);
|
||||
iter, BKE_pbvh_make_vref(f_adj_v[j]), BKE_pbvh_make_eref(j ? e2 : e1), f_adj_v[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1910,8 +1920,9 @@ static void sculpt_vertex_neighbors_get_faces_vemap(const SculptSession *ss,
|
|||
const MEdge *me = &ss->medge[vert_map->indices[i]];
|
||||
|
||||
unsigned int v = me->v1 == (unsigned int)vertex.i ? me->v2 : me->v1;
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts + v;
|
||||
|
||||
if (ss->face_sets[v] < 0) {
|
||||
if (mv->flag & DYNVERT_VERT_FSET_HIDDEN) {
|
||||
/* Skip connectivity from hidden faces. */
|
||||
continue;
|
||||
}
|
||||
|
@ -2128,18 +2139,39 @@ static bool sculpt_check_boundary_vertex_in_base_mesh(const SculptSession *ss,
|
|||
return BLI_BITMAP_TEST(ss->vertex_info.boundary,
|
||||
BKE_pbvh_vertex_index_to_table(ss->pbvh, index));
|
||||
}
|
||||
static void faces_update_boundary_flags(const SculptSession *ss, const SculptVertRef vertex)
|
||||
{
|
||||
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
|
||||
ss->mvert,
|
||||
ss->medge,
|
||||
ss->mloop,
|
||||
ss->mpoly,
|
||||
ss->mdyntopo_verts,
|
||||
ss->pmap,
|
||||
vertex);
|
||||
// have to handle boundary here
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex)) {
|
||||
mv->flag |= DYNVERT_BOUNDARY;
|
||||
|
||||
if (ss->pmap[vertex.i].count < 4) {
|
||||
mv->flag |= DYNVERT_CORNER;
|
||||
}
|
||||
}
|
||||
}
|
||||
SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
|
||||
const SculptVertRef vertex,
|
||||
SculptCornerType cornertype)
|
||||
{
|
||||
bool check_facesets = cornertype & SCULPT_CORNER_FACE_SET;
|
||||
SculptCornerType ret = 0;
|
||||
MDynTopoVert *mv = NULL;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
BMVert *v = (BMVert *)vertex.i;
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
|
||||
mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
|
||||
|
||||
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
BKE_pbvh_update_vert_boundary(ss->cd_dyn_vert,
|
||||
|
@ -2150,36 +2182,13 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
|
|||
ss->boundary_symmetry);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (cornertype & SCULPT_CORNER_MESH) {
|
||||
ret |= (mv->flag & DYNVERT_CORNER) ? SCULPT_CORNER_MESH : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_FACE_SET) {
|
||||
ret |= (mv->flag & DYNVERT_FSET_CORNER) ? SCULPT_CORNER_FACE_SET : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_SEAM) {
|
||||
ret |= (mv->flag & DYNVERT_SEAM_CORNER) ? SCULPT_CORNER_SEAM : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_SHARP) {
|
||||
ret |= (mv->flag & DYNVERT_SHARP_CORNER) ? SCULPT_CORNER_SHARP : 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES:
|
||||
if (ss->pmap) {
|
||||
// sculpt_check_corner_face_set_in_base_mesh
|
||||
ret = sculpt_check_corner_in_base_mesh(ss, vertex, check_facesets);
|
||||
}
|
||||
else {
|
||||
// approximate
|
||||
if (SCULPT_vertex_is_boundary(ss, vertex, SCULPT_BOUNDARY_MESH) &&
|
||||
SCULPT_vertex_valence_get(ss, vertex) < 4) {
|
||||
ret = SCULPT_CORNER_MESH;
|
||||
}
|
||||
mv = ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
// can't check face sets in this case
|
||||
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
faces_update_boundary_flags(ss, vertex);
|
||||
}
|
||||
break;
|
||||
case PBVH_GRIDS: {
|
||||
|
@ -2199,11 +2208,27 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
|
|||
return false; // sculpt_check_unique_face_set_for_edge_in_base_mesh(ss, v1, v2);
|
||||
case SUBDIV_CCG_ADJACENT_NONE:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (cornertype & SCULPT_CORNER_MESH) {
|
||||
ret |= (mv->flag & DYNVERT_CORNER) ? SCULPT_CORNER_MESH : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_FACE_SET) {
|
||||
ret |= (mv->flag & DYNVERT_FSET_CORNER) ? SCULPT_CORNER_FACE_SET : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_SEAM) {
|
||||
ret |= (mv->flag & DYNVERT_SEAM_CORNER) ? SCULPT_CORNER_SEAM : 0;
|
||||
}
|
||||
if (cornertype & SCULPT_CORNER_SHARP) {
|
||||
ret |= (mv->flag & DYNVERT_SHARP_CORNER) ? SCULPT_CORNER_SHARP : 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2212,10 +2237,11 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
|
|||
SculptBoundaryType boundary_types)
|
||||
{
|
||||
bool check_facesets = boundary_types & SCULPT_BOUNDARY_FACE_SET;
|
||||
MDynTopoVert *mv = NULL;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, ((BMVert *)(vertex.i)));
|
||||
mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, ((BMVert *)(vertex.i)));
|
||||
|
||||
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
BKE_pbvh_update_vert_boundary(ss->cd_dyn_vert,
|
||||
|
@ -2226,47 +2252,15 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
|
|||
ss->boundary_symmetry);
|
||||
}
|
||||
|
||||
int flag = 0;
|
||||
if (boundary_types & SCULPT_BOUNDARY_MESH) {
|
||||
flag |= (mv->flag & DYNVERT_BOUNDARY) ? SCULPT_BOUNDARY_MESH : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_FACE_SET) {
|
||||
flag |= (mv->flag & DYNVERT_FSET_BOUNDARY) ? SCULPT_BOUNDARY_FACE_SET : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_SHARP) {
|
||||
flag |= (mv->flag & DYNVERT_SHARP_BOUNDARY) ? SCULPT_BOUNDARY_SHARP : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_SEAM) {
|
||||
flag |= (mv->flag & DYNVERT_SEAM_BOUNDARY) ? SCULPT_BOUNDARY_SEAM : 0;
|
||||
}
|
||||
|
||||
return flag;
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
int flag = 0;
|
||||
mv = ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) {
|
||||
flag |= SCULPT_BOUNDARY_MESH;
|
||||
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
faces_update_boundary_flags(ss, vertex);
|
||||
}
|
||||
|
||||
if (check_facesets) {
|
||||
bool ret = sculpt_check_boundary_vertex_in_base_mesh(ss, vertex);
|
||||
|
||||
if (ret) {
|
||||
flag |= SCULPT_BOUNDARY_MESH;
|
||||
}
|
||||
|
||||
if (!SCULPT_vertex_has_unique_face_set(ss, vertex)) {
|
||||
flag |= SCULPT_BOUNDARY_FACE_SET;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
else if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex)) {
|
||||
return SCULPT_BOUNDARY_MESH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case PBVH_GRIDS: {
|
||||
|
@ -2296,6 +2290,21 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
|
|||
}
|
||||
}
|
||||
|
||||
int flag = 0;
|
||||
if (boundary_types & SCULPT_BOUNDARY_MESH) {
|
||||
flag |= (mv->flag & DYNVERT_BOUNDARY) ? SCULPT_BOUNDARY_MESH : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_FACE_SET) {
|
||||
flag |= (mv->flag & DYNVERT_FSET_BOUNDARY) ? SCULPT_BOUNDARY_FACE_SET : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_SHARP) {
|
||||
flag |= (mv->flag & DYNVERT_SHARP_BOUNDARY) ? SCULPT_BOUNDARY_SHARP : 0;
|
||||
}
|
||||
if (boundary_types & SCULPT_BOUNDARY_SEAM) {
|
||||
flag |= (mv->flag & DYNVERT_SEAM_BOUNDARY) ? SCULPT_BOUNDARY_SEAM : 0;
|
||||
}
|
||||
|
||||
return flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7417,6 +7426,8 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
BKE_pbvh_node_mark_update(data->nodes[n]);
|
||||
}
|
||||
|
||||
static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
||||
|
@ -8702,7 +8713,7 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
|
|||
return;
|
||||
}
|
||||
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_ARRAY && type != PBVH_FACES) {
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_ARRAY && !ELEM(type, PBVH_FACES, PBVH_BMESH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8787,7 +8798,7 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
|
|||
BKE_pbvh_node_mark_update(nodes[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (brush->sculpt_tool != SCULPT_TOOL_ARRAY) {
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COORDS, -1);
|
||||
|
||||
|
@ -9162,7 +9173,7 @@ static void SCULPT_run_command_list(
|
|||
return;
|
||||
}
|
||||
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_ARRAY && type != PBVH_FACES) {
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_ARRAY && !ELEM(type, PBVH_FACES, PBVH_BMESH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -9346,6 +9357,11 @@ static void SCULPT_run_command_list(
|
|||
|
||||
ss->cache->bstrength = brush_strength(
|
||||
sd, ss->cache, calc_symmetry_feather(sd, ss->cache), ups);
|
||||
|
||||
if (!BRUSHSET_GET_INT(cmd->params_mapped, use_ctrl_invert, NULL)) {
|
||||
ss->cache->bstrength = fabsf(ss->cache->bstrength);
|
||||
}
|
||||
|
||||
brush2->alpha = fabs(ss->cache->bstrength);
|
||||
|
||||
// printf("brush2->alpha: %f\n", brush2->alpha);
|
||||
|
@ -10892,6 +10908,8 @@ static bool sculpt_needs_connectivity_info(Sculpt *sd,
|
|||
SculptSession *ss,
|
||||
int stroke_mode)
|
||||
{
|
||||
return true;
|
||||
#if 0
|
||||
if (ss && ss->pbvh && SCULPT_is_automasking_enabled(sd, ss, brush)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -10909,6 +10927,7 @@ static bool sculpt_needs_connectivity_info(Sculpt *sd,
|
|||
(brush->sculpt_tool == SCULPT_TOOL_CLOTH) || (brush->sculpt_tool == SCULPT_TOOL_SMEAR) ||
|
||||
(brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) ||
|
||||
(brush->sculpt_tool == SCULPT_TOOL_DISPLACEMENT_SMEAR));
|
||||
#endif
|
||||
}
|
||||
|
||||
void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
|
||||
|
@ -13952,20 +13971,20 @@ int SCULPT_vertex_valence_get(const struct SculptSession *ss, SculptVertRef vert
|
|||
}
|
||||
#endif
|
||||
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
tot++;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
#ifdef NDEBUG
|
||||
if (mval >= 0 && mval != tot) {
|
||||
printf("Out of date vertex valence detected! old: %d, should be: %d\n", mval, tot);
|
||||
}
|
||||
#else
|
||||
BLI_assert(mval < 0 || mval == tot);
|
||||
#endif
|
||||
if (mv->flag & DYNVERT_NEED_VALENCE) {
|
||||
mv->flag &= ~DYNVERT_NEED_VALENCE;
|
||||
|
||||
return tot;
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
tot++;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
|
||||
mv->valence = tot;
|
||||
}
|
||||
|
||||
return mv->valence;
|
||||
}
|
||||
|
||||
typedef struct BMLinkItem {
|
||||
|
|
|
@ -82,20 +82,59 @@ static void sculpt_vertex_array_data_get(SculptArray *array,
|
|||
*r_symmetry_pass = array->symmetry_pass[vertex];
|
||||
}
|
||||
|
||||
static void sculpt_array_datalayers_add(Mesh *mesh)
|
||||
static void sculpt_array_datalayers_init(SculptArray *array, SculptSession *ss)
|
||||
{
|
||||
int *v_array_instance = CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_INT32, CD_CALLOC, NULL, mesh->totvert, array_instance_cd_name);
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
v_array_instance[i] = ARRAY_INSTANCE_ORIGINAL;
|
||||
SculptLayerParams params = {.permanent = true, .simple_array = false};
|
||||
|
||||
if (!array->scl_inst) {
|
||||
array->scl_inst = MEM_callocN(sizeof(SculptCustomLayer), __func__);
|
||||
}
|
||||
|
||||
CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_INT32, CD_CALLOC, NULL, mesh->totvert, array_symmetry_pass_cd_name);
|
||||
if (!array->scl_sym) {
|
||||
array->scl_sym = MEM_callocN(sizeof(SculptCustomLayer), __func__);
|
||||
}
|
||||
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, ¶ms);
|
||||
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, array->scl_sym, ¶ms);
|
||||
}
|
||||
|
||||
void SCULPT_array_datalayers_free(Object *ob)
|
||||
static void sculpt_array_datalayers_add(SculptArray *array, SculptSession *ss, Mesh *mesh)
|
||||
{
|
||||
|
||||
// int *v_array_instance = CustomData_add_layer_named(
|
||||
// &mesh->vdata, CD_PROP_INT32, CD_CALLOC, NULL, mesh->totvert, array_instance_cd_name);
|
||||
int totvert = SCULPT_vertex_count_get(ss);
|
||||
const SculptCustomLayer *scl = array->scl_inst;
|
||||
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
*(int *)SCULPT_temp_cdata_get(vertex, scl) = ARRAY_INSTANCE_ORIGINAL;
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (array->scl_inst) {
|
||||
SCULPT_temp_customlayer_release(ss, array->scl_inst);
|
||||
}
|
||||
|
||||
if (array->scl_sym) {
|
||||
SCULPT_temp_customlayer_release(ss, array->scl_sym);
|
||||
}
|
||||
|
||||
array->scl_inst = NULL;
|
||||
array->scl_sym = NULL;
|
||||
return;
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
int v_layer_index = CustomData_get_named_layer_index(
|
||||
&mesh->vdata, CD_PROP_INT32, array_instance_cd_name);
|
||||
|
@ -114,21 +153,39 @@ const float source_geometry_threshold = 0.5f;
|
|||
|
||||
static BMesh *sculpt_array_source_build(Object *ob, Brush *brush, SculptArray *array)
|
||||
{
|
||||
bool have_bmesh = ob->sculpt->bm && ob->sculpt->pbvh &&
|
||||
BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_BMESH;
|
||||
|
||||
Mesh *sculpt_mesh = BKE_object_get_original_mesh(ob);
|
||||
|
||||
BMesh *srcbm;
|
||||
const BMAllocTemplate allocsizea = BMALLOC_TEMPLATE_FROM_ME(sculpt_mesh);
|
||||
srcbm = BM_mesh_create(&allocsizea,
|
||||
&((struct BMeshCreateParams){
|
||||
.use_toolflags = true,
|
||||
}));
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
srcbm,
|
||||
sculpt_mesh,
|
||||
&((struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
}));
|
||||
BMesh *BM_mesh_copy_ex(BMesh * bm_old, struct BMeshCreateParams * params);
|
||||
|
||||
if (have_bmesh) {
|
||||
srcbm = BM_mesh_copy_ex(
|
||||
ob->sculpt->bm,
|
||||
&((struct BMeshCreateParams){.use_toolflags = true,
|
||||
.id_map = false,
|
||||
.id_elem_mask = ob->sculpt->bm->idmap.flag &
|
||||
(BM_VERT | BM_EDGE | BM_FACE | BM_LOOP),
|
||||
.create_unique_ids = true,
|
||||
.copy_all_layers = true}));
|
||||
}
|
||||
else {
|
||||
const BMAllocTemplate allocsizea = BMALLOC_TEMPLATE_FROM_ME(sculpt_mesh);
|
||||
srcbm = BM_mesh_create(&allocsizea,
|
||||
&((struct BMeshCreateParams){
|
||||
.use_toolflags = true,
|
||||
}));
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
srcbm,
|
||||
sculpt_mesh,
|
||||
&((struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
}));
|
||||
}
|
||||
|
||||
BM_mesh_elem_table_ensure(srcbm, BM_VERT);
|
||||
BM_mesh_elem_index_ensure(srcbm, BM_VERT);
|
||||
|
@ -186,7 +243,9 @@ static BMesh *sculpt_array_source_build(Object *ob, Brush *brush, SculptArray *a
|
|||
return srcbm;
|
||||
}
|
||||
|
||||
void sculpt_array_source_datalayer_update(BMesh *bm, const int symm_pass, const int copy_index)
|
||||
ATTR_NO_OPT void sculpt_array_source_datalayer_update(BMesh *bm,
|
||||
const int symm_pass,
|
||||
const int copy_index)
|
||||
{
|
||||
const int cd_array_instance_index = CustomData_get_named_layer_index(
|
||||
&bm->vdata, CD_PROP_INT32, array_instance_cd_name);
|
||||
|
@ -216,7 +275,6 @@ static void sculpt_array_final_mesh_write(Object *ob, BMesh *final_mesh)
|
|||
Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(final_mesh, NULL, sculpt_mesh);
|
||||
result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
||||
BKE_mesh_nomain_to_mesh(result, ob->data, ob, &CD_MASK_MESH, true);
|
||||
BKE_id_free(NULL, result);
|
||||
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
|
||||
|
||||
const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data);
|
||||
|
@ -225,61 +283,70 @@ static void sculpt_array_final_mesh_write(Object *ob, BMesh *final_mesh)
|
|||
ss->needs_pbvh_rebuild = true;
|
||||
}
|
||||
|
||||
static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
|
||||
ATTR_NO_OPT static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
|
||||
{
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
|
||||
if (array->copy_index) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
printf("ALLOCATION COPY INDEX\n");
|
||||
|
||||
array->copy_index = MEM_malloc_arrayN(mesh->totvert, sizeof(int), "array copy index");
|
||||
array->symmetry_pass = MEM_malloc_arrayN(
|
||||
mesh->totvert, sizeof(int), "array symmetry pass index");
|
||||
SculptSession *ss = ob->sculpt;
|
||||
int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
||||
int *cd_array_instance = CustomData_get_layer_named(
|
||||
&mesh->vdata, CD_PROP_INT32, array_instance_cd_name);
|
||||
array->copy_index = MEM_malloc_arrayN(totvert, sizeof(int), "array copy index");
|
||||
array->symmetry_pass = MEM_malloc_arrayN(totvert, sizeof(int), "array symmetry pass index");
|
||||
|
||||
int *cd_array_symm_pass = CustomData_get_layer_named(
|
||||
&mesh->vdata, CD_PROP_INT32, array_symmetry_pass_cd_name);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
if (!cd_array_instance) {
|
||||
printf("ERROR 1");
|
||||
array->copy_index[i] = *(int *)SCULPT_temp_cdata_get(vertex, array->scl_inst);
|
||||
array->symmetry_pass[i] = *(int *)SCULPT_temp_cdata_get(vertex, array->scl_sym);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
array->copy_index[i] = cd_array_instance[i];
|
||||
array->symmetry_pass[i] = cd_array_symm_pass[i];
|
||||
}
|
||||
|
||||
SCULPT_array_datalayers_free(ob);
|
||||
SCULPT_array_datalayers_free(array, ob);
|
||||
}
|
||||
|
||||
static void sculpt_array_mesh_build(Sculpt *sd, Object *ob, SculptArray *array)
|
||||
ATTR_NO_OPT static void sculpt_array_mesh_build(Sculpt *sd, Object *ob, SculptArray *array)
|
||||
{
|
||||
bool have_bmesh = ob->sculpt->bm && ob->sculpt->pbvh &&
|
||||
BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_BMESH;
|
||||
|
||||
Mesh *sculpt_mesh = BKE_object_get_original_mesh(ob);
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
sculpt_array_datalayers_add(sculpt_mesh);
|
||||
|
||||
sculpt_array_datalayers_init(array, ob->sculpt);
|
||||
sculpt_array_datalayers_add(array, ob->sculpt, sculpt_mesh);
|
||||
|
||||
BMesh *srcbm = sculpt_array_source_build(ob, brush, array);
|
||||
|
||||
BMesh *destbm;
|
||||
const BMAllocTemplate allocsizeb = BMALLOC_TEMPLATE_FROM_ME(sculpt_mesh);
|
||||
destbm = BM_mesh_create(&allocsizeb,
|
||||
&((struct BMeshCreateParams){
|
||||
.use_toolflags = true,
|
||||
}));
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
destbm,
|
||||
sculpt_mesh,
|
||||
&((struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
}));
|
||||
|
||||
if (!have_bmesh) {
|
||||
destbm = BM_mesh_create(&allocsizeb,
|
||||
&((struct BMeshCreateParams){
|
||||
.use_toolflags = true,
|
||||
}));
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
destbm,
|
||||
sculpt_mesh,
|
||||
&((struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
}));
|
||||
}
|
||||
else {
|
||||
destbm = ob->sculpt->bm;
|
||||
}
|
||||
|
||||
BM_mesh_toolflags_set(destbm, true);
|
||||
BM_mesh_toolflags_set(srcbm, true);
|
||||
|
||||
BM_mesh_elem_toolflags_ensure(destbm);
|
||||
BM_mesh_elem_toolflags_ensure(srcbm);
|
||||
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
for (char symm_it = 0; symm_it <= symm; symm_it++) {
|
||||
if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
|
||||
|
@ -289,16 +356,25 @@ static void sculpt_array_mesh_build(Sculpt *sd, Object *ob, SculptArray *array)
|
|||
for (int copy_index = 0; copy_index < array->num_copies; copy_index++) {
|
||||
sculpt_array_source_datalayer_update(srcbm, symm_it, copy_index);
|
||||
|
||||
BM_mesh_copy_init_customdata(destbm, srcbm, &bm_mesh_allocsize_default);
|
||||
if (1) { //! have_bmesh) {
|
||||
// BM_mesh_copy_init_customdata(destbm, srcbm, &bm_mesh_allocsize_default);
|
||||
}
|
||||
|
||||
const int opflag = (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE);
|
||||
BMO_op_callf(srcbm, opflag, "duplicate geom=%avef dest=%p", destbm);
|
||||
}
|
||||
}
|
||||
|
||||
sculpt_array_final_mesh_write(ob, destbm);
|
||||
if (!have_bmesh) {
|
||||
sculpt_array_final_mesh_write(ob, destbm);
|
||||
BM_mesh_free(destbm);
|
||||
}
|
||||
else {
|
||||
SCULPT_update_customdata_refs(ob->sculpt);
|
||||
ob->sculpt->needs_pbvh_rebuild = true;
|
||||
}
|
||||
|
||||
BM_mesh_free(srcbm);
|
||||
BM_mesh_free(destbm);
|
||||
}
|
||||
|
||||
static SculptArray *sculpt_array_cache_create(Object *ob,
|
||||
|
@ -532,9 +608,9 @@ static void sculpt_array_update(Object *ob, Brush *brush, SculptArray *array)
|
|||
}
|
||||
}
|
||||
|
||||
static void do_array_deform_task_cb_ex(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
ATTR_NO_OPT static void do_array_deform_task_cb_ex(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
SculptThreadedTaskData *data = userdata;
|
||||
SculptSession *ss = data->ob->sculpt;
|
||||
|
@ -696,7 +772,8 @@ static void sculpt_array_ensure_original_coordinates(Object *ob, SculptArray *ar
|
|||
return;
|
||||
}
|
||||
|
||||
array->orco = MEM_malloc_arrayN(sculpt_mesh->totvert, sizeof(float) * 3, "array orco");
|
||||
array->orco = MEM_malloc_arrayN(totvert, sizeof(float) * 3, "array orco");
|
||||
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
|
@ -788,7 +865,7 @@ static void sculpt_array_stroke_sample_add(Object *ob, SculptArray *array)
|
|||
array->path.tot_points++;
|
||||
}
|
||||
|
||||
void SCULPT_do_array_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
||||
ATTR_NO_OPT void SCULPT_do_array_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
@ -947,6 +1024,8 @@ void SCULPT_do_array_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
return;
|
||||
}
|
||||
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
|
||||
sculpt_array_ensure_base_transform(sd, ob, ss->array);
|
||||
sculpt_array_ensure_original_coordinates(ob, ss->array);
|
||||
sculpt_array_ensure_geometry_indices(ob, ss->array);
|
||||
|
|
|
@ -928,7 +928,8 @@ static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
|||
SculptClothTaskData *tasks = MEM_calloc_arrayN(
|
||||
totthread + 1, sizeof(SculptClothTaskData), "SculptClothTaskData");
|
||||
|
||||
int *vthreads = MEM_calloc_arrayN(ss->totvert, sizeof(*vthreads), "cloth vthreads");
|
||||
int *vthreads = MEM_calloc_arrayN(
|
||||
SCULPT_vertex_count_get(ss), sizeof(*vthreads), "cloth vthreads");
|
||||
|
||||
SculptClothLengthConstraint *cons = cloth_sim->length_constraints, *con;
|
||||
int totcon = cloth_sim->tot_length_constraints;
|
||||
|
|
Loading…
Reference in New Issue