From f4df036bc497b134789b624efd9008c6f4b9c6c8 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 14 Dec 2020 16:14:21 +0100 Subject: Cryptomatte: Data structure in compositor node This changes the way how the mattes are stored in the compositor node. This used to be a single string what was decoded/encoded when needed. The new data structure stores all entries in `CryptomatteEntry` and is converted to the old `matte_id` property on the fly. This is done for some future changes in the workflow where a more structured approach leads to less confusing and easier to read code. --- .../composite/nodes/node_composite_cryptomatte.c | 178 +++------------------ 1 file changed, 18 insertions(+), 160 deletions(-) (limited to 'source/blender/nodes') diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c index c8d2d993e75..f5308fe2671 100644 --- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c @@ -27,172 +27,36 @@ #include "BLI_utildefines.h" #include "node_composite_util.h" -/* this is taken from the cryptomatte specification 1.0 */ - -BLI_INLINE float hash_to_float(uint32_t hash) +static CryptomatteEntry *cryptomatte_find(NodeCryptomatte *n, float encoded_hash) { - uint32_t mantissa = hash & ((1 << 23) - 1); - uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); - exponent = MAX2(exponent, (uint32_t)1); - exponent = MIN2(exponent, (uint32_t)254); - exponent = exponent << 23; - uint32_t sign = (hash >> 31); - sign = sign << 31; - uint32_t float_bits = sign | exponent | mantissa; - float f; - /* Bit casting relies on equal size for both types. */ - BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size") - memcpy(&f, &float_bits, sizeof(float)); - return f; + LISTBASE_FOREACH (CryptomatteEntry *, entry, &n->entries) { + if (entry->encoded_hash == encoded_hash) { + return entry; + } + } + return NULL; } static void cryptomatte_add(NodeCryptomatte *n, float f) { - /* Turn the number into a string. */ - char number[32]; - BLI_snprintf(number, sizeof(number), "<%.9g>", f); - - /* Search if we already have the number. */ - if (n->matte_id && strlen(n->matte_id) != 0) { - size_t start = 0; - const size_t end = strlen(n->matte_id); - size_t token_len = 0; - while (start < end) { - /* Ignore leading whitespace. */ - while (start < end && n->matte_id[start] == ' ') { - start++; - } - - /* Find the next separator. */ - char *token_end = strchr(n->matte_id + start, ','); - if (ELEM(token_end, NULL, n->matte_id + start)) { - token_end = n->matte_id + end; - } - /* Be aware that token_len still contains any trailing white space. */ - token_len = token_end - (n->matte_id + start); - - /* If this has a leading bracket, - * assume a raw floating point number and look for the closing bracket. */ - if (n->matte_id[start] == '<') { - if (strncmp(n->matte_id + start, number, strlen(number)) == 0) { - /* This number is already there, so continue. */ - return; - } - } - else { - /* Remove trailing white space */ - size_t name_len = token_len; - while (n->matte_id[start + name_len] == ' ' && name_len > 0) { - name_len--; - } - /* Calculate the hash of the token and compare. */ - uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0); - if (f == hash_to_float(hash)) { - return; - } - } - start += token_len + 1; - } - } - - DynStr *new_matte = BLI_dynstr_new(); - if (!new_matte) { + /* Check if entry already exist. */ + if (cryptomatte_find(n, f) != NULL) { return; } - - if (n->matte_id) { - BLI_dynstr_append(new_matte, n->matte_id); - MEM_freeN(n->matte_id); - } - - if (BLI_dynstr_get_len(new_matte) > 0) { - BLI_dynstr_append(new_matte, ","); - } - BLI_dynstr_append(new_matte, number); - n->matte_id = BLI_dynstr_get_cstring(new_matte); - BLI_dynstr_free(new_matte); + CryptomatteEntry *entry = MEM_callocN(sizeof(CryptomatteEntry), __func__); + entry->encoded_hash = f; + BLI_addtail(&n->entries, entry); } static void cryptomatte_remove(NodeCryptomatte *n, float f) { - if (n->matte_id == NULL || strlen(n->matte_id) == 0) { - /* Empty string, nothing to remove. */ + CryptomatteEntry *entry = cryptomatte_find(n, f); + if (entry == NULL) { return; } - /* This will be the new string without the removed key. */ - DynStr *new_matte = BLI_dynstr_new(); - if (!new_matte) { - return; - } - - /* Turn the number into a string. */ - static char number[32]; - BLI_snprintf(number, sizeof(number), "<%.9g>", f); - - /* Search if we already have the number. */ - size_t start = 0; - const size_t end = strlen(n->matte_id); - size_t token_len = 0; - bool is_first = true; - while (start < end) { - bool skip = false; - /* Ignore leading whitespace or commas. */ - while (start < end && ((n->matte_id[start] == ' ') || (n->matte_id[start] == ','))) { - start++; - } - - /* Find the next separator. */ - char *token_end = strchr(n->matte_id + start + 1, ','); - if (ELEM(token_end, NULL, n->matte_id + start)) { - token_end = n->matte_id + end; - } - /* Be aware that token_len still contains any trailing white space. */ - token_len = token_end - (n->matte_id + start); - - if (token_len == 1) { - skip = true; - } - /* If this has a leading bracket, - * assume a raw floating point number and look for the closing bracket. */ - else if (n->matte_id[start] == '<') { - if (strncmp(n->matte_id + start, number, strlen(number)) == 0) { - /* This number is already there, so skip it. */ - skip = true; - } - } - else { - /* Remove trailing white space */ - size_t name_len = token_len; - while (n->matte_id[start + name_len] == ' ' && name_len > 0) { - name_len--; - } - /* Calculate the hash of the token and compare. */ - uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0); - if (f == hash_to_float(hash)) { - skip = true; - } - } - if (!skip) { - if (is_first) { - is_first = false; - } - else { - BLI_dynstr_append(new_matte, ", "); - } - BLI_dynstr_nappend(new_matte, n->matte_id + start, token_len); - } - start += token_len + 1; - } - - if (n->matte_id) { - MEM_freeN(n->matte_id); - n->matte_id = NULL; - } - if (BLI_dynstr_get_len(new_matte) > 0) { - n->matte_id = BLI_dynstr_get_cstring(new_matte); - } - BLI_dynstr_free(new_matte); + BLI_remlink(&n->entries, entry); + MEM_freeN(entry); } static bNodeSocketTemplate outputs[] = { @@ -265,10 +129,7 @@ static void node_free_cryptomatte(bNode *node) NodeCryptomatte *nc = node->storage; if (nc) { - if (nc->matte_id) { - MEM_freeN(nc->matte_id); - } - + BLI_freelistN(&nc->entries); MEM_freeN(nc); } } @@ -280,10 +141,7 @@ static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree), NodeCryptomatte *src_nc = src_node->storage; NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc); - if (src_nc->matte_id) { - dest_nc->matte_id = MEM_dupallocN(src_nc->matte_id); - } - + BLI_duplicatelist(&dest_nc->entries, &src_nc->entries); dest_node->storage = dest_nc; } -- cgit v1.2.3