diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/attribute.c | 298 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.cc | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/data_transfer.c | 25 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.cc | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 54 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 143 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.cc | 210 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_intern.h | 16 |
9 files changed, 726 insertions, 28 deletions
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index ba33a9fee97..13c896fd1ab 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -19,6 +19,7 @@ #include "DNA_pointcloud_types.h" #include "BLI_string_utf8.h" +#include "BLI_string_utils.h" #include "BKE_attribute.h" #include "BKE_curves.h" @@ -91,7 +92,8 @@ static CustomData *attribute_customdata_find(ID *id, CustomDataLayer *layer) for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) { CustomData *customdata = info[domain].customdata; - if (customdata && ARRAY_HAS_ITEM(layer, customdata->layers, customdata->totlayer)) { + if (customdata && + ARRAY_HAS_ITEM(layer, (CustomDataLayer const *)customdata->layers, customdata->totlayer)) { return customdata; } } @@ -132,6 +134,44 @@ bool BKE_id_attribute_rename(ID *id, return true; } +typedef struct AttrUniqueData { + ID *id; +} AttrUniqueData; + +static bool unique_name_cb(void *arg, const char *name) +{ + AttrUniqueData *data = (AttrUniqueData *)arg; + + DomainInfo info[ATTR_DOMAIN_NUM]; + get_domains(data->id, info); + + for (AttributeDomain domain = ATTR_DOMAIN_POINT; domain < ATTR_DOMAIN_NUM; domain++) { + if (!info[domain].customdata) { + continue; + } + + CustomData *cdata = info[domain].customdata; + for (int i = 0; i < cdata->totlayer; i++) { + CustomDataLayer *layer = cdata->layers + i; + + if (STREQ(layer->name, name)) { + return true; + } + } + } + + return false; +} + +bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname) +{ + AttrUniqueData data = {.id = id}; + + BLI_strncpy_utf8(outname, name, MAX_CUSTOMDATA_LAYER_NAME); + + return BLI_uniquename_cb(unique_name_cb, &data, NULL, '.', outname, MAX_CUSTOMDATA_LAYER_NAME); +} + CustomDataLayer *BKE_id_attribute_new( ID *id, const char *name, const int type, const AttributeDomain domain, ReportList *reports) { @@ -144,25 +184,30 @@ CustomDataLayer *BKE_id_attribute_new( return NULL; } + char uniquename[MAX_CUSTOMDATA_LAYER_NAME]; + BKE_id_attribute_calc_unique_name(id, name, uniquename); + switch (GS(id->name)) { case ID_ME: { Mesh *me = (Mesh *)id; BMEditMesh *em = me->edit_mesh; if (em != NULL) { - BM_data_layer_add_named(em->bm, customdata, type, name); + BM_data_layer_add_named(em->bm, customdata, type, uniquename); } else { - CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name); + CustomData_add_layer_named( + customdata, type, CD_DEFAULT, NULL, info[domain].length, uniquename); } break; } default: { - CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name); + CustomData_add_layer_named( + customdata, type, CD_DEFAULT, NULL, info[domain].length, uniquename); break; } } - const int index = CustomData_get_named_layer_index(customdata, type, name); + const int index = CustomData_get_named_layer_index(customdata, type, uniquename); return (index == -1) ? NULL : &(customdata->layers[index]); } @@ -229,7 +274,7 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id, return NULL; } -int BKE_id_attributes_length(ID *id, const CustomDataMask mask) +int BKE_id_attributes_length(const ID *id, AttributeDomainMask domain_mask, CustomDataMask mask) { DomainInfo info[ATTR_DOMAIN_NUM]; get_domains(id, info); @@ -238,7 +283,8 @@ int BKE_id_attributes_length(ID *id, const CustomDataMask mask) for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) { CustomData *customdata = info[domain].customdata; - if (customdata) { + + if (customdata && ((1 << (int)domain) & domain_mask)) { length += CustomData_number_of_layers_typemask(customdata, mask); } } @@ -246,7 +292,7 @@ int BKE_id_attributes_length(ID *id, const CustomDataMask mask) return length; } -AttributeDomain BKE_id_attribute_domain(ID *id, CustomDataLayer *layer) +AttributeDomain BKE_id_attribute_domain(ID *id, const CustomDataLayer *layer) { DomainInfo info[ATTR_DOMAIN_NUM]; get_domains(id, info); @@ -295,7 +341,7 @@ bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer) CustomDataLayer *BKE_id_attributes_active_get(ID *id) { int active_index = *BKE_id_attributes_active_index_p(id); - if (active_index > BKE_id_attributes_length(id, CD_MASK_PROP_ALL)) { + if (active_index > BKE_id_attributes_length(id, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL)) { active_index = 0; } @@ -384,3 +430,237 @@ CustomData *BKE_id_attributes_iterator_next_domain(ID *id, CustomDataLayer *laye return NULL; } + +CustomDataLayer *BKE_id_attribute_from_index(ID *id, + int lookup_index, + AttributeDomainMask domain_mask, + CustomDataMask layer_mask) +{ + DomainInfo info[ATTR_DOMAIN_NUM]; + get_domains(id, info); + + int index = 0; + for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) { + CustomData *customdata = info[domain].customdata; + + if (!customdata || !((1 << (int)domain) & domain_mask)) { + continue; + } + + for (int i = 0; i < customdata->totlayer; i++) { + if (!(layer_mask & CD_TYPE_AS_MASK(customdata->layers[i].type)) || + (CD_TYPE_AS_MASK(customdata->layers[i].type) & CD_FLAG_TEMPORARY)) { + continue; + } + + if (index == lookup_index) { + return customdata->layers + i; + } + + index++; + } + } + + return NULL; +} + +/** Get list of domain types but with ATTR_DOMAIN_FACE and + * ATTR_DOMAIN_CORNER swapped. + */ +static void get_domains_types(AttributeDomain domains[ATTR_DOMAIN_NUM]) +{ + for (AttributeDomain i = 0; i < ATTR_DOMAIN_NUM; i++) { + domains[i] = i; + } + + /* Swap corner and face. */ + SWAP(AttributeDomain, domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]); +} + +int BKE_id_attribute_to_index(const struct ID *id, + const CustomDataLayer *layer, + AttributeDomainMask domain_mask, + CustomDataMask layer_mask) +{ + if (!layer) { + return -1; + } + + DomainInfo info[ATTR_DOMAIN_NUM]; + AttributeDomain domains[ATTR_DOMAIN_NUM]; + get_domains_types(domains); + get_domains(id, info); + + int index = 0; + for (int i = 0; i < ATTR_DOMAIN_NUM; i++) { + if (!(domain_mask & (1 << domains[i])) || !info[domains[i]].customdata) { + continue; + } + + CustomData *cdata = info[domains[i]].customdata; + for (int j = 0; j < cdata->totlayer; j++) { + CustomDataLayer *layer_iter = cdata->layers + j; + + if (!(CD_TYPE_AS_MASK(layer_iter->type) & layer_mask) || + (CD_TYPE_AS_MASK(layer_iter->type) & CD_FLAG_TEMPORARY)) { + continue; + } + + if (layer == layer_iter) { + return index; + } + + index++; + } + } + + return -1; +} + +CustomDataLayer *BKE_id_attribute_subset_active_get(const ID *id, + int active_flag, + AttributeDomainMask domain_mask, + CustomDataMask mask) +{ + DomainInfo info[ATTR_DOMAIN_NUM]; + AttributeDomain domains[ATTR_DOMAIN_NUM]; + + get_domains_types(domains); + get_domains(id, info); + + CustomDataLayer *candidate = NULL; + for (int i = 0; i < ARRAY_SIZE(domains); i++) { + if (!((1 << domains[i]) & domain_mask) || !info[domains[i]].customdata) { + continue; + } + + CustomData *cdata = info[domains[i]].customdata; + + for (int j = 0; j < cdata->totlayer; j++) { + CustomDataLayer *layer = cdata->layers + j; + + if (!(CD_TYPE_AS_MASK(layer->type) & mask) || + (CD_TYPE_AS_MASK(layer->type) & CD_FLAG_TEMPORARY)) { + continue; + } + + if (layer->flag & active_flag) { + return layer; + } + + candidate = layer; + } + } + + return candidate; +} + +void BKE_id_attribute_subset_active_set(ID *id, + CustomDataLayer *layer, + int active_flag, + AttributeDomainMask domain_mask, + CustomDataMask mask) +{ + DomainInfo info[ATTR_DOMAIN_NUM]; + AttributeDomain domains[ATTR_DOMAIN_NUM]; + + get_domains_types(domains); + get_domains(id, info); + + for (int i = 0; i < ATTR_DOMAIN_NUM; i++) { + AttributeDomainMask domain_mask2 = (AttributeDomainMask)(1 << domains[i]); + + if (!(domain_mask2 & domain_mask) || !info[domains[i]].customdata) { + continue; + } + + CustomData *cdata = info[domains[i]].customdata; + + for (int j = 0; j < cdata->totlayer; j++) { + CustomDataLayer *layer_iter = cdata->layers + j; + + if (!(CD_TYPE_AS_MASK(layer_iter->type) & mask) || + (CD_TYPE_AS_MASK(layer_iter->type) & CD_FLAG_TEMPORARY)) { + continue; + } + + layer_iter->flag &= ~active_flag; + } + } + + layer->flag |= active_flag; +} + +CustomDataLayer *BKE_id_attributes_active_color_get(const ID *id) +{ + return BKE_id_attribute_subset_active_get( + id, CD_FLAG_COLOR_ACTIVE, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); +} + +void BKE_id_attributes_active_color_set(ID *id, CustomDataLayer *active_layer) +{ + BKE_id_attribute_subset_active_set( + id, active_layer, CD_FLAG_COLOR_ACTIVE, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); +} + +CustomDataLayer *BKE_id_attributes_render_color_get(const ID *id) +{ + return BKE_id_attribute_subset_active_get( + id, CD_FLAG_COLOR_RENDER, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); +} + +void BKE_id_attributes_render_color_set(ID *id, CustomDataLayer *active_layer) +{ + BKE_id_attribute_subset_active_set( + id, active_layer, CD_FLAG_COLOR_RENDER, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); +} + +void BKE_id_attribute_copy_domains_temp(short id_type, + const CustomData *vdata, + const CustomData *edata, + const CustomData *ldata, + const CustomData *pdata, + const CustomData *cdata, + ID *r_id) +{ + CustomData reset; + + CustomData_reset(&reset); + + switch (id_type) { + case ID_ME: { + Mesh *me = (Mesh *)r_id; + memset((void *)me, 0, sizeof(*me)); + + me->edit_mesh = NULL; + + me->vdata = vdata ? *vdata : reset; + me->edata = edata ? *edata : reset; + me->ldata = ldata ? *ldata : reset; + me->pdata = pdata ? *pdata : reset; + + break; + } + case ID_PT: { + PointCloud *pointcloud = (PointCloud *)r_id; + + memset((void *)pointcloud, 0, sizeof(*pointcloud)); + + pointcloud->pdata = vdata ? *vdata : reset; + break; + } + case ID_CV: { + Curves *curves = (Curves *)r_id; + + memset((void *)curves, 0, sizeof(*curves)); + + curves->geometry.point_data = vdata ? *vdata : reset; + curves->geometry.curve_data = cdata ? *cdata : reset; + break; + } + default: + break; + } + + *((short *)r_id->name) = id_type; +} diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 601c867d8db..b9cd9e1ee59 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1834,7 +1834,8 @@ void BKE_brush_sculpt_reset(Brush *br) br->tip_roundness = 1.0f; br->density = 1.0f; br->flag &= ~BRUSH_SPACE_ATTEN; - zero_v3(br->rgb); + copy_v3_fl(br->rgb, 1.0f); + zero_v3(br->secondary_rgb); break; case SCULPT_TOOL_SMEAR: br->alpha = 1.0f; diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 9258c1ffb66..6dd9460aaa9 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2279,7 +2279,8 @@ bool CustomData_merge(const struct CustomData *source, newlayer->active_rnd = lastrender; newlayer->active_clone = lastclone; newlayer->active_mask = lastmask; - newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY); + newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY | CD_FLAG_COLOR_ACTIVE | + CD_FLAG_COLOR_RENDER); changed = true; if (layer->anonymous_id != nullptr) { diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 5be993ca1f7..2369ce88ebc 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -19,6 +19,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BKE_attribute.h" #include "BKE_customdata.h" #include "BKE_data_transfer.h" #include "BKE_deform.h" @@ -129,7 +130,10 @@ bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types, case DT_TYPE_UV: ret = true; break; - case DT_TYPE_VCOL: + case DT_TYPE_MPROPCOL_VERT: + case DT_TYPE_MLOOPCOL_VERT: + case DT_TYPE_MPROPCOL_LOOP: + case DT_TYPE_MLOOPCOL_LOOP: *r_advanced_mixing = true; *r_threshold = true; ret = true; @@ -209,12 +213,14 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) return CD_FAKE_SHARP; case DT_TYPE_FREESTYLE_FACE: return CD_FREESTYLE_FACE; - - case DT_TYPE_VCOL: - return CD_MLOOPCOL; case DT_TYPE_LNOR: return CD_FAKE_LNOR; - + case DT_TYPE_MLOOPCOL_VERT: + case DT_TYPE_MLOOPCOL_LOOP: + return CD_MLOOPCOL; + case DT_TYPE_MPROPCOL_VERT: + case DT_TYPE_MPROPCOL_LOOP: + return CD_PROP_COLOR; default: BLI_assert(0); } @@ -230,8 +236,12 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type) return DT_MULTILAYER_INDEX_SHAPEKEY; case DT_TYPE_UV: return DT_MULTILAYER_INDEX_UV; - case DT_TYPE_VCOL: - return DT_MULTILAYER_INDEX_VCOL; + case DT_TYPE_MPROPCOL_VERT: + case DT_TYPE_MLOOPCOL_VERT: + return DT_MULTILAYER_INDEX_VCOL_VERT; + case DT_TYPE_MPROPCOL_LOOP: + case DT_TYPE_MLOOPCOL_LOOP: + return DT_MULTILAYER_INDEX_VCOL_LOOP; default: return DT_MULTILAYER_INDEX_INVALID; } @@ -1231,6 +1241,7 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); + if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { fromlayers = fromlayers_select[fromto_idx]; tolayers = tolayers_select[fromto_idx]; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index b30d8f92cc6..5afc3c0be3b 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -433,7 +433,7 @@ static const char *cmpcode_to_str(int code) case MESHCMP_DVERT_TOTGROUPMISMATCH: return "Vertex Doesn't Belong To Same Number Of Groups"; case MESHCMP_LOOPCOLMISMATCH: - return "Vertex Color Mismatch"; + return "Color Attribute Mismatch"; case MESHCMP_LOOPUVMISMATCH: return "UV Mismatch"; case MESHCMP_LOOPMISMATCH: diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1c58173f570..80c3ead3039 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "BKE_attribute.h" #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_colortools.h" @@ -1666,7 +1667,28 @@ static void sculpt_update_object(Depsgraph *depsgraph, ss->multires.modifier = NULL; ss->multires.level = 0; ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); - ss->vcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); + + CustomDataLayer *layer; + AttributeDomain domain; + + if (BKE_pbvh_get_color_layer(me, &layer, &domain)) { + if (layer->type == CD_PROP_COLOR) { + ss->vcol = layer->data; + } + else { + ss->mcol = layer->data; + } + + ss->vcol_domain = domain; + ss->vcol_type = layer->type; + } + else { + ss->vcol = NULL; + ss->mcol = NULL; + + ss->vcol_type = -1; + ss->vcol_domain = ATTR_DOMAIN_NUM; + } } /* Sculpt Face Sets. */ @@ -1692,6 +1714,10 @@ static void sculpt_update_object(Depsgraph *depsgraph, if (need_pmap && ob->type == OB_MESH && !ss->pmap) { BKE_mesh_vert_poly_map_create( &ss->pmap, &ss->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop); + + if (ss->pbvh) { + BKE_pbvh_pmap_set(ss->pbvh, ss->pmap); + } } pbvh_show_mask_set(ss->pbvh, ss->show_mask); @@ -1791,16 +1817,30 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) void BKE_sculpt_color_layer_create_if_needed(struct Object *object) { Mesh *orig_me = BKE_object_get_original_mesh(object); - if (!U.experimental.use_sculpt_vertex_colors) { - return; + + int types[] = {CD_PROP_COLOR, CD_MLOOPCOL}; + bool has_color = false; + + for (int i = 0; i < ARRAY_SIZE(types); i++) { + has_color = CustomData_has_layer(&orig_me->vdata, types[i]) || + CustomData_has_layer(&orig_me->ldata, types[i]); + + if (has_color) { + break; + } } - if (CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { + if (has_color) { return; } CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); + CustomDataLayer *layer = orig_me->vdata.layers + + CustomData_get_layer_index(&orig_me->vdata, CD_PROP_COLOR); + BKE_mesh_update_customdata_pointers(orig_me, true); + + BKE_id_attributes_active_color_set(&orig_me->id, layer); DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES); } @@ -2173,6 +2213,10 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob) BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg); } } + + BKE_pbvh_update_active_vcol(pbvh, BKE_object_get_original_mesh(ob)); + BKE_pbvh_pmap_set(pbvh, ob->sculpt->pmap); + return pbvh; } @@ -2192,6 +2236,8 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob) } } + BKE_pbvh_pmap_set(pbvh, ob->sculpt->pmap); + ob->sculpt->pbvh = pbvh; return pbvh; } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 3ed3c7badc3..5d307697208 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -17,8 +17,10 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BKE_attribute.h" #include "BKE_ccg.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_paint.h" #include "BKE_pbvh.h" #include "BKE_subdiv_ccg.h" @@ -599,6 +601,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, /* Clear the bitmap so it can be used as an update tag later on. */ BLI_bitmap_set_all(pbvh->vert_bitmap, false, totvert); + + BKE_pbvh_update_active_vcol(pbvh, mesh); } void BKE_pbvh_build_grids(PBVH *pbvh, @@ -667,6 +671,9 @@ void BKE_pbvh_free(PBVH *pbvh) if (node->vert_indices) { MEM_freeN((void *)node->vert_indices); } + if (node->loop_indices) { + MEM_freeN(node->loop_indices); + } if (node->face_vert_indices) { MEM_freeN((void *)node->face_vert_indices); } @@ -1254,6 +1261,30 @@ static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh)) return update_flags; } +bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, AttributeDomain *r_attr) +{ + CustomDataLayer *layer = BKE_id_attributes_active_color_get((ID *)me); + + if (!layer || !ELEM(layer->type, CD_PROP_COLOR, CD_MLOOPCOL)) { + *r_layer = NULL; + *r_attr = ATTR_DOMAIN_NUM; + return false; + } + + AttributeDomain domain = BKE_id_attribute_domain((ID *)me, layer); + + if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) { + *r_layer = NULL; + *r_attr = ATTR_DOMAIN_NUM; + return false; + } + + *r_layer = layer; + *r_attr = domain; + + return true; +} + static void pbvh_update_draw_buffer_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -1304,18 +1335,25 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, &pbvh->gridkey, update_flags); break; - case PBVH_FACES: + case PBVH_FACES: { + CustomDataLayer *layer = NULL; + AttributeDomain domain; + + BKE_pbvh_get_color_layer(pbvh->mesh, &layer, &domain); + GPU_pbvh_mesh_buffers_update(node->draw_buffers, pbvh->verts, pbvh->vert_normals, CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK), - CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL), + layer ? layer->data : NULL, + layer ? layer->type : -1, + layer ? domain : ATTR_DOMAIN_AUTO, CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), pbvh->face_sets_color_seed, pbvh->face_sets_color_default, - CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR), update_flags); break; + } case PBVH_BMESH: GPU_pbvh_bmesh_buffers_update(node->draw_buffers, pbvh->bm, @@ -1442,7 +1480,9 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag) } if (flag & (PBVH_UpdateColor)) { - /* Do nothing */ + for (int i = 0; i < totnode; i++) { + nodes[i]->flag |= PBVH_UpdateRedraw | PBVH_UpdateDrawBuffers | PBVH_UpdateColor; + } } if (flag & (PBVH_UpdateVisibility)) { @@ -1820,6 +1860,22 @@ void BKE_pbvh_vert_mark_update(PBVH *pbvh, int index) BLI_BITMAP_ENABLE(pbvh->vert_bitmap, index); } +void BKE_pbvh_node_get_loops(PBVH *pbvh, + PBVHNode *node, + const int **r_loop_indices, + const MLoop **r_loops) +{ + BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES); + + if (r_loop_indices) { + *r_loop_indices = node->loop_indices; + } + + if (r_loops) { + *r_loops = pbvh->mloop; + } +} + void BKE_pbvh_node_get_verts(PBVH *pbvh, PBVHNode *node, const int **r_vert_indices, @@ -2980,7 +3036,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m vi->vert_normals = pbvh->vert_normals; vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK); - vi->vcol = CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR); } } @@ -3072,3 +3127,81 @@ void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide) { pbvh->respect_hide = respect_hide; } +bool BKE_pbvh_is_drawing(const PBVH *pbvh) +{ + return pbvh->is_drawing; +} + +void BKE_pbvh_is_drawing_set(PBVH *pbvh, bool val) +{ + pbvh->is_drawing = val; +} + +void BKE_pbvh_node_num_loops(PBVH *pbvh, PBVHNode *node, int *r_totloop) +{ + UNUSED_VARS(pbvh); + BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES); + + if (r_totloop) { + *r_totloop = node->loop_indices_num; + } +} + +void BKE_pbvh_update_active_vcol(PBVH *pbvh, const Mesh *mesh) +{ + BKE_pbvh_get_color_layer(mesh, &pbvh->color_layer, &pbvh->color_domain); +} + +void BKE_pbvh_pmap_set(PBVH *pbvh, const MeshElemMap *pmap) +{ + pbvh->pmap = pmap; +} + +void BKE_pbvh_ensure_node_loops(PBVH *pbvh) +{ + BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES); + + int totloop = 0; + + /* Check if nodes already have loop indices. */ + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = pbvh->nodes + i; + + if (!(node->flag & PBVH_Leaf)) { + continue; + } + + if (node->loop_indices) { + return; + } + + totloop += node->totprim * 3; + } + + BLI_bitmap *visit = BLI_BITMAP_NEW(totloop, __func__); + + /* Create loop indices from node loop triangles. */ + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = pbvh->nodes + i; + + if (!(node->flag & PBVH_Leaf)) { + continue; + } + + node->loop_indices = MEM_malloc_arrayN(node->totprim * 3, sizeof(int), __func__); + node->loop_indices_num = 0; + + for (int j = 0; j < node->totprim; j++) { + const MLoopTri *mlt = pbvh->looptri + node->prim_indices[j]; + + for (int k = 0; k < 3; k++) { + if (!BLI_BITMAP_TEST(visit, mlt->tri[k])) { + node->loop_indices[node->loop_indices_num++] = mlt->tri[k]; + BLI_BITMAP_ENABLE(visit, mlt->tri[k]); + } + } + } + } + + MEM_SAFE_FREE(visit); +} diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc new file mode 100644 index 00000000000..d32a03186e3 --- /dev/null +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "BLI_bitmap.h" +#include "BLI_ghash.h" +#include "BLI_index_range.hh" +#include "BLI_math.h" +#include "BLI_rand.h" +#include "BLI_span.hh" +#include "BLI_task.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_attribute.h" +#include "BKE_ccg.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_paint.h" +#include "BKE_pbvh.h" +#include "BKE_subdiv_ccg.h" + +#include "PIL_time.h" + +#include "GPU_buffers.h" + +#include "bmesh.h" + +#include "atomic_ops.h" + +#include "pbvh_intern.h" + +#include <climits> + +using blender::IndexRange; + +namespace blender::bke { + +template<typename Func> +inline void to_static_color_type(const CustomDataType type, const Func &func) +{ + switch (type) { + case CD_PROP_COLOR: + func(MPropCol()); + break; + case CD_MLOOPCOL: + func(MLoopCol()); + break; + default: + BLI_assert_unreachable(); + break; + } +} + +template<typename T> void to_float(const T &src, float dst[4]); + +template<> void to_float(const MLoopCol &src, float dst[4]) +{ + rgba_uchar_to_float(dst, reinterpret_cast<const unsigned char *>(&src)); + srgb_to_linearrgb_v3_v3(dst, dst); +} +template<> void to_float(const MPropCol &src, float dst[4]) +{ + copy_v4_v4(dst, src.color); +} + +template<typename T> void from_float(const float src[4], T &dst); + +template<> void from_float(const float src[4], MLoopCol &dst) +{ + float temp[4]; + linearrgb_to_srgb_v3_v3(temp, src); + temp[3] = src[3]; + rgba_float_to_uchar(reinterpret_cast<unsigned char *>(&dst), temp); +} +template<> void from_float(const float src[4], MPropCol &dst) +{ + copy_v4_v4(dst.color, src); +} + +template<typename T> +static void pbvh_vertex_color_get(const PBVH &pbvh, int vertex, float r_color[4]) +{ + if (pbvh.color_domain == ATTR_DOMAIN_CORNER) { + const MeshElemMap &melem = pbvh.pmap[vertex]; + + int count = 0; + zero_v4(r_color); + for (const int i_poly : Span(melem.indices, melem.count)) { + const MPoly &mp = pbvh.mpoly[i_poly]; + Span<T> colors{static_cast<const T *>(pbvh.color_layer->data) + mp.loopstart, mp.totloop}; + Span<MLoop> loops{pbvh.mloop + mp.loopstart, mp.totloop}; + + for (const int i_loop : IndexRange(mp.totloop)) { + if (loops[i_loop].v == vertex) { + float temp[4]; + to_float(colors[i_loop], temp); + + add_v4_v4(r_color, temp); + count++; + } + } + } + + if (count) { + mul_v4_fl(r_color, 1.0f / (float)count); + } + } + else { + to_float(static_cast<T *>(pbvh.color_layer->data)[vertex], r_color); + } +} + +template<typename T> +static void pbvh_vertex_color_set(PBVH &pbvh, int vertex, const float color[4]) +{ + if (pbvh.color_domain == ATTR_DOMAIN_CORNER) { + const MeshElemMap &melem = pbvh.pmap[vertex]; + + for (const int i_poly : Span(melem.indices, melem.count)) { + const MPoly &mp = pbvh.mpoly[i_poly]; + MutableSpan<T> colors{static_cast<T *>(pbvh.color_layer->data) + mp.loopstart, mp.totloop}; + Span<MLoop> loops{pbvh.mloop + mp.loopstart, mp.totloop}; + + for (const int i_loop : IndexRange(mp.totloop)) { + if (loops[i_loop].v == vertex) { + from_float(color, colors[i_loop]); + } + } + } + } + else { + from_float(color, static_cast<T *>(pbvh.color_layer->data)[vertex]); + } +} + +} // namespace blender::bke + +extern "C" { +void BKE_pbvh_vertex_color_get(const PBVH *pbvh, int vertex, float r_color[4]) +{ + blender::bke::to_static_color_type(CustomDataType(pbvh->color_layer->type), [&](auto dummy) { + using T = decltype(dummy); + blender::bke::pbvh_vertex_color_get<T>(*pbvh, vertex, r_color); + }); +} + +void BKE_pbvh_vertex_color_set(PBVH *pbvh, int vertex, const float color[4]) +{ + blender::bke::to_static_color_type(CustomDataType(pbvh->color_layer->type), [&](auto dummy) { + using T = decltype(dummy); + blender::bke::pbvh_vertex_color_set<T>(*pbvh, vertex, color); + }); +} + +void BKE_pbvh_swap_colors(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*r_colors)[4]) +{ + blender::bke::to_static_color_type(CustomDataType(pbvh->color_layer->type), [&](auto dummy) { + using T = decltype(dummy); + T *pbvh_colors = static_cast<T *>(pbvh->color_layer->data); + for (const int i : IndexRange(indices_num)) { + T temp = pbvh_colors[indices[i]]; + blender::bke::from_float(r_colors[i], pbvh_colors[indices[i]]); + blender::bke::to_float(temp, r_colors[i]); + } + }); +} + +void BKE_pbvh_store_colors(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*r_colors)[4]) +{ + blender::bke::to_static_color_type(CustomDataType(pbvh->color_layer->type), [&](auto dummy) { + using T = decltype(dummy); + T *pbvh_colors = static_cast<T *>(pbvh->color_layer->data); + for (const int i : IndexRange(indices_num)) { + blender::bke::to_float(pbvh_colors[indices[i]], r_colors[i]); + } + }); +} + +void BKE_pbvh_store_colors_vertex(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*r_colors)[4]) +{ + if (pbvh->color_domain == ATTR_DOMAIN_POINT) { + BKE_pbvh_store_colors(pbvh, indices, indices_num, r_colors); + } + else { + blender::bke::to_static_color_type(CustomDataType(pbvh->color_layer->type), [&](auto dummy) { + using T = decltype(dummy); + for (const int i : IndexRange(indices_num)) { + blender::bke::pbvh_vertex_color_get<T>(*pbvh, indices[i], r_colors[i]); + } + }); + } +} +} diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index a10d09e106c..37f8dfd9b6b 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -16,6 +16,8 @@ typedef struct { float bmin[3], bmax[3], bcentroid[3]; } BBC; +struct MeshElemMap; + /* NOTE: this structure is getting large, might want to split it into * union'd structs */ struct PBVHNode { @@ -60,6 +62,13 @@ struct PBVHNode { const int *vert_indices; unsigned int uniq_verts, face_verts; + /* Array of indices into the Mesh's MLoop array. + * PBVH_FACES only. The first part of the array + * are loops unique to this node, see comment for + * vert_indices for more details.*/ + int *loop_indices; + unsigned int loop_indices_num; + /* An array mapping face corners into the vert_indices * array. The array is sized to match 'totprim', and each of * the face's corners gets an index into the vert_indices @@ -165,6 +174,13 @@ struct PBVH { struct BMLog *bm_log; struct SubdivCCG *subdiv_ccg; + + const struct MeshElemMap *pmap; + + CustomDataLayer *color_layer; + AttributeDomain color_domain; + + bool is_drawing; }; /* pbvh.c */ |