diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_attribute.h | 65 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_data_transfer.h | 41 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_pbvh.h | 54 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 1 | ||||
-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 |
14 files changed, 873 insertions, 49 deletions
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 452d6a4316e..f3968c0d761 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -34,10 +34,25 @@ typedef enum AttributeDomain { ATTR_DOMAIN_NUM } AttributeDomain; -/* Attributes */ +typedef enum AttributeDomainMask { + ATTR_DOMAIN_MASK_POINT = (1 << 0), + ATTR_DOMAIN_MASK_EDGE = (1 << 1), + ATTR_DOMAIN_MASK_FACE = (1 << 2), + ATTR_DOMAIN_MASK_CORNER = (1 << 3), + ATTR_DOMAIN_MASK_CURVE = (1 << 4), + ATTR_DOMAIN_MASK_ALL = (1 << 5) - 1 +} AttributeDomainMask; + +/* All domains that support color attributes. */ +#define ATTR_DOMAIN_MASK_COLOR \ + ((AttributeDomainMask)((ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_CORNER))) + +/* Attributes. */ bool BKE_id_attributes_supported(struct ID *id); +/** Create a new attribute layer. + */ struct CustomDataLayer *BKE_id_attribute_new( struct ID *id, const char *name, int type, AttributeDomain domain, struct ReportList *reports); bool BKE_id_attribute_remove(struct ID *id, @@ -49,7 +64,7 @@ struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id, int type, AttributeDomain domain); -AttributeDomain BKE_id_attribute_domain(struct ID *id, struct CustomDataLayer *layer); +AttributeDomain BKE_id_attribute_domain(struct ID *id, const struct CustomDataLayer *layer); int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer); bool BKE_id_attribute_required(struct ID *id, struct CustomDataLayer *layer); bool BKE_id_attribute_rename(struct ID *id, @@ -57,13 +72,57 @@ bool BKE_id_attribute_rename(struct ID *id, const char *new_name, struct ReportList *reports); -int BKE_id_attributes_length(struct ID *id, CustomDataMask mask); +int BKE_id_attributes_length(const struct ID *id, + AttributeDomainMask domain_mask, + CustomDataMask mask); struct CustomDataLayer *BKE_id_attributes_active_get(struct ID *id); void BKE_id_attributes_active_set(struct ID *id, struct CustomDataLayer *layer); int *BKE_id_attributes_active_index_p(struct ID *id); CustomData *BKE_id_attributes_iterator_next_domain(struct ID *id, struct CustomDataLayer *layers); +CustomDataLayer *BKE_id_attribute_from_index(struct ID *id, + int lookup_index, + AttributeDomainMask domain_mask, + CustomDataMask layer_mask); + +/** Layer is allowed to be nullptr; if so -1 (layer not found) will be returned. */ +int BKE_id_attribute_to_index(const struct ID *id, + const CustomDataLayer *layer, + AttributeDomainMask domain_mask, + CustomDataMask layer_mask); + +struct CustomDataLayer *BKE_id_attribute_subset_active_get(const struct ID *id, + int active_flag, + AttributeDomainMask domain_mask, + CustomDataMask mask); +void BKE_id_attribute_subset_active_set(struct ID *id, + struct CustomDataLayer *layer, + int active_flag, + AttributeDomainMask domain_mask, + CustomDataMask mask); + +/** + * Sets up a temporary ID with arbitrary CustomData domains. r_id will + * be zero initialized with ID type id_type and any non-nullptr + * CustomData parameter will be copied into the appropriate struct members. + * + * \param r_id Pointer to storage sufficient for ID typecode id_type. + */ +void BKE_id_attribute_copy_domains_temp(short id_type, + const struct CustomData *vdata, + const struct CustomData *edata, + const struct CustomData *ldata, + const struct CustomData *pdata, + const struct CustomData *cdata, + struct ID *r_id); + +struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID *id); +void BKE_id_attributes_active_color_set(struct ID *id, struct CustomDataLayer *active_layer); +struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID *id); +void BKE_id_attributes_render_color_set(struct ID *id, struct CustomDataLayer *active_layer); + +bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index fcf84edeb23..1b6c1dc4205 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -8,6 +8,7 @@ #pragma once #include "BKE_customdata.h" +#include "BLI_compiler_compat.h" #ifdef __cplusplus extern "C" { @@ -32,18 +33,23 @@ enum { DT_TYPE_BWEIGHT_EDGE = 1 << 11, DT_TYPE_FREESTYLE_EDGE = 1 << 12, - DT_TYPE_VCOL = 1 << 16, + DT_TYPE_MPROPCOL_VERT = 1 << 16, DT_TYPE_LNOR = 1 << 17, DT_TYPE_UV = 1 << 24, DT_TYPE_SHARP_FACE = 1 << 25, DT_TYPE_FREESTYLE_FACE = 1 << 26, -#define DT_TYPE_MAX 27 - - DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT, + DT_TYPE_MLOOPCOL_VERT = 1 << 27, + DT_TYPE_MPROPCOL_LOOP = 1 << 28, + DT_TYPE_MLOOPCOL_LOOP = 1 << 29, + DT_TYPE_VCOL_ALL = (1 << 16) | (1 << 27) | (1 << 28) | (1 << 29), +#define DT_TYPE_MAX 30 + + DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT | + DT_TYPE_MPROPCOL_VERT | DT_TYPE_MLOOPCOL_VERT, DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_FREESTYLE_EDGE, - DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV, + DT_TYPE_LOOP_ALL = DT_TYPE_LNOR | DT_TYPE_UV | DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP, DT_TYPE_POLY_ALL = DT_TYPE_UV | DT_TYPE_SHARP_FACE | DT_TYPE_FREESTYLE_FACE, }; @@ -62,7 +68,13 @@ int BKE_object_data_transfer_dttype_to_cdtype(int dtdata_type); int BKE_object_data_transfer_dttype_to_srcdst_index(int dtdata_type); #define DT_DATATYPE_IS_VERT(_dt) \ - ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT) + ELEM(_dt, \ + DT_TYPE_MDEFORMVERT, \ + DT_TYPE_SHAPEKEY, \ + DT_TYPE_SKIN, \ + DT_TYPE_BWEIGHT_VERT, \ + DT_TYPE_MLOOPCOL_VERT, \ + DT_TYPE_MPROPCOL_VERT) #define DT_DATATYPE_IS_EDGE(_dt) \ ELEM(_dt, \ DT_TYPE_CREASE, \ @@ -70,19 +82,28 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(int dtdata_type); DT_TYPE_SEAM, \ DT_TYPE_BWEIGHT_EDGE, \ DT_TYPE_FREESTYLE_EDGE) -#define DT_DATATYPE_IS_LOOP(_dt) ELEM(_dt, DT_TYPE_UV, DT_TYPE_VCOL, DT_TYPE_LNOR) +#define DT_DATATYPE_IS_LOOP(_dt) \ + ELEM(_dt, DT_TYPE_UV, DT_TYPE_LNOR, DT_TYPE_MLOOPCOL_LOOP, DT_TYPE_MPROPCOL_LOOP) #define DT_DATATYPE_IS_POLY(_dt) ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE) #define DT_DATATYPE_IS_MULTILAYERS(_dt) \ - ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_VCOL, DT_TYPE_UV) + ELEM(_dt, \ + DT_TYPE_MDEFORMVERT, \ + DT_TYPE_SHAPEKEY, \ + DT_TYPE_MPROPCOL_VERT, \ + DT_TYPE_MLOOPCOL_VERT, \ + DT_TYPE_MPROPCOL_LOOP, \ + DT_TYPE_MLOOPCOL_LOOP, \ + DT_TYPE_UV) enum { DT_MULTILAYER_INDEX_INVALID = -1, DT_MULTILAYER_INDEX_MDEFORMVERT = 0, DT_MULTILAYER_INDEX_SHAPEKEY = 1, - DT_MULTILAYER_INDEX_VCOL = 2, + DT_MULTILAYER_INDEX_VCOL_LOOP = 2, DT_MULTILAYER_INDEX_UV = 3, - DT_MULTILAYER_INDEX_MAX = 4, + DT_MULTILAYER_INDEX_VCOL_VERT = 4, + DT_MULTILAYER_INDEX_MAX = 5, }; /* Below we keep positive values for real layers idx (generated dynamically). */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 8ab89b6c244..5633c476dc1 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -12,6 +12,8 @@ #include "DNA_brush_enums.h" #include "DNA_object_enums.h" +#include "BKE_attribute.h" + #ifdef __cplusplus extern "C" { #endif @@ -493,6 +495,11 @@ typedef struct SculptSession { struct KeyBlock *shapekey_active; struct MPropCol *vcol; + struct MLoopCol *mcol; + + AttributeDomain vcol_domain; + CustomDataType vcol_type; + float *vmask; /* Mesh connectivity maps. */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index eadbe52d091..775847f27f8 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -11,6 +11,7 @@ #include "BLI_ghash.h" /* For embedding CCGKey in iterator. */ +#include "BKE_attribute.h" #include "BKE_ccg.h" #ifdef __cplusplus @@ -34,6 +35,7 @@ struct PBVH; struct PBVHNode; struct SubdivCCG; struct TaskParallelSettings; +struct MeshElemMap; typedef struct PBVH PBVH; typedef struct PBVHNode PBVHNode; @@ -299,6 +301,10 @@ void BKE_pbvh_node_get_verts(PBVH *pbvh, PBVHNode *node, const int **r_vert_indices, struct MVert **r_verts); +void BKE_pbvh_node_get_loops(PBVH *pbvh, + PBVHNode *node, + const int **r_loop_indices, + const struct MLoop **r_loops); void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]); void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]); @@ -388,7 +394,6 @@ typedef struct PBVHVertexIter { float (*vert_normals)[3]; int totvert; const int *vert_indices; - struct MPropCol *vcol; float *vmask; /* bmesh */ @@ -405,7 +410,6 @@ typedef struct PBVHVertexIter { float *no; float *fno; float *mask; - float *col; bool visible; } PBVHVertexIter; @@ -461,17 +465,14 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m if (vi.vmask) { \ vi.mask = &vi.vmask[vi.index]; \ } \ - if (vi.vcol) { \ - vi.col = vi.vcol[vi.index].color; \ - } \ } \ else { \ if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \ - vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \ + vi.bm_vert = (BMVert *)BLI_gsetIterator_getKey(&vi.bm_unique_verts); \ BLI_gsetIterator_step(&vi.bm_unique_verts); \ } \ else { \ - vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \ + vi.bm_vert = (BMVert *)BLI_gsetIterator_getKey(&vi.bm_other_verts); \ BLI_gsetIterator_step(&vi.bm_other_verts); \ } \ vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \ @@ -481,7 +482,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m vi.co = vi.bm_vert->co; \ vi.fno = vi.bm_vert->no; \ vi.index = BM_elem_index_get(vi.bm_vert); \ - vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \ + vi.mask = (float *)BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \ } #define BKE_pbvh_vertex_iter_end \ @@ -526,6 +527,43 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]; PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node); void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); +bool BKE_pbvh_get_color_layer(const struct Mesh *me, + CustomDataLayer **r_layer, + AttributeDomain *r_attr); + +/* Swaps colors at each element in indices (of domain pbvh->vcol_domain) + * with values in colors. */ +void BKE_pbvh_swap_colors(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*colors)[4]); + +/* Stores colors from the elements in indices (of domain pbvh->vcol_domain) + * into colors. */ +void BKE_pbvh_store_colors(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*colors)[4]); + +/* Like BKE_pbvh_store_colors but handles loop->vert conversion */ +void BKE_pbvh_store_colors_vertex(PBVH *pbvh, + const int *indices, + const int indices_num, + float (*colors)[4]); + +bool BKE_pbvh_is_drawing(const PBVH *pbvh); +void BKE_pbvh_is_drawing_set(PBVH *pbvh, bool val); + +/* Do not call in PBVH_GRIDS mode */ +void BKE_pbvh_node_num_loops(PBVH *pbvh, PBVHNode *node, int *r_totloop); + +void BKE_pbvh_update_active_vcol(PBVH *pbvh, const struct Mesh *mesh); +void BKE_pbvh_pmap_set(PBVH *pbvh, const struct MeshElemMap *pmap); + +void BKE_pbvh_vertex_color_set(PBVH *pbvh, int vertex, const float color[4]); +void BKE_pbvh_vertex_color_get(const PBVH *pbvh, int vertex, float r_color[4]); + +void BKE_pbvh_ensure_node_loops(PBVH *pbvh); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c60d708c075..61131cff06d 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -239,6 +239,7 @@ set(SRC intern/particle_child.c intern/particle_distribute.c intern/particle_system.c + intern/pbvh.cc intern/pbvh.c intern/pbvh_bmesh.c intern/pointcache.c 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 */ |