diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/blenlib/intern | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/blenlib/intern')
91 files changed, 35027 insertions, 34248 deletions
diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index 61619bc114b..8f282373cf5 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -37,267 +37,288 @@ static char NO_DOCS[] = "NO DOCUMENTATION SPECIFIED"; struct bArgDoc; typedef struct bArgDoc { - struct bArgDoc *next, *prev; - const char *short_arg; - const char *long_arg; - const char *documentation; - bool done; + struct bArgDoc *next, *prev; + const char *short_arg; + const char *long_arg; + const char *documentation; + bool done; } bArgDoc; typedef struct bAKey { - const char *arg; - uintptr_t pass; /* cast easier */ - int case_str; /* case specific or not */ + const char *arg; + uintptr_t pass; /* cast easier */ + int case_str; /* case specific or not */ } bAKey; typedef struct bArgument { - bAKey *key; - BA_ArgCallback func; - void *data; - bArgDoc *doc; + bAKey *key; + BA_ArgCallback func; + void *data; + bArgDoc *doc; } bArgument; struct bArgs { - ListBase docs; - GHash *items; - int argc; - const char **argv; - int *passes; + ListBase docs; + GHash *items; + int argc; + const char **argv; + int *passes; }; static uint case_strhash(const void *ptr) { - const char *s = ptr; - uint i = 0; - unsigned char c; + const char *s = ptr; + uint i = 0; + unsigned char c; - while ((c = tolower(*s++))) { - i = i * 37 + c; - } + while ((c = tolower(*s++))) { + i = i * 37 + c; + } - return i; + return i; } static uint keyhash(const void *ptr) { - const bAKey *k = ptr; - return case_strhash(k->arg); /* ^ BLI_ghashutil_inthash((void *)k->pass); */ + const bAKey *k = ptr; + return case_strhash(k->arg); /* ^ BLI_ghashutil_inthash((void *)k->pass); */ } static bool keycmp(const void *a, const void *b) { - const bAKey *ka = a; - const bAKey *kb = b; - if (ka->pass == kb->pass || ka->pass == -1 || kb->pass == -1) { /* -1 is wildcard for pass */ - if (ka->case_str == 1 || kb->case_str == 1) { - return (BLI_strcasecmp(ka->arg, kb->arg) != 0); - } - else { - return (!STREQ(ka->arg, kb->arg)); - } - } - else { - return BLI_ghashutil_intcmp((const void *)ka->pass, (const void *)kb->pass); - } + const bAKey *ka = a; + const bAKey *kb = b; + if (ka->pass == kb->pass || ka->pass == -1 || kb->pass == -1) { /* -1 is wildcard for pass */ + if (ka->case_str == 1 || kb->case_str == 1) { + return (BLI_strcasecmp(ka->arg, kb->arg) != 0); + } + else { + return (!STREQ(ka->arg, kb->arg)); + } + } + else { + return BLI_ghashutil_intcmp((const void *)ka->pass, (const void *)kb->pass); + } } static bArgument *lookUp(struct bArgs *ba, const char *arg, int pass, int case_str) { - bAKey key; + bAKey key; - key.case_str = case_str; - key.pass = pass; - key.arg = arg; + key.case_str = case_str; + key.pass = pass; + key.arg = arg; - return BLI_ghash_lookup(ba->items, &key); + return BLI_ghash_lookup(ba->items, &key); } bArgs *BLI_argsInit(int argc, const char **argv) { - bArgs *ba = MEM_callocN(sizeof(bArgs), "bArgs"); - ba->passes = MEM_callocN(sizeof(int) * argc, "bArgs passes"); - ba->items = BLI_ghash_new(keyhash, keycmp, "bArgs passes gh"); - BLI_listbase_clear(&ba->docs); - ba->argc = argc; - ba->argv = argv; - - return ba; + bArgs *ba = MEM_callocN(sizeof(bArgs), "bArgs"); + ba->passes = MEM_callocN(sizeof(int) * argc, "bArgs passes"); + ba->items = BLI_ghash_new(keyhash, keycmp, "bArgs passes gh"); + BLI_listbase_clear(&ba->docs); + ba->argc = argc; + ba->argv = argv; + + return ba; } void BLI_argsFree(struct bArgs *ba) { - BLI_ghash_free(ba->items, MEM_freeN, MEM_freeN); - MEM_freeN(ba->passes); - BLI_freelistN(&ba->docs); - MEM_freeN(ba); + BLI_ghash_free(ba->items, MEM_freeN, MEM_freeN); + MEM_freeN(ba->passes); + BLI_freelistN(&ba->docs); + MEM_freeN(ba); } void BLI_argsPrint(struct bArgs *ba) { - int i; - for (i = 0; i < ba->argc; i++) { - printf("argv[%d] = %s\n", i, ba->argv[i]); - } + int i; + for (i = 0; i < ba->argc; i++) { + printf("argv[%d] = %s\n", i, ba->argv[i]); + } } const char **BLI_argsArgv(struct bArgs *ba) { - return ba->argv; + return ba->argv; } -static bArgDoc *internalDocs(struct bArgs *ba, const char *short_arg, const char *long_arg, const char *doc) +static bArgDoc *internalDocs(struct bArgs *ba, + const char *short_arg, + const char *long_arg, + const char *doc) { - bArgDoc *d; + bArgDoc *d; - d = MEM_callocN(sizeof(bArgDoc), "bArgDoc"); + d = MEM_callocN(sizeof(bArgDoc), "bArgDoc"); - if (doc == NULL) { - doc = NO_DOCS; - } + if (doc == NULL) { + doc = NO_DOCS; + } - d->short_arg = short_arg; - d->long_arg = long_arg; - d->documentation = doc; + d->short_arg = short_arg; + d->long_arg = long_arg; + d->documentation = doc; - BLI_addtail(&ba->docs, d); + BLI_addtail(&ba->docs, d); - return d; + return d; } -static void internalAdd(struct bArgs *ba, const char *arg, int pass, - int case_str, BA_ArgCallback cb, void *data, bArgDoc *d) +static void internalAdd(struct bArgs *ba, + const char *arg, + int pass, + int case_str, + BA_ArgCallback cb, + void *data, + bArgDoc *d) { - bArgument *a; - bAKey *key; - - a = lookUp(ba, arg, pass, case_str); - - if (a) { - printf("WARNING: conflicting argument\n"); - printf("\ttrying to add '%s' on pass %i, %scase sensitive\n", - arg, pass, case_str == 1 ? "not " : ""); - printf("\tconflict with '%s' on pass %i, %scase sensitive\n\n", - a->key->arg, (int)a->key->pass, a->key->case_str == 1 ? "not " : ""); - } - - a = MEM_callocN(sizeof(bArgument), "bArgument"); - key = MEM_callocN(sizeof(bAKey), "bAKey"); - - key->arg = arg; - key->pass = pass; - key->case_str = case_str; - - a->key = key; - a->func = cb; - a->data = data; - a->doc = d; - - BLI_ghash_insert(ba->items, key, a); + bArgument *a; + bAKey *key; + + a = lookUp(ba, arg, pass, case_str); + + if (a) { + printf("WARNING: conflicting argument\n"); + printf("\ttrying to add '%s' on pass %i, %scase sensitive\n", + arg, + pass, + case_str == 1 ? "not " : ""); + printf("\tconflict with '%s' on pass %i, %scase sensitive\n\n", + a->key->arg, + (int)a->key->pass, + a->key->case_str == 1 ? "not " : ""); + } + + a = MEM_callocN(sizeof(bArgument), "bArgument"); + key = MEM_callocN(sizeof(bAKey), "bAKey"); + + key->arg = arg; + key->pass = pass; + key->case_str = case_str; + + a->key = key; + a->func = cb; + a->data = data; + a->doc = d; + + BLI_ghash_insert(ba->items, key, a); } -void BLI_argsAddCase(struct bArgs *ba, int pass, - const char *short_arg, int short_case, - const char *long_arg, int long_case, - const char *doc, BA_ArgCallback cb, void *data) +void BLI_argsAddCase(struct bArgs *ba, + int pass, + const char *short_arg, + int short_case, + const char *long_arg, + int long_case, + const char *doc, + BA_ArgCallback cb, + void *data) { - bArgDoc *d = internalDocs(ba, short_arg, long_arg, doc); + bArgDoc *d = internalDocs(ba, short_arg, long_arg, doc); - if (short_arg) { - internalAdd(ba, short_arg, pass, short_case, cb, data, d); - } + if (short_arg) { + internalAdd(ba, short_arg, pass, short_case, cb, data, d); + } - if (long_arg) { - internalAdd(ba, long_arg, pass, long_case, cb, data, d); - } + if (long_arg) { + internalAdd(ba, long_arg, pass, long_case, cb, data, d); + } } -void BLI_argsAdd(struct bArgs *ba, int pass, - const char *short_arg, const char *long_arg, - const char *doc, BA_ArgCallback cb, void *data) +void BLI_argsAdd(struct bArgs *ba, + int pass, + const char *short_arg, + const char *long_arg, + const char *doc, + BA_ArgCallback cb, + void *data) { - BLI_argsAddCase(ba, pass, short_arg, 0, long_arg, 0, doc, cb, data); + BLI_argsAddCase(ba, pass, short_arg, 0, long_arg, 0, doc, cb, data); } static void internalDocPrint(bArgDoc *d) { - if (d->short_arg && d->long_arg) { - printf("%s or %s", d->short_arg, d->long_arg); - } - else if (d->short_arg) { - printf("%s", d->short_arg); - } - else if (d->long_arg) { - printf("%s", d->long_arg); - } - - printf(" %s\n\n", d->documentation); + if (d->short_arg && d->long_arg) { + printf("%s or %s", d->short_arg, d->long_arg); + } + else if (d->short_arg) { + printf("%s", d->short_arg); + } + else if (d->long_arg) { + printf("%s", d->long_arg); + } + + printf(" %s\n\n", d->documentation); } void BLI_argsPrintArgDoc(struct bArgs *ba, const char *arg) { - bArgument *a = lookUp(ba, arg, -1, -1); + bArgument *a = lookUp(ba, arg, -1, -1); - if (a) { - bArgDoc *d = a->doc; + if (a) { + bArgDoc *d = a->doc; - internalDocPrint(d); + internalDocPrint(d); - d->done = true; - } + d->done = true; + } } void BLI_argsPrintOtherDoc(struct bArgs *ba) { - bArgDoc *d; + bArgDoc *d; - for (d = ba->docs.first; d; d = d->next) { - if (d->done == 0) { - internalDocPrint(d); - } - } + for (d = ba->docs.first; d; d = d->next) { + if (d->done == 0) { + internalDocPrint(d); + } + } } void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *default_data) { - int i = 0; - - for (i = 1; i < ba->argc; i++) { /* skip argv[0] */ - if (ba->passes[i] == 0) { - /* -1 signal what side of the comparison it is */ - bArgument *a = lookUp(ba, ba->argv[i], pass, -1); - BA_ArgCallback func = NULL; - void *data = NULL; - - if (a) { - func = a->func; - data = a->data; - } - else { - func = default_cb; - data = default_data; - } - - if (func) { - int retval = func(ba->argc - i, ba->argv + i, data); - - if (retval >= 0) { - int j; - - /* use extra arguments */ - for (j = 0; j <= retval; j++) { - ba->passes[i + j] = pass; - } - i += retval; - } - else if (retval == -1) { - if (a) { - if (a->key->pass != -1) { - ba->passes[i] = pass; - } - } - break; - } - } - } - } + int i = 0; + + for (i = 1; i < ba->argc; i++) { /* skip argv[0] */ + if (ba->passes[i] == 0) { + /* -1 signal what side of the comparison it is */ + bArgument *a = lookUp(ba, ba->argv[i], pass, -1); + BA_ArgCallback func = NULL; + void *data = NULL; + + if (a) { + func = a->func; + data = a->data; + } + else { + func = default_cb; + data = default_data; + } + + if (func) { + int retval = func(ba->argc - i, ba->argv + i, data); + + if (retval >= 0) { + int j; + + /* use extra arguments */ + for (j = 0; j <= retval; j++) { + ba->passes[i + j] = pass; + } + i += retval; + } + else if (retval == -1) { + if (a) { + if (a->key->pass != -1) { + ba->passes[i] = pass; + } + } + break; + } + } + } + } } diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c index 6c22b128f5c..7a9cf416d91 100644 --- a/source/blender/blenlib/intern/BLI_array.c +++ b/source/blender/blenlib/intern/BLI_array.c @@ -59,26 +59,26 @@ * * \note The caller must adjust \a arr_len */ -void _bli_array_grow_func( - void **arr_p, const void *arr_static, - const int sizeof_arr_p, const int arr_len, const int num, - const char *alloc_str) +void _bli_array_grow_func(void **arr_p, + const void *arr_static, + const int sizeof_arr_p, + const int arr_len, + const int num, + const char *alloc_str) { - void *arr = *arr_p; - void *arr_tmp; + void *arr = *arr_p; + void *arr_tmp; - arr_tmp = MEM_mallocN( - sizeof_arr_p * - ((num < arr_len) ? - (arr_len * 2 + 2) : (arr_len + num)), alloc_str); + arr_tmp = MEM_mallocN(sizeof_arr_p * ((num < arr_len) ? (arr_len * 2 + 2) : (arr_len + num)), + alloc_str); - if (arr) { - memcpy(arr_tmp, arr, sizeof_arr_p * arr_len); + if (arr) { + memcpy(arr_tmp, arr, sizeof_arr_p * arr_len); - if (arr != arr_static) { - MEM_freeN(arr); - } - } + if (arr != arr_static) { + MEM_freeN(arr); + } + } - *arr_p = arr_tmp; + *arr_p = arr_tmp; } diff --git a/source/blender/blenlib/intern/BLI_dial_2d.c b/source/blender/blenlib/intern/BLI_dial_2d.c index dd983fe7f8f..c6d28e20f35 100644 --- a/source/blender/blenlib/intern/BLI_dial_2d.c +++ b/source/blender/blenlib/intern/BLI_dial_2d.c @@ -24,81 +24,78 @@ #include "MEM_guardedalloc.h" struct Dial { - /* center of the dial */ - float center[2]; + /* center of the dial */ + float center[2]; - /* threshold of the dial. Distance of current position has to be greater - * than the threshold to be used in any calculations */ - float threshold_squared; + /* threshold of the dial. Distance of current position has to be greater + * than the threshold to be used in any calculations */ + float threshold_squared; - /* the direction of the first dial position exceeding the threshold. This - * is later used as the basis against which rotation angle is calculated */ - float initial_direction[2]; + /* the direction of the first dial position exceeding the threshold. This + * is later used as the basis against which rotation angle is calculated */ + float initial_direction[2]; - /* cache the last angle to detect rotations bigger than -/+ PI */ - float last_angle; + /* cache the last angle to detect rotations bigger than -/+ PI */ + float last_angle; - /* number of full rotations */ - int rotations; + /* number of full rotations */ + int rotations; - /* has initial_direction been initialized */ - bool initialized; + /* has initial_direction been initialized */ + bool initialized; }; - Dial *BLI_dial_initialize(const float start_position[2], float threshold) { - Dial *dial = MEM_callocN(sizeof(Dial), "dial"); + Dial *dial = MEM_callocN(sizeof(Dial), "dial"); - copy_v2_v2(dial->center, start_position); - dial->threshold_squared = threshold * threshold; + copy_v2_v2(dial->center, start_position); + dial->threshold_squared = threshold * threshold; - return dial; + return dial; } float BLI_dial_angle(Dial *dial, const float current_position[2]) { - float current_direction[2]; - - sub_v2_v2v2(current_direction, current_position, dial->center); - - /* only update when we have enough precision, - * by having the mouse adequately away from center */ - if (len_squared_v2(current_direction) > dial->threshold_squared) { - float angle; - float cosval, sinval; - - normalize_v2(current_direction); - - if (!dial->initialized) { - copy_v2_v2(dial->initial_direction, current_direction); - dial->initialized = true; - } - - /* calculate mouse angle between initial and final mouse position */ - cosval = dot_v2v2(current_direction, dial->initial_direction); - sinval = cross_v2v2(current_direction, dial->initial_direction); - - /* clamp to avoid nans in acos */ - angle = atan2f(sinval, cosval); - - /* change of sign, we passed the 180 degree threshold. This means we need to add a turn. - * to distinguish between transition from 0 to -1 and -PI to +PI, - * use comparison with PI/2 */ - if ((angle * dial->last_angle < 0.0f) && - (fabsf(dial->last_angle) > (float)M_PI_2)) - { - if (dial->last_angle < 0.0f) { - dial->rotations--; - } - else { - dial->rotations++; - } - } - dial->last_angle = angle; - - return angle + 2.0f * (float)M_PI * dial->rotations; - } - - return dial->last_angle; + float current_direction[2]; + + sub_v2_v2v2(current_direction, current_position, dial->center); + + /* only update when we have enough precision, + * by having the mouse adequately away from center */ + if (len_squared_v2(current_direction) > dial->threshold_squared) { + float angle; + float cosval, sinval; + + normalize_v2(current_direction); + + if (!dial->initialized) { + copy_v2_v2(dial->initial_direction, current_direction); + dial->initialized = true; + } + + /* calculate mouse angle between initial and final mouse position */ + cosval = dot_v2v2(current_direction, dial->initial_direction); + sinval = cross_v2v2(current_direction, dial->initial_direction); + + /* clamp to avoid nans in acos */ + angle = atan2f(sinval, cosval); + + /* change of sign, we passed the 180 degree threshold. This means we need to add a turn. + * to distinguish between transition from 0 to -1 and -PI to +PI, + * use comparison with PI/2 */ + if ((angle * dial->last_angle < 0.0f) && (fabsf(dial->last_angle) > (float)M_PI_2)) { + if (dial->last_angle < 0.0f) { + dial->rotations--; + } + else { + dial->rotations++; + } + } + dial->last_angle = angle; + + return angle + 2.0f * (float)M_PI * dial->rotations; + } + + return dial->last_angle; } diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c index ef45d7b2a47..c325c010330 100644 --- a/source/blender/blenlib/intern/BLI_dynstr.c +++ b/source/blender/blenlib/intern/BLI_dynstr.c @@ -22,7 +22,7 @@ * \ingroup bli */ -#include <stdlib.h> /* malloc */ +#include <stdlib.h> /* malloc */ #include <string.h> #include "MEM_guardedalloc.h" @@ -32,32 +32,32 @@ #include "BLI_dynstr.h" #ifdef _WIN32 -#ifndef vsnprintf -#define vsnprintf _vsnprintf -#endif +# ifndef vsnprintf +# define vsnprintf _vsnprintf +# endif #endif #ifndef va_copy -# ifdef __va_copy -# define va_copy(a, b) __va_copy(a, b) -# else /* !__va_copy */ -# define va_copy(a, b) ((a) = (b)) -# endif /* __va_copy */ -#endif /* va_copy */ +# ifdef __va_copy +# define va_copy(a, b) __va_copy(a, b) +# else /* !__va_copy */ +# define va_copy(a, b) ((a) = (b)) +# endif /* __va_copy */ +#endif /* va_copy */ /***/ typedef struct DynStrElem DynStrElem; struct DynStrElem { - DynStrElem *next; + DynStrElem *next; - char *str; + char *str; }; struct DynStr { - DynStrElem *elems, *last; - int curlen; - MemArena *memarena; + DynStrElem *elems, *last; + int curlen; + MemArena *memarena; }; /***/ @@ -69,12 +69,12 @@ struct DynStr { */ DynStr *BLI_dynstr_new(void) { - DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); - ds->elems = ds->last = NULL; - ds->curlen = 0; - ds->memarena = NULL; + DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); + ds->elems = ds->last = NULL; + ds->curlen = 0; + ds->memarena = NULL; - return ds; + return ds; } /** @@ -84,17 +84,17 @@ DynStr *BLI_dynstr_new(void) */ DynStr *BLI_dynstr_new_memarena(void) { - DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); - ds->elems = ds->last = NULL; - ds->curlen = 0; - ds->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); + ds->elems = ds->last = NULL; + ds->curlen = 0; + ds->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - return ds; + return ds; } BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size) { - return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size); + return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size); } /** @@ -105,21 +105,21 @@ BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size) */ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) { - DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); - int cstrlen = strlen(cstr); + DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); + int cstrlen = strlen(cstr); - dse->str = dynstr_alloc(ds, cstrlen + 1); - memcpy(dse->str, cstr, cstrlen + 1); - dse->next = NULL; + dse->str = dynstr_alloc(ds, cstrlen + 1); + memcpy(dse->str, cstr, cstrlen + 1); + dse->next = NULL; - if (!ds->last) { - ds->last = ds->elems = dse; - } - else { - ds->last = ds->last->next = dse; - } + if (!ds->last) { + ds->last = ds->elems = dse; + } + else { + ds->last = ds->last->next = dse; + } - ds->curlen += cstrlen; + ds->curlen += cstrlen; } /** @@ -131,81 +131,81 @@ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) */ void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) { - DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); - int cstrlen = BLI_strnlen(cstr, len); - - dse->str = dynstr_alloc(ds, cstrlen + 1); - memcpy(dse->str, cstr, cstrlen); - dse->str[cstrlen] = '\0'; - dse->next = NULL; - - if (!ds->last) { - ds->last = ds->elems = dse; - } - else { - ds->last = ds->last->next = dse; - } - - ds->curlen += cstrlen; + DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); + int cstrlen = BLI_strnlen(cstr, len); + + dse->str = dynstr_alloc(ds, cstrlen + 1); + memcpy(dse->str, cstr, cstrlen); + dse->str[cstrlen] = '\0'; + dse->next = NULL; + + if (!ds->last) { + ds->last = ds->elems = dse; + } + else { + ds->last = ds->last->next = dse; + } + + ds->curlen += cstrlen; } void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, va_list args) { - char *message, fixedmessage[256]; - int len = sizeof(fixedmessage); - const int maxlen = 65536; - int retval; - - while (1) { - va_list args_cpy; - if (len == sizeof(fixedmessage)) { - message = fixedmessage; - } - else { - message = MEM_callocN(sizeof(char) * len, "BLI_dynstr_appendf"); - } - - /* cant reuse the same args, so work on a copy */ - va_copy(args_cpy, args); - retval = vsnprintf(message, len, format, args_cpy); - va_end(args_cpy); - - if (retval == -1) { - /* -1 means not enough space, but on windows it may also mean - * there is a formatting error, so we impose a maximum length */ - if (message != fixedmessage) { - MEM_freeN(message); - } - message = NULL; - - len *= 2; - if (len > maxlen) { - fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); - break; - } - } - else if (retval >= len) { - /* in C99 the actual length required is returned */ - if (message != fixedmessage) { - MEM_freeN(message); - } - message = NULL; - - /* retval doesn't include \0 terminator */ - len = retval + 1; - } - else { - break; - } - } - - if (message) { - BLI_dynstr_append(ds, message); - - if (message != fixedmessage) { - MEM_freeN(message); - } - } + char *message, fixedmessage[256]; + int len = sizeof(fixedmessage); + const int maxlen = 65536; + int retval; + + while (1) { + va_list args_cpy; + if (len == sizeof(fixedmessage)) { + message = fixedmessage; + } + else { + message = MEM_callocN(sizeof(char) * len, "BLI_dynstr_appendf"); + } + + /* cant reuse the same args, so work on a copy */ + va_copy(args_cpy, args); + retval = vsnprintf(message, len, format, args_cpy); + va_end(args_cpy); + + if (retval == -1) { + /* -1 means not enough space, but on windows it may also mean + * there is a formatting error, so we impose a maximum length */ + if (message != fixedmessage) { + MEM_freeN(message); + } + message = NULL; + + len *= 2; + if (len > maxlen) { + fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); + break; + } + } + else if (retval >= len) { + /* in C99 the actual length required is returned */ + if (message != fixedmessage) { + MEM_freeN(message); + } + message = NULL; + + /* retval doesn't include \0 terminator */ + len = retval + 1; + } + else { + break; + } + } + + if (message) { + BLI_dynstr_append(ds, message); + + if (message != fixedmessage) { + MEM_freeN(message); + } + } } /** @@ -216,64 +216,64 @@ void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, v */ void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format, ...) { - va_list args; - char *message, fixedmessage[256]; - int len = sizeof(fixedmessage); - const int maxlen = 65536; - int retval; - - /* note that it's tempting to just call BLI_dynstr_vappendf here - * and avoid code duplication, that crashes on some system because - * va_start/va_end have to be called for each vsnprintf call */ - - while (1) { - if (len == sizeof(fixedmessage)) { - message = fixedmessage; - } - else { - message = MEM_callocN(sizeof(char) * (len), "BLI_dynstr_appendf"); - } - - va_start(args, format); - retval = vsnprintf(message, len, format, args); - va_end(args); - - if (retval == -1) { - /* -1 means not enough space, but on windows it may also mean - * there is a formatting error, so we impose a maximum length */ - if (message != fixedmessage) { - MEM_freeN(message); - } - message = NULL; - - len *= 2; - if (len > maxlen) { - fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); - break; - } - } - else if (retval >= len) { - /* in C99 the actual length required is returned */ - if (message != fixedmessage) { - MEM_freeN(message); - } - message = NULL; - - /* retval doesn't include \0 terminator */ - len = retval + 1; - } - else { - break; - } - } - - if (message) { - BLI_dynstr_append(ds, message); - - if (message != fixedmessage) { - MEM_freeN(message); - } - } + va_list args; + char *message, fixedmessage[256]; + int len = sizeof(fixedmessage); + const int maxlen = 65536; + int retval; + + /* note that it's tempting to just call BLI_dynstr_vappendf here + * and avoid code duplication, that crashes on some system because + * va_start/va_end have to be called for each vsnprintf call */ + + while (1) { + if (len == sizeof(fixedmessage)) { + message = fixedmessage; + } + else { + message = MEM_callocN(sizeof(char) * (len), "BLI_dynstr_appendf"); + } + + va_start(args, format); + retval = vsnprintf(message, len, format, args); + va_end(args); + + if (retval == -1) { + /* -1 means not enough space, but on windows it may also mean + * there is a formatting error, so we impose a maximum length */ + if (message != fixedmessage) { + MEM_freeN(message); + } + message = NULL; + + len *= 2; + if (len > maxlen) { + fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); + break; + } + } + else if (retval >= len) { + /* in C99 the actual length required is returned */ + if (message != fixedmessage) { + MEM_freeN(message); + } + message = NULL; + + /* retval doesn't include \0 terminator */ + len = retval + 1; + } + else { + break; + } + } + + if (message) { + BLI_dynstr_append(ds, message); + + if (message != fixedmessage) { + MEM_freeN(message); + } + } } /** @@ -284,7 +284,7 @@ void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format, .. */ int BLI_dynstr_get_len(DynStr *ds) { - return ds->curlen; + return ds->curlen; } /** @@ -297,18 +297,18 @@ int BLI_dynstr_get_len(DynStr *ds) */ void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict rets) { - char *s; - DynStrElem *dse; + char *s; + DynStrElem *dse; - for (s = rets, dse = ds->elems; dse; dse = dse->next) { - int slen = strlen(dse->str); + for (s = rets, dse = ds->elems; dse; dse = dse->next) { + int slen = strlen(dse->str); - memcpy(s, dse->str, slen); + memcpy(s, dse->str, slen); - s += slen; - } - BLI_assert((s - rets) == ds->curlen); - rets[ds->curlen] = '\0'; + s += slen; + } + BLI_assert((s - rets) == ds->curlen); + rets[ds->curlen] = '\0'; } /** @@ -321,9 +321,9 @@ void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict rets) */ char *BLI_dynstr_get_cstring(DynStr *ds) { - char *rets = MEM_mallocN(ds->curlen + 1, "dynstr_cstring"); - BLI_dynstr_get_cstring_ex(ds, rets); - return rets; + char *rets = MEM_mallocN(ds->curlen + 1, "dynstr_cstring"); + BLI_dynstr_get_cstring_ex(ds, rets); + return rets; } /** @@ -333,20 +333,20 @@ char *BLI_dynstr_get_cstring(DynStr *ds) */ void BLI_dynstr_clear(DynStr *ds) { - if (ds->memarena) { - BLI_memarena_clear(ds->memarena); - } - else { - for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) { - dse_next = dse->next; - - free(dse->str); - free(dse); - } - } - - ds->elems = ds->last = NULL; - ds->curlen = 0; + if (ds->memarena) { + BLI_memarena_clear(ds->memarena); + } + else { + for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) { + dse_next = dse->next; + + free(dse->str); + free(dse); + } + } + + ds->elems = ds->last = NULL; + ds->curlen = 0; } /** @@ -356,12 +356,12 @@ void BLI_dynstr_clear(DynStr *ds) */ void BLI_dynstr_free(DynStr *ds) { - if (ds->memarena) { - BLI_memarena_free(ds->memarena); - } - else { - BLI_dynstr_clear(ds); - } - - MEM_freeN(ds); + if (ds->memarena) { + BLI_memarena_free(ds->memarena); + } + else { + BLI_dynstr_clear(ds); + } + + MEM_freeN(ds); } diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index 243c7d95da1..91f16ca9b7b 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -28,7 +28,7 @@ #include <time.h> #include <sys/stat.h> -#include <string.h> /* strcpy etc.. */ +#include <string.h> /* strcpy etc.. */ #ifdef WIN32 # include <io.h> @@ -54,55 +54,65 @@ #include "../imbuf/IMB_imbuf.h" - /* * Ordering function for sorting lists of files/directories. Returns -1 if * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped. */ static int bli_compare(struct direntry *entry1, struct direntry *entry2) { - /* type is equal to stat.st_mode */ - - /* directories come before non-directories */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) { - return -1; - } - } - else { - if (S_ISDIR(entry2->type)) { - return 1; - } - } - /* non-regular files come after regular files */ - if (S_ISREG(entry1->type)) { - if (S_ISREG(entry2->type) == 0) { - return -1; - } - } - else { - if (S_ISREG(entry2->type)) { - return 1; - } - } - /* arbitrary, but consistent, ordering of different types of non-regular files */ - if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) { return -1; } - if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) { return 1; } - - /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */ - /* make sure "." and ".." are always first */ - if (FILENAME_IS_CURRENT(entry1->relname)) { return -1; } - if (FILENAME_IS_CURRENT(entry2->relname)) { return 1; } - if (FILENAME_IS_PARENT(entry1->relname)) { return -1; } - if (FILENAME_IS_PARENT(entry2->relname)) { return 1; } - - return (BLI_natstrcmp(entry1->relname, entry2->relname)); + /* type is equal to stat.st_mode */ + + /* directories come before non-directories */ + if (S_ISDIR(entry1->type)) { + if (S_ISDIR(entry2->type) == 0) { + return -1; + } + } + else { + if (S_ISDIR(entry2->type)) { + return 1; + } + } + /* non-regular files come after regular files */ + if (S_ISREG(entry1->type)) { + if (S_ISREG(entry2->type) == 0) { + return -1; + } + } + else { + if (S_ISREG(entry2->type)) { + return 1; + } + } + /* arbitrary, but consistent, ordering of different types of non-regular files */ + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) { + return -1; + } + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) { + return 1; + } + + /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */ + /* make sure "." and ".." are always first */ + if (FILENAME_IS_CURRENT(entry1->relname)) { + return -1; + } + if (FILENAME_IS_CURRENT(entry2->relname)) { + return 1; + } + if (FILENAME_IS_PARENT(entry1->relname)) { + return -1; + } + if (FILENAME_IS_PARENT(entry2->relname)) { + return 1; + } + + return (BLI_natstrcmp(entry1->relname, entry2->relname)); } - struct BuildDirCtx { - struct direntry *files; /* array[nrfiles] */ - int nrfiles; + struct direntry *files; /* array[nrfiles] */ + int nrfiles; }; /** @@ -110,108 +120,113 @@ struct BuildDirCtx { */ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) { - struct ListBase dirbase = {NULL, NULL}; - int newnum = 0; - DIR *dir; - - if ((dir = opendir(dirname)) != NULL) { - const struct dirent *fname; - bool has_current = false, has_parent = false; - - while ((fname = readdir(dir)) != NULL) { - struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink != NULL) { - dlink->name = BLI_strdup(fname->d_name); - if (FILENAME_IS_PARENT(dlink->name)) { - has_parent = true; - } - else if (FILENAME_IS_CURRENT(dlink->name)) { - has_current = true; - } - BLI_addhead(&dirbase, dlink); - newnum++; - } - } - - if (!has_parent) { - char pardir[FILE_MAXDIR]; - - BLI_strncpy(pardir, dirname, sizeof(pardir)); - if (BLI_parent_dir(pardir) && (BLI_access(pardir, R_OK) == 0)) { - struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink != NULL) { - dlink->name = BLI_strdup(FILENAME_PARENT); - BLI_addhead(&dirbase, dlink); - newnum++; - } - } - } - if (!has_current) { - struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink != NULL) { - dlink->name = BLI_strdup(FILENAME_CURRENT); - BLI_addhead(&dirbase, dlink); - newnum++; - } - } - - if (newnum) { - if (dir_ctx->files) { - void * const tmp = MEM_reallocN(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); - if (tmp) { - dir_ctx->files = (struct direntry *)tmp; - } - else { /* realloc fail */ - MEM_freeN(dir_ctx->files); - dir_ctx->files = NULL; - } - } - - if (dir_ctx->files == NULL) { - dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(struct direntry), __func__); - } - - if (dir_ctx->files) { - struct dirlink * dlink = (struct dirlink *) dirbase.first; - struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; - while (dlink) { - char fullname[PATH_MAX]; - memset(file, 0, sizeof(struct direntry)); - file->relname = dlink->name; - file->path = BLI_strdupcat(dirname, dlink->name); - BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); - if (BLI_stat(fullname, &file->s) != -1) { - file->type = file->s.st_mode; - } - else if (FILENAME_IS_CURRPAR(file->relname)) { - /* Hack around for UNC paths on windows: - * does not support stat on '\\SERVER\foo\..', sigh... */ - file->type |= S_IFDIR; - } - dir_ctx->nrfiles++; - file++; - dlink = dlink->next; - } - } - else { - printf("Couldn't get memory for dir\n"); - exit(1); - } - - BLI_freelist(&dirbase); - if (dir_ctx->files) { - qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); - } - } - else { - printf("%s empty directory\n", dirname); - } - - closedir(dir); - } - else { - printf("%s non-existent directory\n", dirname); - } + struct ListBase dirbase = {NULL, NULL}; + int newnum = 0; + DIR *dir; + + if ((dir = opendir(dirname)) != NULL) { + const struct dirent *fname; + bool has_current = false, has_parent = false; + + while ((fname = readdir(dir)) != NULL) { + struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(fname->d_name); + if (FILENAME_IS_PARENT(dlink->name)) { + has_parent = true; + } + else if (FILENAME_IS_CURRENT(dlink->name)) { + has_current = true; + } + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + + if (!has_parent) { + char pardir[FILE_MAXDIR]; + + BLI_strncpy(pardir, dirname, sizeof(pardir)); + if (BLI_parent_dir(pardir) && (BLI_access(pardir, R_OK) == 0)) { + struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(FILENAME_PARENT); + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + } + if (!has_current) { + struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(FILENAME_CURRENT); + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + + if (newnum) { + if (dir_ctx->files) { + void *const tmp = MEM_reallocN(dir_ctx->files, + (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); + if (tmp) { + dir_ctx->files = (struct direntry *)tmp; + } + else { /* realloc fail */ + MEM_freeN(dir_ctx->files); + dir_ctx->files = NULL; + } + } + + if (dir_ctx->files == NULL) { + dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(struct direntry), + __func__); + } + + if (dir_ctx->files) { + struct dirlink *dlink = (struct dirlink *)dirbase.first; + struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; + while (dlink) { + char fullname[PATH_MAX]; + memset(file, 0, sizeof(struct direntry)); + file->relname = dlink->name; + file->path = BLI_strdupcat(dirname, dlink->name); + BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); + if (BLI_stat(fullname, &file->s) != -1) { + file->type = file->s.st_mode; + } + else if (FILENAME_IS_CURRPAR(file->relname)) { + /* Hack around for UNC paths on windows: + * does not support stat on '\\SERVER\foo\..', sigh... */ + file->type |= S_IFDIR; + } + dir_ctx->nrfiles++; + file++; + dlink = dlink->next; + } + } + else { + printf("Couldn't get memory for dir\n"); + exit(1); + } + + BLI_freelist(&dirbase); + if (dir_ctx->files) { + qsort(dir_ctx->files, + dir_ctx->nrfiles, + sizeof(struct direntry), + (int (*)(const void *, const void *))bli_compare); + } + } + else { + printf("%s empty directory\n", dirname); + } + + closedir(dir); + } + else { + printf("%s non-existent directory\n", dirname); + } } /** @@ -220,151 +235,162 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) * * \return The length of filelist array. */ -unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist) +unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist) { - struct BuildDirCtx dir_ctx; + struct BuildDirCtx dir_ctx; - dir_ctx.nrfiles = 0; - dir_ctx.files = NULL; + dir_ctx.nrfiles = 0; + dir_ctx.files = NULL; - bli_builddir(&dir_ctx, dirname); + bli_builddir(&dir_ctx, dirname); - if (dir_ctx.files) { - *r_filelist = dir_ctx.files; - } - else { - // keep blender happy. Blender stores this in a variable - // where 0 has special meaning..... - *r_filelist = MEM_mallocN(sizeof(**r_filelist), __func__); - } + if (dir_ctx.files) { + *r_filelist = dir_ctx.files; + } + else { + // keep blender happy. Blender stores this in a variable + // where 0 has special meaning..... + *r_filelist = MEM_mallocN(sizeof(**r_filelist), __func__); + } - return dir_ctx.nrfiles; + return dir_ctx.nrfiles; } /** * Convert given entry's size into human-readable strings. */ -void BLI_filelist_entry_size_to_string( - const struct stat *st, const uint64_t sz, const bool compact, char r_size[FILELIST_DIRENTRY_SIZE_LEN]) +void BLI_filelist_entry_size_to_string(const struct stat *st, + const uint64_t sz, + const bool compact, + char r_size[FILELIST_DIRENTRY_SIZE_LEN]) { - double size; - const char *fmt; - const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL}; - const char *units_compact[] = {"K", "M", "G", "T", NULL}; - const char *unit = "B"; - - /* - * Seems st_size is signed 32-bit value in *nix and Windows. This - * will buy us some time until files get bigger than 4GB or until - * everyone starts using __USE_FILE_OFFSET64 or equivalent. - */ - size = (double)(st ? st->st_size : sz); - - if (size > 1024.0) { - const char **u; - for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1); u++, size /= 1024.0) { - /* pass */ - } - fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s"); - unit = *u; - } - else { - fmt = "%.0f %s"; - } - - BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit); + double size; + const char *fmt; + const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL}; + const char *units_compact[] = {"K", "M", "G", "T", NULL}; + const char *unit = "B"; + + /* + * Seems st_size is signed 32-bit value in *nix and Windows. This + * will buy us some time until files get bigger than 4GB or until + * everyone starts using __USE_FILE_OFFSET64 or equivalent. + */ + size = (double)(st ? st->st_size : sz); + + if (size > 1024.0) { + const char **u; + for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1); + u++, size /= 1024.0) { + /* pass */ + } + fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s"); + unit = *u; + } + else { + fmt = "%.0f %s"; + } + + BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit); } /** * Convert given entry's modes into human-readable strings. */ -void BLI_filelist_entry_mode_to_string( - const struct stat *st, const bool UNUSED(compact), char r_mode1[FILELIST_DIRENTRY_MODE_LEN], - char r_mode2[FILELIST_DIRENTRY_MODE_LEN], char r_mode3[FILELIST_DIRENTRY_MODE_LEN]) +void BLI_filelist_entry_mode_to_string(const struct stat *st, + const bool UNUSED(compact), + char r_mode1[FILELIST_DIRENTRY_MODE_LEN], + char r_mode2[FILELIST_DIRENTRY_MODE_LEN], + char r_mode3[FILELIST_DIRENTRY_MODE_LEN]) { - const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; + const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; #ifdef WIN32 - BLI_strncpy(r_mode1, types[0], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN); - BLI_strncpy(r_mode2, types[0], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN); - BLI_strncpy(r_mode3, types[0], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN); + BLI_strncpy(r_mode1, types[0], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN); + BLI_strncpy(r_mode2, types[0], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN); + BLI_strncpy(r_mode3, types[0], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN); #else - const int mode = st->st_mode; - - BLI_strncpy(r_mode1, types[(mode & 0700) >> 6], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN); - BLI_strncpy(r_mode2, types[(mode & 0070) >> 3], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN); - BLI_strncpy(r_mode3, types[(mode & 0007)], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN); - - if (((mode & S_ISGID) == S_ISGID) && (r_mode2[2] == '-')) { - r_mode2[2] = 'l'; - } - - if (mode & (S_ISUID | S_ISGID)) { - if (r_mode1[2] == 'x') { - r_mode1[2] = 's'; - } - else { - r_mode1[2] = 'S'; - } - - if (r_mode2[2] == 'x') { - r_mode2[2] = 's'; - } - } - - if (mode & S_ISVTX) { - if (r_mode3[2] == 'x') { - r_mode3[2] = 't'; - } - else { - r_mode3[2] = 'T'; - } - } + const int mode = st->st_mode; + + BLI_strncpy(r_mode1, types[(mode & 0700) >> 6], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN); + BLI_strncpy(r_mode2, types[(mode & 0070) >> 3], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN); + BLI_strncpy(r_mode3, types[(mode & 0007)], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN); + + if (((mode & S_ISGID) == S_ISGID) && (r_mode2[2] == '-')) { + r_mode2[2] = 'l'; + } + + if (mode & (S_ISUID | S_ISGID)) { + if (r_mode1[2] == 'x') { + r_mode1[2] = 's'; + } + else { + r_mode1[2] = 'S'; + } + + if (r_mode2[2] == 'x') { + r_mode2[2] = 's'; + } + } + + if (mode & S_ISVTX) { + if (r_mode3[2] == 'x') { + r_mode3[2] = 't'; + } + else { + r_mode3[2] = 'T'; + } + } #endif } /** * Convert given entry's owner into human-readable strings. */ -void BLI_filelist_entry_owner_to_string( - const struct stat *st, const bool UNUSED(compact), char r_owner[FILELIST_DIRENTRY_OWNER_LEN]) +void BLI_filelist_entry_owner_to_string(const struct stat *st, + const bool UNUSED(compact), + char r_owner[FILELIST_DIRENTRY_OWNER_LEN]) { #ifdef WIN32 - strcpy(r_owner, "unknown"); + strcpy(r_owner, "unknown"); #else - struct passwd *pwuser = getpwuid(st->st_uid); - - if (pwuser) { - BLI_strncpy(r_owner, pwuser->pw_name, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN); - } - else { - BLI_snprintf(r_owner, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN, "%u", st->st_uid); - } + struct passwd *pwuser = getpwuid(st->st_uid); + + if (pwuser) { + BLI_strncpy(r_owner, pwuser->pw_name, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN); + } + else { + BLI_snprintf(r_owner, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN, "%u", st->st_uid); + } #endif } /** * Convert given entry's time into human-readable strings. */ -void BLI_filelist_entry_datetime_to_string( - const struct stat *st, const int64_t ts, const bool compact, - char r_time[FILELIST_DIRENTRY_TIME_LEN], char r_date[FILELIST_DIRENTRY_DATE_LEN]) +void BLI_filelist_entry_datetime_to_string(const struct stat *st, + const int64_t ts, + const bool compact, + char r_time[FILELIST_DIRENTRY_TIME_LEN], + char r_date[FILELIST_DIRENTRY_DATE_LEN]) { - time_t ts_mtime = ts; - const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime); - const time_t zero = 0; - - /* Prevent impossible dates in windows. */ - if (tm == NULL) { - tm = localtime(&zero); - } - - if (r_time) { - strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm); - } - if (r_date) { - strftime(r_date, sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN, compact ? "%d/%m/%y" : "%d-%b-%y", tm); - } + time_t ts_mtime = ts; + const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime); + const time_t zero = 0; + + /* Prevent impossible dates in windows. */ + if (tm == NULL) { + tm = localtime(&zero); + } + + if (r_time) { + strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm); + } + if (r_date) { + strftime(r_date, + sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN, + compact ? "%d/%m/%y" : "%d-%b-%y", + tm); + } } /** @@ -372,29 +398,30 @@ void BLI_filelist_entry_datetime_to_string( */ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *src) { - *dst = *src; - if (dst->relname) { - dst->relname = MEM_dupallocN(src->relname); - } - if (dst->path) { - dst->path = MEM_dupallocN(src->path); - } + *dst = *src; + if (dst->relname) { + dst->relname = MEM_dupallocN(src->relname); + } + if (dst->path) { + dst->path = MEM_dupallocN(src->path); + } } /** * Deep-duplicate of an array of direntries, including the array itself. */ -void BLI_filelist_duplicate( - struct direntry **dest_filelist, struct direntry * const src_filelist, const unsigned int nrentries) +void BLI_filelist_duplicate(struct direntry **dest_filelist, + struct direntry *const src_filelist, + const unsigned int nrentries) { - unsigned int i; - - *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); - for (i = 0; i < nrentries; ++i) { - struct direntry * const src = &src_filelist[i]; - struct direntry *dst = &(*dest_filelist)[i]; - BLI_filelist_entry_duplicate(dst, src); - } + unsigned int i; + + *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); + for (i = 0; i < nrentries; ++i) { + struct direntry *const src = &src_filelist[i]; + struct direntry *dst = &(*dest_filelist)[i]; + BLI_filelist_entry_duplicate(dst, src); + } } /** @@ -402,12 +429,12 @@ void BLI_filelist_duplicate( */ void BLI_filelist_entry_free(struct direntry *entry) { - if (entry->relname) { - MEM_freeN((void *)entry->relname); - } - if (entry->path) { - MEM_freeN((void *)entry->path); - } + if (entry->relname) { + MEM_freeN((void *)entry->relname); + } + if (entry->path) { + MEM_freeN((void *)entry->path); + } } /** @@ -415,12 +442,12 @@ void BLI_filelist_entry_free(struct direntry *entry) */ void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries) { - unsigned int i; - for (i = 0; i < nrentries; ++i) { - BLI_filelist_entry_free(&filelist[i]); - } - - if (filelist != NULL) { - MEM_freeN(filelist); - } + unsigned int i; + for (i = 0; i < nrentries; ++i) { + BLI_filelist_entry_free(&filelist[i]); + } + + if (filelist != NULL) { + MEM_freeN(filelist); + } } diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index ae1c6e0ba0b..c0ec1eba9c0 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -33,12 +33,12 @@ #include "MEM_guardedalloc.h" -#include "BLI_sys_types.h" /* for intptr_t support */ +#include "BLI_sys_types.h" /* for intptr_t support */ #include "BLI_utildefines.h" #include "BLI_mempool.h" #define GHASH_INTERNAL_API -#include "BLI_ghash.h" /* own include */ +#include "BLI_ghash.h" /* own include */ /* keep last */ #include "BLI_strict_flags.h" @@ -54,12 +54,11 @@ * * \note Also used by: `BLI_edgehash` & `BLI_smallhash`. */ -extern const uint BLI_ghash_hash_sizes[]; /* Quiet warning, this is only used by smallhash.c */ +extern const uint BLI_ghash_hash_sizes[]; /* Quiet warning, this is only used by smallhash.c */ const uint BLI_ghash_hash_sizes[] = { - 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, - 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, - 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, - 268435459, + 5, 11, 17, 37, 67, 131, 257, 521, 1031, + 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, + 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459, }; #define hashsizes BLI_ghash_hash_sizes @@ -68,7 +67,7 @@ const uint BLI_ghash_hash_sizes[] = { BLI_STATIC_ASSERT(ARRAY_SIZE(hashsizes) == GHASH_MAX_SIZE, "Invalid 'hashsizes' size"); #else # define GHASH_BUCKET_BIT_MIN 2 -# define GHASH_BUCKET_BIT_MAX 28 /* About 268M of buckets... */ +# define GHASH_BUCKET_BIT_MAX 28 /* About 268M of buckets... */ #endif /** @@ -78,43 +77,42 @@ BLI_STATIC_ASSERT(ARRAY_SIZE(hashsizes) == GHASH_MAX_SIZE, "Invalid 'hashsizes' * about 25% - 30% quicker 'dynamic-topology' stroke drawing e.g.). * Min load #GHASH_LIMIT_SHRINK is a quarter of max load, to avoid resizing to quickly. */ -#define GHASH_LIMIT_GROW(_nbkt) (((_nbkt) * 3) / 4) -#define GHASH_LIMIT_SHRINK(_nbkt) (((_nbkt) * 3) / 16) +#define GHASH_LIMIT_GROW(_nbkt) (((_nbkt)*3) / 4) +#define GHASH_LIMIT_SHRINK(_nbkt) (((_nbkt)*3) / 16) /* WARNING! Keep in sync with ugly _gh_Entry in header!!! */ typedef struct Entry { - struct Entry *next; + struct Entry *next; - void *key; + void *key; } Entry; typedef struct GHashEntry { - Entry e; + Entry e; - void *val; + void *val; } GHashEntry; typedef Entry GSetEntry; -#define GHASH_ENTRY_SIZE(_is_gset) \ - ((_is_gset) ? sizeof(GSetEntry) : sizeof(GHashEntry)) +#define GHASH_ENTRY_SIZE(_is_gset) ((_is_gset) ? sizeof(GSetEntry) : sizeof(GHashEntry)) struct GHash { - GHashHashFP hashfp; - GHashCmpFP cmpfp; + GHashHashFP hashfp; + GHashCmpFP cmpfp; - Entry **buckets; - struct BLI_mempool *entrypool; - uint nbuckets; - uint limit_grow, limit_shrink; + Entry **buckets; + struct BLI_mempool *entrypool; + uint nbuckets; + uint limit_grow, limit_shrink; #ifdef GHASH_USE_MODULO_BUCKETS - uint cursize, size_min; + uint cursize, size_min; #else - uint bucket_mask, bucket_bit, bucket_bit_min; + uint bucket_mask, bucket_bit, bucket_bit_min; #endif - uint nentries; - uint flag; + uint nentries; + uint flag; }; /** \} */ @@ -123,20 +121,24 @@ struct GHash { /** \name Internal Utility API * \{ */ -BLI_INLINE void ghash_entry_copy( - GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src, - GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) +BLI_INLINE void ghash_entry_copy(GHash *gh_dst, + Entry *dst, + GHash *gh_src, + Entry *src, + GHashKeyCopyFP keycopyfp, + GHashValCopyFP valcopyfp) { - dst->key = (keycopyfp) ? keycopyfp(src->key) : src->key; + dst->key = (keycopyfp) ? keycopyfp(src->key) : src->key; - if ((gh_dst->flag & GHASH_FLAG_IS_GSET) == 0) { - if ((gh_src->flag & GHASH_FLAG_IS_GSET) == 0) { - ((GHashEntry *)dst)->val = (valcopyfp) ? valcopyfp(((GHashEntry *)src)->val) : ((GHashEntry *)src)->val; - } - else { - ((GHashEntry *)dst)->val = NULL; - } - } + if ((gh_dst->flag & GHASH_FLAG_IS_GSET) == 0) { + if ((gh_src->flag & GHASH_FLAG_IS_GSET) == 0) { + ((GHashEntry *)dst)->val = (valcopyfp) ? valcopyfp(((GHashEntry *)src)->val) : + ((GHashEntry *)src)->val; + } + else { + ((GHashEntry *)dst)->val = NULL; + } + } } /** @@ -144,7 +146,7 @@ BLI_INLINE void ghash_entry_copy( */ BLI_INLINE uint ghash_keyhash(GHash *gh, const void *key) { - return gh->hashfp(key); + return gh->hashfp(key); } /** @@ -152,7 +154,7 @@ BLI_INLINE uint ghash_keyhash(GHash *gh, const void *key) */ BLI_INLINE uint ghash_entryhash(GHash *gh, const Entry *e) { - return gh->hashfp(e->key); + return gh->hashfp(e->key); } /** @@ -161,9 +163,9 @@ BLI_INLINE uint ghash_entryhash(GHash *gh, const Entry *e) BLI_INLINE uint ghash_bucket_index(GHash *gh, const uint hash) { #ifdef GHASH_USE_MODULO_BUCKETS - return hash % gh->nbuckets; + return hash % gh->nbuckets; #else - return hash & gh->bucket_mask; + return hash & gh->bucket_mask; #endif } @@ -172,24 +174,24 @@ BLI_INLINE uint ghash_bucket_index(GHash *gh, const uint hash) */ BLI_INLINE uint ghash_find_next_bucket_index(GHash *gh, uint curr_bucket) { - if (curr_bucket >= gh->nbuckets) { - curr_bucket = 0; - } - if (gh->buckets[curr_bucket]) { - return curr_bucket; - } - for (; curr_bucket < gh->nbuckets; curr_bucket++) { - if (gh->buckets[curr_bucket]) { - return curr_bucket; - } - } - for (curr_bucket = 0; curr_bucket < gh->nbuckets; curr_bucket++) { - if (gh->buckets[curr_bucket]) { - return curr_bucket; - } - } - BLI_assert(0); - return 0; + if (curr_bucket >= gh->nbuckets) { + curr_bucket = 0; + } + if (gh->buckets[curr_bucket]) { + return curr_bucket; + } + for (; curr_bucket < gh->nbuckets; curr_bucket++) { + if (gh->buckets[curr_bucket]) { + return curr_bucket; + } + } + for (curr_bucket = 0; curr_bucket < gh->nbuckets; curr_bucket++) { + if (gh->buckets[curr_bucket]) { + return curr_bucket; + } + } + BLI_assert(0); + return 0; } /** @@ -197,162 +199,156 @@ BLI_INLINE uint ghash_find_next_bucket_index(GHash *gh, uint curr_bucket) */ static void ghash_buckets_resize(GHash *gh, const uint nbuckets) { - Entry **buckets_old = gh->buckets; - Entry **buckets_new; - const uint nbuckets_old = gh->nbuckets; - uint i; + Entry **buckets_old = gh->buckets; + Entry **buckets_new; + const uint nbuckets_old = gh->nbuckets; + uint i; - BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets); -// printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets); + BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets); + // printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets); - gh->nbuckets = nbuckets; + gh->nbuckets = nbuckets; #ifdef GHASH_USE_MODULO_BUCKETS #else - gh->bucket_mask = nbuckets - 1; + gh->bucket_mask = nbuckets - 1; #endif - buckets_new = (Entry **)MEM_callocN(sizeof(*gh->buckets) * gh->nbuckets, __func__); - - if (buckets_old) { - if (nbuckets > nbuckets_old) { - for (i = 0; i < nbuckets_old; i++) { - for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { - const unsigned hash = ghash_entryhash(gh, e); - const unsigned bucket_index = ghash_bucket_index(gh, hash); - e_next = e->next; - e->next = buckets_new[bucket_index]; - buckets_new[bucket_index] = e; - } - } - } - else { - for (i = 0; i < nbuckets_old; i++) { + buckets_new = (Entry **)MEM_callocN(sizeof(*gh->buckets) * gh->nbuckets, __func__); + + if (buckets_old) { + if (nbuckets > nbuckets_old) { + for (i = 0; i < nbuckets_old; i++) { + for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { + const unsigned hash = ghash_entryhash(gh, e); + const unsigned bucket_index = ghash_bucket_index(gh, hash); + e_next = e->next; + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = e; + } + } + } + else { + for (i = 0; i < nbuckets_old; i++) { #ifdef GHASH_USE_MODULO_BUCKETS - for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { - const unsigned hash = ghash_entryhash(gh, e); - const unsigned bucket_index = ghash_bucket_index(gh, hash); - e_next = e->next; - e->next = buckets_new[bucket_index]; - buckets_new[bucket_index] = e; - } + for (Entry *e = buckets_old[i], *e_next; e; e = e_next) { + const unsigned hash = ghash_entryhash(gh, e); + const unsigned bucket_index = ghash_bucket_index(gh, hash); + e_next = e->next; + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = e; + } #else - /* No need to recompute hashes in this case, since our mask is just smaller, - * all items in old bucket 'i' will go in same new bucket (i & new_mask)! */ - const unsigned bucket_index = ghash_bucket_index(gh, i); - BLI_assert(!buckets_old[i] || (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i])))); - Entry *e; - for (e = buckets_old[i]; e && e->next; e = e->next) { - /* pass */ - } - if (e) { - e->next = buckets_new[bucket_index]; - buckets_new[bucket_index] = buckets_old[i]; - } + /* No need to recompute hashes in this case, since our mask is just smaller, + * all items in old bucket 'i' will go in same new bucket (i & new_mask)! */ + const unsigned bucket_index = ghash_bucket_index(gh, i); + BLI_assert(!buckets_old[i] || + (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i])))); + Entry *e; + for (e = buckets_old[i]; e && e->next; e = e->next) { + /* pass */ + } + if (e) { + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = buckets_old[i]; + } #endif - } - } - } + } + } + } - gh->buckets = buckets_new; - if (buckets_old) { - MEM_freeN(buckets_old); - } + gh->buckets = buckets_new; + if (buckets_old) { + MEM_freeN(buckets_old); + } } /** * Check if the number of items in the GHash is large enough to require more buckets, * or small enough to require less buckets, and resize \a gh accordingly. */ -static void ghash_buckets_expand( - GHash *gh, const uint nentries, const bool user_defined) +static void ghash_buckets_expand(GHash *gh, const uint nentries, const bool user_defined) { - uint new_nbuckets; + uint new_nbuckets; - if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) { - return; - } + if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) { + return; + } - new_nbuckets = gh->nbuckets; + new_nbuckets = gh->nbuckets; #ifdef GHASH_USE_MODULO_BUCKETS - while ((nentries > gh->limit_grow) && - (gh->cursize < GHASH_MAX_SIZE - 1)) - { - new_nbuckets = hashsizes[++gh->cursize]; - gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); - } + while ((nentries > gh->limit_grow) && (gh->cursize < GHASH_MAX_SIZE - 1)) { + new_nbuckets = hashsizes[++gh->cursize]; + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + } #else - while ((nentries > gh->limit_grow) && - (gh->bucket_bit < GHASH_BUCKET_BIT_MAX)) - { - new_nbuckets = 1u << ++gh->bucket_bit; - gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); - } + while ((nentries > gh->limit_grow) && (gh->bucket_bit < GHASH_BUCKET_BIT_MAX)) { + new_nbuckets = 1u << ++gh->bucket_bit; + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + } #endif - if (user_defined) { + if (user_defined) { #ifdef GHASH_USE_MODULO_BUCKETS - gh->size_min = gh->cursize; + gh->size_min = gh->cursize; #else - gh->bucket_bit_min = gh->bucket_bit; + gh->bucket_bit_min = gh->bucket_bit; #endif - } + } - if ((new_nbuckets == gh->nbuckets) && gh->buckets) { - return; - } + if ((new_nbuckets == gh->nbuckets) && gh->buckets) { + return; + } - gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); - gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); - ghash_buckets_resize(gh, new_nbuckets); + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + ghash_buckets_resize(gh, new_nbuckets); } -static void ghash_buckets_contract( - GHash *gh, const uint nentries, const bool user_defined, const bool force_shrink) +static void ghash_buckets_contract(GHash *gh, + const uint nentries, + const bool user_defined, + const bool force_shrink) { - uint new_nbuckets; + uint new_nbuckets; - if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) { - return; - } + if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) { + return; + } - if (LIKELY(gh->buckets && (nentries > gh->limit_shrink))) { - return; - } + if (LIKELY(gh->buckets && (nentries > gh->limit_shrink))) { + return; + } - new_nbuckets = gh->nbuckets; + new_nbuckets = gh->nbuckets; #ifdef GHASH_USE_MODULO_BUCKETS - while ((nentries < gh->limit_shrink) && - (gh->cursize > gh->size_min)) - { - new_nbuckets = hashsizes[--gh->cursize]; - gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); - } + while ((nentries < gh->limit_shrink) && (gh->cursize > gh->size_min)) { + new_nbuckets = hashsizes[--gh->cursize]; + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + } #else - while ((nentries < gh->limit_shrink) && - (gh->bucket_bit > gh->bucket_bit_min)) - { - new_nbuckets = 1u << --gh->bucket_bit; - gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); - } + while ((nentries < gh->limit_shrink) && (gh->bucket_bit > gh->bucket_bit_min)) { + new_nbuckets = 1u << --gh->bucket_bit; + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + } #endif - if (user_defined) { + if (user_defined) { #ifdef GHASH_USE_MODULO_BUCKETS - gh->size_min = gh->cursize; + gh->size_min = gh->cursize; #else - gh->bucket_bit_min = gh->bucket_bit; + gh->bucket_bit_min = gh->bucket_bit; #endif - } + } - if ((new_nbuckets == gh->nbuckets) && gh->buckets) { - return; - } + if ((new_nbuckets == gh->nbuckets) && gh->buckets) { + return; + } - gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); - gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); - ghash_buckets_resize(gh, new_nbuckets); + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + ghash_buckets_resize(gh, new_nbuckets); } /** @@ -360,44 +356,43 @@ static void ghash_buckets_contract( */ BLI_INLINE void ghash_buckets_reset(GHash *gh, const uint nentries) { - MEM_SAFE_FREE(gh->buckets); + MEM_SAFE_FREE(gh->buckets); #ifdef GHASH_USE_MODULO_BUCKETS - gh->cursize = 0; - gh->size_min = 0; - gh->nbuckets = hashsizes[gh->cursize]; + gh->cursize = 0; + gh->size_min = 0; + gh->nbuckets = hashsizes[gh->cursize]; #else - gh->bucket_bit = GHASH_BUCKET_BIT_MIN; - gh->bucket_bit_min = GHASH_BUCKET_BIT_MIN; - gh->nbuckets = 1u << gh->bucket_bit; - gh->bucket_mask = gh->nbuckets - 1; + gh->bucket_bit = GHASH_BUCKET_BIT_MIN; + gh->bucket_bit_min = GHASH_BUCKET_BIT_MIN; + gh->nbuckets = 1u << gh->bucket_bit; + gh->bucket_mask = gh->nbuckets - 1; #endif - gh->limit_grow = GHASH_LIMIT_GROW(gh->nbuckets); - gh->limit_shrink = GHASH_LIMIT_SHRINK(gh->nbuckets); + gh->limit_grow = GHASH_LIMIT_GROW(gh->nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(gh->nbuckets); - gh->nentries = 0; + gh->nentries = 0; - ghash_buckets_expand(gh, nentries, (nentries != 0)); + ghash_buckets_expand(gh, nentries, (nentries != 0)); } /** * Internal lookup function. * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ -BLI_INLINE Entry *ghash_lookup_entry_ex( - GHash *gh, const void *key, const uint bucket_index) +BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key, const uint bucket_index) { - Entry *e; - /* If we do not store GHash, not worth computing it for each entry here! - * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ - for (e = gh->buckets[bucket_index]; e; e = e->next) { - if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { - return e; - } - } + Entry *e; + /* If we do not store GHash, not worth computing it for each entry here! + * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ + for (e = gh->buckets[bucket_index]; e; e = e->next) { + if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { + return e; + } + } - return NULL; + return NULL; } /** @@ -405,21 +400,22 @@ BLI_INLINE Entry *ghash_lookup_entry_ex( * Takes bucket_index argument to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. * Useful when modifying buckets somehow (like removing an entry...). */ -BLI_INLINE Entry *ghash_lookup_entry_prev_ex( - GHash *gh, const void *key, - Entry **r_e_prev, const uint bucket_index) +BLI_INLINE Entry *ghash_lookup_entry_prev_ex(GHash *gh, + const void *key, + Entry **r_e_prev, + const uint bucket_index) { - /* If we do not store GHash, not worth computing it for each entry here! - * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ - for (Entry *e_prev = NULL, *e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) { - if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { - *r_e_prev = e_prev; - return e; - } - } + /* If we do not store GHash, not worth computing it for each entry here! + * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ + for (Entry *e_prev = NULL, *e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) { + if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { + *r_e_prev = e_prev; + return e; + } + } - *r_e_prev = NULL; - return NULL; + *r_e_prev = NULL; + return NULL; } /** @@ -427,177 +423,184 @@ BLI_INLINE Entry *ghash_lookup_entry_prev_ex( */ BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - return ghash_lookup_entry_ex(gh, key, bucket_index); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + return ghash_lookup_entry_ex(gh, key, bucket_index); } -static GHash *ghash_new( - GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, - const uint nentries_reserve, const uint flag) +static GHash *ghash_new(GHashHashFP hashfp, + GHashCmpFP cmpfp, + const char *info, + const uint nentries_reserve, + const uint flag) { - GHash *gh = MEM_mallocN(sizeof(*gh), info); + GHash *gh = MEM_mallocN(sizeof(*gh), info); - gh->hashfp = hashfp; - gh->cmpfp = cmpfp; + gh->hashfp = hashfp; + gh->cmpfp = cmpfp; - gh->buckets = NULL; - gh->flag = flag; + gh->buckets = NULL; + gh->flag = flag; - ghash_buckets_reset(gh, nentries_reserve); - gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP); + ghash_buckets_reset(gh, nentries_reserve); + gh->entrypool = BLI_mempool_create( + GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP); - return gh; + return gh; } /** * Internal insert function. * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ -BLI_INLINE void ghash_insert_ex( - GHash *gh, void *key, void *val, const uint bucket_index) +BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val, const uint bucket_index) { - GHashEntry *e = BLI_mempool_alloc(gh->entrypool); + GHashEntry *e = BLI_mempool_alloc(gh->entrypool); - BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - e->e.next = gh->buckets[bucket_index]; - e->e.key = key; - e->val = val; - gh->buckets[bucket_index] = (Entry *)e; + e->e.next = gh->buckets[bucket_index]; + e->e.key = key; + e->val = val; + gh->buckets[bucket_index] = (Entry *)e; - ghash_buckets_expand(gh, ++gh->nentries, false); + ghash_buckets_expand(gh, ++gh->nentries, false); } /** * Insert function that takes a pre-allocated entry. */ -BLI_INLINE void ghash_insert_ex_keyonly_entry( - GHash *gh, void *key, const uint bucket_index, - Entry *e) +BLI_INLINE void ghash_insert_ex_keyonly_entry(GHash *gh, + void *key, + const uint bucket_index, + Entry *e) { - BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); - e->next = gh->buckets[bucket_index]; - e->key = key; - gh->buckets[bucket_index] = e; + e->next = gh->buckets[bucket_index]; + e->key = key; + gh->buckets[bucket_index] = e; - ghash_buckets_expand(gh, ++gh->nentries, false); + ghash_buckets_expand(gh, ++gh->nentries, false); } /** * Insert function that doesn't set the value (use for GSet) */ -BLI_INLINE void ghash_insert_ex_keyonly( - GHash *gh, void *key, const uint bucket_index) +BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key, const uint bucket_index) { - Entry *e = BLI_mempool_alloc(gh->entrypool); + Entry *e = BLI_mempool_alloc(gh->entrypool); - BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); - BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); - e->next = gh->buckets[bucket_index]; - e->key = key; - gh->buckets[bucket_index] = e; + e->next = gh->buckets[bucket_index]; + e->key = key; + gh->buckets[bucket_index] = e; - ghash_buckets_expand(gh, ++gh->nentries, false); + ghash_buckets_expand(gh, ++gh->nentries, false); } BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - - ghash_insert_ex(gh, key, val, bucket_index); -} - -BLI_INLINE bool ghash_insert_safe( - GHash *gh, void *key, void *val, const bool override, - GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) -{ - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); - - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - - if (e) { - if (override) { - if (keyfreefp) { - keyfreefp(e->e.key); - } - if (valfreefp) { - valfreefp(e->val); - } - e->e.key = key; - e->val = val; - } - return false; - } - else { - ghash_insert_ex(gh, key, val, bucket_index); - return true; - } -} - -BLI_INLINE bool ghash_insert_safe_keyonly( - GHash *gh, void *key, const bool override, - GHashKeyFreeFP keyfreefp) -{ - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index); - - BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); - - if (e) { - if (override) { - if (keyfreefp) { - keyfreefp(e->key); - } - e->key = key; - } - return false; - } - else { - ghash_insert_ex_keyonly(gh, key, bucket_index); - return true; - } + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + + ghash_insert_ex(gh, key, val, bucket_index); +} + +BLI_INLINE bool ghash_insert_safe(GHash *gh, + void *key, + void *val, + const bool override, + GHashKeyFreeFP keyfreefp, + GHashValFreeFP valfreefp) +{ + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + + if (e) { + if (override) { + if (keyfreefp) { + keyfreefp(e->e.key); + } + if (valfreefp) { + valfreefp(e->val); + } + e->e.key = key; + e->val = val; + } + return false; + } + else { + ghash_insert_ex(gh, key, val, bucket_index); + return true; + } +} + +BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, + void *key, + const bool override, + GHashKeyFreeFP keyfreefp) +{ + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index); + + BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); + + if (e) { + if (override) { + if (keyfreefp) { + keyfreefp(e->key); + } + e->key = key; + } + return false; + } + else { + ghash_insert_ex_keyonly(gh, key, bucket_index); + return true; + } } /** * Remove the entry and return it, caller must free from gh->entrypool. */ -static Entry *ghash_remove_ex( - GHash *gh, const void *key, - GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, - const uint bucket_index) +static Entry *ghash_remove_ex(GHash *gh, + const void *key, + GHashKeyFreeFP keyfreefp, + GHashValFreeFP valfreefp, + const uint bucket_index) { - Entry *e_prev; - Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index); + Entry *e_prev; + Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index); - BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); - if (e) { - if (keyfreefp) { - keyfreefp(e->key); - } - if (valfreefp) { - valfreefp(((GHashEntry *)e)->val); - } + if (e) { + if (keyfreefp) { + keyfreefp(e->key); + } + if (valfreefp) { + valfreefp(((GHashEntry *)e)->val); + } - if (e_prev) { - e_prev->next = e->next; - } - else { - gh->buckets[bucket_index] = e->next; - } + if (e_prev) { + e_prev->next = e->next; + } + else { + gh->buckets[bucket_index] = e->next; + } - ghash_buckets_contract(gh, --gh->nentries, false, false); - } + ghash_buckets_contract(gh, --gh->nentries, false, false); + } - return e; + return e; } /** @@ -605,49 +608,47 @@ static Entry *ghash_remove_ex( */ static Entry *ghash_pop(GHash *gh, GHashIterState *state) { - uint curr_bucket = state->curr_bucket; - if (gh->nentries == 0) { - return NULL; - } + uint curr_bucket = state->curr_bucket; + if (gh->nentries == 0) { + return NULL; + } - /* Note: using first_bucket_index here allows us to avoid potential - * huge number of loops over buckets, - * in case we are popping from a large ghash with few items in it... */ - curr_bucket = ghash_find_next_bucket_index(gh, curr_bucket); + /* Note: using first_bucket_index here allows us to avoid potential + * huge number of loops over buckets, + * in case we are popping from a large ghash with few items in it... */ + curr_bucket = ghash_find_next_bucket_index(gh, curr_bucket); - Entry *e = gh->buckets[curr_bucket]; - BLI_assert(e); + Entry *e = gh->buckets[curr_bucket]; + BLI_assert(e); - ghash_remove_ex(gh, e->key, NULL, NULL, curr_bucket); + ghash_remove_ex(gh, e->key, NULL, NULL, curr_bucket); - state->curr_bucket = curr_bucket; - return e; + state->curr_bucket = curr_bucket; + return e; } /** * Run free callbacks for freeing entries. */ -static void ghash_free_cb( - GHash *gh, - GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - uint i; + uint i; - BLI_assert(keyfreefp || valfreefp); - BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(keyfreefp || valfreefp); + BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); - for (i = 0; i < gh->nbuckets; i++) { - Entry *e; + for (i = 0; i < gh->nbuckets; i++) { + Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - if (keyfreefp) { - keyfreefp(e->key); - } - if (valfreefp) { - valfreefp(((GHashEntry *)e)->val); - } - } - } + for (e = gh->buckets[i]; e; e = e->next) { + if (keyfreefp) { + keyfreefp(e->key); + } + if (valfreefp) { + valfreefp(((GHashEntry *)e)->val); + } + } + } } /** @@ -655,38 +656,38 @@ static void ghash_free_cb( */ static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) { - GHash *gh_new; - uint i; - /* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */ - const uint reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries); + GHash *gh_new; + uint i; + /* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */ + const uint reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries); - BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET)); - gh_new = ghash_new(gh->hashfp, gh->cmpfp, __func__, 0, gh->flag); - ghash_buckets_expand(gh_new, reserve_nentries_new, false); + gh_new = ghash_new(gh->hashfp, gh->cmpfp, __func__, 0, gh->flag); + ghash_buckets_expand(gh_new, reserve_nentries_new, false); - BLI_assert(gh_new->nbuckets == gh->nbuckets); + BLI_assert(gh_new->nbuckets == gh->nbuckets); - for (i = 0; i < gh->nbuckets; i++) { - Entry *e; + for (i = 0; i < gh->nbuckets; i++) { + Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - Entry *e_new = BLI_mempool_alloc(gh_new->entrypool); - ghash_entry_copy(gh_new, e_new, gh, e, keycopyfp, valcopyfp); + for (e = gh->buckets[i]; e; e = e->next) { + Entry *e_new = BLI_mempool_alloc(gh_new->entrypool); + ghash_entry_copy(gh_new, e_new, gh, e, keycopyfp, valcopyfp); - /* Warning! - * This means entries in buckets in new copy will be in reversed order! - * This shall not be an issue though, since order should never be assumed in ghash. */ + /* Warning! + * This means entries in buckets in new copy will be in reversed order! + * This shall not be an issue though, since order should never be assumed in ghash. */ - /* Note: We can use 'i' here, since we are sure that - * 'gh' and 'gh_new' have the same number of buckets! */ - e_new->next = gh_new->buckets[i]; - gh_new->buckets[i] = e_new; - } - } - gh_new->nentries = gh->nentries; + /* Note: We can use 'i' here, since we are sure that + * 'gh' and 'gh_new' have the same number of buckets! */ + e_new->next = gh_new->buckets[i]; + gh_new->buckets[i] = e_new; + } + } + gh_new->nentries = gh->nentries; - return gh_new; + return gh_new; } /** \} */ @@ -705,11 +706,12 @@ static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP val * Use this to avoid resizing buckets if the size is known or can be closely approximated. * \return An empty GHash. */ -GHash *BLI_ghash_new_ex( - GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, - const uint nentries_reserve) +GHash *BLI_ghash_new_ex(GHashHashFP hashfp, + GHashCmpFP cmpfp, + const char *info, + const uint nentries_reserve) { - return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0); + return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0); } /** @@ -717,7 +719,7 @@ GHash *BLI_ghash_new_ex( */ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) { - return BLI_ghash_new_ex(hashfp, cmpfp, info, 0); + return BLI_ghash_new_ex(hashfp, cmpfp, info, 0); } /** @@ -725,7 +727,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) */ GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) { - return ghash_copy(gh, keycopyfp, valcopyfp); + return ghash_copy(gh, keycopyfp, valcopyfp); } /** @@ -733,8 +735,8 @@ GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcop */ void BLI_ghash_reserve(GHash *gh, const uint nentries_reserve) { - ghash_buckets_expand(gh, nentries_reserve, true); - ghash_buckets_contract(gh, nentries_reserve, true, false); + ghash_buckets_expand(gh, nentries_reserve, true); + ghash_buckets_contract(gh, nentries_reserve, true, false); } /** @@ -742,7 +744,7 @@ void BLI_ghash_reserve(GHash *gh, const uint nentries_reserve) */ uint BLI_ghash_len(GHash *gh) { - return gh->nentries; + return gh->nentries; } /** @@ -754,7 +756,7 @@ uint BLI_ghash_len(GHash *gh) */ void BLI_ghash_insert(GHash *gh, void *key, void *val) { - ghash_insert(gh, key, val); + ghash_insert(gh, key, val); } /** @@ -764,9 +766,10 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val) * * \returns true if a new key has been added. */ -bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +bool BLI_ghash_reinsert( + GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - return ghash_insert_safe(gh, key, val, true, keyfreefp, valfreefp); + return ghash_insert_safe(gh, key, val, true, keyfreefp, valfreefp); } /** @@ -778,17 +781,17 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef */ void *BLI_ghash_replace_key(GHash *gh, void *key) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); - if (e != NULL) { - void *key_prev = e->e.key; - e->e.key = key; - return key_prev; - } - else { - return NULL; - } + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + if (e != NULL) { + void *key_prev = e->e.key; + e->e.key = key; + return key_prev; + } + else { + return NULL; + } } /** @@ -802,9 +805,9 @@ void *BLI_ghash_replace_key(GHash *gh, void *key) */ void *BLI_ghash_lookup(GHash *gh, const void *key) { - GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - return e ? e->val : NULL; + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + return e ? e->val : NULL; } /** @@ -812,9 +815,9 @@ void *BLI_ghash_lookup(GHash *gh, const void *key) */ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) { - GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - return e ? e->val : val_default; + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + return e ? e->val : val_default; } /** @@ -829,9 +832,9 @@ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) */ void **BLI_ghash_lookup_p(GHash *gh, const void *key) { - GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - return e ? &e->val : NULL; + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + return e ? &e->val : NULL; } /** @@ -850,18 +853,18 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key) */ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); - const bool haskey = (e != NULL); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + const bool haskey = (e != NULL); - if (!haskey) { - e = BLI_mempool_alloc(gh->entrypool); - ghash_insert_ex_keyonly_entry(gh, key, bucket_index, (Entry *)e); - } + if (!haskey) { + e = BLI_mempool_alloc(gh->entrypool); + ghash_insert_ex_keyonly_entry(gh, key, bucket_index, (Entry *)e); + } - *r_val = &e->val; - return haskey; + *r_val = &e->val; + return haskey; } /** @@ -870,24 +873,23 @@ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) * * \warning Caller _must_ write to \a r_key when returning false. */ -bool BLI_ghash_ensure_p_ex( - GHash *gh, const void *key, void ***r_key, void ***r_val) +bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); - const bool haskey = (e != NULL); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + const bool haskey = (e != NULL); - if (!haskey) { - /* pass 'key' incase we resize */ - e = BLI_mempool_alloc(gh->entrypool); - ghash_insert_ex_keyonly_entry(gh, (void *)key, bucket_index, (Entry *)e); - e->e.key = NULL; /* caller must re-assign */ - } + if (!haskey) { + /* pass 'key' incase we resize */ + e = BLI_mempool_alloc(gh->entrypool); + ghash_insert_ex_keyonly_entry(gh, (void *)key, bucket_index, (Entry *)e); + e->e.key = NULL; /* caller must re-assign */ + } - *r_key = &e->e.key; - *r_val = &e->val; - return haskey; + *r_key = &e->e.key; + *r_val = &e->val; + return haskey; } /** @@ -898,18 +900,21 @@ bool BLI_ghash_ensure_p_ex( * \param valfreefp: Optional callback to free the value. * \return true if \a key was removed from \a gh. */ -bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) -{ - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index); - if (e) { - BLI_mempool_free(gh->entrypool, e); - return true; - } - else { - return false; - } +bool BLI_ghash_remove(GHash *gh, + const void *key, + GHashKeyFreeFP keyfreefp, + GHashValFreeFP valfreefp) +{ + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index); + if (e) { + BLI_mempool_free(gh->entrypool, e); + return true; + } + else { + return false; + } } /* same as above but return the value, @@ -923,18 +928,18 @@ bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHas */ void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) { - const uint hash = ghash_keyhash(gh, key); - const uint bucket_index = ghash_bucket_index(gh, hash); - GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - if (e) { - void *val = e->val; - BLI_mempool_free(gh->entrypool, e); - return val; - } - else { - return NULL; - } + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + if (e) { + void *val = e->val; + BLI_mempool_free(gh->entrypool, e); + return val; + } + else { + return NULL; + } } /** @@ -942,7 +947,7 @@ void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) */ bool BLI_ghash_haskey(GHash *gh, const void *key) { - return (ghash_lookup_entry(gh, key) != NULL); + return (ghash_lookup_entry(gh, key) != NULL); } /** @@ -953,25 +958,23 @@ bool BLI_ghash_haskey(GHash *gh, const void *key) * \param state: Used for efficient removal. * \return true if there was something to pop, false if ghash was already empty. */ -bool BLI_ghash_pop( - GHash *gh, GHashIterState *state, - void **r_key, void **r_val) +bool BLI_ghash_pop(GHash *gh, GHashIterState *state, void **r_key, void **r_val) { - GHashEntry *e = (GHashEntry *)ghash_pop(gh, state); + GHashEntry *e = (GHashEntry *)ghash_pop(gh, state); - BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - if (e) { - *r_key = e->e.key; - *r_val = e->val; + if (e) { + *r_key = e->e.key; + *r_val = e->val; - BLI_mempool_free(gh->entrypool, e); - return true; - } - else { - *r_key = *r_val = NULL; - return false; - } + BLI_mempool_free(gh->entrypool, e); + return true; + } + else { + *r_key = *r_val = NULL; + return false; + } } /** @@ -981,16 +984,17 @@ bool BLI_ghash_pop( * \param valfreefp: Optional callback to free the value. * \param nentries_reserve: Optionally reserve the number of members that the hash will hold. */ -void BLI_ghash_clear_ex( - GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, - const uint nentries_reserve) +void BLI_ghash_clear_ex(GHash *gh, + GHashKeyFreeFP keyfreefp, + GHashValFreeFP valfreefp, + const uint nentries_reserve) { - if (keyfreefp || valfreefp) { - ghash_free_cb(gh, keyfreefp, valfreefp); - } + if (keyfreefp || valfreefp) { + ghash_free_cb(gh, keyfreefp, valfreefp); + } - ghash_buckets_reset(gh, nentries_reserve); - BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1); + ghash_buckets_reset(gh, nentries_reserve); + BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1); } /** @@ -998,7 +1002,7 @@ void BLI_ghash_clear_ex( */ void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - BLI_ghash_clear_ex(gh, keyfreefp, valfreefp, 0); + BLI_ghash_clear_ex(gh, keyfreefp, valfreefp, 0); } /** @@ -1010,14 +1014,14 @@ void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfree */ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - BLI_assert((int)gh->nentries == BLI_mempool_len(gh->entrypool)); - if (keyfreefp || valfreefp) { - ghash_free_cb(gh, keyfreefp, valfreefp); - } + BLI_assert((int)gh->nentries == BLI_mempool_len(gh->entrypool)); + if (keyfreefp || valfreefp) { + ghash_free_cb(gh, keyfreefp, valfreefp); + } - MEM_freeN(gh->buckets); - BLI_mempool_destroy(gh->entrypool); - MEM_freeN(gh); + MEM_freeN(gh->buckets); + BLI_mempool_destroy(gh->entrypool); + MEM_freeN(gh); } /** @@ -1025,7 +1029,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef */ void BLI_ghash_flag_set(GHash *gh, uint flag) { - gh->flag |= flag; + gh->flag |= flag; } /** @@ -1033,7 +1037,7 @@ void BLI_ghash_flag_set(GHash *gh, uint flag) */ void BLI_ghash_flag_clear(GHash *gh, uint flag) { - gh->flag &= ~flag; + gh->flag &= ~flag; } /** \} */ @@ -1052,9 +1056,9 @@ void BLI_ghash_flag_clear(GHash *gh, uint flag) */ GHashIterator *BLI_ghashIterator_new(GHash *gh) { - GHashIterator *ghi = MEM_mallocN(sizeof(*ghi), "ghash iterator"); - BLI_ghashIterator_init(ghi, gh); - return ghi; + GHashIterator *ghi = MEM_mallocN(sizeof(*ghi), "ghash iterator"); + BLI_ghashIterator_init(ghi, gh); + return ghi; } /** @@ -1067,18 +1071,18 @@ GHashIterator *BLI_ghashIterator_new(GHash *gh) */ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) { - ghi->gh = gh; - ghi->curEntry = NULL; - ghi->curBucket = UINT_MAX; /* wraps to zero */ - if (gh->nentries) { - do { - ghi->curBucket++; - if (UNLIKELY(ghi->curBucket == ghi->gh->nbuckets)) { - break; - } - ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; - } while (!ghi->curEntry); - } + ghi->gh = gh; + ghi->curEntry = NULL; + ghi->curBucket = UINT_MAX; /* wraps to zero */ + if (gh->nentries) { + do { + ghi->curBucket++; + if (UNLIKELY(ghi->curBucket == ghi->gh->nbuckets)) { + break; + } + ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; + } while (!ghi->curEntry); + } } /** @@ -1088,16 +1092,16 @@ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) */ void BLI_ghashIterator_step(GHashIterator *ghi) { - if (ghi->curEntry) { - ghi->curEntry = ghi->curEntry->next; - while (!ghi->curEntry) { - ghi->curBucket++; - if (ghi->curBucket == ghi->gh->nbuckets) { - break; - } - ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; - } - } + if (ghi->curEntry) { + ghi->curEntry = ghi->curEntry->next; + while (!ghi->curEntry) { + ghi->curBucket++; + if (ghi->curBucket == ghi->gh->nbuckets) { + break; + } + ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; + } + } } /** @@ -1107,7 +1111,7 @@ void BLI_ghashIterator_step(GHashIterator *ghi) */ void BLI_ghashIterator_free(GHashIterator *ghi) { - MEM_freeN(ghi); + MEM_freeN(ghi); } /** \} */ @@ -1117,16 +1121,17 @@ void BLI_ghashIterator_free(GHashIterator *ghi) * * Use ghash API to give 'set' functionality * \{ */ -GSet *BLI_gset_new_ex( - GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, - const uint nentries_reserve) +GSet *BLI_gset_new_ex(GSetHashFP hashfp, + GSetCmpFP cmpfp, + const char *info, + const uint nentries_reserve) { - return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET); + return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET); } GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) { - return BLI_gset_new_ex(hashfp, cmpfp, info, 0); + return BLI_gset_new_ex(hashfp, cmpfp, info, 0); } /** @@ -1134,12 +1139,12 @@ GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) */ GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp) { - return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL); + return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL); } uint BLI_gset_len(GSet *gs) { - return ((GHash *)gs)->nentries; + return ((GHash *)gs)->nentries; } /** @@ -1148,9 +1153,9 @@ uint BLI_gset_len(GSet *gs) */ void BLI_gset_insert(GSet *gs, void *key) { - const uint hash = ghash_keyhash((GHash *)gs, key); - const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); - ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index); + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); + ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index); } /** @@ -1161,7 +1166,7 @@ void BLI_gset_insert(GSet *gs, void *key) */ bool BLI_gset_add(GSet *gs, void *key) { - return ghash_insert_safe_keyonly((GHash *)gs, key, false, NULL); + return ghash_insert_safe_keyonly((GHash *)gs, key, false, NULL); } /** @@ -1172,20 +1177,20 @@ bool BLI_gset_add(GSet *gs, void *key) */ bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key) { - const uint hash = ghash_keyhash((GHash *)gs, key); - const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); - GSetEntry *e = (GSetEntry *)ghash_lookup_entry_ex((GHash *)gs, key, bucket_index); - const bool haskey = (e != NULL); + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); + GSetEntry *e = (GSetEntry *)ghash_lookup_entry_ex((GHash *)gs, key, bucket_index); + const bool haskey = (e != NULL); - if (!haskey) { - /* pass 'key' incase we resize */ - e = BLI_mempool_alloc(((GHash *)gs)->entrypool); - ghash_insert_ex_keyonly_entry((GHash *)gs, (void *)key, bucket_index, (Entry *)e); - e->key = NULL; /* caller must re-assign */ - } + if (!haskey) { + /* pass 'key' incase we resize */ + e = BLI_mempool_alloc(((GHash *)gs)->entrypool); + ghash_insert_ex_keyonly_entry((GHash *)gs, (void *)key, bucket_index, (Entry *)e); + e->key = NULL; /* caller must re-assign */ + } - *r_key = &e->key; - return haskey; + *r_key = &e->key; + return haskey; } /** @@ -1196,7 +1201,7 @@ bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key) */ bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) { - return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp); + return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp); } /** @@ -1207,19 +1212,17 @@ bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) */ void *BLI_gset_replace_key(GSet *gs, void *key) { - return BLI_ghash_replace_key((GHash *)gs, key); + return BLI_ghash_replace_key((GHash *)gs, key); } - bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp) { - return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL); + return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL); } - bool BLI_gset_haskey(GSet *gs, const void *key) { - return (ghash_lookup_entry((GHash *)gs, key) != NULL); + return (ghash_lookup_entry((GHash *)gs, key) != NULL); } /** @@ -1229,51 +1232,45 @@ bool BLI_gset_haskey(GSet *gs, const void *key) * \param state: Used for efficient removal. * \return true if there was something to pop, false if gset was already empty. */ -bool BLI_gset_pop( - GSet *gs, GSetIterState *state, - void **r_key) +bool BLI_gset_pop(GSet *gs, GSetIterState *state, void **r_key) { - GSetEntry *e = (GSetEntry *)ghash_pop((GHash *)gs, (GHashIterState *)state); + GSetEntry *e = (GSetEntry *)ghash_pop((GHash *)gs, (GHashIterState *)state); - if (e) { - *r_key = e->key; + if (e) { + *r_key = e->key; - BLI_mempool_free(((GHash *)gs)->entrypool, e); - return true; - } - else { - *r_key = NULL; - return false; - } + BLI_mempool_free(((GHash *)gs)->entrypool, e); + return true; + } + else { + *r_key = NULL; + return false; + } } -void BLI_gset_clear_ex( - GSet *gs, GSetKeyFreeFP keyfreefp, - const uint nentries_reserve) +void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, const uint nentries_reserve) { - BLI_ghash_clear_ex( - (GHash *)gs, keyfreefp, NULL, - nentries_reserve); + BLI_ghash_clear_ex((GHash *)gs, keyfreefp, NULL, nentries_reserve); } void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp) { - BLI_ghash_clear((GHash *)gs, keyfreefp, NULL); + BLI_ghash_clear((GHash *)gs, keyfreefp, NULL); } void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp) { - BLI_ghash_free((GHash *)gs, keyfreefp, NULL); + BLI_ghash_free((GHash *)gs, keyfreefp, NULL); } void BLI_gset_flag_set(GSet *gs, uint flag) { - ((GHash *)gs)->flag |= flag; + ((GHash *)gs)->flag |= flag; } void BLI_gset_flag_clear(GSet *gs, uint flag) { - ((GHash *)gs)->flag &= ~flag; + ((GHash *)gs)->flag &= ~flag; } /** \} */ @@ -1290,8 +1287,8 @@ void BLI_gset_flag_clear(GSet *gs, uint flag) */ void *BLI_gset_lookup(GSet *gs, const void *key) { - Entry *e = ghash_lookup_entry((GHash *)gs, key); - return e ? e->key : NULL; + Entry *e = ghash_lookup_entry((GHash *)gs, key); + return e ? e->key : NULL; } /** @@ -1300,17 +1297,17 @@ void *BLI_gset_lookup(GSet *gs, const void *key) */ void *BLI_gset_pop_key(GSet *gs, const void *key) { - const uint hash = ghash_keyhash((GHash *)gs, key); - const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); - Entry *e = ghash_remove_ex((GHash *)gs, key, NULL, NULL, bucket_index); - if (e) { - void *key_ret = e->key; - BLI_mempool_free(((GHash *)gs)->entrypool, e); - return key_ret; - } - else { - return NULL; - } + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); + Entry *e = ghash_remove_ex((GHash *)gs, key, NULL, NULL, bucket_index); + if (e) { + void *key_ret = e->key; + BLI_mempool_free(((GHash *)gs)->entrypool, e); + return key_ret; + } + else { + return NULL; + } } /** \} */ @@ -1326,11 +1323,11 @@ void *BLI_gset_pop_key(GSet *gs, const void *key) */ int BLI_ghash_buckets_len(GHash *gh) { - return (int)gh->nbuckets; + return (int)gh->nbuckets; } int BLI_gset_buckets_len(GSet *gs) { - return BLI_ghash_buckets_len((GHash *)gs); + return BLI_ghash_buckets_len((GHash *)gs); } /** @@ -1339,106 +1336,115 @@ int BLI_gset_buckets_len(GSet *gs) * * Smaller is better! */ -double BLI_ghash_calc_quality_ex( - GHash *gh, double *r_load, double *r_variance, - double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket) -{ - double mean; - uint i; - - if (gh->nentries == 0) { - if (r_load) { - *r_load = 0.0; - } - if (r_variance) { - *r_variance = 0.0; - } - if (r_prop_empty_buckets) { - *r_prop_empty_buckets = 1.0; - } - if (r_prop_overloaded_buckets) { - *r_prop_overloaded_buckets = 0.0; - } - if (r_biggest_bucket) { - *r_biggest_bucket = 0; - } - - return 0.0; - } - - mean = (double)gh->nentries / (double)gh->nbuckets; - if (r_load) { - *r_load = mean; - } - if (r_biggest_bucket) { - *r_biggest_bucket = 0; - } - - if (r_variance) { - /* We already know our mean (i.e. load factor), easy to compute variance. - * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm - */ - double sum = 0.0; - for (i = 0; i < gh->nbuckets; i++) { - int count = 0; - Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - count++; - } - sum += ((double)count - mean) * ((double)count - mean); - } - *r_variance = sum / (double)(gh->nbuckets - 1); - } - - { - uint64_t sum = 0; - uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1); - uint64_t sum_overloaded = 0; - uint64_t sum_empty = 0; - - for (i = 0; i < gh->nbuckets; i++) { - uint64_t count = 0; - Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - count++; - } - if (r_biggest_bucket) { - *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count); - } - if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) { - sum_overloaded++; - } - if (r_prop_empty_buckets && !count) { - sum_empty++; - } - sum += count * (count + 1); - } - if (r_prop_overloaded_buckets) { - *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets; - } - if (r_prop_empty_buckets) { - *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets; - } - return ((double)sum * (double)gh->nbuckets / - ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); - } -} -double BLI_gset_calc_quality_ex( - GSet *gs, double *r_load, double *r_variance, - double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket) -{ - return BLI_ghash_calc_quality_ex( - (GHash *)gs, r_load, r_variance, - r_prop_empty_buckets, r_prop_overloaded_buckets, r_biggest_bucket); +double BLI_ghash_calc_quality_ex(GHash *gh, + double *r_load, + double *r_variance, + double *r_prop_empty_buckets, + double *r_prop_overloaded_buckets, + int *r_biggest_bucket) +{ + double mean; + uint i; + + if (gh->nentries == 0) { + if (r_load) { + *r_load = 0.0; + } + if (r_variance) { + *r_variance = 0.0; + } + if (r_prop_empty_buckets) { + *r_prop_empty_buckets = 1.0; + } + if (r_prop_overloaded_buckets) { + *r_prop_overloaded_buckets = 0.0; + } + if (r_biggest_bucket) { + *r_biggest_bucket = 0; + } + + return 0.0; + } + + mean = (double)gh->nentries / (double)gh->nbuckets; + if (r_load) { + *r_load = mean; + } + if (r_biggest_bucket) { + *r_biggest_bucket = 0; + } + + if (r_variance) { + /* We already know our mean (i.e. load factor), easy to compute variance. + * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm + */ + double sum = 0.0; + for (i = 0; i < gh->nbuckets; i++) { + int count = 0; + Entry *e; + for (e = gh->buckets[i]; e; e = e->next) { + count++; + } + sum += ((double)count - mean) * ((double)count - mean); + } + *r_variance = sum / (double)(gh->nbuckets - 1); + } + + { + uint64_t sum = 0; + uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1); + uint64_t sum_overloaded = 0; + uint64_t sum_empty = 0; + + for (i = 0; i < gh->nbuckets; i++) { + uint64_t count = 0; + Entry *e; + for (e = gh->buckets[i]; e; e = e->next) { + count++; + } + if (r_biggest_bucket) { + *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count); + } + if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) { + sum_overloaded++; + } + if (r_prop_empty_buckets && !count) { + sum_empty++; + } + sum += count * (count + 1); + } + if (r_prop_overloaded_buckets) { + *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets; + } + if (r_prop_empty_buckets) { + *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets; + } + return ((double)sum * (double)gh->nbuckets / + ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); + } +} +double BLI_gset_calc_quality_ex(GSet *gs, + double *r_load, + double *r_variance, + double *r_prop_empty_buckets, + double *r_prop_overloaded_buckets, + int *r_biggest_bucket) +{ + return BLI_ghash_calc_quality_ex((GHash *)gs, + r_load, + r_variance, + r_prop_empty_buckets, + r_prop_overloaded_buckets, + r_biggest_bucket); } double BLI_ghash_calc_quality(GHash *gh) { - return BLI_ghash_calc_quality_ex(gh, NULL, NULL, NULL, NULL, NULL); + return BLI_ghash_calc_quality_ex(gh, NULL, NULL, NULL, NULL, NULL); } double BLI_gset_calc_quality(GSet *gs) { - return BLI_ghash_calc_quality_ex((GHash *)gs, NULL, NULL, NULL, NULL, NULL); + return BLI_ghash_calc_quality_ex((GHash *)gs, NULL, NULL, NULL, NULL, NULL); } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c index 5e271c21830..1c6484acbdf 100644 --- a/source/blender/blenlib/intern/BLI_ghash_utils.c +++ b/source/blender/blenlib/intern/BLI_ghash_utils.c @@ -30,7 +30,7 @@ #include "BLI_utildefines.h" #include "BLI_hash_mm2a.h" -#include "BLI_ghash.h" /* own include */ +#include "BLI_ghash.h" /* own include */ /* keep last */ #include "BLI_strict_flags.h" @@ -43,94 +43,94 @@ /* works but slower */ uint BLI_ghashutil_ptrhash(const void *key) { - return (uint)(intptr_t)key; + return (uint)(intptr_t)key; } #else /* Based Python3.7's pointer hashing function. */ uint BLI_ghashutil_ptrhash(const void *key) { - size_t y = (size_t)key; - /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid - * excessive hash collisions for dicts and sets */ + size_t y = (size_t)key; + /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid + * excessive hash collisions for dicts and sets */ - /* Note: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)', - * Otherwise casting to 'uint' ignores the upper bits on 64bit platforms. */ - return (uint)(y >> 4) | ((uint)y << (8 * sizeof(uint) - 4)); + /* Note: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)', + * Otherwise casting to 'uint' ignores the upper bits on 64bit platforms. */ + return (uint)(y >> 4) | ((uint)y << (8 * sizeof(uint) - 4)); } #endif bool BLI_ghashutil_ptrcmp(const void *a, const void *b) { - return (a != b); + return (a != b); } uint BLI_ghashutil_uinthash_v4(const uint key[4]) { - uint hash; - hash = key[0]; - hash *= 37; - hash += key[1]; - hash *= 37; - hash += key[2]; - hash *= 37; - hash += key[3]; - return hash; + uint hash; + hash = key[0]; + hash *= 37; + hash += key[1]; + hash *= 37; + hash += key[2]; + hash *= 37; + hash += key[3]; + return hash; } uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4]) { - return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0); + return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0); } bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) { - return (memcmp(a, b, sizeof(uint[4])) != 0); + return (memcmp(a, b, sizeof(uint[4])) != 0); } uint BLI_ghashutil_uinthash(uint key) { - key += ~(key << 16); - key ^= (key >> 5); - key += (key << 3); - key ^= (key >> 13); - key += ~(key << 9); - key ^= (key >> 17); + key += ~(key << 16); + key ^= (key >> 5); + key += (key << 3); + key ^= (key >> 13); + key += ~(key << 9); + key ^= (key >> 17); - return key; + return key; } uint BLI_ghashutil_inthash_p(const void *ptr) { - uintptr_t key = (uintptr_t)ptr; + uintptr_t key = (uintptr_t)ptr; - key += ~(key << 16); - key ^= (key >> 5); - key += (key << 3); - key ^= (key >> 13); - key += ~(key << 9); - key ^= (key >> 17); + key += ~(key << 16); + key ^= (key >> 5); + key += (key << 3); + key ^= (key >> 13); + key += ~(key << 9); + key ^= (key >> 17); - return (uint)(key & 0xffffffff); + return (uint)(key & 0xffffffff); } uint BLI_ghashutil_inthash_p_murmur(const void *ptr) { - uintptr_t key = (uintptr_t)ptr; + uintptr_t key = (uintptr_t)ptr; - return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); + return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); } uint BLI_ghashutil_inthash_p_simple(const void *ptr) { - return POINTER_AS_UINT(ptr); + return POINTER_AS_UINT(ptr); } bool BLI_ghashutil_intcmp(const void *a, const void *b) { - return (a != b); + return (a != b); } size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) { - return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); + return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); } /** @@ -144,64 +144,63 @@ size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) */ uint BLI_ghashutil_strhash_n(const char *key, size_t n) { - const signed char *p; - uint h = 5381; + const signed char *p; + uint h = 5381; - for (p = (const signed char *)key; n-- && *p != '\0'; p++) { - h = (uint)((h << 5) + h) + (uint)*p; - } + for (p = (const signed char *)key; n-- && *p != '\0'; p++) { + h = (uint)((h << 5) + h) + (uint)*p; + } - return h; + return h; } uint BLI_ghashutil_strhash_p(const void *ptr) { - const signed char *p; - uint h = 5381; + const signed char *p; + uint h = 5381; - for (p = ptr; *p != '\0'; p++) { - h = (uint)((h << 5) + h) + (uint)*p; - } + for (p = ptr; *p != '\0'; p++) { + h = (uint)((h << 5) + h) + (uint)*p; + } - return h; + return h; } uint BLI_ghashutil_strhash_p_murmur(const void *ptr) { - const unsigned char *key = ptr; + const unsigned char *key = ptr; - return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0); + return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0); } bool BLI_ghashutil_strcmp(const void *a, const void *b) { - return (a == b) ? false : !STREQ(a, b); + return (a == b) ? false : !STREQ(a, b); } GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second) { - GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair"); - pair->first = first; - pair->second = second; - return pair; + GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair"); + pair->first = first; + pair->second = second; + return pair; } uint BLI_ghashutil_pairhash(const void *ptr) { - const GHashPair *pair = ptr; - uint hash = BLI_ghashutil_ptrhash(pair->first); - return hash ^ BLI_ghashutil_ptrhash(pair->second); + const GHashPair *pair = ptr; + uint hash = BLI_ghashutil_ptrhash(pair->first); + return hash ^ BLI_ghashutil_ptrhash(pair->second); } bool BLI_ghashutil_paircmp(const void *a, const void *b) { - const GHashPair *A = a; - const GHashPair *B = b; + const GHashPair *A = a; + const GHashPair *B = b; - return ((A->first != B->first) || - (A->second != B->second)); + return ((A->first != B->first) || (A->second != B->second)); } void BLI_ghashutil_pairfree(void *ptr) { - MEM_freeN(ptr); + MEM_freeN(ptr); } /** \} */ @@ -212,38 +211,38 @@ void BLI_ghashutil_pairfree(void *ptr) GHash *BLI_ghash_ptr_new_ex(const char *info, const uint nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } GHash *BLI_ghash_ptr_new(const char *info) { - return BLI_ghash_ptr_new_ex(info, 0); + return BLI_ghash_ptr_new_ex(info, 0); } GHash *BLI_ghash_str_new_ex(const char *info, const uint nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); } GHash *BLI_ghash_str_new(const char *info) { - return BLI_ghash_str_new_ex(info, 0); + return BLI_ghash_str_new_ex(info, 0); } GHash *BLI_ghash_int_new_ex(const char *info, const uint nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve); } GHash *BLI_ghash_int_new(const char *info) { - return BLI_ghash_int_new_ex(info, 0); + return BLI_ghash_int_new_ex(info, 0); } GHash *BLI_ghash_pair_new_ex(const char *info, const uint nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } GHash *BLI_ghash_pair_new(const char *info) { - return BLI_ghash_pair_new_ex(info, 0); + return BLI_ghash_pair_new_ex(info, 0); } /** \} */ @@ -254,29 +253,29 @@ GHash *BLI_ghash_pair_new(const char *info) GSet *BLI_gset_ptr_new_ex(const char *info, const uint nentries_reserve) { - return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); + return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } GSet *BLI_gset_ptr_new(const char *info) { - return BLI_gset_ptr_new_ex(info, 0); + return BLI_gset_ptr_new_ex(info, 0); } GSet *BLI_gset_str_new_ex(const char *info, const uint nentries_reserve) { - return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); + return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); } GSet *BLI_gset_str_new(const char *info) { - return BLI_gset_str_new_ex(info, 0); + return BLI_gset_str_new_ex(info, 0); } GSet *BLI_gset_pair_new_ex(const char *info, const uint nentries_reserve) { - return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); + return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } GSet *BLI_gset_pair_new(const char *info) { - return BLI_gset_pair_new_ex(info, 0); + return BLI_gset_pair_new_ex(info, 0); } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 0e5cfd02939..836b11baa85 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -32,16 +32,16 @@ /***/ struct HeapNode { - float value; - uint index; - void *ptr; + float value; + uint index; + void *ptr; }; struct HeapNode_Chunk { - struct HeapNode_Chunk *prev; - uint size; - uint bufsize; - struct HeapNode buf[0]; + struct HeapNode_Chunk *prev; + uint size; + uint bufsize; + struct HeapNode buf[0]; }; /** @@ -52,143 +52,141 @@ struct HeapNode_Chunk { * \note keep type in sync with tot_nodes in heap_node_alloc_chunk. */ #define HEAP_CHUNK_DEFAULT_NUM \ - ((uint)((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode))) + ((uint)((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode))) struct Heap { - uint size; - uint bufsize; - HeapNode **tree; - - struct { - /* Always keep at least one chunk (never NULL) */ - struct HeapNode_Chunk *chunk; - /* when NULL, allocate a new chunk */ - HeapNode *free; - } nodes; + uint size; + uint bufsize; + HeapNode **tree; + + struct { + /* Always keep at least one chunk (never NULL) */ + struct HeapNode_Chunk *chunk; + /* when NULL, allocate a new chunk */ + HeapNode *free; + } nodes; }; /** \name Internal Functions * \{ */ -#define HEAP_PARENT(i) (((i) - 1) >> 1) -#define HEAP_LEFT(i) (((i) << 1) + 1) -#define HEAP_RIGHT(i) (((i) << 1) + 2) +#define HEAP_PARENT(i) (((i)-1) >> 1) +#define HEAP_LEFT(i) (((i) << 1) + 1) +#define HEAP_RIGHT(i) (((i) << 1) + 2) #define HEAP_COMPARE(a, b) ((a)->value < (b)->value) -#if 0 /* UNUSED */ -#define HEAP_EQUALS(a, b) ((a)->value == (b)->value) +#if 0 /* UNUSED */ +# define HEAP_EQUALS(a, b) ((a)->value == (b)->value) #endif BLI_INLINE void heap_swap(Heap *heap, const uint i, const uint j) { #if 1 - HeapNode **tree = heap->tree; - HeapNode *pi = tree[i], *pj = tree[j]; - pi->index = j; - tree[j] = pi; - pj->index = i; - tree[i] = pj; + HeapNode **tree = heap->tree; + HeapNode *pi = tree[i], *pj = tree[j]; + pi->index = j; + tree[j] = pi; + pj->index = i; + tree[i] = pj; #elif 0 - SWAP(uint, heap->tree[i]->index, heap->tree[j]->index); - SWAP(HeapNode *, heap->tree[i], heap->tree[j]); + SWAP(uint, heap->tree[i]->index, heap->tree[j]->index); + SWAP(HeapNode *, heap->tree[i], heap->tree[j]); #else - HeapNode **tree = heap->tree; - union { - uint index; - HeapNode *node; - } tmp; - SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index); - SWAP_TVAL(tmp.node, tree[i], tree[j]); + HeapNode **tree = heap->tree; + union { + uint index; + HeapNode *node; + } tmp; + SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index); + SWAP_TVAL(tmp.node, tree[i], tree[j]); #endif } static void heap_down(Heap *heap, uint i) { - /* size won't change in the loop */ - HeapNode **const tree = heap->tree; - const uint size = heap->size; - - while (1) { - const uint l = HEAP_LEFT(i); - const uint r = HEAP_RIGHT(i); - uint smallest = i; - - if (LIKELY(l < size) && HEAP_COMPARE(tree[l], tree[smallest])) { - smallest = l; - } - if (LIKELY(r < size) && HEAP_COMPARE(tree[r], tree[smallest])) { - smallest = r; - } - - if (UNLIKELY(smallest == i)) { - break; - } - - heap_swap(heap, i, smallest); - i = smallest; - } + /* size won't change in the loop */ + HeapNode **const tree = heap->tree; + const uint size = heap->size; + + while (1) { + const uint l = HEAP_LEFT(i); + const uint r = HEAP_RIGHT(i); + uint smallest = i; + + if (LIKELY(l < size) && HEAP_COMPARE(tree[l], tree[smallest])) { + smallest = l; + } + if (LIKELY(r < size) && HEAP_COMPARE(tree[r], tree[smallest])) { + smallest = r; + } + + if (UNLIKELY(smallest == i)) { + break; + } + + heap_swap(heap, i, smallest); + i = smallest; + } } static void heap_up(Heap *heap, uint i) { - HeapNode **const tree = heap->tree; + HeapNode **const tree = heap->tree; - while (LIKELY(i > 0)) { - const uint p = HEAP_PARENT(i); + while (LIKELY(i > 0)) { + const uint p = HEAP_PARENT(i); - if (HEAP_COMPARE(tree[p], tree[i])) { - break; - } - heap_swap(heap, p, i); - i = p; - } + if (HEAP_COMPARE(tree[p], tree[i])) { + break; + } + heap_swap(heap, p, i); + i = p; + } } /** \} */ - /** \name Internal Memory Management * \{ */ -static struct HeapNode_Chunk *heap_node_alloc_chunk( - uint tot_nodes, struct HeapNode_Chunk *chunk_prev) +static struct HeapNode_Chunk *heap_node_alloc_chunk(uint tot_nodes, + struct HeapNode_Chunk *chunk_prev) { - struct HeapNode_Chunk *chunk = MEM_mallocN( - sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__); - chunk->prev = chunk_prev; - chunk->bufsize = tot_nodes; - chunk->size = 0; - return chunk; + struct HeapNode_Chunk *chunk = MEM_mallocN( + sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__); + chunk->prev = chunk_prev; + chunk->bufsize = tot_nodes; + chunk->size = 0; + return chunk; } static struct HeapNode *heap_node_alloc(Heap *heap) { - HeapNode *node; - - if (heap->nodes.free) { - node = heap->nodes.free; - heap->nodes.free = heap->nodes.free->ptr; - } - else { - struct HeapNode_Chunk *chunk = heap->nodes.chunk; - if (UNLIKELY(chunk->size == chunk->bufsize)) { - chunk = heap->nodes.chunk = heap_node_alloc_chunk(HEAP_CHUNK_DEFAULT_NUM, chunk); - } - node = &chunk->buf[chunk->size++]; - } - - return node; + HeapNode *node; + + if (heap->nodes.free) { + node = heap->nodes.free; + heap->nodes.free = heap->nodes.free->ptr; + } + else { + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + if (UNLIKELY(chunk->size == chunk->bufsize)) { + chunk = heap->nodes.chunk = heap_node_alloc_chunk(HEAP_CHUNK_DEFAULT_NUM, chunk); + } + node = &chunk->buf[chunk->size++]; + } + + return node; } static void heap_node_free(Heap *heap, HeapNode *node) { - node->ptr = heap->nodes.free; - heap->nodes.free = node; + node->ptr = heap->nodes.free; + heap->nodes.free = node; } /** \} */ - /** \name Public Heap API * \{ */ @@ -199,64 +197,65 @@ static void heap_node_free(Heap *heap, HeapNode *node) */ Heap *BLI_heap_new_ex(uint tot_reserve) { - Heap *heap = MEM_mallocN(sizeof(Heap), __func__); - /* ensure we have at least one so we can keep doubling it */ - heap->size = 0; - heap->bufsize = MAX2(1u, tot_reserve); - heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); + Heap *heap = MEM_mallocN(sizeof(Heap), __func__); + /* ensure we have at least one so we can keep doubling it */ + heap->size = 0; + heap->bufsize = MAX2(1u, tot_reserve); + heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); - heap->nodes.chunk = heap_node_alloc_chunk((tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL); - heap->nodes.free = NULL; + heap->nodes.chunk = heap_node_alloc_chunk( + (tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL); + heap->nodes.free = NULL; - return heap; + return heap; } Heap *BLI_heap_new(void) { - return BLI_heap_new_ex(1); + return BLI_heap_new_ex(1); } void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) { - if (ptrfreefp) { - uint i; - - for (i = 0; i < heap->size; i++) { - ptrfreefp(heap->tree[i]->ptr); - } - } - - struct HeapNode_Chunk *chunk = heap->nodes.chunk; - do { - struct HeapNode_Chunk *chunk_prev; - chunk_prev = chunk->prev; - MEM_freeN(chunk); - chunk = chunk_prev; - } while (chunk); - - MEM_freeN(heap->tree); - MEM_freeN(heap); + if (ptrfreefp) { + uint i; + + for (i = 0; i < heap->size; i++) { + ptrfreefp(heap->tree[i]->ptr); + } + } + + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + do { + struct HeapNode_Chunk *chunk_prev; + chunk_prev = chunk->prev; + MEM_freeN(chunk); + chunk = chunk_prev; + } while (chunk); + + MEM_freeN(heap->tree); + MEM_freeN(heap); } void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) { - if (ptrfreefp) { - uint i; - - for (i = 0; i < heap->size; i++) { - ptrfreefp(heap->tree[i]->ptr); - } - } - heap->size = 0; - - /* Remove all except the last chunk */ - while (heap->nodes.chunk->prev) { - struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev; - MEM_freeN(heap->nodes.chunk); - heap->nodes.chunk = chunk_prev; - } - heap->nodes.chunk->size = 0; - heap->nodes.free = NULL; + if (ptrfreefp) { + uint i; + + for (i = 0; i < heap->size; i++) { + ptrfreefp(heap->tree[i]->ptr); + } + } + heap->size = 0; + + /* Remove all except the last chunk */ + while (heap->nodes.chunk->prev) { + struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev; + MEM_freeN(heap->nodes.chunk); + heap->nodes.chunk = chunk_prev; + } + heap->nodes.chunk->size = 0; + heap->nodes.free = NULL; } /** @@ -265,26 +264,26 @@ void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) */ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) { - HeapNode *node; + HeapNode *node; - if (UNLIKELY(heap->size >= heap->bufsize)) { - heap->bufsize *= 2; - heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); - } + if (UNLIKELY(heap->size >= heap->bufsize)) { + heap->bufsize *= 2; + heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); + } - node = heap_node_alloc(heap); + node = heap_node_alloc(heap); - node->ptr = ptr; - node->value = value; - node->index = heap->size; + node->ptr = ptr; + node->value = value; + node->index = heap->size; - heap->tree[node->index] = node; + heap->tree[node->index] = node; - heap->size++; + heap->size++; - heap_up(heap, node->index); + heap_up(heap, node->index); - return node; + return node; } /** @@ -292,23 +291,22 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) */ void BLI_heap_insert_or_update(Heap *heap, HeapNode **node_p, float value, void *ptr) { - if (*node_p == NULL) { - *node_p = BLI_heap_insert(heap, value, ptr); - } - else { - BLI_heap_node_value_update_ptr(heap, *node_p, value, ptr); - } + if (*node_p == NULL) { + *node_p = BLI_heap_insert(heap, value, ptr); + } + else { + BLI_heap_node_value_update_ptr(heap, *node_p, value, ptr); + } } - bool BLI_heap_is_empty(const Heap *heap) { - return (heap->size == 0); + return (heap->size == 0); } uint BLI_heap_len(const Heap *heap) { - return heap->size; + return heap->size; } /** @@ -317,7 +315,7 @@ uint BLI_heap_len(const Heap *heap) */ HeapNode *BLI_heap_top(const Heap *heap) { - return heap->tree[0]; + return heap->tree[0]; } /** @@ -326,9 +324,9 @@ HeapNode *BLI_heap_top(const Heap *heap) */ float BLI_heap_top_value(const Heap *heap) { - BLI_assert(heap->size != 0); + BLI_assert(heap->size != 0); - return heap->tree[0]->value; + return heap->tree[0]->value; } /** @@ -336,33 +334,33 @@ float BLI_heap_top_value(const Heap *heap) */ void *BLI_heap_pop_min(Heap *heap) { - BLI_assert(heap->size != 0); + BLI_assert(heap->size != 0); - void *ptr = heap->tree[0]->ptr; + void *ptr = heap->tree[0]->ptr; - heap_node_free(heap, heap->tree[0]); + heap_node_free(heap, heap->tree[0]); - if (--heap->size) { - heap_swap(heap, 0, heap->size); - heap_down(heap, 0); - } + if (--heap->size) { + heap_swap(heap, 0, heap->size); + heap_down(heap, 0); + } - return ptr; + return ptr; } void BLI_heap_remove(Heap *heap, HeapNode *node) { - BLI_assert(heap->size != 0); + BLI_assert(heap->size != 0); - uint i = node->index; + uint i = node->index; - while (i > 0) { - uint p = HEAP_PARENT(i); - heap_swap(heap, p, i); - i = p; - } + while (i > 0) { + uint p = HEAP_PARENT(i); + heap_swap(heap, p, i); + i = p; + } - BLI_heap_pop_min(heap); + BLI_heap_pop_min(heap); } /** @@ -372,66 +370,66 @@ void BLI_heap_remove(Heap *heap, HeapNode *node) */ void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value) { - if (value < node->value) { - node->value = value; - heap_up(heap, node->index); - } - else if (value > node->value) { - node->value = value; - heap_down(heap, node->index); - } + if (value < node->value) { + node->value = value; + heap_up(heap, node->index); + } + else if (value > node->value) { + node->value = value; + heap_down(heap, node->index); + } } void BLI_heap_node_value_update_ptr(Heap *heap, HeapNode *node, float value, void *ptr) { - node->ptr = ptr; /* only difference */ - if (value < node->value) { - node->value = value; - heap_up(heap, node->index); - } - else if (value > node->value) { - node->value = value; - heap_down(heap, node->index); - } + node->ptr = ptr; /* only difference */ + if (value < node->value) { + node->value = value; + heap_up(heap, node->index); + } + else if (value > node->value) { + node->value = value; + heap_down(heap, node->index); + } } float BLI_heap_node_value(const HeapNode *node) { - return node->value; + return node->value; } void *BLI_heap_node_ptr(const HeapNode *node) { - return node->ptr; + return node->ptr; } static bool heap_is_minheap(const Heap *heap, uint root) { - if (root < heap->size) { - if (heap->tree[root]->index != root) { - return false; - } - const uint l = HEAP_LEFT(root); - if (l < heap->size) { - if (HEAP_COMPARE(heap->tree[l], heap->tree[root]) || !heap_is_minheap(heap, l)) { - return false; - } - } - const uint r = HEAP_RIGHT(root); - if (r < heap->size) { - if (HEAP_COMPARE(heap->tree[r], heap->tree[root]) || !heap_is_minheap(heap, r)) { - return false; - } - } - } - return true; + if (root < heap->size) { + if (heap->tree[root]->index != root) { + return false; + } + const uint l = HEAP_LEFT(root); + if (l < heap->size) { + if (HEAP_COMPARE(heap->tree[l], heap->tree[root]) || !heap_is_minheap(heap, l)) { + return false; + } + } + const uint r = HEAP_RIGHT(root); + if (r < heap->size) { + if (HEAP_COMPARE(heap->tree[r], heap->tree[root]) || !heap_is_minheap(heap, r)) { + return false; + } + } + } + return true; } /** * Only for checking internal errors (gtest). */ bool BLI_heap_is_valid(const Heap *heap) { - return heap_is_minheap(heap, 0); + return heap_is_minheap(heap, 0); } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_heap_simple.c b/source/blender/blenlib/intern/BLI_heap_simple.c index 50eb06e5d5d..6b27799b808 100644 --- a/source/blender/blenlib/intern/BLI_heap_simple.c +++ b/source/blender/blenlib/intern/BLI_heap_simple.c @@ -33,21 +33,21 @@ #include "BLI_heap_simple.h" #include "BLI_strict_flags.h" -#define HEAP_PARENT(i) (((i) - 1) >> 1) +#define HEAP_PARENT(i) (((i)-1) >> 1) /* -------------------------------------------------------------------- */ /** \name HeapSimple Internal Structs * \{ */ typedef struct HeapSimpleNode { - float value; - void *ptr; + float value; + void *ptr; } HeapSimpleNode; struct HeapSimple { - uint size; - uint bufsize; - HeapSimpleNode *tree; + uint size; + uint bufsize; + HeapSimpleNode *tree; }; /** \} */ @@ -59,63 +59,63 @@ struct HeapSimple { static void heapsimple_down(HeapSimple *heap, uint start_i, const HeapSimpleNode *init) { #if 1 - /* The compiler isn't smart enough to realize that all computations - * using index here can be modified to work with byte offset. */ - uint8_t * const tree_buf = (uint8_t *)heap->tree; + /* The compiler isn't smart enough to realize that all computations + * using index here can be modified to work with byte offset. */ + uint8_t *const tree_buf = (uint8_t *)heap->tree; -#define OFFSET(i) (i * (uint)sizeof(HeapSimpleNode)) -#define NODE(offset) (*(HeapSimpleNode*)(tree_buf + (offset))) +# define OFFSET(i) (i * (uint)sizeof(HeapSimpleNode)) +# define NODE(offset) (*(HeapSimpleNode *)(tree_buf + (offset))) #else - HeapSimpleNode *const tree = heap->tree; + HeapSimpleNode *const tree = heap->tree; -#define OFFSET(i) (i) -#define NODE(i) tree[i] +# define OFFSET(i) (i) +# define NODE(i) tree[i] #endif #define HEAP_LEFT_OFFSET(i) (((i) << 1) + OFFSET(1)) - const uint size = OFFSET(heap->size); + const uint size = OFFSET(heap->size); - /* Pull the active node values into locals. This allows spilling - * the data from registers instead of literally swapping nodes. */ - float active_val = init->value; - void *active_ptr = init->ptr; + /* Pull the active node values into locals. This allows spilling + * the data from registers instead of literally swapping nodes. */ + float active_val = init->value; + void *active_ptr = init->ptr; - /* Prepare the first iteration and spill value. */ - uint i = OFFSET(start_i); + /* Prepare the first iteration and spill value. */ + uint i = OFFSET(start_i); - NODE(i).value = active_val; + NODE(i).value = active_val; - for (;;) { - const uint l = HEAP_LEFT_OFFSET(i); - const uint r = l + OFFSET(1); /* right */ + for (;;) { + const uint l = HEAP_LEFT_OFFSET(i); + const uint r = l + OFFSET(1); /* right */ - /* Find the child with the smallest value. */ - uint smallest = i; + /* Find the child with the smallest value. */ + uint smallest = i; - if (LIKELY(l < size) && NODE(l).value < active_val) { - smallest = l; - } - if (LIKELY(r < size) && NODE(r).value < NODE(smallest).value) { - smallest = r; - } + if (LIKELY(l < size) && NODE(l).value < active_val) { + smallest = l; + } + if (LIKELY(r < size) && NODE(r).value < NODE(smallest).value) { + smallest = r; + } - if (UNLIKELY(smallest == i)) { - break; - } + if (UNLIKELY(smallest == i)) { + break; + } - /* Move the smallest child into the current node. - * Skip padding: for some reason that makes it faster here. */ - NODE(i).value = NODE(smallest).value; - NODE(i).ptr = NODE(smallest).ptr; + /* Move the smallest child into the current node. + * Skip padding: for some reason that makes it faster here. */ + NODE(i).value = NODE(smallest).value; + NODE(i).ptr = NODE(smallest).ptr; - /* Proceed to next iteration and spill value. */ - i = smallest; - NODE(i).value = active_val; - } + /* Proceed to next iteration and spill value. */ + i = smallest; + NODE(i).value = active_val; + } - /* Spill the pointer into the final position of the node. */ - NODE(i).ptr = active_ptr; + /* Spill the pointer into the final position of the node. */ + NODE(i).ptr = active_ptr; #undef NODE #undef OFFSET @@ -124,21 +124,21 @@ static void heapsimple_down(HeapSimple *heap, uint start_i, const HeapSimpleNode static void heapsimple_up(HeapSimple *heap, uint i, float active_val, void *active_ptr) { - HeapSimpleNode *const tree = heap->tree; + HeapSimpleNode *const tree = heap->tree; - while (LIKELY(i > 0)) { - const uint p = HEAP_PARENT(i); + while (LIKELY(i > 0)) { + const uint p = HEAP_PARENT(i); - if (active_val >= tree[p].value) { - break; - } + if (active_val >= tree[p].value) { + break; + } - tree[i] = tree[p]; - i = p; - } + tree[i] = tree[p]; + i = p; + } - tree[i].value = active_val; - tree[i].ptr = active_ptr; + tree[i].value = active_val; + tree[i].ptr = active_ptr; } /** \} */ @@ -154,40 +154,40 @@ static void heapsimple_up(HeapSimple *heap, uint i, float active_val, void *acti */ HeapSimple *BLI_heapsimple_new_ex(uint tot_reserve) { - HeapSimple *heap = MEM_mallocN(sizeof(HeapSimple), __func__); - /* ensure we have at least one so we can keep doubling it */ - heap->size = 0; - heap->bufsize = MAX2(1u, tot_reserve); - heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapSimpleNode), "BLIHeapSimpleTree"); - return heap; + HeapSimple *heap = MEM_mallocN(sizeof(HeapSimple), __func__); + /* ensure we have at least one so we can keep doubling it */ + heap->size = 0; + heap->bufsize = MAX2(1u, tot_reserve); + heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapSimpleNode), "BLIHeapSimpleTree"); + return heap; } HeapSimple *BLI_heapsimple_new(void) { - return BLI_heapsimple_new_ex(1); + return BLI_heapsimple_new_ex(1); } void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) { - if (ptrfreefp) { - for (uint i = 0; i < heap->size; i++) { - ptrfreefp(heap->tree[i].ptr); - } - } - - MEM_freeN(heap->tree); - MEM_freeN(heap); + if (ptrfreefp) { + for (uint i = 0; i < heap->size; i++) { + ptrfreefp(heap->tree[i].ptr); + } + } + + MEM_freeN(heap->tree); + MEM_freeN(heap); } void BLI_heapsimple_clear(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) { - if (ptrfreefp) { - for (uint i = 0; i < heap->size; i++) { - ptrfreefp(heap->tree[i].ptr); - } - } + if (ptrfreefp) { + for (uint i = 0; i < heap->size; i++) { + ptrfreefp(heap->tree[i].ptr); + } + } - heap->size = 0; + heap->size = 0; } /** @@ -196,22 +196,22 @@ void BLI_heapsimple_clear(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) */ void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) { - if (UNLIKELY(heap->size >= heap->bufsize)) { - heap->bufsize *= 2; - heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); - } + if (UNLIKELY(heap->size >= heap->bufsize)) { + heap->bufsize *= 2; + heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); + } - heapsimple_up(heap, heap->size++, value, ptr); + heapsimple_up(heap, heap->size++, value, ptr); } bool BLI_heapsimple_is_empty(const HeapSimple *heap) { - return (heap->size == 0); + return (heap->size == 0); } uint BLI_heapsimple_len(const HeapSimple *heap) { - return heap->size; + return heap->size; } /** @@ -219,9 +219,9 @@ uint BLI_heapsimple_len(const HeapSimple *heap) */ float BLI_heapsimple_top_value(const HeapSimple *heap) { - BLI_assert(heap->size != 0); + BLI_assert(heap->size != 0); - return heap->tree[0].value; + return heap->tree[0].value; } /** @@ -229,15 +229,15 @@ float BLI_heapsimple_top_value(const HeapSimple *heap) */ void *BLI_heapsimple_pop_min(HeapSimple *heap) { - BLI_assert(heap->size != 0); + BLI_assert(heap->size != 0); - void *ptr = heap->tree[0].ptr; + void *ptr = heap->tree[0].ptr; - if (--heap->size) { - heapsimple_down(heap, 0, &heap->tree[heap->size]); - } + if (--heap->size) { + heapsimple_down(heap, 0, &heap->tree[heap->size]); + } - return ptr; + return ptr; } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7887c55a907..22e64d6717b 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -61,7 +61,6 @@ /* Check tree is valid. */ // #define USE_VERIFY_TREE - #define MAX_TREETYPE 32 /* Setting zero so we can catch bugs in BLI_task/KDOPBVH. @@ -73,7 +72,6 @@ # define KDOPBVH_THREAD_LEAF_THRESHOLD 1024 #endif - /* -------------------------------------------------------------------- */ /** \name Struct Definitions * \{ */ @@ -81,99 +79,97 @@ typedef unsigned char axis_t; typedef struct BVHNode { - struct BVHNode **children; - struct BVHNode *parent; /* some user defined traversed need that */ + struct BVHNode **children; + struct BVHNode *parent; /* some user defined traversed need that */ #ifdef USE_SKIP_LINKS - struct BVHNode *skip[2]; + struct BVHNode *skip[2]; #endif - float *bv; /* Bounding volume of all nodes, max 13 axis */ - int index; /* face, edge, vertex index */ - char totnode; /* how many nodes are used, used for speedup */ - char main_axis; /* Axis used to split this node */ + float *bv; /* Bounding volume of all nodes, max 13 axis */ + int index; /* face, edge, vertex index */ + char totnode; /* how many nodes are used, used for speedup */ + char main_axis; /* Axis used to split this node */ } BVHNode; /* keep under 26 bytes for speed purposes */ struct BVHTree { - BVHNode **nodes; - BVHNode *nodearray; /* pre-alloc branch nodes */ - BVHNode **nodechild; /* pre-alloc childs for nodes */ - float *nodebv; /* pre-alloc bounding-volumes for nodes */ - float epsilon; /* epslion is used for inflation of the k-dop */ - int totleaf; /* leafs */ - int totbranch; - axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ - axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ - char tree_type; /* type of tree (4 => quadtree) */ + BVHNode **nodes; + BVHNode *nodearray; /* pre-alloc branch nodes */ + BVHNode **nodechild; /* pre-alloc childs for nodes */ + float *nodebv; /* pre-alloc bounding-volumes for nodes */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int totleaf; /* leafs */ + int totbranch; + axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ + axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ + char tree_type; /* type of tree (4 => quadtree) */ }; /* optimization, ensure we stay small */ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) || - (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), + (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), "over sized") /* avoid duplicating vars in BVHOverlapData_Thread */ typedef struct BVHOverlapData_Shared { - const BVHTree *tree1, *tree2; - axis_t start_axis, stop_axis; + const BVHTree *tree1, *tree2; + axis_t start_axis, stop_axis; - /* use for callbacks */ - BVHTree_OverlapCallback callback; - void *userdata; + /* use for callbacks */ + BVHTree_OverlapCallback callback; + void *userdata; } BVHOverlapData_Shared; typedef struct BVHOverlapData_Thread { - BVHOverlapData_Shared *shared; - struct BLI_Stack *overlap; /* store BVHTreeOverlap */ - /* use for callbacks */ - int thread; + BVHOverlapData_Shared *shared; + struct BLI_Stack *overlap; /* store BVHTreeOverlap */ + /* use for callbacks */ + int thread; } BVHOverlapData_Thread; typedef struct BVHNearestData { - const BVHTree *tree; - const float *co; - BVHTree_NearestPointCallback callback; - void *userdata; - float proj[13]; /* coordinates projection over axis */ - BVHTreeNearest nearest; + const BVHTree *tree; + const float *co; + BVHTree_NearestPointCallback callback; + void *userdata; + float proj[13]; /* coordinates projection over axis */ + BVHTreeNearest nearest; } BVHNearestData; typedef struct BVHRayCastData { - const BVHTree *tree; + const BVHTree *tree; - BVHTree_RayCastCallback callback; - void *userdata; + BVHTree_RayCastCallback callback; + void *userdata; - - BVHTreeRay ray; + BVHTreeRay ray; #ifdef USE_KDOPBVH_WATERTIGHT - struct IsectRayPrecalc isect_precalc; + struct IsectRayPrecalc isect_precalc; #endif - /* initialized by bvhtree_ray_cast_data_precalc */ - float ray_dot_axis[13]; - float idot_axis[13]; - int index[6]; + /* initialized by bvhtree_ray_cast_data_precalc */ + float ray_dot_axis[13]; + float idot_axis[13]; + int index[6]; - BVHTreeRayHit hit; + BVHTreeRayHit hit; } BVHRayCastData; typedef struct BVHNearestProjectedData { - const BVHTree *tree; - struct DistProjectedAABBPrecalc precalc; - bool closest_axis[3]; - float clip_plane[6][4]; - int clip_plane_len; - BVHTree_NearestProjectedCallback callback; - void *userdata; - BVHTreeNearest nearest; + const BVHTree *tree; + struct DistProjectedAABBPrecalc precalc; + bool closest_axis[3]; + float clip_plane[6][4]; + int clip_plane_len; + BVHTree_NearestProjectedCallback callback; + void *userdata; + BVHTreeNearest nearest; } BVHNearestProjectedData; /** \} */ - /** * Bounding Volume Hierarchy Definition * @@ -183,24 +179,33 @@ typedef struct BVHNearestProjectedData { */ const float bvhtree_kdop_axes[13][3] = { - {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, - {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, - {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, {0, 1.0, -1.0}, + {1.0, 0, 0}, + {0, 1.0, 0}, + {0, 0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, -1.0, 1.0}, + {1.0, 1.0, -1.0}, + {1.0, -1.0, -1.0}, + {1.0, 1.0, 0}, + {1.0, 0, 1.0}, + {0, 1.0, 1.0}, + {1.0, -1.0, 0}, + {1.0, 0, -1.0}, + {0, 1.0, -1.0}, }; - /* -------------------------------------------------------------------- */ /** \name Utility Functions * \{ */ MINLINE axis_t min_axis(axis_t a, axis_t b) { - return (a < b) ? a : b; + return (a < b) ? a : b; } #if 0 MINLINE axis_t max_axis(axis_t a, axis_t b) { - return (b < a) ? a : b; + return (b < a) ? a : b; } #endif @@ -211,22 +216,19 @@ MINLINE axis_t max_axis(axis_t a, axis_t b) * and he derived it from the SUN STL */ - - static void node_minmax_init(const BVHTree *tree, BVHNode *node) { - axis_t axis_iter; - float (*bv)[2] = (float (*)[2])node->bv; + axis_t axis_iter; + float(*bv)[2] = (float(*)[2])node->bv; - for (axis_iter = tree->start_axis; axis_iter != tree->stop_axis; axis_iter++) { - bv[axis_iter][0] = FLT_MAX; - bv[axis_iter][1] = -FLT_MAX; - } + for (axis_iter = tree->start_axis; axis_iter != tree->stop_axis; axis_iter++) { + bv[axis_iter][0] = FLT_MAX; + bv[axis_iter][1] = -FLT_MAX; + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Balance Utility Functions * \{ */ @@ -236,67 +238,67 @@ static void node_minmax_init(const BVHTree *tree, BVHNode *node) */ static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis) { - int i, j; - BVHNode *t; - for (i = lo; i < hi; i++) { - j = i; - t = a[i]; - while ((j != lo) && (t->bv[axis] < (a[j - 1])->bv[axis])) { - a[j] = a[j - 1]; - j--; - } - a[j] = t; - } + int i, j; + BVHNode *t; + for (i = lo; i < hi; i++) { + j = i; + t = a[i]; + while ((j != lo) && (t->bv[axis] < (a[j - 1])->bv[axis])) { + a[j] = a[j - 1]; + j--; + } + a[j] = t; + } } static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode *x, int axis) { - int i = lo, j = hi; - while (1) { - while (a[i]->bv[axis] < x->bv[axis]) { - i++; - } - j--; - while (x->bv[axis] < a[j]->bv[axis]) { - j--; - } - if (!(i < j)) { - return i; - } - SWAP(BVHNode *, a[i], a[j]); - i++; - } + int i = lo, j = hi; + while (1) { + while (a[i]->bv[axis] < x->bv[axis]) { + i++; + } + j--; + while (x->bv[axis] < a[j]->bv[axis]) { + j--; + } + if (!(i < j)) { + return i; + } + SWAP(BVHNode *, a[i], a[j]); + i++; + } } /* returns Sortable */ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) { - if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { - return a[mid]; - } - else { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { - return a[hi]; - } - else { - return a[lo]; - } - } - } - else { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { - return a[lo]; - } - else { - return a[hi]; - } - } - else { - return a[mid]; - } - } + if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { + return a[mid]; + } + else { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { + return a[hi]; + } + else { + return a[lo]; + } + } + } + else { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { + return a[lo]; + } + else { + return a[hi]; + } + } + else { + return a[mid]; + } + } } /** @@ -305,66 +307,68 @@ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) * - every node to the right of a[n] are greater or equal to it */ static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis) { - while (end - begin > 3) { - const int cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); - if (cut <= n) { - begin = cut; - } - else { - end = cut; - } - } - bvh_insertionsort(a, begin, end, axis); + while (end - begin > 3) { + const int cut = bvh_partition( + a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); + if (cut <= n) { + begin = cut; + } + else { + end = cut; + } + } + bvh_insertionsort(a, begin, end, axis); } #ifdef USE_SKIP_LINKS static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right) { - int i; + int i; - node->skip[0] = left; - node->skip[1] = right; + node->skip[0] = left; + node->skip[1] = right; - for (i = 0; i < node->totnode; i++) { - if (i + 1 < node->totnode) { - build_skip_links(tree, node->children[i], left, node->children[i + 1]); - } - else { - build_skip_links(tree, node->children[i], left, right); - } + for (i = 0; i < node->totnode; i++) { + if (i + 1 < node->totnode) { + build_skip_links(tree, node->children[i], left, node->children[i + 1]); + } + else { + build_skip_links(tree, node->children[i], left, right); + } - left = node->children[i]; - } + left = node->children[i]; + } } #endif /* * BVHTree bounding volumes functions */ -static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) +static void create_kdop_hull( + const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) { - float newminmax; - float *bv = node->bv; - int k; - axis_t axis_iter; - - /* don't init boudings for the moving case */ - if (!moving) { - node_minmax_init(tree, node); - } - - for (k = 0; k < numpoints; k++) { - /* for all Axes. */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - newminmax = dot_v3v3(&co[k * 3], bvhtree_kdop_axes[axis_iter]); - if (newminmax < bv[2 * axis_iter]) { - bv[2 * axis_iter] = newminmax; - } - if (newminmax > bv[(2 * axis_iter) + 1]) { - bv[(2 * axis_iter) + 1] = newminmax; - } - } - } + float newminmax; + float *bv = node->bv; + int k; + axis_t axis_iter; + + /* don't init boudings for the moving case */ + if (!moving) { + node_minmax_init(tree, node); + } + + for (k = 0; k < numpoints; k++) { + /* for all Axes. */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newminmax = dot_v3v3(&co[k * 3], bvhtree_kdop_axes[axis_iter]); + if (newminmax < bv[2 * axis_iter]) { + bv[2 * axis_iter] = newminmax; + } + if (newminmax > bv[(2 * axis_iter) + 1]) { + bv[(2 * axis_iter) + 1] = newminmax; + } + } + } } /** @@ -372,30 +376,29 @@ static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co */ static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end) { - float newmin, newmax; - float *__restrict bv = node->bv; - int j; - axis_t axis_iter; - - node_minmax_init(tree, node); - - for (j = start; j < end; j++) { - float *__restrict node_bv = tree->nodes[j]->bv; - - /* for all Axes. */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - newmin = node_bv[(2 * axis_iter)]; - if ((newmin < bv[(2 * axis_iter)])) { - bv[(2 * axis_iter)] = newmin; - } - - newmax = node_bv[(2 * axis_iter) + 1]; - if ((newmax > bv[(2 * axis_iter) + 1])) { - bv[(2 * axis_iter) + 1] = newmax; - } - } - } - + float newmin, newmax; + float *__restrict bv = node->bv; + int j; + axis_t axis_iter; + + node_minmax_init(tree, node); + + for (j = start; j < end; j++) { + float *__restrict node_bv = tree->nodes[j]->bv; + + /* for all Axes. */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newmin = node_bv[(2 * axis_iter)]; + if ((newmin < bv[(2 * axis_iter)])) { + bv[(2 * axis_iter)] = newmin; + } + + newmax = node_bv[(2 * axis_iter) + 1]; + if ((newmax > bv[(2 * axis_iter) + 1])) { + bv[(2 * axis_iter) + 1] = newmax; + } + } + } } /** @@ -403,27 +406,27 @@ static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int e * but we should use a plain and simple function here for speed sake */ static char get_largest_axis(const float *bv) { - float middle_point[3]; - - middle_point[0] = (bv[1]) - (bv[0]); /* x axis */ - middle_point[1] = (bv[3]) - (bv[2]); /* y axis */ - middle_point[2] = (bv[5]) - (bv[4]); /* z axis */ - if (middle_point[0] > middle_point[1]) { - if (middle_point[0] > middle_point[2]) { - return 1; /* max x axis */ - } - else { - return 5; /* max z axis */ - } - } - else { - if (middle_point[1] > middle_point[2]) { - return 3; /* max y axis */ - } - else { - return 5; /* max z axis */ - } - } + float middle_point[3]; + + middle_point[0] = (bv[1]) - (bv[0]); /* x axis */ + middle_point[1] = (bv[3]) - (bv[2]); /* y axis */ + middle_point[2] = (bv[5]) - (bv[4]); /* z axis */ + if (middle_point[0] > middle_point[1]) { + if (middle_point[0] > middle_point[2]) { + return 1; /* max x axis */ + } + else { + return 5; /* max z axis */ + } + } + else { + if (middle_point[1] > middle_point[2]) { + return 3; /* max y axis */ + } + else { + return 5; /* max z axis */ + } + } } /** @@ -431,29 +434,29 @@ static char get_largest_axis(const float *bv) * join the children on the parent BV */ static void node_join(BVHTree *tree, BVHNode *node) { - int i; - axis_t axis_iter; - - node_minmax_init(tree, node); - - for (i = 0; i < tree->tree_type; i++) { - if (node->children[i]) { - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - /* update minimum */ - if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) { - node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)]; - } - - /* update maximum */ - if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) { - node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1]; - } - } - } - else { - break; - } - } + int i; + axis_t axis_iter; + + node_minmax_init(tree, node); + + for (i = 0; i < tree->tree_type; i++) { + if (node->children[i]) { + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + /* update minimum */ + if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) { + node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)]; + } + + /* update maximum */ + if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) { + node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1]; + } + } + } + else { + break; + } + } } #ifdef USE_PRINT_TREE @@ -464,156 +467,156 @@ static void node_join(BVHTree *tree, BVHNode *node) static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { - int i; - axis_t axis_iter; - - for (i = 0; i < depth; i++) { - printf(" "); - } - printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray)); - for (axis_iter = (axis_t)(2 * tree->start_axis); - axis_iter < (axis_t)(2 * tree->stop_axis); - axis_iter++) - { - printf("%.3f ", node->bv[axis_iter]); - } - printf("\n"); - - for (i = 0; i < tree->tree_type; i++) { - if (node->children[i]) { - bvhtree_print_tree(tree, node->children[i], depth + 1); - } - } + int i; + axis_t axis_iter; + + for (i = 0; i < depth; i++) { + printf(" "); + } + printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray)); + for (axis_iter = (axis_t)(2 * tree->start_axis); axis_iter < (axis_t)(2 * tree->stop_axis); + axis_iter++) { + printf("%.3f ", node->bv[axis_iter]); + } + printf("\n"); + + for (i = 0; i < tree->tree_type; i++) { + if (node->children[i]) { + bvhtree_print_tree(tree, node->children[i], depth + 1); + } + } } static void bvhtree_info(BVHTree *tree) { - printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n", - tree->tree_type, tree->axis, tree->epsilon); - printf("nodes = %d, branches = %d, leafs = %d\n", - tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %ubytes\n", - (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); - printf("BV memory = %ubytes\n", - (uint)MEM_allocN_len(tree->nodebv)); - - printf("Total memory = %ubytes\n", - (uint)(sizeof(BVHTree) + - MEM_allocN_len(tree->nodes) + - MEM_allocN_len(tree->nodearray) + - MEM_allocN_len(tree->nodechild) + - MEM_allocN_len(tree->nodebv))); - - bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); + printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n", + tree->tree_type, + tree->axis, + tree->epsilon); + printf("nodes = %d, branches = %d, leafs = %d\n", + tree->totbranch + tree->totleaf, + tree->totbranch, + tree->totleaf); + printf( + "Memory per node = %ubytes\n", + (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); + printf("BV memory = %ubytes\n", (uint)MEM_allocN_len(tree->nodebv)); + + printf("Total memory = %ubytes\n", + (uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + + MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv))); + + bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); } -#endif /* USE_PRINT_TREE */ +#endif /* USE_PRINT_TREE */ #ifdef USE_VERIFY_TREE static void bvhtree_verify(BVHTree *tree) { - int i, j, check = 0; - - /* check the pointer list */ - for (i = 0; i < tree->totleaf; i++) { - if (tree->nodes[i]->parent == NULL) { - printf("Leaf has no parent: %d\n", i); - } - else { - for (j = 0; j < tree->tree_type; j++) { - if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) { - check = 1; - } - } - if (!check) { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - /* check the leaf list */ - for (i = 0; i < tree->totleaf; i++) { - if (tree->nodearray[i].parent == NULL) { - printf("Leaf has no parent: %d\n", i); - } - else { - for (j = 0; j < tree->tree_type; j++) { - if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) { - check = 1; - } - } - if (!check) { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - printf("branches: %d, leafs: %d, total: %d\n", - tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); + int i, j, check = 0; + + /* check the pointer list */ + for (i = 0; i < tree->totleaf; i++) { + if (tree->nodes[i]->parent == NULL) { + printf("Leaf has no parent: %d\n", i); + } + else { + for (j = 0; j < tree->tree_type; j++) { + if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) { + check = 1; + } + } + if (!check) { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + /* check the leaf list */ + for (i = 0; i < tree->totleaf; i++) { + if (tree->nodearray[i].parent == NULL) { + printf("Leaf has no parent: %d\n", i); + } + else { + for (j = 0; j < tree->tree_type; j++) { + if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) { + check = 1; + } + } + if (!check) { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + printf("branches: %d, leafs: %d, total: %d\n", + tree->totbranch, + tree->totleaf, + tree->totbranch + tree->totleaf); } -#endif /* USE_VERIFY_TREE */ +#endif /* USE_VERIFY_TREE */ /* Helper data and structures to build a min-leaf generalized implicit tree * This code can be easily reduced * (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */ typedef struct BVHBuildHelper { - int tree_type; - int totleafs; + int tree_type; + int totleafs; - /** Min number of leafs that are archievable from a node at depth N */ - int leafs_per_child[32]; - /** Number of nodes at depth N (tree_type^N) */ - int branches_on_level[32]; + /** Min number of leafs that are archievable from a node at depth N */ + int leafs_per_child[32]; + /** Number of nodes at depth N (tree_type^N) */ + int branches_on_level[32]; - /** Number of leafs that are placed on the level that is not 100% filled */ - int remain_leafs; + /** Number of leafs that are placed on the level that is not 100% filled */ + int remain_leafs; } BVHBuildHelper; static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data) { - int depth = 0; - int remain; - int nnodes; - - data->totleafs = tree->totleaf; - data->tree_type = tree->tree_type; - - /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */ - for (data->leafs_per_child[0] = 1; - data->leafs_per_child[0] < data->totleafs; - data->leafs_per_child[0] *= data->tree_type) - { - /* pass */ - } - - data->branches_on_level[0] = 1; - - for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) { - data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type; - data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; - } - - remain = data->totleafs - data->leafs_per_child[1]; - nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); - data->remain_leafs = remain + nnodes; + int depth = 0; + int remain; + int nnodes; + + data->totleafs = tree->totleaf; + data->tree_type = tree->tree_type; + + /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */ + for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->totleafs; + data->leafs_per_child[0] *= data->tree_type) { + /* pass */ + } + + data->branches_on_level[0] = 1; + + for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) { + data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type; + data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; + } + + remain = data->totleafs - data->leafs_per_child[1]; + nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); + data->remain_leafs = remain + nnodes; } // return the min index of all the leafs archivable with the given branch static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index) { - int min_leaf_index = child_index * data->leafs_per_child[depth - 1]; - if (min_leaf_index <= data->remain_leafs) { - return min_leaf_index; - } - else if (data->leafs_per_child[depth]) { - return data->totleafs - (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth]; - } - else { - return data->remain_leafs; - } + int min_leaf_index = child_index * data->leafs_per_child[depth - 1]; + if (min_leaf_index <= data->remain_leafs) { + return min_leaf_index; + } + else if (data->leafs_per_child[depth]) { + return data->totleafs - + (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth]; + } + else { + return data->remain_leafs; + } } /** @@ -645,7 +648,7 @@ static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, con /* This functions returns the number of branches needed to have the requested number of leafs. */ static int implicit_needed_branches(int tree_type, int leafs) { - return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1)); + return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1)); } /** @@ -660,96 +663,100 @@ static int implicit_needed_branches(int tree_type, int leafs) * * TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements */ -static void split_leafs(BVHNode **leafs_array, const int nth[], const int partitions, const int split_axis) +static void split_leafs(BVHNode **leafs_array, + const int nth[], + const int partitions, + const int split_axis) { - int i; - for (i = 0; i < partitions - 1; i++) { - if (nth[i] >= nth[partitions]) { - break; - } - - partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis); - } + int i; + for (i = 0; i < partitions - 1; i++) { + if (nth[i] >= nth[partitions]) { + break; + } + + partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis); + } } typedef struct BVHDivNodesData { - const BVHTree *tree; - BVHNode *branches_array; - BVHNode **leafs_array; + const BVHTree *tree; + BVHNode *branches_array; + BVHNode **leafs_array; - int tree_type; - int tree_offset; + int tree_type; + int tree_offset; - const BVHBuildHelper *data; + const BVHBuildHelper *data; - int depth; - int i; - int first_of_next_level; + int depth; + int i; + int first_of_next_level; } BVHDivNodesData; -static void non_recursive_bvh_div_nodes_task_cb( - void *__restrict userdata, - const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, + const int j, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - BVHDivNodesData *data = userdata; - - int k; - const int parent_level_index = j - data->i; - BVHNode *parent = &data->branches_array[j]; - int nth_positions[MAX_TREETYPE + 1]; - char split_axis; - - int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index); - int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1); - - /* This calculates the bounding box of this branch - * and chooses the largest axis as the axis to divide leafs */ - refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end); - split_axis = get_largest_axis(parent->bv); - - /* Save split axis (this can be used on raytracing to speedup the query time) */ - parent->main_axis = split_axis / 2; - - /* Split the childs along the split_axis, note: its not needed to sort the whole leafs array - * Only to assure that the elements are partitioned on a way that each child takes the elements - * it would take in case the whole array was sorted. - * Split_leafs takes care of that "sort" problem. */ - nth_positions[0] = parent_leafs_begin; - nth_positions[data->tree_type] = parent_leafs_end; - for (k = 1; k < data->tree_type; k++) { - const int child_index = j * data->tree_type + data->tree_offset + k; - /* child level index */ - const int child_level_index = child_index - data->first_of_next_level; - nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index); - } - - split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis); - - /* Setup children and totnode counters - * Not really needed but currently most of BVH code - * relies on having an explicit children structure */ - for (k = 0; k < data->tree_type; k++) { - const int child_index = j * data->tree_type + data->tree_offset + k; - /* child level index */ - const int child_level_index = child_index - data->first_of_next_level; - - const int child_leafs_begin = implicit_leafs_index(data->data, data->depth + 1, child_level_index); - const int child_leafs_end = implicit_leafs_index(data->data, data->depth + 1, child_level_index + 1); - - if (child_leafs_end - child_leafs_begin > 1) { - parent->children[k] = &data->branches_array[child_index]; - parent->children[k]->parent = parent; - } - else if (child_leafs_end - child_leafs_begin == 1) { - parent->children[k] = data->leafs_array[child_leafs_begin]; - parent->children[k]->parent = parent; - } - else { - break; - } - } - parent->totnode = (char)k; + BVHDivNodesData *data = userdata; + + int k; + const int parent_level_index = j - data->i; + BVHNode *parent = &data->branches_array[j]; + int nth_positions[MAX_TREETYPE + 1]; + char split_axis; + + int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index); + int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1); + + /* This calculates the bounding box of this branch + * and chooses the largest axis as the axis to divide leafs */ + refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end); + split_axis = get_largest_axis(parent->bv); + + /* Save split axis (this can be used on raytracing to speedup the query time) */ + parent->main_axis = split_axis / 2; + + /* Split the childs along the split_axis, note: its not needed to sort the whole leafs array + * Only to assure that the elements are partitioned on a way that each child takes the elements + * it would take in case the whole array was sorted. + * Split_leafs takes care of that "sort" problem. */ + nth_positions[0] = parent_leafs_begin; + nth_positions[data->tree_type] = parent_leafs_end; + for (k = 1; k < data->tree_type; k++) { + const int child_index = j * data->tree_type + data->tree_offset + k; + /* child level index */ + const int child_level_index = child_index - data->first_of_next_level; + nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index); + } + + split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis); + + /* Setup children and totnode counters + * Not really needed but currently most of BVH code + * relies on having an explicit children structure */ + for (k = 0; k < data->tree_type; k++) { + const int child_index = j * data->tree_type + data->tree_offset + k; + /* child level index */ + const int child_level_index = child_index - data->first_of_next_level; + + const int child_leafs_begin = implicit_leafs_index( + data->data, data->depth + 1, child_level_index); + const int child_leafs_end = implicit_leafs_index( + data->data, data->depth + 1, child_level_index + 1); + + if (child_leafs_end - child_leafs_begin > 1) { + parent->children[k] = &data->branches_array[child_index]; + parent->children[k]->parent = parent; + } + else if (child_leafs_end - child_leafs_begin == 1) { + parent->children[k] = data->leafs_array[child_leafs_begin]; + parent->children[k]->parent = parent; + } + else { + break; + } + } + parent->totnode = (char)k; } /** @@ -768,79 +775,82 @@ static void non_recursive_bvh_div_nodes_task_cb( * To archive this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper * #implicit_needed_branches and #implicit_leafs_index are auxiliary functions to solve that "optimal-split". */ -static void non_recursive_bvh_div_nodes( - const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs) +static void non_recursive_bvh_div_nodes(const BVHTree *tree, + BVHNode *branches_array, + BVHNode **leafs_array, + int num_leafs) { - int i; - - const int tree_type = tree->tree_type; - /* this value is 0 (on binary trees) and negative on the others */ - const int tree_offset = 2 - tree->tree_type; - - const int num_branches = implicit_needed_branches(tree_type, num_leafs); - - BVHBuildHelper data; - int depth; - - { - /* set parent from root node to NULL */ - BVHNode *root = &branches_array[1]; - root->parent = NULL; - - /* Most of bvhtree code relies on 1-leaf trees having at least one branch - * We handle that special case here */ - if (num_leafs == 1) { - refit_kdop_hull(tree, root, 0, num_leafs); - root->main_axis = get_largest_axis(root->bv) / 2; - root->totnode = 1; - root->children[0] = leafs_array[0]; - root->children[0]->parent = root; - return; - } - } - - build_implicit_tree_helper(tree, &data); - - BVHDivNodesData cb_data = { - .tree = tree, .branches_array = branches_array, .leafs_array = leafs_array, - .tree_type = tree_type, .tree_offset = tree_offset, .data = &data, - .first_of_next_level = 0, .depth = 0, .i = 0, - }; - - /* Loop tree levels (log N) loops */ - for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { - const int first_of_next_level = i * tree_type + tree_offset; - /* index of last branch on this level */ - const int i_stop = min_ii(first_of_next_level, num_branches + 1); - - /* Loop all branches on this level */ - cb_data.first_of_next_level = first_of_next_level; - cb_data.i = i; - cb_data.depth = depth; - - if (true) { - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); - BLI_task_parallel_range( - i, i_stop, - &cb_data, - non_recursive_bvh_div_nodes_task_cb, - &settings); - } - else { - /* Less hassle for debugging. */ - ParallelRangeTLS tls = {0}; - for (int i_task = i; i_task < i_stop; i_task++) { - non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls); - } - } - } + int i; + + const int tree_type = tree->tree_type; + /* this value is 0 (on binary trees) and negative on the others */ + const int tree_offset = 2 - tree->tree_type; + + const int num_branches = implicit_needed_branches(tree_type, num_leafs); + + BVHBuildHelper data; + int depth; + + { + /* set parent from root node to NULL */ + BVHNode *root = &branches_array[1]; + root->parent = NULL; + + /* Most of bvhtree code relies on 1-leaf trees having at least one branch + * We handle that special case here */ + if (num_leafs == 1) { + refit_kdop_hull(tree, root, 0, num_leafs); + root->main_axis = get_largest_axis(root->bv) / 2; + root->totnode = 1; + root->children[0] = leafs_array[0]; + root->children[0]->parent = root; + return; + } + } + + build_implicit_tree_helper(tree, &data); + + BVHDivNodesData cb_data = { + .tree = tree, + .branches_array = branches_array, + .leafs_array = leafs_array, + .tree_type = tree_type, + .tree_offset = tree_offset, + .data = &data, + .first_of_next_level = 0, + .depth = 0, + .i = 0, + }; + + /* Loop tree levels (log N) loops */ + for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { + const int first_of_next_level = i * tree_type + tree_offset; + /* index of last branch on this level */ + const int i_stop = min_ii(first_of_next_level, num_branches + 1); + + /* Loop all branches on this level */ + cb_data.first_of_next_level = first_of_next_level; + cb_data.i = i; + cb_data.depth = depth; + + if (true) { + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); + BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings); + } + else { + /* Less hassle for debugging. */ + ParallelRangeTLS tls = {0}; + for (int i_task = i; i_task < i_stop; i_task++) { + non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls); + } + } + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree API * \{ */ @@ -850,189 +860,183 @@ static void non_recursive_bvh_div_nodes( */ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) { - BVHTree *tree; - int numnodes, i; - - BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE); - - tree = MEM_callocN(sizeof(BVHTree), "BVHTree"); - - /* tree epsilon must be >= FLT_EPSILON - * so that tangent rays can still hit a bounding volume.. - * this bug would show up when casting a ray aligned with a kdop-axis - * and with an edge of 2 faces */ - epsilon = max_ff(FLT_EPSILON, epsilon); - - if (tree) { - tree->epsilon = epsilon; - tree->tree_type = tree_type; - tree->axis = axis; - - if (axis == 26) { - tree->start_axis = 0; - tree->stop_axis = 13; - } - else if (axis == 18) { - tree->start_axis = 7; - tree->stop_axis = 13; - } - else if (axis == 14) { - tree->start_axis = 0; - tree->stop_axis = 7; - } - else if (axis == 8) { /* AABB */ - tree->start_axis = 0; - tree->stop_axis = 4; - } - else if (axis == 6) { /* OBB */ - tree->start_axis = 0; - tree->stop_axis = 3; - } - else { - /* should never happen! */ - BLI_assert(0); - - goto fail; - } - - - /* Allocate arrays */ - numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; - - tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes"); - tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV"); - tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV"); - tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray"); - - if (UNLIKELY((!tree->nodes) || - (!tree->nodebv) || - (!tree->nodechild) || - (!tree->nodearray))) - { - goto fail; - } - - /* link the dynamic bv and child links */ - for (i = 0; i < numnodes; i++) { - tree->nodearray[i].bv = &tree->nodebv[i * axis]; - tree->nodearray[i].children = &tree->nodechild[i * tree_type]; - } - - } - return tree; - + BVHTree *tree; + int numnodes, i; + + BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE); + + tree = MEM_callocN(sizeof(BVHTree), "BVHTree"); + + /* tree epsilon must be >= FLT_EPSILON + * so that tangent rays can still hit a bounding volume.. + * this bug would show up when casting a ray aligned with a kdop-axis + * and with an edge of 2 faces */ + epsilon = max_ff(FLT_EPSILON, epsilon); + + if (tree) { + tree->epsilon = epsilon; + tree->tree_type = tree_type; + tree->axis = axis; + + if (axis == 26) { + tree->start_axis = 0; + tree->stop_axis = 13; + } + else if (axis == 18) { + tree->start_axis = 7; + tree->stop_axis = 13; + } + else if (axis == 14) { + tree->start_axis = 0; + tree->stop_axis = 7; + } + else if (axis == 8) { /* AABB */ + tree->start_axis = 0; + tree->stop_axis = 4; + } + else if (axis == 6) { /* OBB */ + tree->start_axis = 0; + tree->stop_axis = 3; + } + else { + /* should never happen! */ + BLI_assert(0); + + goto fail; + } + + /* Allocate arrays */ + numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; + + tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes"); + tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV"); + tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV"); + tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray"); + + if (UNLIKELY((!tree->nodes) || (!tree->nodebv) || (!tree->nodechild) || (!tree->nodearray))) { + goto fail; + } + + /* link the dynamic bv and child links */ + for (i = 0; i < numnodes; i++) { + tree->nodearray[i].bv = &tree->nodebv[i * axis]; + tree->nodearray[i].children = &tree->nodechild[i * tree_type]; + } + } + return tree; fail: - BLI_bvhtree_free(tree); - return NULL; + BLI_bvhtree_free(tree); + return NULL; } void BLI_bvhtree_free(BVHTree *tree) { - if (tree) { - MEM_SAFE_FREE(tree->nodes); - MEM_SAFE_FREE(tree->nodearray); - MEM_SAFE_FREE(tree->nodebv); - MEM_SAFE_FREE(tree->nodechild); - MEM_freeN(tree); - } + if (tree) { + MEM_SAFE_FREE(tree->nodes); + MEM_SAFE_FREE(tree->nodearray); + MEM_SAFE_FREE(tree->nodebv); + MEM_SAFE_FREE(tree->nodechild); + MEM_freeN(tree); + } } void BLI_bvhtree_balance(BVHTree *tree) { - BVHNode **leafs_array = tree->nodes; + BVHNode **leafs_array = tree->nodes; - /* This function should only be called once - * (some big bug goes here if its being called more than once per tree) */ - BLI_assert(tree->totbranch == 0); + /* This function should only be called once + * (some big bug goes here if its being called more than once per tree) */ + BLI_assert(tree->totbranch == 0); - /* Build the implicit tree */ - non_recursive_bvh_div_nodes(tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf); + /* Build the implicit tree */ + non_recursive_bvh_div_nodes( + tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf); - /* current code expects the branches to be linked to the nodes array - * we perform that linkage here */ - tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); - for (int i = 0; i < tree->totbranch; i++) { - tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i]; - } + /* current code expects the branches to be linked to the nodes array + * we perform that linkage here */ + tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); + for (int i = 0; i < tree->totbranch; i++) { + tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i]; + } #ifdef USE_SKIP_LINKS - build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); + build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); #endif #ifdef USE_VERIFY_TREE - bvhtree_verify(tree); + bvhtree_verify(tree); #endif #ifdef USE_PRINT_TREE - bvhtree_info(tree); + bvhtree_info(tree); #endif } void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) { - axis_t axis_iter; - BVHNode *node = NULL; + axis_t axis_iter; + BVHNode *node = NULL; - /* insert should only possible as long as tree->totbranch is 0 */ - BLI_assert(tree->totbranch <= 0); - BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); + /* insert should only possible as long as tree->totbranch is 0 */ + BLI_assert(tree->totbranch <= 0); + BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totleaf++; + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totleaf++; - create_kdop_hull(tree, node, co, numpoints, 0); - node->index = index; + create_kdop_hull(tree, node, co, numpoints, 0); + node->index = index; - /* inflate the bv with some epsilon */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ - node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ - } + /* inflate the bv with some epsilon */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ + } } - /* call before BLI_bvhtree_update_tree() */ -bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) +bool BLI_bvhtree_update_node( + BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) { - BVHNode *node = NULL; - axis_t axis_iter; + BVHNode *node = NULL; + axis_t axis_iter; - /* check if index exists */ - if (index > tree->totleaf) { - return false; - } + /* check if index exists */ + if (index > tree->totleaf) { + return false; + } - node = tree->nodearray + index; + node = tree->nodearray + index; - create_kdop_hull(tree, node, co, numpoints, 0); + create_kdop_hull(tree, node, co, numpoints, 0); - if (co_moving) { - create_kdop_hull(tree, node, co_moving, numpoints, 1); - } + if (co_moving) { + create_kdop_hull(tree, node, co_moving, numpoints, 1); + } - /* inflate the bv with some epsilon */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ - node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ - } + /* inflate the bv with some epsilon */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ + } - return true; + return true; } /* call BLI_bvhtree_update_node() first for every node/point/triangle */ void BLI_bvhtree_update_tree(BVHTree *tree) { - /* Update bottom=>top - * TRICKY: the way we build the tree all the childs have an index greater than the parent - * This allows us todo a bottom up update by starting on the bigger numbered branch */ + /* Update bottom=>top + * TRICKY: the way we build the tree all the childs have an index greater than the parent + * This allows us todo a bottom up update by starting on the bigger numbered branch */ - BVHNode **root = tree->nodes + tree->totleaf; - BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1; + BVHNode **root = tree->nodes + tree->totleaf; + BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1; - for (; index >= root; index--) { - node_join(tree, *index); - } + for (; index >= root; index--) { + node_join(tree, *index); + } } /** * Number of times #BLI_bvhtree_insert has been called. @@ -1040,7 +1044,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) */ int BLI_bvhtree_get_len(const BVHTree *tree) { - return tree->totleaf; + return tree->totleaf; } /** @@ -1048,17 +1052,16 @@ int BLI_bvhtree_get_len(const BVHTree *tree) */ int BLI_bvhtree_get_tree_type(const BVHTree *tree) { - return tree->tree_type; + return tree->tree_type; } float BLI_bvhtree_get_epsilon(const BVHTree *tree) { - return tree->epsilon; + return tree->epsilon; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_overlap * \{ */ @@ -1066,108 +1069,111 @@ float BLI_bvhtree_get_epsilon(const BVHTree *tree) /** * overlap - is it possible for 2 bv's to collide ? */ -static bool tree_overlap_test(const BVHNode *node1, const BVHNode *node2, axis_t start_axis, axis_t stop_axis) +static bool tree_overlap_test(const BVHNode *node1, + const BVHNode *node2, + axis_t start_axis, + axis_t stop_axis) { - const float *bv1 = node1->bv + (start_axis << 1); - const float *bv2 = node2->bv + (start_axis << 1); - const float *bv1_end = node1->bv + (stop_axis << 1); - - /* test all axis if min + max overlap */ - for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) { - if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) { - return 0; - } - } - - return 1; + const float *bv1 = node1->bv + (start_axis << 1); + const float *bv2 = node2->bv + (start_axis << 1); + const float *bv1_end = node1->bv + (stop_axis << 1); + + /* test all axis if min + max overlap */ + for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) { + if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) { + return 0; + } + } + + return 1; } -static void tree_overlap_traverse( - BVHOverlapData_Thread *data_thread, - const BVHNode *node1, const BVHNode *node2) +static void tree_overlap_traverse(BVHOverlapData_Thread *data_thread, + const BVHNode *node1, + const BVHNode *node2) { - BVHOverlapData_Shared *data = data_thread->shared; - int j; - - if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { - /* check if node1 is a leaf */ - if (!node1->totnode) { - /* check if node2 is a leaf */ - if (!node2->totnode) { - BVHTreeOverlap *overlap; - - if (UNLIKELY(node1 == node2)) { - return; - } - - /* both leafs, insert overlap! */ - overlap = BLI_stack_push_r(data_thread->overlap); - overlap->indexA = node1->index; - overlap->indexB = node2->index; - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node2->children[j]) { - tree_overlap_traverse(data_thread, node1, node2->children[j]); - } - } - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node1->children[j]) { - tree_overlap_traverse(data_thread, node1->children[j], node2); - } - } - } - } + BVHOverlapData_Shared *data = data_thread->shared; + int j; + + if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { + /* check if node1 is a leaf */ + if (!node1->totnode) { + /* check if node2 is a leaf */ + if (!node2->totnode) { + BVHTreeOverlap *overlap; + + if (UNLIKELY(node1 == node2)) { + return; + } + + /* both leafs, insert overlap! */ + overlap = BLI_stack_push_r(data_thread->overlap); + overlap->indexA = node1->index; + overlap->indexB = node2->index; + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node2->children[j]) { + tree_overlap_traverse(data_thread, node1, node2->children[j]); + } + } + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node1->children[j]) { + tree_overlap_traverse(data_thread, node1->children[j], node2); + } + } + } + } } /** * a version of #tree_overlap_traverse that runs a callback to check if the nodes really intersect. */ -static void tree_overlap_traverse_cb( - BVHOverlapData_Thread *data_thread, - const BVHNode *node1, const BVHNode *node2) +static void tree_overlap_traverse_cb(BVHOverlapData_Thread *data_thread, + const BVHNode *node1, + const BVHNode *node2) { - BVHOverlapData_Shared *data = data_thread->shared; - int j; - - if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { - /* check if node1 is a leaf */ - if (!node1->totnode) { - /* check if node2 is a leaf */ - if (!node2->totnode) { - BVHTreeOverlap *overlap; - - if (UNLIKELY(node1 == node2)) { - return; - } - - /* only difference to tree_overlap_traverse! */ - if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) { - /* both leafs, insert overlap! */ - overlap = BLI_stack_push_r(data_thread->overlap); - overlap->indexA = node1->index; - overlap->indexB = node2->index; - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node2->children[j]) { - tree_overlap_traverse_cb(data_thread, node1, node2->children[j]); - } - } - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node1->children[j]) { - tree_overlap_traverse_cb(data_thread, node1->children[j], node2); - } - } - } - } + BVHOverlapData_Shared *data = data_thread->shared; + int j; + + if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { + /* check if node1 is a leaf */ + if (!node1->totnode) { + /* check if node2 is a leaf */ + if (!node2->totnode) { + BVHTreeOverlap *overlap; + + if (UNLIKELY(node1 == node2)) { + return; + } + + /* only difference to tree_overlap_traverse! */ + if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) { + /* both leafs, insert overlap! */ + overlap = BLI_stack_push_r(data_thread->overlap); + overlap->indexA = node1->index; + overlap->indexB = node2->index; + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node2->children[j]) { + tree_overlap_traverse_cb(data_thread, node1, node2->children[j]); + } + } + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node1->children[j]) { + tree_overlap_traverse_cb(data_thread, node1->children[j], node2); + } + } + } + } } /** @@ -1177,106 +1183,102 @@ static void tree_overlap_traverse_cb( */ int BLI_bvhtree_overlap_thread_num(const BVHTree *tree) { - return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode); + return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode); } -static void bvhtree_overlap_task_cb( - void *__restrict userdata, - const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void bvhtree_overlap_task_cb(void *__restrict userdata, + const int j, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j]; - BVHOverlapData_Shared *data_shared = data->shared; - - if (data_shared->callback) { - tree_overlap_traverse_cb( - data, data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); - } - else { - tree_overlap_traverse( - data, data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); - } + BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j]; + BVHOverlapData_Shared *data_shared = data->shared; + + if (data_shared->callback) { + tree_overlap_traverse_cb(data, + data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], + data_shared->tree2->nodes[data_shared->tree2->totleaf]); + } + else { + tree_overlap_traverse(data, + data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], + data_shared->tree2->nodes[data_shared->tree2->totleaf]); + } } BVHTreeOverlap *BLI_bvhtree_overlap( - const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_tot, - /* optional callback to test the overlap before adding (must be thread-safe!) */ - BVHTree_OverlapCallback callback, void *userdata) + const BVHTree *tree1, + const BVHTree *tree2, + uint *r_overlap_tot, + /* optional callback to test the overlap before adding (must be thread-safe!) */ + BVHTree_OverlapCallback callback, + void *userdata) { - const int thread_num = BLI_bvhtree_overlap_thread_num(tree1); - int j; - size_t total = 0; - BVHTreeOverlap *overlap = NULL, *to = NULL; - BVHOverlapData_Shared data_shared; - BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num); - axis_t start_axis, stop_axis; - - /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ - if (UNLIKELY((tree1->axis != tree2->axis) && - (tree1->axis == 14 || tree2->axis == 14) && - (tree1->axis == 18 || tree2->axis == 18))) - { - BLI_assert(0); - return NULL; - } - - start_axis = min_axis(tree1->start_axis, tree2->start_axis); - stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); - - /* fast check root nodes for collision before doing big splitting + traversal */ - if (!tree_overlap_test(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], start_axis, stop_axis)) { - return NULL; - } - - data_shared.tree1 = tree1; - data_shared.tree2 = tree2; - data_shared.start_axis = start_axis; - data_shared.stop_axis = stop_axis; - - /* can be NULL */ - data_shared.callback = callback; - data_shared.userdata = userdata; - - for (j = 0; j < thread_num; j++) { - /* init BVHOverlapData_Thread */ - data[j].shared = &data_shared; - data[j].overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__); - - /* for callback */ - data[j].thread = j; - } - - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); - BLI_task_parallel_range( - 0, thread_num, - data, - bvhtree_overlap_task_cb, - &settings); - - for (j = 0; j < thread_num; j++) { - total += BLI_stack_count(data[j].overlap); - } - - to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); - - for (j = 0; j < thread_num; j++) { - uint count = (uint)BLI_stack_count(data[j].overlap); - BLI_stack_pop_n(data[j].overlap, to, count); - BLI_stack_free(data[j].overlap); - to += count; - } - - *r_overlap_tot = (uint)total; - return overlap; + const int thread_num = BLI_bvhtree_overlap_thread_num(tree1); + int j; + size_t total = 0; + BVHTreeOverlap *overlap = NULL, *to = NULL; + BVHOverlapData_Shared data_shared; + BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num); + axis_t start_axis, stop_axis; + + /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ + if (UNLIKELY((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && + (tree1->axis == 18 || tree2->axis == 18))) { + BLI_assert(0); + return NULL; + } + + start_axis = min_axis(tree1->start_axis, tree2->start_axis); + stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); + + /* fast check root nodes for collision before doing big splitting + traversal */ + if (!tree_overlap_test( + tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], start_axis, stop_axis)) { + return NULL; + } + + data_shared.tree1 = tree1; + data_shared.tree2 = tree2; + data_shared.start_axis = start_axis; + data_shared.stop_axis = stop_axis; + + /* can be NULL */ + data_shared.callback = callback; + data_shared.userdata = userdata; + + for (j = 0; j < thread_num; j++) { + /* init BVHOverlapData_Thread */ + data[j].shared = &data_shared; + data[j].overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__); + + /* for callback */ + data[j].thread = j; + } + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); + BLI_task_parallel_range(0, thread_num, data, bvhtree_overlap_task_cb, &settings); + + for (j = 0; j < thread_num; j++) { + total += BLI_stack_count(data[j].overlap); + } + + to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); + + for (j = 0; j < thread_num; j++) { + uint count = (uint)BLI_stack_count(data[j].overlap); + BLI_stack_pop_n(data[j].overlap, to, count); + BLI_stack_free(data[j].overlap); + to += count; + } + + *r_overlap_tot = (uint)total; + return overlap; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_find_nearest * \{ */ @@ -1285,172 +1287,178 @@ BVHTreeOverlap *BLI_bvhtree_overlap( * Returns the squared distance to that point. */ static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3]) { - int i; - const float *bv = node->bv; - - /* nearest on AABB hull */ - for (i = 0; i != 3; i++, bv += 2) { - float val = proj[i]; - if (bv[0] > val) { - val = bv[0]; - } - if (bv[1] < val) { - val = bv[1]; - } - nearest[i] = val; - } - - return len_squared_v3v3(proj, nearest); + int i; + const float *bv = node->bv; + + /* nearest on AABB hull */ + for (i = 0; i != 3; i++, bv += 2) { + float val = proj[i]; + if (bv[0] > val) { + val = bv[0]; + } + if (bv[1] < val) { + val = bv[1]; + } + nearest[i] = val; + } + + return len_squared_v3v3(proj, nearest); } /* Depth first search method */ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, data->co, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); - } - } - else { - /* Better heuristic to pick the closest node to dive on */ - int i; - float nearest[3]; - - if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { - - for (i = 0; i != node->totnode; i++) { - if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { - continue; - } - dfs_find_nearest_dfs(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { - continue; - } - dfs_find_nearest_dfs(data, node->children[i]); - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, data->co, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); + } + } + else { + /* Better heuristic to pick the closest node to dive on */ + int i; + float nearest[3]; + + if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { + + for (i = 0; i != node->totnode; i++) { + if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= + data->nearest.dist_sq) { + continue; + } + dfs_find_nearest_dfs(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= + data->nearest.dist_sq) { + continue; + } + dfs_find_nearest_dfs(data, node->children[i]); + } + } + } } static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { - float nearest[3], dist_sq; - dist_sq = calc_nearest_point_squared(data->proj, node, nearest); - if (dist_sq >= data->nearest.dist_sq) { - return; - } - dfs_find_nearest_dfs(data, node); + float nearest[3], dist_sq; + dist_sq = calc_nearest_point_squared(data->proj, node, nearest); + if (dist_sq >= data->nearest.dist_sq) { + return; + } + dfs_find_nearest_dfs(data, node); } /* Priority queue method */ static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, data->co, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); - } - } - else { - float nearest[3]; - - for (int i = 0; i != node->totnode; i++) { - float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest); - - if (dist_sq < data->nearest.dist_sq) { - BLI_heapsimple_insert(heap, dist_sq, node->children[i]); - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, data->co, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); + } + } + else { + float nearest[3]; + + for (int i = 0; i != node->totnode; i++) { + float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest); + + if (dist_sq < data->nearest.dist_sq) { + BLI_heapsimple_insert(heap, dist_sq, node->children[i]); + } + } + } } static void heap_find_nearest_begin(BVHNearestData *data, BVHNode *root) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data->proj, root, nearest); + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data->proj, root, nearest); - if (dist_sq < data->nearest.dist_sq) { - HeapSimple *heap = BLI_heapsimple_new_ex(32); + if (dist_sq < data->nearest.dist_sq) { + HeapSimple *heap = BLI_heapsimple_new_ex(32); - heap_find_nearest_inner(data, heap, root); + heap_find_nearest_inner(data, heap, root); - while (!BLI_heapsimple_is_empty(heap) && BLI_heapsimple_top_value(heap) < data->nearest.dist_sq) { - BVHNode *node = BLI_heapsimple_pop_min(heap); - heap_find_nearest_inner(data, heap, node); - } + while (!BLI_heapsimple_is_empty(heap) && + BLI_heapsimple_top_value(heap) < data->nearest.dist_sq) { + BVHNode *node = BLI_heapsimple_pop_min(heap); + heap_find_nearest_inner(data, heap, node); + } - BLI_heapsimple_free(heap, NULL); - } + BLI_heapsimple_free(heap, NULL); + } } -int BLI_bvhtree_find_nearest_ex( - BVHTree *tree, const float co[3], BVHTreeNearest *nearest, - BVHTree_NearestPointCallback callback, void *userdata, - int flag) +int BLI_bvhtree_find_nearest_ex(BVHTree *tree, + const float co[3], + BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, + void *userdata, + int flag) { - axis_t axis_iter; - - BVHNearestData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - /* init data to search */ - data.tree = tree; - data.co = co; - - data.callback = callback; - data.userdata = userdata; - - for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) { - data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]); - } - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - - /* dfs search */ - if (root) { - if (flag & BVH_NEAREST_OPTIMAL_ORDER) { - heap_find_nearest_begin(&data, root); - } - else { - dfs_find_nearest_begin(&data, root); - } - } - - /* copy back results */ - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; + axis_t axis_iter; + + BVHNearestData data; + BVHNode *root = tree->nodes[tree->totleaf]; + + /* init data to search */ + data.tree = tree; + data.co = co; + + data.callback = callback; + data.userdata = userdata; + + for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) { + data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]); + } + + if (nearest) { + memcpy(&data.nearest, nearest, sizeof(*nearest)); + } + else { + data.nearest.index = -1; + data.nearest.dist_sq = FLT_MAX; + } + + /* dfs search */ + if (root) { + if (flag & BVH_NEAREST_OPTIMAL_ORDER) { + heap_find_nearest_begin(&data, root); + } + else { + dfs_find_nearest_begin(&data, root); + } + } + + /* copy back results */ + if (nearest) { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; } -int BLI_bvhtree_find_nearest( - BVHTree *tree, const float co[3], BVHTreeNearest *nearest, - BVHTree_NearestPointCallback callback, void *userdata) +int BLI_bvhtree_find_nearest(BVHTree *tree, + const float co[3], + BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, + void *userdata) { - return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0); + return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_ray_cast * @@ -1458,50 +1466,48 @@ int BLI_bvhtree_find_nearest( * * \{ */ - /* Determines the distance that the ray must travel to hit the bounding volume of the given node */ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6]) { - int i; - - float low = 0, upper = data->hit.dist; - - for (i = 0; i != 3; i++, bv += 2) { - if (data->ray_dot_axis[i] == 0.0f) { - /* axis aligned ray */ - if (data->ray.origin[i] < bv[0] - data->ray.radius || - data->ray.origin[i] > bv[1] + data->ray.radius) - { - return FLT_MAX; - } - } - else { - float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; - - if (data->ray_dot_axis[i] > 0.0f) { - if (ll > low) { - low = ll; - } - if (lu < upper) { - upper = lu; - } - } - else { - if (lu > low) { - low = lu; - } - if (ll < upper) { - upper = ll; - } - } - - if (low > upper) { - return FLT_MAX; - } - } - } - return low; + int i; + + float low = 0, upper = data->hit.dist; + + for (i = 0; i != 3; i++, bv += 2) { + if (data->ray_dot_axis[i] == 0.0f) { + /* axis aligned ray */ + if (data->ray.origin[i] < bv[0] - data->ray.radius || + data->ray.origin[i] > bv[1] + data->ray.radius) { + return FLT_MAX; + } + } + else { + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + + if (data->ray_dot_axis[i] > 0.0f) { + if (ll > low) { + low = ll; + } + if (lu < upper) { + upper = lu; + } + } + else { + if (lu > low) { + low = lu; + } + if (ll < upper) { + upper = ll; + } + } + + if (low > upper) { + return FLT_MAX; + } + } + } + return low; } /** @@ -1512,61 +1518,61 @@ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6]) * TODO this doesn't take data->ray.radius into consideration */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { - const float *bv = node->bv; - - float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0]; - float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0]; - float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1]; - float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1]; - float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2]; - float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2]; - - if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) || - (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) || - (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist)) - { - return FLT_MAX; - } - else { - return max_fff(t1x, t1y, t1z); - } + const float *bv = node->bv; + + float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0]; + float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0]; + float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1]; + float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1]; + float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2]; + float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2]; + + if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) || + (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) || + (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist)) { + return FLT_MAX; + } + else { + return max_fff(t1x, t1y, t1z); + } } static void dfs_raycast(BVHRayCastData *data, BVHNode *node) { - int i; - - /* ray-bv is really fast.. and simple tests revealed its worth to test it - * before calling the ray-primitive functions */ - /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ - float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : ray_nearest_hit(data, node->bv); - if (dist >= data->hit.dist) { - return; - } - - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, &data->ray, &data->hit); - } - else { - data->hit.index = node->index; - data->hit.dist = dist; - madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist); - } - } - else { - /* pick loop direction to dive into the tree (based on ray direction and split axis) */ - if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { - dfs_raycast(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - dfs_raycast(data, node->children[i]); - } - } - } + int i; + + /* ray-bv is really fast.. and simple tests revealed its worth to test it + * before calling the ray-primitive functions */ + /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ + float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : + ray_nearest_hit(data, node->bv); + if (dist >= data->hit.dist) { + return; + } + + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, &data->ray, &data->hit); + } + else { + data->hit.index = node->index; + data->hit.dist = dist; + madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist); + } + } + else { + /* pick loop direction to dive into the tree (based on ray direction and split axis) */ + if (data->ray_dot_axis[node->main_axis] > 0.0f) { + for (i = 0; i != node->totnode; i++) { + dfs_raycast(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + dfs_raycast(data, node->children[i]); + } + } + } } /** @@ -1574,140 +1580,151 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) */ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node) { - int i; - - /* ray-bv is really fast.. and simple tests revealed its worth to test it - * before calling the ray-primitive functions */ - /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ - float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : ray_nearest_hit(data, node->bv); - if (dist >= data->hit.dist) { - return; - } - - if (node->totnode == 0) { - /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */ - dist = data->hit.dist; - data->callback(data->userdata, node->index, &data->ray, &data->hit); - data->hit.index = -1; - data->hit.dist = dist; - } - else { - /* pick loop direction to dive into the tree (based on ray direction and split axis) */ - if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { - dfs_raycast_all(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - dfs_raycast_all(data, node->children[i]); - } - } - } + int i; + + /* ray-bv is really fast.. and simple tests revealed its worth to test it + * before calling the ray-primitive functions */ + /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ + float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : + ray_nearest_hit(data, node->bv); + if (dist >= data->hit.dist) { + return; + } + + if (node->totnode == 0) { + /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */ + dist = data->hit.dist; + data->callback(data->userdata, node->index, &data->ray, &data->hit); + data->hit.index = -1; + data->hit.dist = dist; + } + else { + /* pick loop direction to dive into the tree (based on ray direction and split axis) */ + if (data->ray_dot_axis[node->main_axis] > 0.0f) { + for (i = 0; i != node->totnode; i++) { + dfs_raycast_all(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + dfs_raycast_all(data, node->children[i]); + } + } + } } static void bvhtree_ray_cast_data_precalc(BVHRayCastData *data, int flag) { - int i; + int i; - for (i = 0; i < 3; i++) { - data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]); - data->idot_axis[i] = 1.0f / data->ray_dot_axis[i]; + for (i = 0; i < 3; i++) { + data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]); + data->idot_axis[i] = 1.0f / data->ray_dot_axis[i]; - if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) { - data->ray_dot_axis[i] = 0.0; - } - data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0; - data->index[2 * i + 1] = 1 - data->index[2 * i]; - data->index[2 * i] += 2 * i; - data->index[2 * i + 1] += 2 * i; - } + if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) { + data->ray_dot_axis[i] = 0.0; + } + data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0; + data->index[2 * i + 1] = 1 - data->index[2 * i]; + data->index[2 * i] += 2 * i; + data->index[2 * i + 1] += 2 * i; + } #ifdef USE_KDOPBVH_WATERTIGHT - if (flag & BVH_RAYCAST_WATERTIGHT) { - isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction); - data->ray.isect_precalc = &data->isect_precalc; - } - else { - data->ray.isect_precalc = NULL; - } + if (flag & BVH_RAYCAST_WATERTIGHT) { + isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction); + data->ray.isect_precalc = &data->isect_precalc; + } + else { + data->ray.isect_precalc = NULL; + } #else - UNUSED_VARS(flag); + UNUSED_VARS(flag); #endif } -int BLI_bvhtree_ray_cast_ex( - BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata, - int flag) +int BLI_bvhtree_ray_cast_ex(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, + void *userdata, + int flag) { - BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - BLI_ASSERT_UNIT_V3(dir); + BVHRayCastData data; + BVHNode *root = tree->nodes[tree->totleaf]; - data.tree = tree; + BLI_ASSERT_UNIT_V3(dir); - data.callback = callback; - data.userdata = userdata; + data.tree = tree; - copy_v3_v3(data.ray.origin, co); - copy_v3_v3(data.ray.direction, dir); - data.ray.radius = radius; + data.callback = callback; + data.userdata = userdata; - bvhtree_ray_cast_data_precalc(&data, flag); + copy_v3_v3(data.ray.origin, co); + copy_v3_v3(data.ray.direction, dir); + data.ray.radius = radius; - if (hit) { - memcpy(&data.hit, hit, sizeof(*hit)); - } - else { - data.hit.index = -1; - data.hit.dist = BVH_RAYCAST_DIST_MAX; - } + bvhtree_ray_cast_data_precalc(&data, flag); - if (root) { - dfs_raycast(&data, root); -// iterative_raycast(&data, root); - } + if (hit) { + memcpy(&data.hit, hit, sizeof(*hit)); + } + else { + data.hit.index = -1; + data.hit.dist = BVH_RAYCAST_DIST_MAX; + } + if (root) { + dfs_raycast(&data, root); + // iterative_raycast(&data, root); + } - if (hit) { - memcpy(hit, &data.hit, sizeof(*hit)); - } + if (hit) { + memcpy(hit, &data.hit, sizeof(*hit)); + } - return data.hit.index; + return data.hit.index; } -int BLI_bvhtree_ray_cast( - BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, + void *userdata) { - return BLI_bvhtree_ray_cast_ex(tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT); + return BLI_bvhtree_ray_cast_ex( + tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT); } -float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3]) +float BLI_bvhtree_bb_raycast(const float bv[6], + const float light_start[3], + const float light_end[3], + float pos[3]) { - BVHRayCastData data; - float dist; - - data.hit.dist = BVH_RAYCAST_DIST_MAX; + BVHRayCastData data; + float dist; - /* get light direction */ - sub_v3_v3v3(data.ray.direction, light_end, light_start); + data.hit.dist = BVH_RAYCAST_DIST_MAX; - data.ray.radius = 0.0; + /* get light direction */ + sub_v3_v3v3(data.ray.direction, light_end, light_start); - copy_v3_v3(data.ray.origin, light_start); + data.ray.radius = 0.0; - normalize_v3(data.ray.direction); - copy_v3_v3(data.ray_dot_axis, data.ray.direction); + copy_v3_v3(data.ray.origin, light_start); - dist = ray_nearest_hit(&data, bv); + normalize_v3(data.ray.direction); + copy_v3_v3(data.ray_dot_axis, data.ray.direction); - madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist); + dist = ray_nearest_hit(&data, bv); - return dist; + madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist); + return dist; } /** @@ -1718,41 +1735,50 @@ float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], cons * having to handle resetting the hit beforehand. * It also avoid redundant argument and return value which aren't meaningful when collecting multiple hits. */ -void BLI_bvhtree_ray_cast_all_ex( - BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, - BVHTree_RayCastCallback callback, void *userdata, - int flag) +void BLI_bvhtree_ray_cast_all_ex(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + float hit_dist, + BVHTree_RayCastCallback callback, + void *userdata, + int flag) { - BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHRayCastData data; + BVHNode *root = tree->nodes[tree->totleaf]; - BLI_ASSERT_UNIT_V3(dir); - BLI_assert(callback != NULL); + BLI_ASSERT_UNIT_V3(dir); + BLI_assert(callback != NULL); - data.tree = tree; + data.tree = tree; - data.callback = callback; - data.userdata = userdata; + data.callback = callback; + data.userdata = userdata; - copy_v3_v3(data.ray.origin, co); - copy_v3_v3(data.ray.direction, dir); - data.ray.radius = radius; + copy_v3_v3(data.ray.origin, co); + copy_v3_v3(data.ray.direction, dir); + data.ray.radius = radius; - bvhtree_ray_cast_data_precalc(&data, flag); + bvhtree_ray_cast_data_precalc(&data, flag); - data.hit.index = -1; - data.hit.dist = hit_dist; + data.hit.index = -1; + data.hit.dist = hit_dist; - if (root) { - dfs_raycast_all(&data, root); - } + if (root) { + dfs_raycast_all(&data, root); + } } -void BLI_bvhtree_ray_cast_all( - BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, - BVHTree_RayCastCallback callback, void *userdata) +void BLI_bvhtree_ray_cast_all(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + float hit_dist, + BVHTree_RayCastCallback callback, + void *userdata) { - BLI_bvhtree_ray_cast_all_ex(tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT); + BLI_bvhtree_ray_cast_all_ex( + tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT); } /** \} */ @@ -1766,284 +1792,274 @@ void BLI_bvhtree_ray_cast_all( * \{ */ typedef struct RangeQueryData { - BVHTree *tree; - const float *center; - float radius_sq; /* squared radius */ + BVHTree *tree; + const float *center; + float radius_sq; /* squared radius */ - int hits; + int hits; - BVHTree_RangeQuery callback; - void *userdata; + BVHTree_RangeQuery callback; + void *userdata; } RangeQueryData; - static void dfs_range_query(RangeQueryData *data, BVHNode *node) { - if (node->totnode == 0) { -#if 0 /*UNUSED*/ - /* Calculate the node min-coords - * (if the node was a point then this is the point coordinates) */ - float co[3]; - co[0] = node->bv[0]; - co[1] = node->bv[2]; - co[2] = node->bv[4]; + if (node->totnode == 0) { +#if 0 /*UNUSED*/ + /* Calculate the node min-coords + * (if the node was a point then this is the point coordinates) */ + float co[3]; + co[0] = node->bv[0]; + co[1] = node->bv[2]; + co[2] = node->bv[4]; #endif - } - else { - int i; - for (i = 0; i != node->totnode; i++) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest); - if (dist_sq < data->radius_sq) { - /* Its a leaf.. call the callback */ - if (node->children[i]->totnode == 0) { - data->hits++; - data->callback(data->userdata, node->children[i]->index, data->center, dist_sq); - } - else { - dfs_range_query(data, node->children[i]); - } - } - } - } + } + else { + int i; + for (i = 0; i != node->totnode; i++) { + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest); + if (dist_sq < data->radius_sq) { + /* Its a leaf.. call the callback */ + if (node->children[i]->totnode == 0) { + data->hits++; + data->callback(data->userdata, node->children[i]->index, data->center, dist_sq); + } + else { + dfs_range_query(data, node->children[i]); + } + } + } + } } int BLI_bvhtree_range_query( - BVHTree *tree, const float co[3], float radius, - BVHTree_RangeQuery callback, void *userdata) + BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; - - RangeQueryData data; - data.tree = tree; - data.center = co; - data.radius_sq = radius * radius; - data.hits = 0; - - data.callback = callback; - data.userdata = userdata; - - if (root != NULL) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data.center, root, nearest); - if (dist_sq < data.radius_sq) { - /* Its a leaf.. call the callback */ - if (root->totnode == 0) { - data.hits++; - data.callback(data.userdata, root->index, co, dist_sq); - } - else { - dfs_range_query(&data, root); - } - } - } - - return data.hits; + BVHNode *root = tree->nodes[tree->totleaf]; + + RangeQueryData data; + data.tree = tree; + data.center = co; + data.radius_sq = radius * radius; + data.hits = 0; + + data.callback = callback; + data.userdata = userdata; + + if (root != NULL) { + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data.center, root, nearest); + if (dist_sq < data.radius_sq) { + /* Its a leaf.. call the callback */ + if (root->totnode == 0) { + data.hits++; + data.callback(data.userdata, root->index, co, dist_sq); + } + else { + dfs_range_query(&data, root); + } + } + } + + return data.hits; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_nearest_projected * \{ */ -static void bvhtree_nearest_projected_dfs_recursive( - BVHNearestProjectedData *__restrict data, const BVHNode *node) +static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__restrict data, + const BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback( - data->userdata, node->index, &data->precalc, - NULL, 0, - &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {node->bv[0], node->bv[2], node->bv[4]}, - (float[3]) {node->bv[1], node->bv[3], node->bv[5]}, - data->closest_axis); - } - } - else { - /* First pick the closest node to recurse into */ - if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { - const float *bv = node->children[i]->bv; - - if (dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {bv[0], bv[2], bv[4]}, - (float[3]) {bv[1], bv[3], bv[5]}, - data->closest_axis) <= data->nearest.dist_sq) - { - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - else { - for (int i = node->totnode; i--;) { - const float *bv = node->children[i]->bv; - - if (dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {bv[0], bv[2], bv[4]}, - (float[3]) {bv[1], bv[3], bv[5]}, - data->closest_axis) <= data->nearest.dist_sq) - { - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, &data->precalc, NULL, 0, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = dist_squared_to_projected_aabb( + &data->precalc, + (float[3]){node->bv[0], node->bv[2], node->bv[4]}, + (float[3]){node->bv[1], node->bv[3], node->bv[5]}, + data->closest_axis); + } + } + else { + /* First pick the closest node to recurse into */ + if (data->closest_axis[node->main_axis]) { + for (int i = 0; i != node->totnode; i++) { + const float *bv = node->children[i]->bv; + + if (dist_squared_to_projected_aabb(&data->precalc, + (float[3]){bv[0], bv[2], bv[4]}, + (float[3]){bv[1], bv[3], bv[5]}, + data->closest_axis) <= data->nearest.dist_sq) { + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + else { + for (int i = node->totnode; i--;) { + const float *bv = node->children[i]->bv; + + if (dist_squared_to_projected_aabb(&data->precalc, + (float[3]){bv[0], bv[2], bv[4]}, + (float[3]){bv[1], bv[3], bv[5]}, + data->closest_axis) <= data->nearest.dist_sq) { + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } } static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive( - BVHNearestProjectedData *__restrict data, const BVHNode *node) + BVHNearestProjectedData *__restrict data, const BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback( - data->userdata, node->index, &data->precalc, - data->clip_plane, data->clip_plane_len, - &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {node->bv[0], node->bv[2], node->bv[4]}, - (float[3]) {node->bv[1], node->bv[3], node->bv[5]}, - data->closest_axis); - } - } - else { - /* First pick the closest node to recurse into */ - if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { - const float *bv = node->children[i]->bv; - const float bb_min[3] = {bv[0], bv[2], bv[4]}; - const float bb_max[3] = {bv[1], bv[3], bv[5]}; - - int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max); - - if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) && dist_squared_to_projected_aabb( - &data->precalc, bb_min, bb_max, - data->closest_axis) <= data->nearest.dist_sq) - { - if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); - } - else { - /* ISECT_AABB_PLANE_IN_FRONT_ALL */ - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } - else { - for (int i = node->totnode; i--;) { - const float *bv = node->children[i]->bv; - const float bb_min[3] = {bv[0], bv[2], bv[4]}; - const float bb_max[3] = {bv[1], bv[3], bv[5]}; - - int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max); - - if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY && dist_squared_to_projected_aabb( - &data->precalc, bb_min, bb_max, - data->closest_axis) <= data->nearest.dist_sq) - { - if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); - } - else { - /* ISECT_AABB_PLANE_IN_FRONT_ALL */ - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, + node->index, + &data->precalc, + data->clip_plane, + data->clip_plane_len, + &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = dist_squared_to_projected_aabb( + &data->precalc, + (float[3]){node->bv[0], node->bv[2], node->bv[4]}, + (float[3]){node->bv[1], node->bv[3], node->bv[5]}, + data->closest_axis); + } + } + else { + /* First pick the closest node to recurse into */ + if (data->closest_axis[node->main_axis]) { + for (int i = 0; i != node->totnode; i++) { + const float *bv = node->children[i]->bv; + const float bb_min[3] = {bv[0], bv[2], bv[4]}; + const float bb_max[3] = {bv[1], bv[3], bv[5]}; + + int isect_type = isect_aabb_planes_v3( + data->clip_plane, data->clip_plane_len, bb_min, bb_max); + + if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) && + dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <= + data->nearest.dist_sq) { + if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); + } + else { + /* ISECT_AABB_PLANE_IN_FRONT_ALL */ + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } + else { + for (int i = node->totnode; i--;) { + const float *bv = node->children[i]->bv; + const float bb_min[3] = {bv[0], bv[2], bv[4]}; + const float bb_max[3] = {bv[1], bv[3], bv[5]}; + + int isect_type = isect_aabb_planes_v3( + data->clip_plane, data->clip_plane_len, bb_min, bb_max); + + if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY && + dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <= + data->nearest.dist_sq) { + if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); + } + else { + /* ISECT_AABB_PLANE_IN_FRONT_ALL */ + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } + } } -int BLI_bvhtree_find_nearest_projected( - BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2], - float clip_plane[6][4], int clip_plane_len, - BVHTreeNearest *nearest, - BVHTree_NearestProjectedCallback callback, void *userdata) +int BLI_bvhtree_find_nearest_projected(BVHTree *tree, + float projmat[4][4], + float winsize[2], + float mval[2], + float clip_plane[6][4], + int clip_plane_len, + BVHTreeNearest *nearest, + BVHTree_NearestProjectedCallback callback, + void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; - if (root != NULL) { - BVHNearestProjectedData data; - dist_squared_to_projected_aabb_precalc( - &data.precalc, projmat, winsize, mval); - - data.callback = callback; - data.userdata = userdata; - - if (clip_plane) { - data.clip_plane_len = clip_plane_len; - for (int i = 0; i < data.clip_plane_len; i++) { - copy_v4_v4(data.clip_plane[i], clip_plane[i]); - } - } - else { - data.clip_plane_len = 1; - planes_from_projmat( - projmat, - NULL, NULL, NULL, NULL, - data.clip_plane[0], NULL); - } - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - { - const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; - const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; - - int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max); - - if (isect_type != 0 && dist_squared_to_projected_aabb( - &data.precalc, bb_min, bb_max, - data.closest_axis) <= data.nearest.dist_sq) - { - if (isect_type == 1) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root); - } - else { - bvhtree_nearest_projected_dfs_recursive(&data, root); - } - } - } - - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; - } - return -1; + BVHNode *root = tree->nodes[tree->totleaf]; + if (root != NULL) { + BVHNearestProjectedData data; + dist_squared_to_projected_aabb_precalc(&data.precalc, projmat, winsize, mval); + + data.callback = callback; + data.userdata = userdata; + + if (clip_plane) { + data.clip_plane_len = clip_plane_len; + for (int i = 0; i < data.clip_plane_len; i++) { + copy_v4_v4(data.clip_plane[i], clip_plane[i]); + } + } + else { + data.clip_plane_len = 1; + planes_from_projmat(projmat, NULL, NULL, NULL, NULL, data.clip_plane[0], NULL); + } + + if (nearest) { + memcpy(&data.nearest, nearest, sizeof(*nearest)); + } + else { + data.nearest.index = -1; + data.nearest.dist_sq = FLT_MAX; + } + { + const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; + const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; + + int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max); + + if (isect_type != 0 && + dist_squared_to_projected_aabb(&data.precalc, bb_min, bb_max, data.closest_axis) <= + data.nearest.dist_sq) { + if (isect_type == 1) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root); + } + else { + bvhtree_nearest_projected_dfs_recursive(&data, root); + } + } + } + + if (nearest) { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; + } + return -1; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_walk_dfs * \{ */ typedef struct BVHTree_WalkData { - BVHTree_WalkParentCallback walk_parent_cb; - BVHTree_WalkLeafCallback walk_leaf_cb; - BVHTree_WalkOrderCallback walk_order_cb; - void *userdata; + BVHTree_WalkParentCallback walk_parent_cb; + BVHTree_WalkLeafCallback walk_leaf_cb; + BVHTree_WalkOrderCallback walk_order_cb; + void *userdata; } BVHTree_WalkData; /** @@ -2051,35 +2067,37 @@ typedef struct BVHTree_WalkData { * * \return false to break out of the search early. */ -static bool bvhtree_walk_dfs_recursive( - BVHTree_WalkData *walk_data, - const BVHNode *node) +static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNode *node) { - if (node->totnode == 0) { - return walk_data->walk_leaf_cb((const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata); - } - else { - /* First pick the closest node to recurse into */ - if (walk_data->walk_order_cb((const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) { - for (int i = 0; i != node->totnode; i++) { - if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { - if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { - return false; - } - } - } - } - else { - for (int i = node->totnode - 1; i >= 0; i--) { - if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { - if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { - return false; - } - } - } - } - } - return true; + if (node->totnode == 0) { + return walk_data->walk_leaf_cb( + (const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata); + } + else { + /* First pick the closest node to recurse into */ + if (walk_data->walk_order_cb( + (const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) { + for (int i = 0; i != node->totnode; i++) { + if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, + walk_data->userdata)) { + if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { + return false; + } + } + } + } + else { + for (int i = node->totnode - 1; i >= 0; i--) { + if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, + walk_data->userdata)) { + if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { + return false; + } + } + } + } + } + return true; } /** @@ -2094,20 +2112,20 @@ static bool bvhtree_walk_dfs_recursive( * either from the node with the lower or higher k-dop axis value. * \param userdata: Argument passed to all callbacks. */ -void BLI_bvhtree_walk_dfs( - BVHTree *tree, - BVHTree_WalkParentCallback walk_parent_cb, - BVHTree_WalkLeafCallback walk_leaf_cb, - BVHTree_WalkOrderCallback walk_order_cb, void *userdata) +void BLI_bvhtree_walk_dfs(BVHTree *tree, + BVHTree_WalkParentCallback walk_parent_cb, + BVHTree_WalkLeafCallback walk_leaf_cb, + BVHTree_WalkOrderCallback walk_order_cb, + void *userdata) { - const BVHNode *root = tree->nodes[tree->totleaf]; - if (root != NULL) { - BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata}; - /* first make sure the bv of root passes in the test too */ - if (walk_parent_cb((const BVHTreeAxisRange *)root->bv, userdata)) { - bvhtree_walk_dfs_recursive(&walk_data, root); - } - } + const BVHNode *root = tree->nodes[tree->totleaf]; + if (root != NULL) { + BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata}; + /* first make sure the bv of root passes in the test too */ + if (walk_parent_cb((const BVHTreeAxisRange *)root->bv, userdata)) { + bvhtree_walk_dfs_recursive(&walk_data, root); + } + } } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index 3f99f65703f..ae4f5dcebcf 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -39,55 +39,55 @@ int BLI_linklist_count(const LinkNode *list) { - int len; + int len; - for (len = 0; list; list = list->next) { - len++; - } + for (len = 0; list; list = list->next) { + len++; + } - return len; + return len; } int BLI_linklist_index(const LinkNode *list, void *ptr) { - int index; + int index; - for (index = 0; list; list = list->next, index++) { - if (list->link == ptr) { - return index; - } - } + for (index = 0; list; list = list->next, index++) { + if (list->link == ptr) { + return index; + } + } - return -1; + return -1; } LinkNode *BLI_linklist_find(LinkNode *list, int index) { - int i; + int i; - for (i = 0; list; list = list->next, i++) { - if (i == index) { - return list; - } - } + for (i = 0; list; list = list->next, i++) { + if (i == index) { + return list; + } + } - return NULL; + return NULL; } void BLI_linklist_reverse(LinkNode **listp) { - LinkNode *rhead = NULL, *cur = *listp; + LinkNode *rhead = NULL, *cur = *listp; - while (cur) { - LinkNode *next = cur->next; + while (cur) { + LinkNode *next = cur->next; - cur->next = rhead; - rhead = cur; + cur->next = rhead; + rhead = cur; - cur = next; - } + cur = next; + } - *listp = rhead; + *listp = rhead; } /** @@ -96,69 +96,69 @@ void BLI_linklist_reverse(LinkNode **listp) */ void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index) { - LinkNode *lnk, *lnk_psrc = NULL, *lnk_pdst = NULL; - int i; - - if (new_index == curr_index) { - return; - } - - if (new_index < curr_index) { - for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) { - if (i == new_index - 1) { - lnk_pdst = lnk; - } - else if (i == curr_index - 1) { - lnk_psrc = lnk; - break; - } - } - - if (!(lnk_psrc && lnk_psrc->next && (!lnk_pdst || lnk_pdst->next))) { - /* Invalid indices, abort. */ - return; - } - - lnk = lnk_psrc->next; - lnk_psrc->next = lnk->next; - if (lnk_pdst) { - lnk->next = lnk_pdst->next; - lnk_pdst->next = lnk; - } - else { - /* destination is first element of the list... */ - lnk->next = *listp; - *listp = lnk; - } - } - else { - for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) { - if (i == new_index) { - lnk_pdst = lnk; - break; - } - else if (i == curr_index - 1) { - lnk_psrc = lnk; - } - } - - if (!(lnk_pdst && (!lnk_psrc || lnk_psrc->next))) { - /* Invalid indices, abort. */ - return; - } - - if (lnk_psrc) { - lnk = lnk_psrc->next; - lnk_psrc->next = lnk->next; - } - else { - /* source is first element of the list... */ - lnk = *listp; - *listp = lnk->next; - } - lnk->next = lnk_pdst->next; - lnk_pdst->next = lnk; - } + LinkNode *lnk, *lnk_psrc = NULL, *lnk_pdst = NULL; + int i; + + if (new_index == curr_index) { + return; + } + + if (new_index < curr_index) { + for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) { + if (i == new_index - 1) { + lnk_pdst = lnk; + } + else if (i == curr_index - 1) { + lnk_psrc = lnk; + break; + } + } + + if (!(lnk_psrc && lnk_psrc->next && (!lnk_pdst || lnk_pdst->next))) { + /* Invalid indices, abort. */ + return; + } + + lnk = lnk_psrc->next; + lnk_psrc->next = lnk->next; + if (lnk_pdst) { + lnk->next = lnk_pdst->next; + lnk_pdst->next = lnk; + } + else { + /* destination is first element of the list... */ + lnk->next = *listp; + *listp = lnk; + } + } + else { + for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) { + if (i == new_index) { + lnk_pdst = lnk; + break; + } + else if (i == curr_index - 1) { + lnk_psrc = lnk; + } + } + + if (!(lnk_pdst && (!lnk_psrc || lnk_psrc->next))) { + /* Invalid indices, abort. */ + return; + } + + if (lnk_psrc) { + lnk = lnk_psrc->next; + lnk_psrc->next = lnk->next; + } + else { + /* source is first element of the list... */ + lnk = *listp; + *listp = lnk->next; + } + lnk->next = lnk_pdst->next; + lnk_pdst->next = lnk; + } } /** @@ -166,27 +166,27 @@ void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index) */ void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink) { - nlink->link = ptr; - nlink->next = *listp; - *listp = nlink; + nlink->link = ptr; + nlink->next = *listp; + *listp = nlink; } void BLI_linklist_prepend(LinkNode **listp, void *ptr) { - LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); - BLI_linklist_prepend_nlink(listp, ptr, nlink); + LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); + BLI_linklist_prepend_nlink(listp, ptr, nlink); } void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) { - LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink)); - BLI_linklist_prepend_nlink(listp, ptr, nlink); + LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink)); + BLI_linklist_prepend_nlink(listp, ptr, nlink); } void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool) { - LinkNode *nlink = BLI_mempool_alloc(mempool); - BLI_linklist_prepend_nlink(listp, ptr, nlink); + LinkNode *nlink = BLI_mempool_alloc(mempool); + BLI_linklist_prepend_nlink(listp, ptr, nlink); } /** @@ -194,125 +194,125 @@ void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool */ void BLI_linklist_append_nlink(LinkNodePair *list_pair, void *ptr, LinkNode *nlink) { - nlink->link = ptr; - nlink->next = NULL; - - if (list_pair->list) { - BLI_assert((list_pair->last_node != NULL) && (list_pair->last_node->next == NULL)); - list_pair->last_node->next = nlink; - } - else { - BLI_assert(list_pair->last_node == NULL); - list_pair->list = nlink; - } - - list_pair->last_node = nlink; + nlink->link = ptr; + nlink->next = NULL; + + if (list_pair->list) { + BLI_assert((list_pair->last_node != NULL) && (list_pair->last_node->next == NULL)); + list_pair->last_node->next = nlink; + } + else { + BLI_assert(list_pair->last_node == NULL); + list_pair->list = nlink; + } + + list_pair->last_node = nlink; } void BLI_linklist_append(LinkNodePair *list_pair, void *ptr) { - LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); - BLI_linklist_append_nlink(list_pair, ptr, nlink); + LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); + BLI_linklist_append_nlink(list_pair, ptr, nlink); } void BLI_linklist_append_arena(LinkNodePair *list_pair, void *ptr, MemArena *ma) { - LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink)); - BLI_linklist_append_nlink(list_pair, ptr, nlink); + LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink)); + BLI_linklist_append_nlink(list_pair, ptr, nlink); } void BLI_linklist_append_pool(LinkNodePair *list_pair, void *ptr, BLI_mempool *mempool) { - LinkNode *nlink = BLI_mempool_alloc(mempool); - BLI_linklist_append_nlink(list_pair, ptr, nlink); + LinkNode *nlink = BLI_mempool_alloc(mempool); + BLI_linklist_append_nlink(list_pair, ptr, nlink); } void *BLI_linklist_pop(struct LinkNode **listp) { - /* intentionally no NULL check */ - void *link = (*listp)->link; - void *next = (*listp)->next; + /* intentionally no NULL check */ + void *link = (*listp)->link; + void *next = (*listp)->next; - MEM_freeN(*listp); + MEM_freeN(*listp); - *listp = next; - return link; + *listp = next; + return link; } void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool) { - /* intentionally no NULL check */ - void *link = (*listp)->link; - void *next = (*listp)->next; + /* intentionally no NULL check */ + void *link = (*listp)->link; + void *next = (*listp)->next; - BLI_mempool_free(mempool, (*listp)); + BLI_mempool_free(mempool, (*listp)); - *listp = next; - return link; + *listp = next; + return link; } void BLI_linklist_insert_after(LinkNode **listp, void *ptr) { - LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); - LinkNode *node = *listp; - - nlink->link = ptr; - - if (node) { - nlink->next = node->next; - node->next = nlink; - } - else { - nlink->next = NULL; - *listp = nlink; - } + LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__); + LinkNode *node = *listp; + + nlink->link = ptr; + + if (node) { + nlink->next = node->next; + node->next = nlink; + } + else { + nlink->next = NULL; + *listp = nlink; + } } void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc) { - while (list) { - LinkNode *next = list->next; + while (list) { + LinkNode *next = list->next; - if (freefunc) { - freefunc(list->link); - } - MEM_freeN(list); + if (freefunc) { + freefunc(list->link); + } + MEM_freeN(list); - list = next; - } + list = next; + } } void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool) { - while (list) { - LinkNode *next = list->next; + while (list) { + LinkNode *next = list->next; - if (freefunc) { - freefunc(list->link); - } - BLI_mempool_free(mempool, list); + if (freefunc) { + freefunc(list->link); + } + BLI_mempool_free(mempool, list); - list = next; - } + list = next; + } } void BLI_linklist_freeN(LinkNode *list) { - while (list) { - LinkNode *next = list->next; + while (list) { + LinkNode *next = list->next; - MEM_freeN(list->link); - MEM_freeN(list); + MEM_freeN(list->link); + MEM_freeN(list); - list = next; - } + list = next; + } } void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata) { - for (; list; list = list->next) { - applyfunc(list->link, userdata); - } + for (; list; list = list->next) { + applyfunc(list->link, userdata); + } } /* -------------------------------------------------------------------- */ @@ -335,19 +335,20 @@ void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdat #undef SORT_IMPL_LINKTYPE #undef SORT_IMPL_LINKTYPE_DATA - LinkNode *BLI_linklist_sort(LinkNode *list, int (*cmp)(const void *, const void *)) { - if (list && list->next) { - list = linklist_sort_fn(list, cmp); - } - return list; + if (list && list->next) { + list = linklist_sort_fn(list, cmp); + } + return list; } -LinkNode *BLI_linklist_sort_r(LinkNode *list, int (*cmp)(void *, const void *, const void *), void *thunk) +LinkNode *BLI_linklist_sort_r(LinkNode *list, + int (*cmp)(void *, const void *, const void *), + void *thunk) { - if (list && list->next) { - list = linklist_sort_fn_r(list, cmp, thunk); - } - return list; + if (list && list->next) { + list = linklist_sort_fn_r(list, cmp, thunk); + } + return list; } diff --git a/source/blender/blenlib/intern/BLI_linklist_lockfree.c b/source/blender/blenlib/intern/BLI_linklist_lockfree.c index d5dca86ae50..d27e65af778 100644 --- a/source/blender/blenlib/intern/BLI_linklist_lockfree.c +++ b/source/blender/blenlib/intern/BLI_linklist_lockfree.c @@ -30,56 +30,52 @@ void BLI_linklist_lockfree_init(LockfreeLinkList *list) { - list->dummy_node.next = NULL; - list->head = list->tail = &list->dummy_node; + list->dummy_node.next = NULL; + list->head = list->tail = &list->dummy_node; } -void BLI_linklist_lockfree_free(LockfreeLinkList *list, - LockfreeeLinkNodeFreeFP free_func) +void BLI_linklist_lockfree_free(LockfreeLinkList *list, LockfreeeLinkNodeFreeFP free_func) { - if (free_func != NULL) { - /* NOTE: We start from a first user-added node. */ - LockfreeLinkNode *node = list->head->next; - while (node != NULL) { - LockfreeLinkNode *node_next = node->next; - free_func(node); - node = node_next; - } - } + if (free_func != NULL) { + /* NOTE: We start from a first user-added node. */ + LockfreeLinkNode *node = list->head->next; + while (node != NULL) { + LockfreeLinkNode *node_next = node->next; + free_func(node); + node = node_next; + } + } } -void BLI_linklist_lockfree_clear(LockfreeLinkList *list, - LockfreeeLinkNodeFreeFP free_func) +void BLI_linklist_lockfree_clear(LockfreeLinkList *list, LockfreeeLinkNodeFreeFP free_func) { - BLI_linklist_lockfree_free(list, free_func); - BLI_linklist_lockfree_init(list); + BLI_linklist_lockfree_free(list, free_func); + BLI_linklist_lockfree_init(list); } -void BLI_linklist_lockfree_insert(LockfreeLinkList *list, - LockfreeLinkNode *node) +void BLI_linklist_lockfree_insert(LockfreeLinkList *list, LockfreeLinkNode *node) { - /* Based on: - * - * John D. Valois - * Implementing Lock-Free Queues - * - * http://people.csail.mit.edu/bushl2/rpi/portfolio/lockfree-grape/documents/lock-free-linked-lists.pdf - */ - bool keep_working; - LockfreeLinkNode *tail_node; - node->next = NULL; - do { - tail_node = list->tail; - keep_working = - (atomic_cas_ptr((void **)&tail_node->next, NULL, node) != NULL); - if (keep_working) { - atomic_cas_ptr((void **)&list->tail, tail_node, tail_node->next); - } - } while (keep_working); - atomic_cas_ptr((void **)&list->tail, tail_node, node); + /* Based on: + * + * John D. Valois + * Implementing Lock-Free Queues + * + * http://people.csail.mit.edu/bushl2/rpi/portfolio/lockfree-grape/documents/lock-free-linked-lists.pdf + */ + bool keep_working; + LockfreeLinkNode *tail_node; + node->next = NULL; + do { + tail_node = list->tail; + keep_working = (atomic_cas_ptr((void **)&tail_node->next, NULL, node) != NULL); + if (keep_working) { + atomic_cas_ptr((void **)&list->tail, tail_node, tail_node->next); + } + } while (keep_working); + atomic_cas_ptr((void **)&list->tail, tail_node, node); } LockfreeLinkNode *BLI_linklist_lockfree_begin(LockfreeLinkList *list) { - return list->head->next; + return list->head->next; } diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 8be64a44d2c..b5815f7b503 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -58,129 +58,130 @@ #endif struct MemBuf { - struct MemBuf *next; - uchar data[0]; + struct MemBuf *next; + uchar data[0]; }; struct MemArena { - unsigned char *curbuf; - const char *name; - struct MemBuf *bufs; + unsigned char *curbuf; + const char *name; + struct MemBuf *bufs; - size_t bufsize, cursize; - size_t align; + size_t bufsize, cursize; + size_t align; - bool use_calloc; + bool use_calloc; }; static void memarena_buf_free_all(struct MemBuf *mb) { - while (mb != NULL) { - struct MemBuf *mb_next = mb->next; - MEM_freeN(mb); - mb = mb_next; - } + while (mb != NULL) { + struct MemBuf *mb_next = mb->next; + MEM_freeN(mb); + mb = mb_next; + } } MemArena *BLI_memarena_new(const size_t bufsize, const char *name) { - MemArena *ma = MEM_callocN(sizeof(*ma), "memarena"); - ma->bufsize = bufsize; - ma->align = 8; - ma->name = name; + MemArena *ma = MEM_callocN(sizeof(*ma), "memarena"); + ma->bufsize = bufsize; + ma->align = 8; + ma->name = name; - VALGRIND_CREATE_MEMPOOL(ma, 0, false); + VALGRIND_CREATE_MEMPOOL(ma, 0, false); - return ma; + return ma; } void BLI_memarena_use_calloc(MemArena *ma) { - ma->use_calloc = 1; + ma->use_calloc = 1; } void BLI_memarena_use_malloc(MemArena *ma) { - ma->use_calloc = 0; + ma->use_calloc = 0; } void BLI_memarena_use_align(struct MemArena *ma, const size_t align) { - /* Align must be a power of two. */ - BLI_assert((align & (align - 1)) == 0); + /* Align must be a power of two. */ + BLI_assert((align & (align - 1)) == 0); - ma->align = align; + ma->align = align; } void BLI_memarena_free(MemArena *ma) { - memarena_buf_free_all(ma->bufs); + memarena_buf_free_all(ma->bufs); - VALGRIND_DESTROY_MEMPOOL(ma); + VALGRIND_DESTROY_MEMPOOL(ma); - MEM_freeN(ma); + MEM_freeN(ma); } /** Pad num up by \a amt (must be power of two). */ -#define PADUP(num, amt) (((num) + ((amt) - 1)) & ~((amt) - 1)) +#define PADUP(num, amt) (((num) + ((amt)-1)) & ~((amt)-1)) /** Align alloc'ed memory (needed if `align > 8`). */ static void memarena_curbuf_align(MemArena *ma) { - unsigned char *tmp; + unsigned char *tmp; - tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); - ma->cursize -= (size_t)(tmp - ma->curbuf); - ma->curbuf = tmp; + tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); + ma->cursize -= (size_t)(tmp - ma->curbuf); + ma->curbuf = tmp; } void *BLI_memarena_alloc(MemArena *ma, size_t size) { - void *ptr; + void *ptr; - /* Ensure proper alignment by rounding size up to multiple of 8. */ - size = PADUP(size, ma->align); + /* Ensure proper alignment by rounding size up to multiple of 8. */ + size = PADUP(size, ma->align); - if (UNLIKELY(size > ma->cursize)) { - if (size > ma->bufsize - (ma->align - 1)) { - ma->cursize = PADUP(size + 1, ma->align); - } - else { - ma->cursize = ma->bufsize; - } + if (UNLIKELY(size > ma->cursize)) { + if (size > ma->bufsize - (ma->align - 1)) { + ma->cursize = PADUP(size + 1, ma->align); + } + else { + ma->cursize = ma->bufsize; + } - struct MemBuf *mb = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(sizeof(*mb) + ma->cursize, ma->name); - ma->curbuf = mb->data; - mb->next = ma->bufs; - ma->bufs = mb; + struct MemBuf *mb = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(sizeof(*mb) + ma->cursize, + ma->name); + ma->curbuf = mb->data; + mb->next = ma->bufs; + ma->bufs = mb; - ASAN_POISON_MEMORY_REGION(ma->curbuf, ma->cursize); + ASAN_POISON_MEMORY_REGION(ma->curbuf, ma->cursize); - memarena_curbuf_align(ma); - } + memarena_curbuf_align(ma); + } - ptr = ma->curbuf; - ma->curbuf += size; - ma->cursize -= size; + ptr = ma->curbuf; + ma->curbuf += size; + ma->cursize -= size; - VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); + VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); - ASAN_UNPOISON_MEMORY_REGION(ptr, size); + ASAN_UNPOISON_MEMORY_REGION(ptr, size); - return ptr; + return ptr; } void *BLI_memarena_calloc(MemArena *ma, size_t size) { - void *ptr; + void *ptr; - /* No need to use this function call if we're calloc'ing by default. */ - BLI_assert(ma->use_calloc == false); + /* No need to use this function call if we're calloc'ing by default. */ + BLI_assert(ma->use_calloc == false); - ptr = BLI_memarena_alloc(ma, size); - memset(ptr, 0, size); + ptr = BLI_memarena_alloc(ma, size); + memset(ptr, 0, size); - return ptr; + return ptr; } /** @@ -189,29 +190,29 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size) */ void BLI_memarena_clear(MemArena *ma) { - if (ma->bufs) { - unsigned char *curbuf_prev; - size_t curbuf_used; - - if (ma->bufs->next) { - memarena_buf_free_all(ma->bufs->next); - ma->bufs->next = NULL; - } - - curbuf_prev = ma->curbuf; - ma->curbuf = ma->bufs->data; - memarena_curbuf_align(ma); - - /* restore to original size */ - curbuf_used = (size_t)(curbuf_prev - ma->curbuf); - ma->cursize += curbuf_used; - - if (ma->use_calloc) { - memset(ma->curbuf, 0, curbuf_used); - } - ASAN_POISON_MEMORY_REGION(ma->curbuf, ma->cursize); - } - - VALGRIND_DESTROY_MEMPOOL(ma); - VALGRIND_CREATE_MEMPOOL(ma, 0, false); + if (ma->bufs) { + unsigned char *curbuf_prev; + size_t curbuf_used; + + if (ma->bufs->next) { + memarena_buf_free_all(ma->bufs->next); + ma->bufs->next = NULL; + } + + curbuf_prev = ma->curbuf; + ma->curbuf = ma->bufs->data; + memarena_curbuf_align(ma); + + /* restore to original size */ + curbuf_used = (size_t)(curbuf_prev - ma->curbuf); + ma->cursize += curbuf_used; + + if (ma->use_calloc) { + memset(ma->curbuf, 0, curbuf_used); + } + ASAN_POISON_MEMORY_REGION(ma->curbuf, ma->cursize); + } + + VALGRIND_DESTROY_MEMPOOL(ma); + VALGRIND_CREATE_MEMPOOL(ma, 0, false); } diff --git a/source/blender/blenlib/intern/BLI_memiter.c b/source/blender/blenlib/intern/BLI_memiter.c index df8a1de84e4..c7df7d5fdd4 100644 --- a/source/blender/blenlib/intern/BLI_memiter.c +++ b/source/blender/blenlib/intern/BLI_memiter.c @@ -69,66 +69,65 @@ typedef intptr_t offset_t; // #define USE_TERMINATE_PARANOID /* Currently totalloc isnt used. */ - // #define USE_TOTALLOC +// #define USE_TOTALLOC /* pad must be power of two */ -#define PADUP(num, pad) (((num) + ((pad) - 1)) & ~((pad) - 1)) +#define PADUP(num, pad) (((num) + ((pad)-1)) & ~((pad)-1)) typedef struct BLI_memiter_elem { - offset_t size; - data_t data[0]; + offset_t size; + data_t data[0]; } BLI_memiter_elem; typedef struct BLI_memiter_chunk { - struct BLI_memiter_chunk *next; - /** - * internal format is: - * ``[next_pointer, size:data, size:data, ..., negative_offset]`` - * - * Where negative offset rewinds to the start. - */ - data_t data[0]; + struct BLI_memiter_chunk *next; + /** + * internal format is: + * ``[next_pointer, size:data, size:data, ..., negative_offset]`` + * + * Where negative offset rewinds to the start. + */ + data_t data[0]; } BLI_memiter_chunk; typedef struct BLI_memiter { - /* A pointer to 'head' is needed so we can iterate in the order allocated. */ - struct BLI_memiter_chunk *head, *tail; - data_t *data_curr; - data_t *data_last; - /* Used unless a large element is requested. - * (which should be very rare!). */ - uint chunk_size_in_bytes_min; - uint count; + /* A pointer to 'head' is needed so we can iterate in the order allocated. */ + struct BLI_memiter_chunk *head, *tail; + data_t *data_curr; + data_t *data_last; + /* Used unless a large element is requested. + * (which should be very rare!). */ + uint chunk_size_in_bytes_min; + uint count; #ifdef USE_TOTALLOC - uint totalloc; + uint totalloc; #endif } BLI_memiter; - BLI_INLINE uint data_offset_from_size(uint size) { - return (PADUP(size, (uint)sizeof(data_t))) / (uint)sizeof(data_t); + return (PADUP(size, (uint)sizeof(data_t))) / (uint)sizeof(data_t); } static void memiter_set_rewind_offset(BLI_memiter *mi) { - BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; + BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; - ASAN_UNPOISON_MEMORY_REGION(elem, sizeof(BLI_memiter_elem)); + ASAN_UNPOISON_MEMORY_REGION(elem, sizeof(BLI_memiter_elem)); - elem->size = (offset_t)(((data_t *)mi->tail) - mi->data_curr); - BLI_assert(elem->size < 0); + elem->size = (offset_t)(((data_t *)mi->tail) - mi->data_curr); + BLI_assert(elem->size < 0); } static void memiter_init(BLI_memiter *mi) { - mi->head = NULL; - mi->tail = NULL; - mi->data_curr = NULL; - mi->data_last = NULL; - mi->count = 0; + mi->head = NULL; + mi->tail = NULL; + mi->data_curr = NULL; + mi->data_last = NULL; + mi->count = 0; #ifdef USE_TOTALLOC - mi->totalloc = 0; + mi->totalloc = 0; #endif } @@ -147,126 +146,123 @@ static void memiter_init(BLI_memiter *mi) */ BLI_memiter *BLI_memiter_create(uint chunk_size_min) { - BLI_memiter *mi = MEM_mallocN(sizeof(BLI_memiter), "BLI_memiter"); - memiter_init(mi); - - /* Small values are used for tests to check for correctness, - * but otherwise not that useful. */ - const uint slop_space = (sizeof(BLI_memiter_chunk) + MEM_SIZE_OVERHEAD); - if (chunk_size_min >= 1024) { - /* As long as the input is a power of 2, this will give efficient sizes. */ - chunk_size_min -= slop_space; - } - - mi->chunk_size_in_bytes_min = chunk_size_min; - return mi; + BLI_memiter *mi = MEM_mallocN(sizeof(BLI_memiter), "BLI_memiter"); + memiter_init(mi); + + /* Small values are used for tests to check for correctness, + * but otherwise not that useful. */ + const uint slop_space = (sizeof(BLI_memiter_chunk) + MEM_SIZE_OVERHEAD); + if (chunk_size_min >= 1024) { + /* As long as the input is a power of 2, this will give efficient sizes. */ + chunk_size_min -= slop_space; + } + + mi->chunk_size_in_bytes_min = chunk_size_min; + return mi; } void *BLI_memiter_alloc(BLI_memiter *mi, uint elem_size) { - const uint data_offset = data_offset_from_size(elem_size); - data_t *data_curr_next = mi->data_curr + (1 + data_offset); + const uint data_offset = data_offset_from_size(elem_size); + data_t *data_curr_next = mi->data_curr + (1 + data_offset); - if (UNLIKELY(mi->data_curr == NULL) || (data_curr_next > mi->data_last)) { + if (UNLIKELY(mi->data_curr == NULL) || (data_curr_next > mi->data_last)) { #ifndef USE_TERMINATE_PARANOID - if (mi->data_curr != NULL) { - memiter_set_rewind_offset(mi); - } + if (mi->data_curr != NULL) { + memiter_set_rewind_offset(mi); + } #endif - uint chunk_size_in_bytes = mi->chunk_size_in_bytes_min; - if (UNLIKELY(chunk_size_in_bytes < elem_size + (uint)sizeof(data_t[2]))) { - chunk_size_in_bytes = elem_size + (uint)sizeof(data_t[2]); - } - uint chunk_size = data_offset_from_size(chunk_size_in_bytes); - BLI_memiter_chunk *chunk = MEM_mallocN( - sizeof(BLI_memiter_chunk) + - (chunk_size * sizeof(data_t)), - "BLI_memiter_chunk"); + uint chunk_size_in_bytes = mi->chunk_size_in_bytes_min; + if (UNLIKELY(chunk_size_in_bytes < elem_size + (uint)sizeof(data_t[2]))) { + chunk_size_in_bytes = elem_size + (uint)sizeof(data_t[2]); + } + uint chunk_size = data_offset_from_size(chunk_size_in_bytes); + BLI_memiter_chunk *chunk = MEM_mallocN( + sizeof(BLI_memiter_chunk) + (chunk_size * sizeof(data_t)), "BLI_memiter_chunk"); - if (mi->head == NULL) { - BLI_assert(mi->tail == NULL); - mi->head = chunk; - } - else { - mi->tail->next = chunk; - } - mi->tail = chunk; - chunk->next = NULL; + if (mi->head == NULL) { + BLI_assert(mi->tail == NULL); + mi->head = chunk; + } + else { + mi->tail->next = chunk; + } + mi->tail = chunk; + chunk->next = NULL; - mi->data_curr = chunk->data; - mi->data_last = chunk->data + (chunk_size - 1); - data_curr_next = mi->data_curr + (1 + data_offset); + mi->data_curr = chunk->data; + mi->data_last = chunk->data + (chunk_size - 1); + data_curr_next = mi->data_curr + (1 + data_offset); - ASAN_POISON_MEMORY_REGION(chunk->data, chunk_size * sizeof(data_t)); - } + ASAN_POISON_MEMORY_REGION(chunk->data, chunk_size * sizeof(data_t)); + } - BLI_assert(data_curr_next <= mi->data_last); + BLI_assert(data_curr_next <= mi->data_last); - BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; + BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; - ASAN_UNPOISON_MEMORY_REGION(elem, sizeof(BLI_memiter_elem) + elem_size); + ASAN_UNPOISON_MEMORY_REGION(elem, sizeof(BLI_memiter_elem) + elem_size); - elem->size = (offset_t)elem_size; - mi->data_curr = data_curr_next; + elem->size = (offset_t)elem_size; + mi->data_curr = data_curr_next; #ifdef USE_TERMINATE_PARANOID - memiter_set_rewind_offset(mi); + memiter_set_rewind_offset(mi); #endif - mi->count += 1; + mi->count += 1; #ifdef USE_TOTALLOC - mi->totalloc += elem_size; + mi->totalloc += elem_size; #endif - return elem->data; + return elem->data; } void *BLI_memiter_calloc(BLI_memiter *mi, uint elem_size) { - void *data = BLI_memiter_alloc(mi, elem_size); - memset(data, 0, elem_size); - return data; + void *data = BLI_memiter_alloc(mi, elem_size); + memset(data, 0, elem_size); + return data; } void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from) { - void *data = BLI_memiter_alloc(mi, elem_size); - memcpy(data, data_from, elem_size); + void *data = BLI_memiter_alloc(mi, elem_size); + memcpy(data, data_from, elem_size); } static void memiter_free_data(BLI_memiter *mi) { - BLI_memiter_chunk *chunk = mi->head; - while (chunk) { - BLI_memiter_chunk *chunk_next = chunk->next; - MEM_freeN(chunk); - chunk = chunk_next; - } + BLI_memiter_chunk *chunk = mi->head; + while (chunk) { + BLI_memiter_chunk *chunk_next = chunk->next; + MEM_freeN(chunk); + chunk = chunk_next; + } } void BLI_memiter_destroy(BLI_memiter *mi) { - memiter_free_data(mi); - MEM_freeN(mi); + memiter_free_data(mi); + MEM_freeN(mi); } void BLI_memiter_clear(BLI_memiter *mi) { - memiter_free_data(mi); - memiter_init(mi); + memiter_free_data(mi); + memiter_init(mi); } uint BLI_memiter_count(const BLI_memiter *mi) { - return mi->count; + return mi->count; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Helper API's * \{ */ @@ -274,32 +270,31 @@ uint BLI_memiter_count(const BLI_memiter *mi) /* Support direct lookup for first. */ void *BLI_memiter_elem_first(BLI_memiter *mi) { - if (mi->head != NULL) { - BLI_memiter_chunk *chunk = mi->head; - BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; - return elem->data; - } - else { - return NULL; - } + if (mi->head != NULL) { + BLI_memiter_chunk *chunk = mi->head; + BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; + return elem->data; + } + else { + return NULL; + } } void *BLI_memiter_elem_first_size(BLI_memiter *mi, uint *r_size) { - if (mi->head != NULL) { - BLI_memiter_chunk *chunk = mi->head; - BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; - *r_size = (uint)elem->size; - return elem->data; - } - else { - return NULL; - } + if (mi->head != NULL) { + BLI_memiter_chunk *chunk = mi->head; + BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; + *r_size = (uint)elem->size; + return elem->data; + } + else { + return NULL; + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Iterator API's * @@ -313,59 +308,59 @@ void *BLI_memiter_elem_first_size(BLI_memiter *mi, uint *r_size) void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter) { - iter->elem = mi->head ? (BLI_memiter_elem *)mi->head->data : NULL; - iter->elem_left = mi->count; + iter->elem = mi->head ? (BLI_memiter_elem *)mi->head->data : NULL; + iter->elem_left = mi->count; } bool BLI_memiter_iter_done(const BLI_memiter_handle *iter) { - return iter->elem_left != 0; + return iter->elem_left != 0; } BLI_INLINE void memiter_chunk_step(BLI_memiter_handle *iter) { - BLI_assert(iter->elem->size < 0); - BLI_memiter_chunk *chunk = (BLI_memiter_chunk *)(((data_t *)iter->elem) + iter->elem->size); - chunk = chunk->next; - iter->elem = chunk ? (BLI_memiter_elem *)chunk->data : NULL; - BLI_assert(iter->elem == NULL || iter->elem->size >= 0); + BLI_assert(iter->elem->size < 0); + BLI_memiter_chunk *chunk = (BLI_memiter_chunk *)(((data_t *)iter->elem) + iter->elem->size); + chunk = chunk->next; + iter->elem = chunk ? (BLI_memiter_elem *)chunk->data : NULL; + BLI_assert(iter->elem == NULL || iter->elem->size >= 0); } void *BLI_memiter_iter_step_size(BLI_memiter_handle *iter, uint *r_size) { - if (iter->elem_left != 0) { - iter->elem_left -= 1; - if (UNLIKELY(iter->elem->size < 0)) { - memiter_chunk_step(iter); - } - BLI_assert(iter->elem->size >= 0); - uint size = (uint)iter->elem->size; - *r_size = size; /* <-- only difference */ - data_t *data = iter->elem->data; - iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; - return (void *)data; - } - else { - return NULL; - } + if (iter->elem_left != 0) { + iter->elem_left -= 1; + if (UNLIKELY(iter->elem->size < 0)) { + memiter_chunk_step(iter); + } + BLI_assert(iter->elem->size >= 0); + uint size = (uint)iter->elem->size; + *r_size = size; /* <-- only difference */ + data_t *data = iter->elem->data; + iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; + return (void *)data; + } + else { + return NULL; + } } void *BLI_memiter_iter_step(BLI_memiter_handle *iter) { - if (iter->elem_left != 0) { - iter->elem_left -= 1; - if (UNLIKELY(iter->elem->size < 0)) { - memiter_chunk_step(iter); - } - BLI_assert(iter->elem->size >= 0); - uint size = (uint)iter->elem->size; - data_t *data = iter->elem->data; - iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; - return (void *)data; - } - else { - return NULL; - } + if (iter->elem_left != 0) { + iter->elem_left -= 1; + if (UNLIKELY(iter->elem->size < 0)) { + memiter_chunk_step(iter); + } + BLI_assert(iter->elem->size >= 0); + uint size = (uint)iter->elem->size; + data_t *data = iter->elem->data; + iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; + return (void *)data; + } + else { + return NULL; + } } /** \} */ diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 24e3f22172e..0f65f8ecbf0 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -40,7 +40,7 @@ #include "MEM_guardedalloc.h" -#include "BLI_strict_flags.h" /* keep last */ +#include "BLI_strict_flags.h" /* keep last */ #ifdef WITH_MEM_VALGRIND # include "valgrind/memcheck.h" @@ -49,16 +49,16 @@ /* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */ #ifdef __BIG_ENDIAN__ /* Big Endian */ -# define MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) ) +# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) # define MAKE_ID_8(a, b, c, d, e, f, g, h) \ - ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \ - (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h) ) + ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \ + (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h)) #else /* Little Endian */ -# define MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) ) +# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) # define MAKE_ID_8(a, b, c, d, e, f, g, h) \ - ((int64_t)(h) << 56 | (int64_t)(g) << 48 | (int64_t)(f) << 40 | (int64_t)(e) << 32 | \ - (int64_t)(d) << 24 | (int64_t)(c) << 16 | (int64_t)(b) << 8 | (a) ) + ((int64_t)(h) << 56 | (int64_t)(g) << 48 | (int64_t)(f) << 40 | (int64_t)(e) << 32 | \ + (int64_t)(d) << 24 | (int64_t)(c) << 16 | (int64_t)(b) << 8 | (a)) #endif /** @@ -66,9 +66,9 @@ * So having a pointer to 2/4/8... aligned memory is enough to ensure the freeword will never be used. * To be safe, use a word thats the same in both directions. */ -#define FREEWORD ((sizeof(void *) > sizeof(int32_t)) ? \ - MAKE_ID_8('e', 'e', 'r', 'f', 'f', 'r', 'e', 'e') : \ - MAKE_ID('e', 'f', 'f', 'e')) +#define FREEWORD \ + ((sizeof(void *) > sizeof(int32_t)) ? MAKE_ID_8('e', 'e', 'r', 'f', 'f', 'r', 'e', 'e') : \ + MAKE_ID('e', 'f', 'f', 'e')) /** * The 'used' word just needs to be set to something besides FREEWORD. @@ -81,7 +81,6 @@ /* optimize pool size */ #define USE_CHUNK_POW2 - #ifndef NDEBUG static bool mempool_debug_memset = false; #endif @@ -93,9 +92,9 @@ static bool mempool_debug_memset = false; * Each element represents a block which BLI_mempool_alloc may return. */ typedef struct BLI_freenode { - struct BLI_freenode *next; - /** Used to identify this as a freed node. */ - intptr_t freeword; + struct BLI_freenode *next; + /** Used to identify this as a freed node. */ + intptr_t freeword; } BLI_freenode; /** @@ -103,37 +102,37 @@ typedef struct BLI_freenode { * #BLI_mempool.chunks as a double linked list. */ typedef struct BLI_mempool_chunk { - struct BLI_mempool_chunk *next; + struct BLI_mempool_chunk *next; } BLI_mempool_chunk; /** * The mempool, stores and tracks memory \a chunks and elements within those chunks \a free. */ struct BLI_mempool { - /** Single linked list of allocated chunks. */ - BLI_mempool_chunk *chunks; - /** Keep a pointer to the last, so we can append new chunks there - * this is needed for iteration so we can loop over chunks in the order added. */ - BLI_mempool_chunk *chunk_tail; - - /** Element size in bytes. */ - uint esize; - /** Chunk size in bytes. */ - uint csize; - /** Number of elements per chunk. */ - uint pchunk; - uint flag; - /* keeps aligned to 16 bits */ - - /** Free element list. Interleaved into chunk datas. */ - BLI_freenode *free; - /** Use to know how many chunks to keep for #BLI_mempool_clear. */ - uint maxchunks; - /** Number of elements currently in use. */ - uint totused; + /** Single linked list of allocated chunks. */ + BLI_mempool_chunk *chunks; + /** Keep a pointer to the last, so we can append new chunks there + * this is needed for iteration so we can loop over chunks in the order added. */ + BLI_mempool_chunk *chunk_tail; + + /** Element size in bytes. */ + uint esize; + /** Chunk size in bytes. */ + uint csize; + /** Number of elements per chunk. */ + uint pchunk; + uint flag; + /* keeps aligned to 16 bits */ + + /** Free element list. Interleaved into chunk datas. */ + BLI_freenode *free; + /** Use to know how many chunks to keep for #BLI_mempool_clear. */ + uint maxchunks; + /** Number of elements currently in use. */ + uint totused; #ifdef USE_TOTALLOC - /** Number of elements allocated in total. */ - uint totalloc; + /** Number of elements allocated in total. */ + uint totalloc; #endif }; @@ -141,8 +140,8 @@ struct BLI_mempool { #define CHUNK_DATA(chunk) (CHECK_TYPE_INLINE(chunk, BLI_mempool_chunk *), (void *)((chunk) + 1)) -#define NODE_STEP_NEXT(node) ((void *)((char *)(node) + esize)) -#define NODE_STEP_PREV(node) ((void *)((char *)(node) - esize)) +#define NODE_STEP_NEXT(node) ((void *)((char *)(node) + esize)) +#define NODE_STEP_PREV(node) ((void *)((char *)(node)-esize)) /** Extra bytes implicitly used for every chunk alloc. */ #define CHUNK_OVERHEAD (uint)(MEM_SIZE_OVERHEAD + sizeof(BLI_mempool_chunk)) @@ -150,22 +149,22 @@ struct BLI_mempool { #ifdef USE_CHUNK_POW2 static uint power_of_2_max_u(uint x) { - x -= 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >> 16); - return x + 1; + x -= 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x + 1; } #endif BLI_INLINE BLI_mempool_chunk *mempool_chunk_find(BLI_mempool_chunk *head, uint index) { - while (index-- && head) { - head = head->next; - } - return head; + while (index-- && head) { + head = head->next; + } + return head; } /** @@ -176,12 +175,12 @@ BLI_INLINE BLI_mempool_chunk *mempool_chunk_find(BLI_mempool_chunk *head, uint i */ BLI_INLINE uint mempool_maxchunks(const uint totelem, const uint pchunk) { - return (totelem <= pchunk) ? 1 : ((totelem / pchunk) + 1); + return (totelem <= pchunk) ? 1 : ((totelem / pchunk) + 1); } static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool) { - return MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "BLI_Mempool Chunk"); + return MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "BLI_Mempool Chunk"); } /** @@ -193,179 +192,177 @@ static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool) * (used when building free chunks initially) * \return The last chunk, */ -static BLI_freenode *mempool_chunk_add( - BLI_mempool *pool, BLI_mempool_chunk *mpchunk, - BLI_freenode *last_tail) +static BLI_freenode *mempool_chunk_add(BLI_mempool *pool, + BLI_mempool_chunk *mpchunk, + BLI_freenode *last_tail) { - const uint esize = pool->esize; - BLI_freenode *curnode = CHUNK_DATA(mpchunk); - uint j; - - /* append */ - if (pool->chunk_tail) { - pool->chunk_tail->next = mpchunk; - } - else { - BLI_assert(pool->chunks == NULL); - pool->chunks = mpchunk; - } - - mpchunk->next = NULL; - pool->chunk_tail = mpchunk; - - if (UNLIKELY(pool->free == NULL)) { - pool->free = curnode; - } - - /* loop through the allocated data, building the pointer structures */ - j = pool->pchunk; - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); - curnode->freeword = FREEWORD; - curnode = curnode->next; - } - } - else { - while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); - curnode = curnode->next; - } - } - - /* terminate the list (rewind one) - * will be overwritten if 'curnode' gets passed in again as 'last_tail' */ - curnode = NODE_STEP_PREV(curnode); - curnode->next = NULL; + const uint esize = pool->esize; + BLI_freenode *curnode = CHUNK_DATA(mpchunk); + uint j; + + /* append */ + if (pool->chunk_tail) { + pool->chunk_tail->next = mpchunk; + } + else { + BLI_assert(pool->chunks == NULL); + pool->chunks = mpchunk; + } + + mpchunk->next = NULL; + pool->chunk_tail = mpchunk; + + if (UNLIKELY(pool->free == NULL)) { + pool->free = curnode; + } + + /* loop through the allocated data, building the pointer structures */ + j = pool->pchunk; + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + while (j--) { + curnode->next = NODE_STEP_NEXT(curnode); + curnode->freeword = FREEWORD; + curnode = curnode->next; + } + } + else { + while (j--) { + curnode->next = NODE_STEP_NEXT(curnode); + curnode = curnode->next; + } + } + + /* terminate the list (rewind one) + * will be overwritten if 'curnode' gets passed in again as 'last_tail' */ + curnode = NODE_STEP_PREV(curnode); + curnode->next = NULL; #ifdef USE_TOTALLOC - pool->totalloc += pool->pchunk; + pool->totalloc += pool->pchunk; #endif - /* final pointer in the previously allocated chunk is wrong */ - if (last_tail) { - last_tail->next = CHUNK_DATA(mpchunk); - } + /* final pointer in the previously allocated chunk is wrong */ + if (last_tail) { + last_tail->next = CHUNK_DATA(mpchunk); + } - return curnode; + return curnode; } static void mempool_chunk_free(BLI_mempool_chunk *mpchunk) { - MEM_freeN(mpchunk); + MEM_freeN(mpchunk); } static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk) { - BLI_mempool_chunk *mpchunk_next; + BLI_mempool_chunk *mpchunk_next; - for (; mpchunk; mpchunk = mpchunk_next) { - mpchunk_next = mpchunk->next; - mempool_chunk_free(mpchunk); - } + for (; mpchunk; mpchunk = mpchunk_next) { + mpchunk_next = mpchunk->next; + mempool_chunk_free(mpchunk); + } } -BLI_mempool *BLI_mempool_create( - uint esize, uint totelem, - uint pchunk, uint flag) +BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag) { - BLI_mempool *pool; - BLI_freenode *last_tail = NULL; - uint i, maxchunks; + BLI_mempool *pool; + BLI_freenode *last_tail = NULL; + uint i, maxchunks; - /* allocate the pool structure */ - pool = MEM_mallocN(sizeof(BLI_mempool), "memory pool"); + /* allocate the pool structure */ + pool = MEM_mallocN(sizeof(BLI_mempool), "memory pool"); - /* set the elem size */ - if (esize < (int)MEMPOOL_ELEM_SIZE_MIN) { - esize = (int)MEMPOOL_ELEM_SIZE_MIN; - } + /* set the elem size */ + if (esize < (int)MEMPOOL_ELEM_SIZE_MIN) { + esize = (int)MEMPOOL_ELEM_SIZE_MIN; + } - if (flag & BLI_MEMPOOL_ALLOW_ITER) { - esize = MAX2(esize, (uint)sizeof(BLI_freenode)); - } + if (flag & BLI_MEMPOOL_ALLOW_ITER) { + esize = MAX2(esize, (uint)sizeof(BLI_freenode)); + } - maxchunks = mempool_maxchunks(totelem, pchunk); + maxchunks = mempool_maxchunks(totelem, pchunk); - pool->chunks = NULL; - pool->chunk_tail = NULL; - pool->esize = esize; + pool->chunks = NULL; + pool->chunk_tail = NULL; + pool->esize = esize; - /* Optimize chunk size to powers of 2, accounting for slop-space. */ + /* Optimize chunk size to powers of 2, accounting for slop-space. */ #ifdef USE_CHUNK_POW2 - { - BLI_assert(power_of_2_max_u(pchunk * esize) > CHUNK_OVERHEAD); - pchunk = (power_of_2_max_u(pchunk * esize) - CHUNK_OVERHEAD) / esize; - } + { + BLI_assert(power_of_2_max_u(pchunk * esize) > CHUNK_OVERHEAD); + pchunk = (power_of_2_max_u(pchunk * esize) - CHUNK_OVERHEAD) / esize; + } #endif - pool->csize = esize * pchunk; + pool->csize = esize * pchunk; - /* Ensure this is a power of 2, minus the rounding by element size. */ + /* Ensure this is a power of 2, minus the rounding by element size. */ #if defined(USE_CHUNK_POW2) && !defined(NDEBUG) - { - uint final_size = (uint)MEM_SIZE_OVERHEAD + (uint)sizeof(BLI_mempool_chunk) + pool->csize; - BLI_assert(((uint)power_of_2_max_u(final_size) - final_size) < pool->esize); - } + { + uint final_size = (uint)MEM_SIZE_OVERHEAD + (uint)sizeof(BLI_mempool_chunk) + pool->csize; + BLI_assert(((uint)power_of_2_max_u(final_size) - final_size) < pool->esize); + } #endif - pool->pchunk = pchunk; - pool->flag = flag; - pool->free = NULL; /* mempool_chunk_add assigns */ - pool->maxchunks = maxchunks; + pool->pchunk = pchunk; + pool->flag = flag; + pool->free = NULL; /* mempool_chunk_add assigns */ + pool->maxchunks = maxchunks; #ifdef USE_TOTALLOC - pool->totalloc = 0; + pool->totalloc = 0; #endif - pool->totused = 0; + pool->totused = 0; - if (totelem) { - /* Allocate the actual chunks. */ - for (i = 0; i < maxchunks; i++) { - BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); - last_tail = mempool_chunk_add(pool, mpchunk, last_tail); - } - } + if (totelem) { + /* Allocate the actual chunks. */ + for (i = 0; i < maxchunks; i++) { + BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); + last_tail = mempool_chunk_add(pool, mpchunk, last_tail); + } + } #ifdef WITH_MEM_VALGRIND - VALGRIND_CREATE_MEMPOOL(pool, 0, false); + VALGRIND_CREATE_MEMPOOL(pool, 0, false); #endif - return pool; + return pool; } void *BLI_mempool_alloc(BLI_mempool *pool) { - BLI_freenode *free_pop; + BLI_freenode *free_pop; - if (UNLIKELY(pool->free == NULL)) { - /* Need to allocate a new chunk. */ - BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); - mempool_chunk_add(pool, mpchunk, NULL); - } + if (UNLIKELY(pool->free == NULL)) { + /* Need to allocate a new chunk. */ + BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); + mempool_chunk_add(pool, mpchunk, NULL); + } - free_pop = pool->free; + free_pop = pool->free; - BLI_assert(pool->chunk_tail->next == NULL); + BLI_assert(pool->chunk_tail->next == NULL); - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - free_pop->freeword = USEDWORD; - } + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + free_pop->freeword = USEDWORD; + } - pool->free = free_pop->next; - pool->totused++; + pool->free = free_pop->next; + pool->totused++; #ifdef WITH_MEM_VALGRIND - VALGRIND_MEMPOOL_ALLOC(pool, free_pop, pool->esize); + VALGRIND_MEMPOOL_ALLOC(pool, free_pop, pool->esize); #endif - return (void *)free_pop; + return (void *)free_pop; } void *BLI_mempool_calloc(BLI_mempool *pool) { - void *retval = BLI_mempool_alloc(pool); - memset(retval, 0, (size_t)pool->esize); - return retval; + void *retval = BLI_mempool_alloc(pool); + memset(retval, 0, (size_t)pool->esize); + return retval; } /** @@ -375,107 +372,105 @@ void *BLI_mempool_calloc(BLI_mempool *pool) */ void BLI_mempool_free(BLI_mempool *pool, void *addr) { - BLI_freenode *newhead = addr; + BLI_freenode *newhead = addr; #ifndef NDEBUG - { - BLI_mempool_chunk *chunk; - bool found = false; - for (chunk = pool->chunks; chunk; chunk = chunk->next) { - if (ARRAY_HAS_ITEM((char *)addr, (char *)CHUNK_DATA(chunk), pool->csize)) { - found = true; - break; - } - } - if (!found) { - BLI_assert(!"Attempt to free data which is not in pool.\n"); - } - } - - /* Enable for debugging. */ - if (UNLIKELY(mempool_debug_memset)) { - memset(addr, 255, pool->esize); - } + { + BLI_mempool_chunk *chunk; + bool found = false; + for (chunk = pool->chunks; chunk; chunk = chunk->next) { + if (ARRAY_HAS_ITEM((char *)addr, (char *)CHUNK_DATA(chunk), pool->csize)) { + found = true; + break; + } + } + if (!found) { + BLI_assert(!"Attempt to free data which is not in pool.\n"); + } + } + + /* Enable for debugging. */ + if (UNLIKELY(mempool_debug_memset)) { + memset(addr, 255, pool->esize); + } #endif - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { #ifndef NDEBUG - /* This will detect double free's. */ - BLI_assert(newhead->freeword != FREEWORD); + /* This will detect double free's. */ + BLI_assert(newhead->freeword != FREEWORD); #endif - newhead->freeword = FREEWORD; - } + newhead->freeword = FREEWORD; + } - newhead->next = pool->free; - pool->free = newhead; + newhead->next = pool->free; + pool->free = newhead; - pool->totused--; + pool->totused--; #ifdef WITH_MEM_VALGRIND - VALGRIND_MEMPOOL_FREE(pool, addr); + VALGRIND_MEMPOOL_FREE(pool, addr); #endif - /* Nothing is in use; free all the chunks except the first. */ - if (UNLIKELY(pool->totused == 0) && - (pool->chunks->next)) - { - const uint esize = pool->esize; - BLI_freenode *curnode; - uint j; - BLI_mempool_chunk *first; + /* Nothing is in use; free all the chunks except the first. */ + if (UNLIKELY(pool->totused == 0) && (pool->chunks->next)) { + const uint esize = pool->esize; + BLI_freenode *curnode; + uint j; + BLI_mempool_chunk *first; - first = pool->chunks; - mempool_chunk_free_all(first->next); - first->next = NULL; - pool->chunk_tail = first; + first = pool->chunks; + mempool_chunk_free_all(first->next); + first->next = NULL; + pool->chunk_tail = first; #ifdef USE_TOTALLOC - pool->totalloc = pool->pchunk; + pool->totalloc = pool->pchunk; #endif - /* Temp alloc so valgrind doesn't complain when setting free'd blocks 'next'. */ + /* Temp alloc so valgrind doesn't complain when setting free'd blocks 'next'. */ #ifdef WITH_MEM_VALGRIND - VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize); + VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize); #endif - curnode = CHUNK_DATA(first); - pool->free = curnode; + curnode = CHUNK_DATA(first); + pool->free = curnode; - j = pool->pchunk; - while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); - curnode = curnode->next; - } - curnode = NODE_STEP_PREV(curnode); - curnode->next = NULL; /* terminate the list */ + j = pool->pchunk; + while (j--) { + curnode->next = NODE_STEP_NEXT(curnode); + curnode = curnode->next; + } + curnode = NODE_STEP_PREV(curnode); + curnode->next = NULL; /* terminate the list */ #ifdef WITH_MEM_VALGRIND - VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first)); + VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first)); #endif - } + } } int BLI_mempool_len(BLI_mempool *pool) { - return (int)pool->totused; + return (int)pool->totused; } void *BLI_mempool_findelem(BLI_mempool *pool, uint index) { - BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - - if (index < pool->totused) { - /* We could have some faster mem chunk stepping code inline. */ - BLI_mempool_iter iter; - void *elem; - BLI_mempool_iternew(pool, &iter); - for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) { - /* pass */ - } - return elem; - } - - return NULL; + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + + if (index < pool->totused) { + /* We could have some faster mem chunk stepping code inline. */ + BLI_mempool_iter iter; + void *elem; + BLI_mempool_iternew(pool, &iter); + for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) { + /* pass */ + } + return elem; + } + + return NULL; } /** @@ -487,15 +482,15 @@ void *BLI_mempool_findelem(BLI_mempool *pool, uint index) */ void BLI_mempool_as_table(BLI_mempool *pool, void **data) { - BLI_mempool_iter iter; - void *elem; - void **p = data; - BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - BLI_mempool_iternew(pool, &iter); - while ((elem = BLI_mempool_iterstep(&iter))) { - *p++ = elem; - } - BLI_assert((uint)(p - data) == pool->totused); + BLI_mempool_iter iter; + void *elem; + void **p = data; + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + BLI_mempool_iternew(pool, &iter); + while ((elem = BLI_mempool_iterstep(&iter))) { + *p++ = elem; + } + BLI_assert((uint)(p - data) == pool->totused); } /** @@ -503,9 +498,9 @@ void BLI_mempool_as_table(BLI_mempool *pool, void **data) */ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) { - void **data = MEM_mallocN((size_t)pool->totused * sizeof(void *), allocstr); - BLI_mempool_as_table(pool, data); - return data; + void **data = MEM_mallocN((size_t)pool->totused * sizeof(void *), allocstr); + BLI_mempool_as_table(pool, data); + return data; } /** @@ -513,16 +508,16 @@ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) */ void BLI_mempool_as_array(BLI_mempool *pool, void *data) { - const uint esize = pool->esize; - BLI_mempool_iter iter; - char *elem, *p = data; - BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - BLI_mempool_iternew(pool, &iter); - while ((elem = BLI_mempool_iterstep(&iter))) { - memcpy(p, elem, (size_t)esize); - p = NODE_STEP_NEXT(p); - } - BLI_assert((uint)(p - (char *)data) == pool->totused * esize); + const uint esize = pool->esize; + BLI_mempool_iter iter; + char *elem, *p = data; + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + BLI_mempool_iternew(pool, &iter); + while ((elem = BLI_mempool_iterstep(&iter))) { + memcpy(p, elem, (size_t)esize); + p = NODE_STEP_NEXT(p); + } + BLI_assert((uint)(p - (char *)data) == pool->totused * esize); } /** @@ -530,9 +525,9 @@ void BLI_mempool_as_array(BLI_mempool *pool, void *data) */ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) { - char *data = MEM_mallocN((size_t)(pool->totused * pool->esize), allocstr); - BLI_mempool_as_array(pool, data); - return data; + char *data = MEM_mallocN((size_t)(pool->totused * pool->esize), allocstr); + BLI_mempool_as_array(pool, data); + return data; } /** @@ -540,13 +535,13 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) */ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) { - BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - iter->pool = pool; - iter->curchunk = pool->chunks; - iter->curindex = 0; + iter->pool = pool; + iter->curchunk = pool->chunks; + iter->curindex = 0; - iter->curchunk_threaded_shared = NULL; + iter->curchunk_threaded_shared = NULL; } /** @@ -562,31 +557,32 @@ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) */ BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter) { - BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - BLI_mempool_iter *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__); - BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__); + BLI_mempool_iter *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__); + BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__); - BLI_mempool_iternew(pool, iter_arr); + BLI_mempool_iternew(pool, iter_arr); - *curchunk_threaded_shared = iter_arr->curchunk; - iter_arr->curchunk_threaded_shared = curchunk_threaded_shared; + *curchunk_threaded_shared = iter_arr->curchunk; + iter_arr->curchunk_threaded_shared = curchunk_threaded_shared; - for (size_t i = 1; i < num_iter; i++) { - iter_arr[i] = iter_arr[0]; - *curchunk_threaded_shared = iter_arr[i].curchunk = ( - (*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL); - } + for (size_t i = 1; i < num_iter; i++) { + iter_arr[i] = iter_arr[0]; + *curchunk_threaded_shared = iter_arr[i].curchunk = ((*curchunk_threaded_shared) ? + (*curchunk_threaded_shared)->next : + NULL); + } - return iter_arr; + return iter_arr; } -void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) +void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) { - BLI_assert(iter_arr->curchunk_threaded_shared != NULL); + BLI_assert(iter_arr->curchunk_threaded_shared != NULL); - MEM_freeN(iter_arr->curchunk_threaded_shared); - MEM_freeN(iter_arr); + MEM_freeN(iter_arr->curchunk_threaded_shared); + MEM_freeN(iter_arr); } #if 0 @@ -594,48 +590,48 @@ void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) static void *bli_mempool_iternext(BLI_mempool_iter *iter) { - void *ret = NULL; - - if (iter->curchunk == NULL || !iter->pool->totused) { - return ret; - } - - ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex); - - iter->curindex++; - - if (iter->curindex == iter->pool->pchunk) { - iter->curindex = 0; - if (iter->curchunk_threaded_shared) { - while (1) { - iter->curchunk = *iter->curchunk_threaded_shared; - if (iter->curchunk == NULL) { - return ret; - } - if (atomic_cas_ptr( - (void **)iter->curchunk_threaded_shared, - iter->curchunk, - iter->curchunk->next) == iter->curchunk) - { - break; - } - } - } - iter->curchunk = iter->curchunk->next; - } - - return ret; + void *ret = NULL; + + if (iter->curchunk == NULL || !iter->pool->totused) { + return ret; + } + + ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex); + + iter->curindex++; + + if (iter->curindex == iter->pool->pchunk) { + iter->curindex = 0; + if (iter->curchunk_threaded_shared) { + while (1) { + iter->curchunk = *iter->curchunk_threaded_shared; + if (iter->curchunk == NULL) { + return ret; + } + if (atomic_cas_ptr( + (void **)iter->curchunk_threaded_shared, + iter->curchunk, + iter->curchunk->next) == iter->curchunk) + { + break; + } + } + } + iter->curchunk = iter->curchunk->next; + } + + return ret; } void *BLI_mempool_iterstep(BLI_mempool_iter *iter) { - BLI_freenode *ret; + BLI_freenode *ret; - do { - ret = bli_mempool_iternext(iter); - } while (ret && ret->freeword == FREEWORD); + do { + ret = bli_mempool_iternext(iter); + } while (ret && ret->freeword == FREEWORD); - return ret; + return ret; } #else @@ -647,46 +643,43 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) */ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) { - if (UNLIKELY(iter->curchunk == NULL)) { - return NULL; - } - - const uint esize = iter->pool->esize; - BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex)); - BLI_freenode *ret; - do { - ret = curnode; - - if (++iter->curindex != iter->pool->pchunk) { - curnode = POINTER_OFFSET(curnode, esize); - } - else { - iter->curindex = 0; - if (iter->curchunk_threaded_shared) { - for (iter->curchunk = *iter->curchunk_threaded_shared; - (iter->curchunk != NULL) && - (atomic_cas_ptr( - (void **)iter->curchunk_threaded_shared, - iter->curchunk, - iter->curchunk->next) != iter->curchunk); - iter->curchunk = *iter->curchunk_threaded_shared) - { - /* pass. */ - } - - if (UNLIKELY(iter->curchunk == NULL)) { - return (ret->freeword == FREEWORD) ? NULL : ret; - } - } - iter->curchunk = iter->curchunk->next; - if (UNLIKELY(iter->curchunk == NULL)) { - return (ret->freeword == FREEWORD) ? NULL : ret; - } - curnode = CHUNK_DATA(iter->curchunk); - } - } while (ret->freeword == FREEWORD); - - return ret; + if (UNLIKELY(iter->curchunk == NULL)) { + return NULL; + } + + const uint esize = iter->pool->esize; + BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex)); + BLI_freenode *ret; + do { + ret = curnode; + + if (++iter->curindex != iter->pool->pchunk) { + curnode = POINTER_OFFSET(curnode, esize); + } + else { + iter->curindex = 0; + if (iter->curchunk_threaded_shared) { + for (iter->curchunk = *iter->curchunk_threaded_shared; + (iter->curchunk != NULL) && (atomic_cas_ptr((void **)iter->curchunk_threaded_shared, + iter->curchunk, + iter->curchunk->next) != iter->curchunk); + iter->curchunk = *iter->curchunk_threaded_shared) { + /* pass. */ + } + + if (UNLIKELY(iter->curchunk == NULL)) { + return (ret->freeword == FREEWORD) ? NULL : ret; + } + } + iter->curchunk = iter->curchunk->next; + if (UNLIKELY(iter->curchunk == NULL)) { + return (ret->freeword == FREEWORD) ? NULL : ret; + } + curnode = CHUNK_DATA(iter->curchunk); + } + } while (ret->freeword == FREEWORD); + + return ret; } #endif @@ -699,54 +692,54 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) */ void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) { - BLI_mempool_chunk *mpchunk; - BLI_mempool_chunk *mpchunk_next; - uint maxchunks; + BLI_mempool_chunk *mpchunk; + BLI_mempool_chunk *mpchunk_next; + uint maxchunks; - BLI_mempool_chunk *chunks_temp; - BLI_freenode *last_tail = NULL; + BLI_mempool_chunk *chunks_temp; + BLI_freenode *last_tail = NULL; #ifdef WITH_MEM_VALGRIND - VALGRIND_DESTROY_MEMPOOL(pool); - VALGRIND_CREATE_MEMPOOL(pool, 0, false); + VALGRIND_DESTROY_MEMPOOL(pool); + VALGRIND_CREATE_MEMPOOL(pool, 0, false); #endif - if (totelem_reserve == -1) { - maxchunks = pool->maxchunks; - } - else { - maxchunks = mempool_maxchunks((uint)totelem_reserve, pool->pchunk); - } - - /* Free all after 'pool->maxchunks'. */ - mpchunk = mempool_chunk_find(pool->chunks, maxchunks - 1); - if (mpchunk && mpchunk->next) { - /* terminate */ - mpchunk_next = mpchunk->next; - mpchunk->next = NULL; - mpchunk = mpchunk_next; - - do { - mpchunk_next = mpchunk->next; - mempool_chunk_free(mpchunk); - } while ((mpchunk = mpchunk_next)); - } - - /* re-initialize */ - pool->free = NULL; - pool->totused = 0; + if (totelem_reserve == -1) { + maxchunks = pool->maxchunks; + } + else { + maxchunks = mempool_maxchunks((uint)totelem_reserve, pool->pchunk); + } + + /* Free all after 'pool->maxchunks'. */ + mpchunk = mempool_chunk_find(pool->chunks, maxchunks - 1); + if (mpchunk && mpchunk->next) { + /* terminate */ + mpchunk_next = mpchunk->next; + mpchunk->next = NULL; + mpchunk = mpchunk_next; + + do { + mpchunk_next = mpchunk->next; + mempool_chunk_free(mpchunk); + } while ((mpchunk = mpchunk_next)); + } + + /* re-initialize */ + pool->free = NULL; + pool->totused = 0; #ifdef USE_TOTALLOC - pool->totalloc = 0; + pool->totalloc = 0; #endif - chunks_temp = pool->chunks; - pool->chunks = NULL; - pool->chunk_tail = NULL; + chunks_temp = pool->chunks; + pool->chunks = NULL; + pool->chunk_tail = NULL; - while ((mpchunk = chunks_temp)) { - chunks_temp = mpchunk->next; - last_tail = mempool_chunk_add(pool, mpchunk, last_tail); - } + while ((mpchunk = chunks_temp)) { + chunks_temp = mpchunk->next; + last_tail = mempool_chunk_add(pool, mpchunk, last_tail); + } } /** @@ -754,7 +747,7 @@ void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) */ void BLI_mempool_clear(BLI_mempool *pool) { - BLI_mempool_clear_ex(pool, -1); + BLI_mempool_clear_ex(pool, -1); } /** @@ -762,18 +755,18 @@ void BLI_mempool_clear(BLI_mempool *pool) */ void BLI_mempool_destroy(BLI_mempool *pool) { - mempool_chunk_free_all(pool->chunks); + mempool_chunk_free_all(pool->chunks); #ifdef WITH_MEM_VALGRIND - VALGRIND_DESTROY_MEMPOOL(pool); + VALGRIND_DESTROY_MEMPOOL(pool); #endif - MEM_freeN(pool); + MEM_freeN(pool); } #ifndef NDEBUG void BLI_mempool_set_memory_debug(void) { - mempool_debug_memset = true; + mempool_debug_memset = true; } #endif diff --git a/source/blender/blenlib/intern/BLI_timer.c b/source/blender/blenlib/intern/BLI_timer.c index 77409015aa6..bf9fd1b57f8 100644 --- a/source/blender/blenlib/intern/BLI_timer.c +++ b/source/blender/blenlib/intern/BLI_timer.c @@ -31,154 +31,156 @@ #define GET_TIME() PIL_check_seconds_timer() typedef struct TimedFunction { - struct TimedFunction *next, *prev; - BLI_timer_func func; - BLI_timer_data_free user_data_free; - void *user_data; - double next_time; - uintptr_t uuid; - bool tag_removal; - bool persistent; + struct TimedFunction *next, *prev; + BLI_timer_func func; + BLI_timer_data_free user_data_free; + void *user_data; + double next_time; + uintptr_t uuid; + bool tag_removal; + bool persistent; } TimedFunction; typedef struct TimerContainer { - ListBase funcs; - bool file_load_cb_registered; + ListBase funcs; + bool file_load_cb_registered; } TimerContainer; static TimerContainer GlobalTimer = {{0}}; static void ensure_callback_is_registered(void); -void BLI_timer_register( - uintptr_t uuid, - BLI_timer_func func, - void *user_data, - BLI_timer_data_free user_data_free, - double first_interval, - bool persistent) +void BLI_timer_register(uintptr_t uuid, + BLI_timer_func func, + void *user_data, + BLI_timer_data_free user_data_free, + double first_interval, + bool persistent) { - ensure_callback_is_registered(); - - TimedFunction *timed_func = MEM_callocN(sizeof(TimedFunction), __func__); - timed_func->func = func; - timed_func->user_data_free = user_data_free; - timed_func->user_data = user_data; - timed_func->next_time = GET_TIME() + first_interval; - timed_func->tag_removal = false; - timed_func->persistent = persistent; - timed_func->uuid = uuid; - - BLI_addtail(&GlobalTimer.funcs, timed_func); + ensure_callback_is_registered(); + + TimedFunction *timed_func = MEM_callocN(sizeof(TimedFunction), __func__); + timed_func->func = func; + timed_func->user_data_free = user_data_free; + timed_func->user_data = user_data; + timed_func->next_time = GET_TIME() + first_interval; + timed_func->tag_removal = false; + timed_func->persistent = persistent; + timed_func->uuid = uuid; + + BLI_addtail(&GlobalTimer.funcs, timed_func); } static void clear_user_data(TimedFunction *timed_func) { - if (timed_func->user_data_free) { - timed_func->user_data_free(timed_func->uuid, timed_func->user_data); - timed_func->user_data_free = NULL; - } + if (timed_func->user_data_free) { + timed_func->user_data_free(timed_func->uuid, timed_func->user_data); + timed_func->user_data_free = NULL; + } } bool BLI_timer_unregister(uintptr_t uuid) { - LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) { - if (timed_func->uuid == uuid) { - if (timed_func->tag_removal) { - return false; - } - else { - timed_func->tag_removal = true; - clear_user_data(timed_func); - return true; - } - } - } - return false; + LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) { + if (timed_func->uuid == uuid) { + if (timed_func->tag_removal) { + return false; + } + else { + timed_func->tag_removal = true; + clear_user_data(timed_func); + return true; + } + } + } + return false; } bool BLI_timer_is_registered(uintptr_t uuid) { - LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) { - if (timed_func->uuid == uuid && !timed_func->tag_removal) { - return true; - } - } - return false; + LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) { + if (timed_func->uuid == uuid && !timed_func->tag_removal) { + return true; + } + } + return false; } static void execute_functions_if_necessary(void) { - double current_time = GET_TIME(); - - LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) { - if (timed_func->tag_removal) { - continue; - } - if (timed_func->next_time > current_time) { - continue; - } - - double ret = timed_func->func(timed_func->uuid, timed_func->user_data); - - if (ret < 0) { - timed_func->tag_removal = true; - } - else { - timed_func->next_time = current_time + ret; - } - } + double current_time = GET_TIME(); + + LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) { + if (timed_func->tag_removal) { + continue; + } + if (timed_func->next_time > current_time) { + continue; + } + + double ret = timed_func->func(timed_func->uuid, timed_func->user_data); + + if (ret < 0) { + timed_func->tag_removal = true; + } + else { + timed_func->next_time = current_time + ret; + } + } } static void remove_tagged_functions(void) { - for (TimedFunction *timed_func = GlobalTimer.funcs.first; timed_func; ) { - TimedFunction *next = timed_func->next; - if (timed_func->tag_removal) { - clear_user_data(timed_func); - BLI_freelinkN(&GlobalTimer.funcs, timed_func); - } - timed_func = next; - } + for (TimedFunction *timed_func = GlobalTimer.funcs.first; timed_func;) { + TimedFunction *next = timed_func->next; + if (timed_func->tag_removal) { + clear_user_data(timed_func); + BLI_freelinkN(&GlobalTimer.funcs, timed_func); + } + timed_func = next; + } } void BLI_timer_execute() { - execute_functions_if_necessary(); - remove_tagged_functions(); + execute_functions_if_necessary(); + remove_tagged_functions(); } void BLI_timer_free() { - LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) { - timed_func->tag_removal = true; - } + LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) { + timed_func->tag_removal = true; + } - remove_tagged_functions(); + remove_tagged_functions(); } struct ID; struct Main; -static void remove_non_persistent_functions(struct Main *UNUSED(_1), struct ID *UNUSED(_2), void *UNUSED(_3)) +static void remove_non_persistent_functions(struct Main *UNUSED(_1), + struct ID *UNUSED(_2), + void *UNUSED(_3)) { - LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) { - if (!timed_func->persistent) { - timed_func->tag_removal = true; - } - } + LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) { + if (!timed_func->persistent) { + timed_func->tag_removal = true; + } + } } static bCallbackFuncStore load_pre_callback = { - NULL, NULL, /* next, prev */ - remove_non_persistent_functions, /* func */ - NULL, /* arg */ - 0, /* alloc */ + NULL, + NULL, /* next, prev */ + remove_non_persistent_functions, /* func */ + NULL, /* arg */ + 0, /* alloc */ }; static void ensure_callback_is_registered() { - if (!GlobalTimer.file_load_cb_registered) { - BLI_callback_add(&load_pre_callback, BLI_CB_EVT_LOAD_PRE); - GlobalTimer.file_load_cb_registered = true; - } + if (!GlobalTimer.file_load_cb_registered) { + BLI_callback_add(&load_pre_callback, BLI_CB_EVT_LOAD_PRE); + GlobalTimer.file_load_cb_registered = true; + } } diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index 46818c5a1b9..59d80b45a84 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -21,7 +21,6 @@ * \ingroup bli */ - #include "MEM_guardedalloc.h" #include "BLI_listbase.h" @@ -33,57 +32,57 @@ /* Create a new tree, and initialize as necessary */ DLRBT_Tree *BLI_dlrbTree_new(void) { - /* just allocate for now */ - return MEM_callocN(sizeof(DLRBT_Tree), "DLRBT_Tree"); + /* just allocate for now */ + return MEM_callocN(sizeof(DLRBT_Tree), "DLRBT_Tree"); } /* Just zero out the pointers used */ void BLI_dlrbTree_init(DLRBT_Tree *tree) { - if (tree == NULL) { - return; - } + if (tree == NULL) { + return; + } - tree->first = tree->last = tree->root = NULL; + tree->first = tree->last = tree->root = NULL; } /* Helper for traversing tree and freeing sub-nodes */ static void recursive_tree_free_nodes(DLRBT_Node *node) { - /* sanity check */ - if (node == NULL) { - return; - } + /* sanity check */ + if (node == NULL) { + return; + } - /* free child nodes + subtrees */ - recursive_tree_free_nodes(node->left); - recursive_tree_free_nodes(node->right); + /* free child nodes + subtrees */ + recursive_tree_free_nodes(node->left); + recursive_tree_free_nodes(node->right); - /* free self */ - MEM_freeN(node); + /* free self */ + MEM_freeN(node); } /* Free the given tree's data but not the tree itself */ void BLI_dlrbTree_free(DLRBT_Tree *tree) { - if (tree == NULL) { - return; - } - - /* if the list-base stuff is set, just use that (and assume its set), - * otherwise, we'll need to traverse the tree... - */ - if (tree->first) { - /* free list */ - BLI_freelistN((ListBase *)tree); - } - else { - /* traverse tree, freeing sub-nodes */ - recursive_tree_free_nodes(tree->root); - } - - /* clear pointers */ - tree->first = tree->last = tree->root = NULL; + if (tree == NULL) { + return; + } + + /* if the list-base stuff is set, just use that (and assume its set), + * otherwise, we'll need to traverse the tree... + */ + if (tree->first) { + /* free list */ + BLI_freelistN((ListBase *)tree); + } + else { + /* traverse tree, freeing sub-nodes */ + recursive_tree_free_nodes(tree->root); + } + + /* clear pointers */ + tree->first = tree->last = tree->root = NULL; } /* ------- */ @@ -91,38 +90,38 @@ void BLI_dlrbTree_free(DLRBT_Tree *tree) /* Helper function - used for traversing down the tree from the root to add nodes in order */ static void linkedlist_sync_add_node(DLRBT_Tree *tree, DLRBT_Node *node) { - /* sanity checks */ - if ((tree == NULL) || (node == NULL)) { - return; - } - - /* add left-node (and its subtree) */ - linkedlist_sync_add_node(tree, node->left); - - /* now add self - * - must remove detach from other links first - * (for now, only clear own pointers) - */ - node->prev = node->next = NULL; - BLI_addtail((ListBase *)tree, (Link *)node); - - /* finally, add right node (and its subtree) */ - linkedlist_sync_add_node(tree, node->right); + /* sanity checks */ + if ((tree == NULL) || (node == NULL)) { + return; + } + + /* add left-node (and its subtree) */ + linkedlist_sync_add_node(tree, node->left); + + /* now add self + * - must remove detach from other links first + * (for now, only clear own pointers) + */ + node->prev = node->next = NULL; + BLI_addtail((ListBase *)tree, (Link *)node); + + /* finally, add right node (and its subtree) */ + linkedlist_sync_add_node(tree, node->right); } /* Make sure the tree's Double-Linked list representation is valid */ void BLI_dlrbTree_linkedlist_sync(DLRBT_Tree *tree) { - /* sanity checks */ - if (tree == NULL) { - return; - } + /* sanity checks */ + if (tree == NULL) { + return; + } - /* clear list-base pointers so that the new list can be added properly */ - tree->first = tree->last = NULL; + /* clear list-base pointers so that the new list can be added properly */ + tree->first = tree->last = NULL; - /* start adding items from the root */ - linkedlist_sync_add_node(tree, tree->root); + /* start adding items from the root */ + linkedlist_sync_add_node(tree, tree->root); } /* *********************************************** */ @@ -131,159 +130,164 @@ void BLI_dlrbTree_linkedlist_sync(DLRBT_Tree *tree) /* Find the node which matches or is the closest to the requested node */ DLRBT_Node *BLI_dlrbTree_search(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data) { - DLRBT_Node *node = (tree) ? tree->root : NULL; - short found = 0; - - /* check that there is a comparator to use */ - /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ - if (cmp_cb == NULL) { - return NULL; - } - - /* iteratively perform this search */ - while (node && found == 0) { - /* check if traverse further or not - * NOTE: it is assumed that the values will be unit values only - */ - switch (cmp_cb(node, search_data)) { - case -1: /* data less than node */ - if (node->left) { - node = node->left; - } - else { - found = 1; - } - break; - - case 1: /* data greater than node */ - if (node->right) { - node = node->right; - } - else { - found = 1; - } - break; - - default: /* data equals node */ - found = 1; - break; - } - } - - /* return the nearest matching node */ - return node; + DLRBT_Node *node = (tree) ? tree->root : NULL; + short found = 0; + + /* check that there is a comparator to use */ + /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ + if (cmp_cb == NULL) { + return NULL; + } + + /* iteratively perform this search */ + while (node && found == 0) { + /* check if traverse further or not + * NOTE: it is assumed that the values will be unit values only + */ + switch (cmp_cb(node, search_data)) { + case -1: /* data less than node */ + if (node->left) { + node = node->left; + } + else { + found = 1; + } + break; + + case 1: /* data greater than node */ + if (node->right) { + node = node->right; + } + else { + found = 1; + } + break; + + default: /* data equals node */ + found = 1; + break; + } + } + + /* return the nearest matching node */ + return node; } /* Find the node which exactly matches the required data */ -DLRBT_Node *BLI_dlrbTree_search_exact(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data) +DLRBT_Node *BLI_dlrbTree_search_exact(DLRBT_Tree *tree, + DLRBT_Comparator_FP cmp_cb, + void *search_data) { - DLRBT_Node *node = (tree) ? tree->root : NULL; - short found = 0; - - /* check that there is a comparator to use */ - /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ - if (cmp_cb == NULL) { - return NULL; - } - - /* iteratively perform this search */ - while (node && found == 0) { - /* check if traverse further or not - * NOTE: it is assumed that the values will be unit values only - */ - switch (cmp_cb(node, search_data)) { - case -1: /* data less than node */ - if (node->left) { - node = node->left; - } - else { - found = -1; - } - break; - - case 1: /* data greater than node */ - if (node->right) { - node = node->right; - } - else { - found = -1; - } - break; - - default: /* data equals node */ - found = 1; - break; - } - } - - /* return the exactly matching node */ - return (found == 1) ? (node) : (NULL); + DLRBT_Node *node = (tree) ? tree->root : NULL; + short found = 0; + + /* check that there is a comparator to use */ + /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ + if (cmp_cb == NULL) { + return NULL; + } + + /* iteratively perform this search */ + while (node && found == 0) { + /* check if traverse further or not + * NOTE: it is assumed that the values will be unit values only + */ + switch (cmp_cb(node, search_data)) { + case -1: /* data less than node */ + if (node->left) { + node = node->left; + } + else { + found = -1; + } + break; + + case 1: /* data greater than node */ + if (node->right) { + node = node->right; + } + else { + found = -1; + } + break; + + default: /* data equals node */ + found = 1; + break; + } + } + + /* return the exactly matching node */ + return (found == 1) ? (node) : (NULL); } /* Find the node which occurs immediately before the best matching node */ -DLRBT_Node *BLI_dlrbTree_search_prev(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data) +DLRBT_Node *BLI_dlrbTree_search_prev(DLRBT_Tree *tree, + DLRBT_Comparator_FP cmp_cb, + void *search_data) { - DLRBT_Node *node; - - /* check that there is a comparator to use */ - /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ - if (cmp_cb == NULL) { - return NULL; - } - - /* get the node which best matches this description */ - node = BLI_dlrbTree_search(tree, cmp_cb, search_data); - - if (node) { - /* if the item we're searching for is greater than the node found, we've found the match */ - if (cmp_cb(node, search_data) > 0) { - return node; - } - - /* return the previous node otherwise */ - /* NOTE: what happens if there is no previous node? */ - return node->prev; - } - - /* nothing matching was found */ - return NULL; + DLRBT_Node *node; + + /* check that there is a comparator to use */ + /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ + if (cmp_cb == NULL) { + return NULL; + } + + /* get the node which best matches this description */ + node = BLI_dlrbTree_search(tree, cmp_cb, search_data); + + if (node) { + /* if the item we're searching for is greater than the node found, we've found the match */ + if (cmp_cb(node, search_data) > 0) { + return node; + } + + /* return the previous node otherwise */ + /* NOTE: what happens if there is no previous node? */ + return node->prev; + } + + /* nothing matching was found */ + return NULL; } /* Find the node which occurs immediately after the best matching node */ -DLRBT_Node *BLI_dlrbTree_search_next(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data) +DLRBT_Node *BLI_dlrbTree_search_next(DLRBT_Tree *tree, + DLRBT_Comparator_FP cmp_cb, + void *search_data) { - DLRBT_Node *node; - - /* check that there is a comparator to use */ - /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ - if (cmp_cb == NULL) { - return NULL; - } - - /* get the node which best matches this description */ - node = BLI_dlrbTree_search(tree, cmp_cb, search_data); - - if (node) { - /* if the item we're searching for is less than the node found, we've found the match */ - if (cmp_cb(node, search_data) < 0) { - return node; - } - - /* return the previous node otherwise */ - /* NOTE: what happens if there is no previous node? */ - return node->next; - } - - /* nothing matching was found */ - return NULL; + DLRBT_Node *node; + + /* check that there is a comparator to use */ + /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ + if (cmp_cb == NULL) { + return NULL; + } + + /* get the node which best matches this description */ + node = BLI_dlrbTree_search(tree, cmp_cb, search_data); + + if (node) { + /* if the item we're searching for is less than the node found, we've found the match */ + if (cmp_cb(node, search_data) < 0) { + return node; + } + + /* return the previous node otherwise */ + /* NOTE: what happens if there is no previous node? */ + return node->next; + } + + /* nothing matching was found */ + return NULL; } - /* Check whether there is a node matching the requested node */ short BLI_dlrbTree_contains(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data) { - /* check if an exact search throws up anything... */ - return (BLI_dlrbTree_search_exact(tree, cmp_cb, search_data) != NULL); + /* check if an exact search throws up anything... */ + return (BLI_dlrbTree_search_exact(tree, cmp_cb, search_data) != NULL); } /* *********************************************** */ @@ -292,40 +296,40 @@ short BLI_dlrbTree_contains(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void * /* get the 'grandparent' - the parent of the parent - of the given node */ static DLRBT_Node *get_grandparent(DLRBT_Node *node) { - if (node && node->parent) { - return node->parent->parent; - } - else { - return NULL; - } + if (node && node->parent) { + return node->parent->parent; + } + else { + return NULL; + } } /* get the sibling node (e.g. if node is left child of parent, return right child of parent) */ static DLRBT_Node *get_sibling(DLRBT_Node *node) { - if (node && node->parent) { - if (node == node->parent->left) { - return node->parent->right; - } - else { - return node->parent->left; - } - } - - /* sibling not found */ - return NULL; + if (node && node->parent) { + if (node == node->parent->left) { + return node->parent->right; + } + else { + return node->parent->left; + } + } + + /* sibling not found */ + return NULL; } /* get the 'uncle' - the sibling of the parent - of the given node */ static DLRBT_Node *get_uncle(DLRBT_Node *node) { - if (node) { - /* return the child of the grandparent which isn't the node's parent */ - return get_sibling(node->parent); - } + if (node) { + /* return the child of the grandparent which isn't the node's parent */ + return get_sibling(node->parent); + } - /* uncle not found */ - return NULL; + /* uncle not found */ + return NULL; } /* *********************************************** */ @@ -334,83 +338,83 @@ static DLRBT_Node *get_uncle(DLRBT_Node *node) /* make right child of 'root' the new root */ static void rotate_left(DLRBT_Tree *tree, DLRBT_Node *root) { - DLRBT_Node **root_slot, *pivot; - - /* pivot is simply the root's right child, to become the root's parent */ - pivot = root->right; - if (pivot == NULL) { - return; - } - - if (root->parent) { - if (root == root->parent->left) { - root_slot = &root->parent->left; - } - else { - root_slot = &root->parent->right; - } - } - else { - root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node *)tree->root); */ - } - - /* - pivot's left child becomes root's right child - * - root now becomes pivot's left child - */ - root->right = pivot->left; - if (pivot->left) { - pivot->left->parent = root; - } - - pivot->left = root; - pivot->parent = root->parent; - root->parent = pivot; - - /* make the pivot the new root */ - if (root_slot) { - *root_slot = pivot; - } + DLRBT_Node **root_slot, *pivot; + + /* pivot is simply the root's right child, to become the root's parent */ + pivot = root->right; + if (pivot == NULL) { + return; + } + + if (root->parent) { + if (root == root->parent->left) { + root_slot = &root->parent->left; + } + else { + root_slot = &root->parent->right; + } + } + else { + root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node *)tree->root); */ + } + + /* - pivot's left child becomes root's right child + * - root now becomes pivot's left child + */ + root->right = pivot->left; + if (pivot->left) { + pivot->left->parent = root; + } + + pivot->left = root; + pivot->parent = root->parent; + root->parent = pivot; + + /* make the pivot the new root */ + if (root_slot) { + *root_slot = pivot; + } } /* make the left child of the 'root' the new root */ static void rotate_right(DLRBT_Tree *tree, DLRBT_Node *root) { - DLRBT_Node **root_slot, *pivot; - - /* pivot is simply the root's left child, to become the root's parent */ - pivot = root->left; - if (pivot == NULL) { - return; - } - - if (root->parent) { - if (root == root->parent->left) { - root_slot = &root->parent->left; - } - else { - root_slot = &root->parent->right; - } - } - else { - root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node *)tree->root); */ - } - - /* - pivot's right child becomes root's left child - * - root now becomes pivot's right child - */ - root->left = pivot->right; - if (pivot->right) { - pivot->right->parent = root; - } - - pivot->right = root; - pivot->parent = root->parent; - root->parent = pivot; - - /* make the pivot the new root */ - if (root_slot) { - *root_slot = pivot; - } + DLRBT_Node **root_slot, *pivot; + + /* pivot is simply the root's left child, to become the root's parent */ + pivot = root->left; + if (pivot == NULL) { + return; + } + + if (root->parent) { + if (root == root->parent->left) { + root_slot = &root->parent->left; + } + else { + root_slot = &root->parent->right; + } + } + else { + root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node *)tree->root); */ + } + + /* - pivot's right child becomes root's left child + * - root now becomes pivot's right child + */ + root->left = pivot->right; + if (pivot->right) { + pivot->right->parent = root; + } + + pivot->right = root; + pivot->parent = root->parent; + root->parent = pivot; + + /* make the pivot the new root */ + if (root_slot) { + *root_slot = pivot; + } } /* *********************************************** */ @@ -426,96 +430,96 @@ static void insert_check_3(DLRBT_Tree *tree, DLRBT_Node *node); /* W. 1) Root must be black (so that the 2nd-generation can have a black parent) */ static void insert_check_1(DLRBT_Tree *tree, DLRBT_Node *node) { - if (node) { - /* if this is the root, just ensure that it is black */ - if (node->parent == NULL) { - node->tree_col = DLRBT_BLACK; - } - else { - insert_check_2(tree, node); - } - } + if (node) { + /* if this is the root, just ensure that it is black */ + if (node->parent == NULL) { + node->tree_col = DLRBT_BLACK; + } + else { + insert_check_2(tree, node); + } + } } /* W. 2+3) Parent of node must be black, otherwise recolor and flush */ static void insert_check_2(DLRBT_Tree *tree, DLRBT_Node *node) { - /* if the parent is not black, we need to change that... */ - if (node && node->parent && node->parent->tree_col) { - DLRBT_Node *unc = get_uncle(node); - - /* if uncle and parent are both red, need to change them to black and make - * the parent black in order to satisfy the criteria of each node having the - * same number of black nodes to its leaves - */ - if (unc && unc->tree_col) { - DLRBT_Node *gp = get_grandparent(node); - - /* make the n-1 generation nodes black */ - node->parent->tree_col = unc->tree_col = DLRBT_BLACK; - - /* - make the grandparent red, so that we maintain alternating red/black property - * (it must exist, so no need to check for NULL here), - * - as the grandparent may now cause inconsistencies with the rest of the tree, - * we must flush up the tree and perform checks/re-balancing/re-painting, using the - * grandparent as the node of interest - */ - gp->tree_col = DLRBT_RED; - insert_check_1(tree, gp); - } - else { - /* we've got an unbalanced branch going down the grandparent to the parent, - * so need to perform some rotations to re-balance the tree - */ - insert_check_3(tree, node); - } - } + /* if the parent is not black, we need to change that... */ + if (node && node->parent && node->parent->tree_col) { + DLRBT_Node *unc = get_uncle(node); + + /* if uncle and parent are both red, need to change them to black and make + * the parent black in order to satisfy the criteria of each node having the + * same number of black nodes to its leaves + */ + if (unc && unc->tree_col) { + DLRBT_Node *gp = get_grandparent(node); + + /* make the n-1 generation nodes black */ + node->parent->tree_col = unc->tree_col = DLRBT_BLACK; + + /* - make the grandparent red, so that we maintain alternating red/black property + * (it must exist, so no need to check for NULL here), + * - as the grandparent may now cause inconsistencies with the rest of the tree, + * we must flush up the tree and perform checks/re-balancing/re-painting, using the + * grandparent as the node of interest + */ + gp->tree_col = DLRBT_RED; + insert_check_1(tree, gp); + } + else { + /* we've got an unbalanced branch going down the grandparent to the parent, + * so need to perform some rotations to re-balance the tree + */ + insert_check_3(tree, node); + } + } } /* W. 4+5) Perform rotation on sub-tree containing the 'new' node, then do any */ static void insert_check_3(DLRBT_Tree *tree, DLRBT_Node *node) { - DLRBT_Node *gp = get_grandparent(node); - - /* check that grandparent and node->parent exist - * (jut in case... really shouldn't happen on a good tree) */ - if (node && node->parent && gp) { - /* a left rotation will switch the roles of node and its parent, assuming that - * the parent is the left child of the grandparent... otherwise, rotation direction - * should be swapped - */ - if ((node == node->parent->right) && (node->parent == gp->left)) { - rotate_left(tree, node); - node = node->left; - } - else if ((node == node->parent->left) && (node->parent == gp->right)) { - rotate_right(tree, node); - node = node->right; - } - - /* fix old parent's color-tagging, and perform rotation on the old parent in the - * opposite direction if needed for the current situation - * NOTE: in the code above, node pointer is changed to point to the old parent - */ - if (node) { - /* get 'new' grandparent (i.e. grandparent for old-parent (node)) */ - gp = get_grandparent(node); - - /* modify the coloring of the grandparent and parent - * so that they still satisfy the constraints */ - node->parent->tree_col = DLRBT_BLACK; - gp->tree_col = DLRBT_RED; - - /* if there are several nodes that all form a left chain, do a right rotation to correct - * this (or a rotation in the opposite direction if they all form a right chain) */ - if ((node == node->parent->left) && (node->parent == gp->left)) { - rotate_right(tree, gp); - } - else { //if ((node == node->parent->right) && (node->parent == gp->right)) - rotate_left(tree, gp); - } - } - } + DLRBT_Node *gp = get_grandparent(node); + + /* check that grandparent and node->parent exist + * (jut in case... really shouldn't happen on a good tree) */ + if (node && node->parent && gp) { + /* a left rotation will switch the roles of node and its parent, assuming that + * the parent is the left child of the grandparent... otherwise, rotation direction + * should be swapped + */ + if ((node == node->parent->right) && (node->parent == gp->left)) { + rotate_left(tree, node); + node = node->left; + } + else if ((node == node->parent->left) && (node->parent == gp->right)) { + rotate_right(tree, node); + node = node->right; + } + + /* fix old parent's color-tagging, and perform rotation on the old parent in the + * opposite direction if needed for the current situation + * NOTE: in the code above, node pointer is changed to point to the old parent + */ + if (node) { + /* get 'new' grandparent (i.e. grandparent for old-parent (node)) */ + gp = get_grandparent(node); + + /* modify the coloring of the grandparent and parent + * so that they still satisfy the constraints */ + node->parent->tree_col = DLRBT_BLACK; + gp->tree_col = DLRBT_RED; + + /* if there are several nodes that all form a left chain, do a right rotation to correct + * this (or a rotation in the opposite direction if they all form a right chain) */ + if ((node == node->parent->left) && (node->parent == gp->left)) { + rotate_right(tree, gp); + } + else { //if ((node == node->parent->right) && (node->parent == gp->right)) + rotate_left(tree, gp); + } + } + } } /* ----- */ @@ -525,16 +529,16 @@ static void insert_check_3(DLRBT_Tree *tree, DLRBT_Node *node) */ void BLI_dlrbTree_insert(DLRBT_Tree *tree, DLRBT_Node *node) { - /* sanity checks */ - if ((tree == NULL) || (node == NULL)) { - return; - } + /* sanity checks */ + if ((tree == NULL) || (node == NULL)) { + return; + } - /* firstly, the node we just added should be red by default */ - node->tree_col = DLRBT_RED; + /* firstly, the node we just added should be red by default */ + node->tree_col = DLRBT_RED; - /* start from case 1, an trek through the tail-recursive insertion checks */ - insert_check_1(tree, node); + /* start from case 1, an trek through the tail-recursive insertion checks */ + insert_check_1(tree, node); } /* ----- */ @@ -542,86 +546,89 @@ void BLI_dlrbTree_insert(DLRBT_Tree *tree, DLRBT_Node *node) /* Add the given data to the tree, and return the node added */ /* NOTE: for duplicates, the update_cb is called (if available), * and the existing node is returned */ -DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, - DLRBT_NAlloc_FP new_cb, DLRBT_NUpdate_FP update_cb, void *data) +DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, + DLRBT_Comparator_FP cmp_cb, + DLRBT_NAlloc_FP new_cb, + DLRBT_NUpdate_FP update_cb, + void *data) { - DLRBT_Node *parNode, *node = NULL; - short new_node = 0; - - /* sanity checks */ - if (tree == NULL) { - return NULL; - } - - /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ - if (cmp_cb == NULL) { - return NULL; - } - /* TODO: if no allocator is supplied, try using the one supplied with the tree... */ - if (new_cb == NULL) { - return NULL; - } - /* TODO: if no updater is supplied, try using the one supplied with the tree... */ - - /* try to find the nearest node to this one */ - parNode = BLI_dlrbTree_search(tree, cmp_cb, data); - - /* add new node to the BST in the 'standard way' as appropriate - * NOTE: we do not support duplicates in our tree... - */ - if (parNode) { - /* check how this new node compares with the existing ones - * NOTE: it is assumed that the values will be unit values only - */ - switch (cmp_cb(parNode, data)) { - case -1: /* add new node as left child */ - { - node = new_cb(data); - new_node = 1; - - parNode->left = node; - node->parent = parNode; - break; - } - case 1: /* add new node as right child */ - { - node = new_cb(data); - new_node = 1; - - parNode->right = node; - node->parent = parNode; - break; - } - default: /* update the duplicate node as appropriate */ - { - if (update_cb) { - update_cb(parNode, data); - } - break; - } - } - } - else { - /* no nodes in the tree yet... add a new node as the root */ - node = new_cb(data); - new_node = 1; - - tree->root = node; - } - - /* if a new node was added, it should be tagged as red, and then balanced as appropriate */ - if (new_node) { - /* tag this new node as being 'red' */ - node->tree_col = DLRBT_RED; - - /* perform BST balancing steps: - * start from case 1, an trek through the tail-recursive insertion checks - */ - insert_check_1(tree, node); - } - - /* return the node added */ - return node; + DLRBT_Node *parNode, *node = NULL; + short new_node = 0; + + /* sanity checks */ + if (tree == NULL) { + return NULL; + } + + /* TODO: if no comparator is supplied, try using the one supplied with the tree... */ + if (cmp_cb == NULL) { + return NULL; + } + /* TODO: if no allocator is supplied, try using the one supplied with the tree... */ + if (new_cb == NULL) { + return NULL; + } + /* TODO: if no updater is supplied, try using the one supplied with the tree... */ + + /* try to find the nearest node to this one */ + parNode = BLI_dlrbTree_search(tree, cmp_cb, data); + + /* add new node to the BST in the 'standard way' as appropriate + * NOTE: we do not support duplicates in our tree... + */ + if (parNode) { + /* check how this new node compares with the existing ones + * NOTE: it is assumed that the values will be unit values only + */ + switch (cmp_cb(parNode, data)) { + case -1: /* add new node as left child */ + { + node = new_cb(data); + new_node = 1; + + parNode->left = node; + node->parent = parNode; + break; + } + case 1: /* add new node as right child */ + { + node = new_cb(data); + new_node = 1; + + parNode->right = node; + node->parent = parNode; + break; + } + default: /* update the duplicate node as appropriate */ + { + if (update_cb) { + update_cb(parNode, data); + } + break; + } + } + } + else { + /* no nodes in the tree yet... add a new node as the root */ + node = new_cb(data); + new_node = 1; + + tree->root = node; + } + + /* if a new node was added, it should be tagged as red, and then balanced as appropriate */ + if (new_node) { + /* tag this new node as being 'red' */ + node->tree_col = DLRBT_RED; + + /* perform BST balancing steps: + * start from case 1, an trek through the tail-recursive insertion checks + */ + insert_check_1(tree, node); + } + + /* return the node added */ + return node; } /* *********************************************** */ diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 477d320835e..0e7b9a29ee5 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -105,7 +105,7 @@ #include "BLI_strict_flags.h" -#include "BLI_array_store.h" /* own include */ +#include "BLI_array_store.h" /* own include */ /* only for BLI_array_store_is_valid */ #include "BLI_ghash.h" @@ -161,7 +161,7 @@ */ #define USE_HASH_TABLE_KEY_CACHE #ifdef USE_HASH_TABLE_KEY_CACHE -# define HASH_TABLE_KEY_UNSET ((uint64_t)-1) +# define HASH_TABLE_KEY_UNSET ((uint64_t)-1) # define HASH_TABLE_KEY_FALLBACK ((uint64_t)-2) #endif @@ -192,7 +192,7 @@ * so lower only to check splitting works. */ # define BCHUNK_SIZE_MAX_MUL 2 -#endif /* USE_MERGE_CHUNKS */ +#endif /* USE_MERGE_CHUNKS */ /* slow (keep disabled), but handy for debugging */ // #define USE_VALIDATE_LIST_SIZE @@ -203,50 +203,48 @@ /** \} */ - /** \name Internal Structs * \{ */ typedef uint64_t hash_key; - typedef struct BArrayInfo { - size_t chunk_stride; - // uint chunk_count; /* UNUSED (other values are derived from this) */ + size_t chunk_stride; + // uint chunk_count; /* UNUSED (other values are derived from this) */ - /* pre-calculated */ - size_t chunk_byte_size; - /* min/max limits (inclusive) */ - size_t chunk_byte_size_min; - size_t chunk_byte_size_max; + /* pre-calculated */ + size_t chunk_byte_size; + /* min/max limits (inclusive) */ + size_t chunk_byte_size_min; + size_t chunk_byte_size_max; - size_t accum_read_ahead_bytes; + size_t accum_read_ahead_bytes; #ifdef USE_HASH_TABLE_ACCUMULATE - size_t accum_steps; - size_t accum_read_ahead_len; + size_t accum_steps; + size_t accum_read_ahead_len; #endif } BArrayInfo; typedef struct BArrayMemory { - BLI_mempool *chunk_list; /* BChunkList */ - BLI_mempool *chunk_ref; /* BChunkRef */ - BLI_mempool *chunk; /* BChunk */ + BLI_mempool *chunk_list; /* BChunkList */ + BLI_mempool *chunk_ref; /* BChunkRef */ + BLI_mempool *chunk; /* BChunk */ } BArrayMemory; /** * Main storage for all states */ struct BArrayStore { - /* static */ - BArrayInfo info; + /* static */ + BArrayInfo info; - /* memory storage */ - BArrayMemory memory; + /* memory storage */ + BArrayMemory memory; - /** - * #BArrayState may be in any order (logic should never depend on state order). - */ - ListBase states; + /** + * #BArrayState may be in any order (logic should never depend on state order). + */ + ListBase states; }; /** @@ -260,31 +258,30 @@ struct BArrayStore { * it makes it easier to trace invalid usage, so leave as-is for now. */ struct BArrayState { - /** linked list in #BArrayStore.states */ - struct BArrayState *next, *prev; - - struct BChunkList *chunk_list; /* BChunkList's */ + /** linked list in #BArrayStore.states */ + struct BArrayState *next, *prev; + struct BChunkList *chunk_list; /* BChunkList's */ }; typedef struct BChunkList { - ListBase chunk_refs; /* BChunkRef's */ - uint chunk_refs_len; /* BLI_listbase_count(chunks), store for reuse. */ - size_t total_size; /* size of all chunks */ + ListBase chunk_refs; /* BChunkRef's */ + uint chunk_refs_len; /* BLI_listbase_count(chunks), store for reuse. */ + size_t total_size; /* size of all chunks */ - /** number of #BArrayState using this. */ - int users; + /** number of #BArrayState using this. */ + int users; } BChunkList; /* a chunk of an array */ typedef struct BChunk { - const uchar *data; - size_t data_len; - /** number of #BChunkList using this. */ - int users; + const uchar *data; + size_t data_len; + /** number of #BChunkList using this. */ + int users; #ifdef USE_HASH_TABLE_KEY_CACHE - hash_key key; + hash_key key; #endif } BChunk; @@ -292,8 +289,8 @@ typedef struct BChunk { * Links to store #BChunk data in #BChunkList.chunk_refs. */ typedef struct BChunkRef { - struct BChunkRef *next, *prev; - BChunk *link; + struct BChunkRef *next, *prev; + BChunk *link; } BChunkRef; /** @@ -305,100 +302,92 @@ typedef struct BChunkRef { * this avoids having to do so many table lookups. */ typedef struct BTableRef { - struct BTableRef *next; - const BChunkRef *cref; + struct BTableRef *next; + const BChunkRef *cref; } BTableRef; /** \} */ - static size_t bchunk_list_size(const BChunkList *chunk_list); - /** \name Internal BChunk API * \{ */ -static BChunk *bchunk_new( - BArrayMemory *bs_mem, const uchar *data, const size_t data_len) +static BChunk *bchunk_new(BArrayMemory *bs_mem, const uchar *data, const size_t data_len) { - BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk); - chunk->data = data; - chunk->data_len = data_len; - chunk->users = 0; + BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk); + chunk->data = data; + chunk->data_len = data_len; + chunk->users = 0; #ifdef USE_HASH_TABLE_KEY_CACHE - chunk->key = HASH_TABLE_KEY_UNSET; + chunk->key = HASH_TABLE_KEY_UNSET; #endif - return chunk; + return chunk; } -static BChunk *bchunk_new_copydata( - BArrayMemory *bs_mem, const uchar *data, const size_t data_len) +static BChunk *bchunk_new_copydata(BArrayMemory *bs_mem, const uchar *data, const size_t data_len) { - uchar *data_copy = MEM_mallocN(data_len, __func__); - memcpy(data_copy, data, data_len); - return bchunk_new(bs_mem, data_copy, data_len); + uchar *data_copy = MEM_mallocN(data_len, __func__); + memcpy(data_copy, data, data_len); + return bchunk_new(bs_mem, data_copy, data_len); } -static void bchunk_decref( - BArrayMemory *bs_mem, BChunk *chunk) +static void bchunk_decref(BArrayMemory *bs_mem, BChunk *chunk) { - BLI_assert(chunk->users > 0); - if (chunk->users == 1) { - MEM_freeN((void *)chunk->data); - BLI_mempool_free(bs_mem->chunk, chunk); - } - else { - chunk->users -= 1; - } + BLI_assert(chunk->users > 0); + if (chunk->users == 1) { + MEM_freeN((void *)chunk->data); + BLI_mempool_free(bs_mem->chunk, chunk); + } + else { + chunk->users -= 1; + } } -static bool bchunk_data_compare( - const BChunk *chunk, - const uchar *data_base, const size_t data_base_len, - const size_t offset) +static bool bchunk_data_compare(const BChunk *chunk, + const uchar *data_base, + const size_t data_base_len, + const size_t offset) { - if (offset + (size_t)chunk->data_len <= data_base_len) { - return (memcmp(&data_base[offset], chunk->data, chunk->data_len) == 0); - } - else { - return false; - } + if (offset + (size_t)chunk->data_len <= data_base_len) { + return (memcmp(&data_base[offset], chunk->data, chunk->data_len) == 0); + } + else { + return false; + } } /** \} */ - /** \name Internal BChunkList API * \{ */ -static BChunkList *bchunk_list_new( - BArrayMemory *bs_mem, size_t total_size) +static BChunkList *bchunk_list_new(BArrayMemory *bs_mem, size_t total_size) { - BChunkList *chunk_list = BLI_mempool_alloc(bs_mem->chunk_list); + BChunkList *chunk_list = BLI_mempool_alloc(bs_mem->chunk_list); - BLI_listbase_clear(&chunk_list->chunk_refs); - chunk_list->chunk_refs_len = 0; - chunk_list->total_size = total_size; - chunk_list->users = 0; - return chunk_list; + BLI_listbase_clear(&chunk_list->chunk_refs); + chunk_list->chunk_refs_len = 0; + chunk_list->total_size = total_size; + chunk_list->users = 0; + return chunk_list; } -static void bchunk_list_decref( - BArrayMemory *bs_mem, BChunkList *chunk_list) +static void bchunk_list_decref(BArrayMemory *bs_mem, BChunkList *chunk_list) { - BLI_assert(chunk_list->users > 0); - if (chunk_list->users == 1) { - for (BChunkRef *cref = chunk_list->chunk_refs.first, *cref_next; cref; cref = cref_next) { - cref_next = cref->next; - bchunk_decref(bs_mem, cref->link); - BLI_mempool_free(bs_mem->chunk_ref, cref); - } - - BLI_mempool_free(bs_mem->chunk_list, chunk_list); - } - else { - chunk_list->users -= 1; - } + BLI_assert(chunk_list->users > 0); + if (chunk_list->users == 1) { + for (BChunkRef *cref = chunk_list->chunk_refs.first, *cref_next; cref; cref = cref_next) { + cref_next = cref->next; + bchunk_decref(bs_mem, cref->link); + BLI_mempool_free(bs_mem->chunk_ref, cref); + } + + BLI_mempool_free(bs_mem->chunk_list, chunk_list); + } + else { + chunk_list->users -= 1; + } } #ifdef USE_VALIDATE_LIST_SIZE @@ -410,113 +399,110 @@ static void bchunk_list_decref( # define ASSERT_CHUNKLIST_SIZE(chunk_list, n) (EXPR_NOP(chunk_list), EXPR_NOP(n)) #endif - #ifdef USE_VALIDATE_LIST_DATA_PARTIAL -static size_t bchunk_list_data_check( - const BChunkList *chunk_list, const uchar *data) +static size_t bchunk_list_data_check(const BChunkList *chunk_list, const uchar *data) { - size_t offset = 0; - for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { - if (memcmp(&data[offset], cref->link->data, cref->link->data_len) != 0) { - return false; - } - offset += cref->link->data_len; - } - return true; + size_t offset = 0; + for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { + if (memcmp(&data[offset], cref->link->data, cref->link->data_len) != 0) { + return false; + } + offset += cref->link->data_len; + } + return true; } -# define ASSERT_CHUNKLIST_DATA(chunk_list, data) BLI_assert(bchunk_list_data_check(chunk_list, data)) +# define ASSERT_CHUNKLIST_DATA(chunk_list, data) \ + BLI_assert(bchunk_list_data_check(chunk_list, data)) #else # define ASSERT_CHUNKLIST_DATA(chunk_list, data) (EXPR_NOP(chunk_list), EXPR_NOP(data)) #endif - #ifdef USE_MERGE_CHUNKS -static void bchunk_list_ensure_min_size_last( - const BArrayInfo *info, BArrayMemory *bs_mem, - BChunkList *chunk_list) +static void bchunk_list_ensure_min_size_last(const BArrayInfo *info, + BArrayMemory *bs_mem, + BChunkList *chunk_list) { - BChunkRef *cref = chunk_list->chunk_refs.last; - if (cref && cref->prev) { - /* both are decref'd after use (end of this block) */ - BChunk *chunk_curr = cref->link; - BChunk *chunk_prev = cref->prev->link; - - if (MIN2(chunk_prev->data_len, chunk_curr->data_len) < info->chunk_byte_size_min) { - const size_t data_merge_len = chunk_prev->data_len + chunk_curr->data_len; - /* we could pass, but no need */ - if (data_merge_len <= info->chunk_byte_size_max) { - /* we have enough space to merge */ - - /* remove last from linklist */ - BLI_assert(chunk_list->chunk_refs.last != chunk_list->chunk_refs.first); - cref->prev->next = NULL; - chunk_list->chunk_refs.last = cref->prev; - chunk_list->chunk_refs_len -= 1; - - uchar *data_merge = MEM_mallocN(data_merge_len, __func__); - memcpy(data_merge, chunk_prev->data, chunk_prev->data_len); - memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len); - - cref->prev->link = bchunk_new(bs_mem, data_merge, data_merge_len); - cref->prev->link->users += 1; - - BLI_mempool_free(bs_mem->chunk_ref, cref); - } - else { - /* If we always merge small slices, we should _almost_ - * never end up having very large chunks. - * Gradual expanding on contracting will cause this. - * - * if we do, the code below works (test by setting 'BCHUNK_SIZE_MAX_MUL = 1.2') */ - - /* keep chunk on the left hand side a regular size */ - const size_t split = info->chunk_byte_size; - - /* merge and split */ - const size_t data_prev_len = split; - const size_t data_curr_len = data_merge_len - split; - uchar *data_prev = MEM_mallocN(data_prev_len, __func__); - uchar *data_curr = MEM_mallocN(data_curr_len, __func__); - - if (data_prev_len <= chunk_prev->data_len) { - const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len; - - /* setup 'data_prev' */ - memcpy(data_prev, chunk_prev->data, data_prev_len); - - /* setup 'data_curr' */ - memcpy(data_curr, &chunk_prev->data[data_prev_len], data_curr_shrink_len); - memcpy(&data_curr[data_curr_shrink_len], chunk_curr->data, chunk_curr->data_len); - } - else { - BLI_assert(data_curr_len <= chunk_curr->data_len); - BLI_assert(data_prev_len >= chunk_prev->data_len); - - const size_t data_prev_grow_len = data_prev_len - chunk_prev->data_len; - - /* setup 'data_prev' */ - memcpy(data_prev, chunk_prev->data, chunk_prev->data_len); - memcpy(&data_prev[chunk_prev->data_len], chunk_curr->data, data_prev_grow_len); - - /* setup 'data_curr' */ - memcpy(data_curr, &chunk_curr->data[data_prev_grow_len], data_curr_len); - } - - cref->prev->link = bchunk_new(bs_mem, data_prev, data_prev_len); - cref->prev->link->users += 1; - - cref->link = bchunk_new(bs_mem, data_curr, data_curr_len); - cref->link->users += 1; - } - - /* free zero users */ - bchunk_decref(bs_mem, chunk_curr); - bchunk_decref(bs_mem, chunk_prev); - } - } + BChunkRef *cref = chunk_list->chunk_refs.last; + if (cref && cref->prev) { + /* both are decref'd after use (end of this block) */ + BChunk *chunk_curr = cref->link; + BChunk *chunk_prev = cref->prev->link; + + if (MIN2(chunk_prev->data_len, chunk_curr->data_len) < info->chunk_byte_size_min) { + const size_t data_merge_len = chunk_prev->data_len + chunk_curr->data_len; + /* we could pass, but no need */ + if (data_merge_len <= info->chunk_byte_size_max) { + /* we have enough space to merge */ + + /* remove last from linklist */ + BLI_assert(chunk_list->chunk_refs.last != chunk_list->chunk_refs.first); + cref->prev->next = NULL; + chunk_list->chunk_refs.last = cref->prev; + chunk_list->chunk_refs_len -= 1; + + uchar *data_merge = MEM_mallocN(data_merge_len, __func__); + memcpy(data_merge, chunk_prev->data, chunk_prev->data_len); + memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len); + + cref->prev->link = bchunk_new(bs_mem, data_merge, data_merge_len); + cref->prev->link->users += 1; + + BLI_mempool_free(bs_mem->chunk_ref, cref); + } + else { + /* If we always merge small slices, we should _almost_ + * never end up having very large chunks. + * Gradual expanding on contracting will cause this. + * + * if we do, the code below works (test by setting 'BCHUNK_SIZE_MAX_MUL = 1.2') */ + + /* keep chunk on the left hand side a regular size */ + const size_t split = info->chunk_byte_size; + + /* merge and split */ + const size_t data_prev_len = split; + const size_t data_curr_len = data_merge_len - split; + uchar *data_prev = MEM_mallocN(data_prev_len, __func__); + uchar *data_curr = MEM_mallocN(data_curr_len, __func__); + + if (data_prev_len <= chunk_prev->data_len) { + const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len; + + /* setup 'data_prev' */ + memcpy(data_prev, chunk_prev->data, data_prev_len); + + /* setup 'data_curr' */ + memcpy(data_curr, &chunk_prev->data[data_prev_len], data_curr_shrink_len); + memcpy(&data_curr[data_curr_shrink_len], chunk_curr->data, chunk_curr->data_len); + } + else { + BLI_assert(data_curr_len <= chunk_curr->data_len); + BLI_assert(data_prev_len >= chunk_prev->data_len); + + const size_t data_prev_grow_len = data_prev_len - chunk_prev->data_len; + + /* setup 'data_prev' */ + memcpy(data_prev, chunk_prev->data, chunk_prev->data_len); + memcpy(&data_prev[chunk_prev->data_len], chunk_curr->data, data_prev_grow_len); + + /* setup 'data_curr' */ + memcpy(data_curr, &chunk_curr->data[data_prev_grow_len], data_curr_len); + } + + cref->prev->link = bchunk_new(bs_mem, data_prev, data_prev_len); + cref->prev->link->users += 1; + + cref->link = bchunk_new(bs_mem, data_curr, data_curr_len); + cref->link->users += 1; + } + + /* free zero users */ + bchunk_decref(bs_mem, chunk_curr); + bchunk_decref(bs_mem, chunk_prev); + } + } } -#endif /* USE_MERGE_CHUNKS */ - +#endif /* USE_MERGE_CHUNKS */ /** * Split length into 2 values @@ -526,108 +512,108 @@ static void bchunk_list_ensure_min_size_last( * \note This function ensures the size of \a r_data_last_chunk_len * is larger than #BArrayInfo.chunk_byte_size_min. */ -static void bchunk_list_calc_trim_len( - const BArrayInfo *info, const size_t data_len, - size_t *r_data_trim_len, size_t *r_data_last_chunk_len) +static void bchunk_list_calc_trim_len(const BArrayInfo *info, + const size_t data_len, + size_t *r_data_trim_len, + size_t *r_data_last_chunk_len) { - size_t data_last_chunk_len = 0; - size_t data_trim_len = data_len; + size_t data_last_chunk_len = 0; + size_t data_trim_len = data_len; #ifdef USE_MERGE_CHUNKS - /* avoid creating too-small chunks - * more efficient then merging after */ - if (data_len > info->chunk_byte_size) { - data_last_chunk_len = (data_trim_len % info->chunk_byte_size); - data_trim_len = data_trim_len - data_last_chunk_len; - if (data_last_chunk_len) { - if (data_last_chunk_len < info->chunk_byte_size_min) { - /* may be zero and thats OK */ - data_trim_len -= info->chunk_byte_size; - data_last_chunk_len += info->chunk_byte_size; - } - } - } - else { - data_trim_len = 0; - data_last_chunk_len = data_len; - } - - BLI_assert((data_trim_len == 0) || (data_trim_len >= info->chunk_byte_size)); + /* avoid creating too-small chunks + * more efficient then merging after */ + if (data_len > info->chunk_byte_size) { + data_last_chunk_len = (data_trim_len % info->chunk_byte_size); + data_trim_len = data_trim_len - data_last_chunk_len; + if (data_last_chunk_len) { + if (data_last_chunk_len < info->chunk_byte_size_min) { + /* may be zero and thats OK */ + data_trim_len -= info->chunk_byte_size; + data_last_chunk_len += info->chunk_byte_size; + } + } + } + else { + data_trim_len = 0; + data_last_chunk_len = data_len; + } + + BLI_assert((data_trim_len == 0) || (data_trim_len >= info->chunk_byte_size)); #else - data_last_chunk_len = (data_trim_len % info->chunk_byte_size); - data_trim_len = data_trim_len - data_last_chunk_len; + data_last_chunk_len = (data_trim_len % info->chunk_byte_size); + data_trim_len = data_trim_len - data_last_chunk_len; #endif - BLI_assert(data_trim_len + data_last_chunk_len == data_len); + BLI_assert(data_trim_len + data_last_chunk_len == data_len); - *r_data_trim_len = data_trim_len; - *r_data_last_chunk_len = data_last_chunk_len; + *r_data_trim_len = data_trim_len; + *r_data_last_chunk_len = data_last_chunk_len; } /** * Append and don't manage merging small chunks. */ -static void bchunk_list_append_only( - BArrayMemory *bs_mem, - BChunkList *chunk_list, BChunk *chunk) +static void bchunk_list_append_only(BArrayMemory *bs_mem, BChunkList *chunk_list, BChunk *chunk) { - BChunkRef *cref = BLI_mempool_alloc(bs_mem->chunk_ref); - BLI_addtail(&chunk_list->chunk_refs, cref); - cref->link = chunk; - chunk_list->chunk_refs_len += 1; - chunk->users += 1; + BChunkRef *cref = BLI_mempool_alloc(bs_mem->chunk_ref); + BLI_addtail(&chunk_list->chunk_refs, cref); + cref->link = chunk; + chunk_list->chunk_refs_len += 1; + chunk->users += 1; } /** * \note This is for writing single chunks, * use #bchunk_list_append_data_n when writing large blocks of memory into many chunks. */ -static void bchunk_list_append_data( - const BArrayInfo *info, BArrayMemory *bs_mem, - BChunkList *chunk_list, - const uchar *data, const size_t data_len) +static void bchunk_list_append_data(const BArrayInfo *info, + BArrayMemory *bs_mem, + BChunkList *chunk_list, + const uchar *data, + const size_t data_len) { - BLI_assert(data_len != 0); + BLI_assert(data_len != 0); #ifdef USE_MERGE_CHUNKS - BLI_assert(data_len <= info->chunk_byte_size_max); - - if (!BLI_listbase_is_empty(&chunk_list->chunk_refs)) { - BChunkRef *cref = chunk_list->chunk_refs.last; - BChunk *chunk_prev = cref->link; - - if (MIN2(chunk_prev->data_len, data_len) < info->chunk_byte_size_min) { - const size_t data_merge_len = chunk_prev->data_len + data_len; - /* realloc for single user */ - if (cref->link->users == 1) { - uchar *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len); - memcpy(&data_merge[chunk_prev->data_len], data, data_len); - cref->link->data = data_merge; - cref->link->data_len = data_merge_len; - } - else { - uchar *data_merge = MEM_mallocN(data_merge_len, __func__); - memcpy(data_merge, chunk_prev->data, chunk_prev->data_len); - memcpy(&data_merge[chunk_prev->data_len], data, data_len); - cref->link = bchunk_new(bs_mem, data_merge, data_merge_len); - cref->link->users += 1; - bchunk_decref(bs_mem, chunk_prev); - } - return; - } - } + BLI_assert(data_len <= info->chunk_byte_size_max); + + if (!BLI_listbase_is_empty(&chunk_list->chunk_refs)) { + BChunkRef *cref = chunk_list->chunk_refs.last; + BChunk *chunk_prev = cref->link; + + if (MIN2(chunk_prev->data_len, data_len) < info->chunk_byte_size_min) { + const size_t data_merge_len = chunk_prev->data_len + data_len; + /* realloc for single user */ + if (cref->link->users == 1) { + uchar *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len); + memcpy(&data_merge[chunk_prev->data_len], data, data_len); + cref->link->data = data_merge; + cref->link->data_len = data_merge_len; + } + else { + uchar *data_merge = MEM_mallocN(data_merge_len, __func__); + memcpy(data_merge, chunk_prev->data, chunk_prev->data_len); + memcpy(&data_merge[chunk_prev->data_len], data, data_len); + cref->link = bchunk_new(bs_mem, data_merge, data_merge_len); + cref->link->users += 1; + bchunk_decref(bs_mem, chunk_prev); + } + return; + } + } #else - UNUSED_VARS(info); -#endif /* USE_MERGE_CHUNKS */ + UNUSED_VARS(info); +#endif /* USE_MERGE_CHUNKS */ - BChunk *chunk = bchunk_new_copydata(bs_mem, data, data_len); - bchunk_list_append_only(bs_mem, chunk_list, chunk); + BChunk *chunk = bchunk_new_copydata(bs_mem, data, data_len); + bchunk_list_append_only(bs_mem, chunk_list, chunk); - /* don't run this, instead preemptively avoid creating a chunk only to merge it (above). */ + /* don't run this, instead preemptively avoid creating a chunk only to merge it (above). */ #if 0 -#ifdef USE_MERGE_CHUNKS - bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); -#endif +# ifdef USE_MERGE_CHUNKS + bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); +# endif #endif } @@ -638,106 +624,109 @@ static void bchunk_list_append_data( * \note This function takes care not to perform redundant chunk-merging checks, * so we can write successive fixed size chunks quickly. */ -static void bchunk_list_append_data_n( - const BArrayInfo *info, BArrayMemory *bs_mem, - BChunkList *chunk_list, - const uchar *data, size_t data_len) +static void bchunk_list_append_data_n(const BArrayInfo *info, + BArrayMemory *bs_mem, + BChunkList *chunk_list, + const uchar *data, + size_t data_len) { - size_t data_trim_len, data_last_chunk_len; - bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len); - - if (data_trim_len != 0) { - size_t i_prev; - - { - const size_t i = info->chunk_byte_size; - bchunk_list_append_data(info, bs_mem, chunk_list, data, i); - i_prev = i; - } - - while (i_prev != data_trim_len) { - const size_t i = i_prev + info->chunk_byte_size; - BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev); - bchunk_list_append_only(bs_mem, chunk_list, chunk); - i_prev = i; - } - - if (data_last_chunk_len) { - BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len); - bchunk_list_append_only(bs_mem, chunk_list, chunk); - // i_prev = data_len; /* UNUSED */ - } - } - else { - /* if we didn't write any chunks previously, - * we may need to merge with the last. */ - if (data_last_chunk_len) { - bchunk_list_append_data(info, bs_mem, chunk_list, data, data_last_chunk_len); - // i_prev = data_len; /* UNUSED */ - } - } + size_t data_trim_len, data_last_chunk_len; + bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len); + + if (data_trim_len != 0) { + size_t i_prev; + + { + const size_t i = info->chunk_byte_size; + bchunk_list_append_data(info, bs_mem, chunk_list, data, i); + i_prev = i; + } + + while (i_prev != data_trim_len) { + const size_t i = i_prev + info->chunk_byte_size; + BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev); + bchunk_list_append_only(bs_mem, chunk_list, chunk); + i_prev = i; + } + + if (data_last_chunk_len) { + BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len); + bchunk_list_append_only(bs_mem, chunk_list, chunk); + // i_prev = data_len; /* UNUSED */ + } + } + else { + /* if we didn't write any chunks previously, + * we may need to merge with the last. */ + if (data_last_chunk_len) { + bchunk_list_append_data(info, bs_mem, chunk_list, data, data_last_chunk_len); + // i_prev = data_len; /* UNUSED */ + } + } #ifdef USE_MERGE_CHUNKS - if (data_len > info->chunk_byte_size) { - BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= info->chunk_byte_size_min); - } + if (data_len > info->chunk_byte_size) { + BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= + info->chunk_byte_size_min); + } #endif } -static void bchunk_list_append( - const BArrayInfo *info, BArrayMemory *bs_mem, - BChunkList *chunk_list, - BChunk *chunk) +static void bchunk_list_append(const BArrayInfo *info, + BArrayMemory *bs_mem, + BChunkList *chunk_list, + BChunk *chunk) { - bchunk_list_append_only(bs_mem, chunk_list, chunk); + bchunk_list_append_only(bs_mem, chunk_list, chunk); #ifdef USE_MERGE_CHUNKS - bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); + bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); #else - UNUSED_VARS(info); + UNUSED_VARS(info); #endif } -static void bchunk_list_fill_from_array( - const BArrayInfo *info, BArrayMemory *bs_mem, - BChunkList *chunk_list, - const uchar *data, - const size_t data_len) +static void bchunk_list_fill_from_array(const BArrayInfo *info, + BArrayMemory *bs_mem, + BChunkList *chunk_list, + const uchar *data, + const size_t data_len) { - BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs)); + BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs)); - size_t data_trim_len, data_last_chunk_len; - bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len); + size_t data_trim_len, data_last_chunk_len; + bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len); - size_t i_prev = 0; - while (i_prev != data_trim_len) { - const size_t i = i_prev + info->chunk_byte_size; - BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev); - bchunk_list_append_only(bs_mem, chunk_list, chunk); - i_prev = i; - } + size_t i_prev = 0; + while (i_prev != data_trim_len) { + const size_t i = i_prev + info->chunk_byte_size; + BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev); + bchunk_list_append_only(bs_mem, chunk_list, chunk); + i_prev = i; + } - if (data_last_chunk_len) { - BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len); - bchunk_list_append_only(bs_mem, chunk_list, chunk); - // i_prev = data_len; - } + if (data_last_chunk_len) { + BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len); + bchunk_list_append_only(bs_mem, chunk_list, chunk); + // i_prev = data_len; + } #ifdef USE_MERGE_CHUNKS - if (data_len > info->chunk_byte_size) { - BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= info->chunk_byte_size_min); - } + if (data_len > info->chunk_byte_size) { + BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= + info->chunk_byte_size_min); + } #endif - /* works but better avoid redundant re-alloc */ + /* works but better avoid redundant re-alloc */ #if 0 -#ifdef USE_MERGE_CHUNKS - bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); -#endif +# ifdef USE_MERGE_CHUNKS + bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list); +# endif #endif - ASSERT_CHUNKLIST_SIZE(chunk_list, data_len); - ASSERT_CHUNKLIST_DATA(chunk_list, data); + ASSERT_CHUNKLIST_SIZE(chunk_list, data_len); + ASSERT_CHUNKLIST_DATA(chunk_list, data); } /** \} */ @@ -755,86 +744,87 @@ static void bchunk_list_fill_from_array( BLI_INLINE uint hash_data_single(const uchar p) { - return ((HASH_INIT << 5) + HASH_INIT) + (unsigned int)(*((signed char *)&p)); + return ((HASH_INIT << 5) + HASH_INIT) + (unsigned int)(*((signed char *)&p)); } /* hash bytes, from BLI_ghashutil_strhash_n */ static uint hash_data(const uchar *key, size_t n) { - const signed char *p; - unsigned int h = HASH_INIT; + const signed char *p; + unsigned int h = HASH_INIT; - for (p = (const signed char *)key; n--; p++) { - h = ((h << 5) + h) + (unsigned int)*p; - } + for (p = (const signed char *)key; n--; p++) { + h = ((h << 5) + h) + (unsigned int)*p; + } - return h; + return h; } #undef HASH_INIT - #ifdef USE_HASH_TABLE_ACCUMULATE -static void hash_array_from_data( - const BArrayInfo *info, const uchar *data_slice, const size_t data_slice_len, - hash_key *hash_array) +static void hash_array_from_data(const BArrayInfo *info, + const uchar *data_slice, + const size_t data_slice_len, + hash_key *hash_array) { - if (info->chunk_stride != 1) { - for (size_t i = 0, i_step = 0; i_step < data_slice_len; i++, i_step += info->chunk_stride) { - hash_array[i] = hash_data(&data_slice[i_step], info->chunk_stride); - } - } - else { - /* fast-path for bytes */ - for (size_t i = 0; i < data_slice_len; i++) { - hash_array[i] = hash_data_single(data_slice[i]); - } - } + if (info->chunk_stride != 1) { + for (size_t i = 0, i_step = 0; i_step < data_slice_len; i++, i_step += info->chunk_stride) { + hash_array[i] = hash_data(&data_slice[i_step], info->chunk_stride); + } + } + else { + /* fast-path for bytes */ + for (size_t i = 0; i < data_slice_len; i++) { + hash_array[i] = hash_data_single(data_slice[i]); + } + } } /* * Similar to hash_array_from_data, * but able to step into the next chunk if we run-out of data. */ -static void hash_array_from_cref( - const BArrayInfo *info, const BChunkRef *cref, const size_t data_len, - hash_key *hash_array) +static void hash_array_from_cref(const BArrayInfo *info, + const BChunkRef *cref, + const size_t data_len, + hash_key *hash_array) { - const size_t hash_array_len = data_len / info->chunk_stride; - size_t i = 0; - do { - size_t i_next = hash_array_len - i; - size_t data_trim_len = i_next * info->chunk_stride; - if (data_trim_len > cref->link->data_len) { - data_trim_len = cref->link->data_len; - i_next = data_trim_len / info->chunk_stride; - } - BLI_assert(data_trim_len <= cref->link->data_len); - hash_array_from_data(info, cref->link->data, data_trim_len, &hash_array[i]); - i += i_next; - cref = cref->next; - } while ((i < hash_array_len) && (cref != NULL)); - - /* If this isn't equal, the caller didn't properly check - * that there was enough data left in all chunks */ - BLI_assert(i == hash_array_len); + const size_t hash_array_len = data_len / info->chunk_stride; + size_t i = 0; + do { + size_t i_next = hash_array_len - i; + size_t data_trim_len = i_next * info->chunk_stride; + if (data_trim_len > cref->link->data_len) { + data_trim_len = cref->link->data_len; + i_next = data_trim_len / info->chunk_stride; + } + BLI_assert(data_trim_len <= cref->link->data_len); + hash_array_from_data(info, cref->link->data, data_trim_len, &hash_array[i]); + i += i_next; + cref = cref->next; + } while ((i < hash_array_len) && (cref != NULL)); + + /* If this isn't equal, the caller didn't properly check + * that there was enough data left in all chunks */ + BLI_assert(i == hash_array_len); } static void hash_accum(hash_key *hash_array, const size_t hash_array_len, size_t iter_steps) { - /* _very_ unlikely, can happen if you select a chunk-size of 1 for example. */ - if (UNLIKELY((iter_steps > hash_array_len))) { - iter_steps = hash_array_len; - } - - const size_t hash_array_search_len = hash_array_len - iter_steps; - while (iter_steps != 0) { - const size_t hash_offset = iter_steps; - for (uint i = 0; i < hash_array_search_len; i++) { - hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1); - } - iter_steps -= 1; - } + /* _very_ unlikely, can happen if you select a chunk-size of 1 for example. */ + if (UNLIKELY((iter_steps > hash_array_len))) { + iter_steps = hash_array_len; + } + + const size_t hash_array_search_len = hash_array_len - iter_steps; + while (iter_steps != 0) { + const size_t hash_offset = iter_steps; + for (uint i = 0; i < hash_array_search_len; i++) { + hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1); + } + iter_steps -= 1; + } } /** @@ -843,162 +833,173 @@ static void hash_accum(hash_key *hash_array, const size_t hash_array_len, size_t */ static void hash_accum_single(hash_key *hash_array, const size_t hash_array_len, size_t iter_steps) { - BLI_assert(iter_steps <= hash_array_len); - if (UNLIKELY(!(iter_steps <= hash_array_len))) { - /* while this shouldn't happen, avoid crashing */ - iter_steps = hash_array_len; - } - /* We can increase this value each step to avoid accumulating quite as much - * while getting the same results as hash_accum */ - size_t iter_steps_sub = iter_steps; - - while (iter_steps != 0) { - const size_t hash_array_search_len = hash_array_len - iter_steps_sub; - const size_t hash_offset = iter_steps; - for (uint i = 0; i < hash_array_search_len; i++) { - hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1); - } - iter_steps -= 1; - iter_steps_sub += iter_steps; - } + BLI_assert(iter_steps <= hash_array_len); + if (UNLIKELY(!(iter_steps <= hash_array_len))) { + /* while this shouldn't happen, avoid crashing */ + iter_steps = hash_array_len; + } + /* We can increase this value each step to avoid accumulating quite as much + * while getting the same results as hash_accum */ + size_t iter_steps_sub = iter_steps; + + while (iter_steps != 0) { + const size_t hash_array_search_len = hash_array_len - iter_steps_sub; + const size_t hash_offset = iter_steps; + for (uint i = 0; i < hash_array_search_len; i++) { + hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1); + } + iter_steps -= 1; + iter_steps_sub += iter_steps; + } } -static hash_key key_from_chunk_ref( - const BArrayInfo *info, const BChunkRef *cref, - /* avoid reallocating each time */ - hash_key *hash_store, const size_t hash_store_len) +static hash_key key_from_chunk_ref(const BArrayInfo *info, + const BChunkRef *cref, + /* avoid reallocating each time */ + hash_key *hash_store, + const size_t hash_store_len) { - /* in C, will fill in a reusable array */ - BChunk *chunk = cref->link; - BLI_assert((info->accum_read_ahead_bytes * info->chunk_stride) != 0); - - if (info->accum_read_ahead_bytes <= chunk->data_len) { - hash_key key; - -#ifdef USE_HASH_TABLE_KEY_CACHE - key = chunk->key; - if (key != HASH_TABLE_KEY_UNSET) { - /* Using key cache! - * avoids calculating every time */ - } - else { - hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); - hash_accum_single(hash_store, hash_store_len, info->accum_steps); - key = hash_store[0]; - - /* cache the key */ - if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) { - key = HASH_TABLE_KEY_FALLBACK; - } - chunk->key = key; - } -#else - hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); - hash_accum_single(hash_store, hash_store_len, info->accum_steps); - key = hash_store[0]; -#endif - return key; - } - else { - /* corner case - we're too small, calculate the key each time. */ - - hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); - hash_accum_single(hash_store, hash_store_len, info->accum_steps); - hash_key key = hash_store[0]; - -#ifdef USE_HASH_TABLE_KEY_CACHE - if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) { - key = HASH_TABLE_KEY_FALLBACK; - } -#endif - return key; - } + /* in C, will fill in a reusable array */ + BChunk *chunk = cref->link; + BLI_assert((info->accum_read_ahead_bytes * info->chunk_stride) != 0); + + if (info->accum_read_ahead_bytes <= chunk->data_len) { + hash_key key; + +# ifdef USE_HASH_TABLE_KEY_CACHE + key = chunk->key; + if (key != HASH_TABLE_KEY_UNSET) { + /* Using key cache! + * avoids calculating every time */ + } + else { + hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); + hash_accum_single(hash_store, hash_store_len, info->accum_steps); + key = hash_store[0]; + + /* cache the key */ + if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) { + key = HASH_TABLE_KEY_FALLBACK; + } + chunk->key = key; + } +# else + hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); + hash_accum_single(hash_store, hash_store_len, info->accum_steps); + key = hash_store[0]; +# endif + return key; + } + else { + /* corner case - we're too small, calculate the key each time. */ + + hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store); + hash_accum_single(hash_store, hash_store_len, info->accum_steps); + hash_key key = hash_store[0]; + +# ifdef USE_HASH_TABLE_KEY_CACHE + if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) { + key = HASH_TABLE_KEY_FALLBACK; + } +# endif + return key; + } } -static const BChunkRef *table_lookup( - const BArrayInfo *info, BTableRef **table, const size_t table_len, const size_t i_table_start, - const uchar *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array) +static const BChunkRef *table_lookup(const BArrayInfo *info, + BTableRef **table, + const size_t table_len, + const size_t i_table_start, + const uchar *data, + const size_t data_len, + const size_t offset, + const hash_key *table_hash_array) { - size_t size_left = data_len - offset; - hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)]; - size_t key_index = (size_t)(key % (hash_key)table_len); - for (const BTableRef *tref = table[key_index]; tref; tref = tref->next) { - const BChunkRef *cref = tref->cref; -#ifdef USE_HASH_TABLE_KEY_CACHE - if (cref->link->key == key) -#endif - { - BChunk *chunk_test = cref->link; - if (chunk_test->data_len <= size_left) { - if (bchunk_data_compare(chunk_test, data, data_len, offset)) { - /* we could remove the chunk from the table, to avoid multiple hits */ - return cref; - } - } - } - } - return NULL; + size_t size_left = data_len - offset; + hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)]; + size_t key_index = (size_t)(key % (hash_key)table_len); + for (const BTableRef *tref = table[key_index]; tref; tref = tref->next) { + const BChunkRef *cref = tref->cref; +# ifdef USE_HASH_TABLE_KEY_CACHE + if (cref->link->key == key) +# endif + { + BChunk *chunk_test = cref->link; + if (chunk_test->data_len <= size_left) { + if (bchunk_data_compare(chunk_test, data, data_len, offset)) { + /* we could remove the chunk from the table, to avoid multiple hits */ + return cref; + } + } + } + } + return NULL; } -#else /* USE_HASH_TABLE_ACCUMULATE */ +#else /* USE_HASH_TABLE_ACCUMULATE */ /* NON USE_HASH_TABLE_ACCUMULATE code (simply hash each chunk) */ static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref) { - const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; - hash_key key; - BChunk *chunk = cref->link; - -#ifdef USE_HASH_TABLE_KEY_CACHE - key = chunk->key; - if (key != HASH_TABLE_KEY_UNSET) { - /* Using key cache! - * avoids calculating every time */ - } - else { - /* cache the key */ - key = hash_data(chunk->data, data_hash_len); - if (key == HASH_TABLE_KEY_UNSET) { - key = HASH_TABLE_KEY_FALLBACK; - } - chunk->key = key; - } -#else - key = hash_data(chunk->data, data_hash_len); -#endif + const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; + hash_key key; + BChunk *chunk = cref->link; + +# ifdef USE_HASH_TABLE_KEY_CACHE + key = chunk->key; + if (key != HASH_TABLE_KEY_UNSET) { + /* Using key cache! + * avoids calculating every time */ + } + else { + /* cache the key */ + key = hash_data(chunk->data, data_hash_len); + if (key == HASH_TABLE_KEY_UNSET) { + key = HASH_TABLE_KEY_FALLBACK; + } + chunk->key = key; + } +# else + key = hash_data(chunk->data, data_hash_len); +# endif - return key; + return key; } -static const BChunkRef *table_lookup( - const BArrayInfo *info, BTableRef **table, const size_t table_len, const uint UNUSED(i_table_start), - const uchar *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array)) +static const BChunkRef *table_lookup(const BArrayInfo *info, + BTableRef **table, + const size_t table_len, + const uint UNUSED(i_table_start), + const uchar *data, + const size_t data_len, + const size_t offset, + const hash_key *UNUSED(table_hash_array)) { - const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */ - - size_t size_left = data_len - offset; - hash_key key = hash_data(&data[offset], MIN2(data_hash_len, size_left)); - size_t key_index = (size_t)(key % (hash_key)table_len); - for (BTableRef *tref = table[key_index]; tref; tref = tref->next) { - const BChunkRef *cref = tref->cref; -#ifdef USE_HASH_TABLE_KEY_CACHE - if (cref->link->key == key) -#endif - { - BChunk *chunk_test = cref->link; - if (chunk_test->data_len <= size_left) { - if (bchunk_data_compare(chunk_test, data, data_len, offset)) { - /* we could remove the chunk from the table, to avoid multiple hits */ - return cref; - } - } - } - } - return NULL; + const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */ + + size_t size_left = data_len - offset; + hash_key key = hash_data(&data[offset], MIN2(data_hash_len, size_left)); + size_t key_index = (size_t)(key % (hash_key)table_len); + for (BTableRef *tref = table[key_index]; tref; tref = tref->next) { + const BChunkRef *cref = tref->cref; +# ifdef USE_HASH_TABLE_KEY_CACHE + if (cref->link->key == key) +# endif + { + BChunk *chunk_test = cref->link; + if (chunk_test->data_len <= size_left) { + if (bchunk_data_compare(chunk_test, data, data_len, offset)) { + /* we could remove the chunk from the table, to avoid multiple hits */ + return cref; + } + } + } + } + return NULL; } -#endif /* USE_HASH_TABLE_ACCUMULATE */ +#endif /* USE_HASH_TABLE_ACCUMULATE */ /* End Table Lookup * ---------------- */ @@ -1015,389 +1016,386 @@ static const BChunkRef *table_lookup( * \param chunk_list_reference: Reuse this list or chunks within it, don't modify its content. * \note Caller is responsible for adding the user. */ -static BChunkList *bchunk_list_from_data_merge( - const BArrayInfo *info, BArrayMemory *bs_mem, - const uchar *data, const size_t data_len_original, - const BChunkList *chunk_list_reference) +static BChunkList *bchunk_list_from_data_merge(const BArrayInfo *info, + BArrayMemory *bs_mem, + const uchar *data, + const size_t data_len_original, + const BChunkList *chunk_list_reference) { - ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size); + ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size); - /* ----------------------------------------------------------------------- - * Fast-Path for exact match - * Check for exact match, if so, return the current list. - */ + /* ----------------------------------------------------------------------- + * Fast-Path for exact match + * Check for exact match, if so, return the current list. + */ - const BChunkRef *cref_match_first = NULL; + const BChunkRef *cref_match_first = NULL; - uint chunk_list_reference_skip_len = 0; - size_t chunk_list_reference_skip_bytes = 0; - size_t i_prev = 0; + uint chunk_list_reference_skip_len = 0; + size_t chunk_list_reference_skip_bytes = 0; + size_t i_prev = 0; #ifdef USE_FASTPATH_CHUNKS_FIRST - { - bool full_match = true; - - const BChunkRef *cref = chunk_list_reference->chunk_refs.first; - while (i_prev < data_len_original) { - if (cref != NULL && bchunk_data_compare(cref->link, data, data_len_original, i_prev)) { - cref_match_first = cref; - chunk_list_reference_skip_len += 1; - chunk_list_reference_skip_bytes += cref->link->data_len; - i_prev += cref->link->data_len; - cref = cref->next; - } - else { - full_match = false; - break; - } - } - - if (full_match) { - if (chunk_list_reference->total_size == data_len_original) { - return (BChunkList *)chunk_list_reference; - } - } - } - - /* End Fast-Path (first) - * --------------------- */ - -#endif /* USE_FASTPATH_CHUNKS_FIRST */ - - /* Copy until we have a mismatch */ - BChunkList *chunk_list = bchunk_list_new(bs_mem, data_len_original); - if (cref_match_first != NULL) { - size_t chunk_size_step = 0; - const BChunkRef *cref = chunk_list_reference->chunk_refs.first; - while (true) { - BChunk *chunk = cref->link; - chunk_size_step += chunk->data_len; - bchunk_list_append_only(bs_mem, chunk_list, chunk); - ASSERT_CHUNKLIST_SIZE(chunk_list, chunk_size_step); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - if (cref == cref_match_first) { - break; - } - else { - cref = cref->next; - } - } - /* happens when bytes are removed from the end of the array */ - if (chunk_size_step == data_len_original) { - return chunk_list; - } - - i_prev = chunk_size_step; - } - else { - i_prev = 0; - } - - /* ------------------------------------------------------------------------ - * Fast-Path for end chunks - * - * Check for trailing chunks - */ - - /* In this case use 'chunk_list_reference_last' to define the last index - * index_match_last = -1 */ - - /* warning, from now on don't use len(data) - * since we want to ignore chunks already matched */ - size_t data_len = data_len_original; + { + bool full_match = true; + + const BChunkRef *cref = chunk_list_reference->chunk_refs.first; + while (i_prev < data_len_original) { + if (cref != NULL && bchunk_data_compare(cref->link, data, data_len_original, i_prev)) { + cref_match_first = cref; + chunk_list_reference_skip_len += 1; + chunk_list_reference_skip_bytes += cref->link->data_len; + i_prev += cref->link->data_len; + cref = cref->next; + } + else { + full_match = false; + break; + } + } + + if (full_match) { + if (chunk_list_reference->total_size == data_len_original) { + return (BChunkList *)chunk_list_reference; + } + } + } + + /* End Fast-Path (first) + * --------------------- */ + +#endif /* USE_FASTPATH_CHUNKS_FIRST */ + + /* Copy until we have a mismatch */ + BChunkList *chunk_list = bchunk_list_new(bs_mem, data_len_original); + if (cref_match_first != NULL) { + size_t chunk_size_step = 0; + const BChunkRef *cref = chunk_list_reference->chunk_refs.first; + while (true) { + BChunk *chunk = cref->link; + chunk_size_step += chunk->data_len; + bchunk_list_append_only(bs_mem, chunk_list, chunk); + ASSERT_CHUNKLIST_SIZE(chunk_list, chunk_size_step); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + if (cref == cref_match_first) { + break; + } + else { + cref = cref->next; + } + } + /* happens when bytes are removed from the end of the array */ + if (chunk_size_step == data_len_original) { + return chunk_list; + } + + i_prev = chunk_size_step; + } + else { + i_prev = 0; + } + + /* ------------------------------------------------------------------------ + * Fast-Path for end chunks + * + * Check for trailing chunks + */ + + /* In this case use 'chunk_list_reference_last' to define the last index + * index_match_last = -1 */ + + /* warning, from now on don't use len(data) + * since we want to ignore chunks already matched */ + size_t data_len = data_len_original; #define data_len_original invalid_usage -#ifdef data_len_original /* quiet warning */ +#ifdef data_len_original /* quiet warning */ #endif - const BChunkRef *chunk_list_reference_last = NULL; + const BChunkRef *chunk_list_reference_last = NULL; #ifdef USE_FASTPATH_CHUNKS_LAST - if (!BLI_listbase_is_empty(&chunk_list_reference->chunk_refs)) { - const BChunkRef *cref = chunk_list_reference->chunk_refs.last; - while ((cref->prev != NULL) && - (cref != cref_match_first) && - (cref->link->data_len <= data_len - i_prev)) - { - BChunk *chunk_test = cref->link; - size_t offset = data_len - chunk_test->data_len; - if (bchunk_data_compare(chunk_test, data, data_len, offset)) { - data_len = offset; - chunk_list_reference_last = cref; - chunk_list_reference_skip_len += 1; - chunk_list_reference_skip_bytes += cref->link->data_len; - cref = cref->prev; - } - else { - break; - } - } - } - - /* End Fast-Path (last) - * -------------------- */ -#endif /* USE_FASTPATH_CHUNKS_LAST */ - - /* ----------------------------------------------------------------------- - * Check for aligned chunks - * - * This saves a lot of searching, so use simple heuristics to detect aligned arrays. - * (may need to tweak exact method). - */ - - bool use_aligned = false; + if (!BLI_listbase_is_empty(&chunk_list_reference->chunk_refs)) { + const BChunkRef *cref = chunk_list_reference->chunk_refs.last; + while ((cref->prev != NULL) && (cref != cref_match_first) && + (cref->link->data_len <= data_len - i_prev)) { + BChunk *chunk_test = cref->link; + size_t offset = data_len - chunk_test->data_len; + if (bchunk_data_compare(chunk_test, data, data_len, offset)) { + data_len = offset; + chunk_list_reference_last = cref; + chunk_list_reference_skip_len += 1; + chunk_list_reference_skip_bytes += cref->link->data_len; + cref = cref->prev; + } + else { + break; + } + } + } + + /* End Fast-Path (last) + * -------------------- */ +#endif /* USE_FASTPATH_CHUNKS_LAST */ + + /* ----------------------------------------------------------------------- + * Check for aligned chunks + * + * This saves a lot of searching, so use simple heuristics to detect aligned arrays. + * (may need to tweak exact method). + */ + + bool use_aligned = false; #ifdef USE_ALIGN_CHUNKS_TEST - if (chunk_list->total_size == chunk_list_reference->total_size) { - /* if we're already a quarter aligned */ - if (data_len - i_prev <= chunk_list->total_size / 4) { - use_aligned = true; - } - else { - /* TODO, walk over chunks and check if some arbitrary amount align */ - } - } -#endif /* USE_ALIGN_CHUNKS_TEST */ - - /* End Aligned Chunk Case - * ----------------------- */ - - if (use_aligned) { - /* Copy matching chunks, creates using the same 'layout' as the reference */ - const BChunkRef *cref = cref_match_first ? cref_match_first->next : chunk_list_reference->chunk_refs.first; - while (i_prev != data_len) { - const size_t i = i_prev + cref->link->data_len; - BLI_assert(i != i_prev); - - if ((cref != chunk_list_reference_last) && - bchunk_data_compare(cref->link, data, data_len, i_prev)) - { - bchunk_list_append(info, bs_mem, chunk_list, cref->link); - ASSERT_CHUNKLIST_SIZE(chunk_list, i); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - } - else { - bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev); - ASSERT_CHUNKLIST_SIZE(chunk_list, i); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - } - - cref = cref->next; - - i_prev = i; - } - } - else if ((data_len - i_prev >= info->chunk_byte_size) && - (chunk_list_reference->chunk_refs_len >= chunk_list_reference_skip_len) && - (chunk_list_reference->chunk_refs.first != NULL)) - { - - /* -------------------------------------------------------------------- - * Non-Aligned Chunk De-Duplication */ - - /* only create a table if we have at least one chunk to search - * otherwise just make a new one. - * - * Support re-arranged chunks */ + if (chunk_list->total_size == chunk_list_reference->total_size) { + /* if we're already a quarter aligned */ + if (data_len - i_prev <= chunk_list->total_size / 4) { + use_aligned = true; + } + else { + /* TODO, walk over chunks and check if some arbitrary amount align */ + } + } +#endif /* USE_ALIGN_CHUNKS_TEST */ + + /* End Aligned Chunk Case + * ----------------------- */ + + if (use_aligned) { + /* Copy matching chunks, creates using the same 'layout' as the reference */ + const BChunkRef *cref = cref_match_first ? cref_match_first->next : + chunk_list_reference->chunk_refs.first; + while (i_prev != data_len) { + const size_t i = i_prev + cref->link->data_len; + BLI_assert(i != i_prev); + + if ((cref != chunk_list_reference_last) && + bchunk_data_compare(cref->link, data, data_len, i_prev)) { + bchunk_list_append(info, bs_mem, chunk_list, cref->link); + ASSERT_CHUNKLIST_SIZE(chunk_list, i); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + } + else { + bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev); + ASSERT_CHUNKLIST_SIZE(chunk_list, i); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + } + + cref = cref->next; + + i_prev = i; + } + } + else if ((data_len - i_prev >= info->chunk_byte_size) && + (chunk_list_reference->chunk_refs_len >= chunk_list_reference_skip_len) && + (chunk_list_reference->chunk_refs.first != NULL)) { + + /* -------------------------------------------------------------------- + * Non-Aligned Chunk De-Duplication */ + + /* only create a table if we have at least one chunk to search + * otherwise just make a new one. + * + * Support re-arranged chunks */ #ifdef USE_HASH_TABLE_ACCUMULATE - size_t i_table_start = i_prev; - const size_t table_hash_array_len = (data_len - i_prev) / info->chunk_stride; - hash_key *table_hash_array = MEM_mallocN(sizeof(*table_hash_array) * table_hash_array_len, __func__); - hash_array_from_data(info, &data[i_prev], data_len - i_prev, table_hash_array); + size_t i_table_start = i_prev; + const size_t table_hash_array_len = (data_len - i_prev) / info->chunk_stride; + hash_key *table_hash_array = MEM_mallocN(sizeof(*table_hash_array) * table_hash_array_len, + __func__); + hash_array_from_data(info, &data[i_prev], data_len - i_prev, table_hash_array); - hash_accum(table_hash_array, table_hash_array_len, info->accum_steps); + hash_accum(table_hash_array, table_hash_array_len, info->accum_steps); #else - /* dummy vars */ - uint i_table_start = 0; - hash_key *table_hash_array = NULL; + /* dummy vars */ + uint i_table_start = 0; + hash_key *table_hash_array = NULL; #endif - const uint chunk_list_reference_remaining_len = - (chunk_list_reference->chunk_refs_len - chunk_list_reference_skip_len) + 1; - BTableRef *table_ref_stack = MEM_mallocN(chunk_list_reference_remaining_len * sizeof(BTableRef), __func__); - uint table_ref_stack_n = 0; + const uint chunk_list_reference_remaining_len = (chunk_list_reference->chunk_refs_len - + chunk_list_reference_skip_len) + + 1; + BTableRef *table_ref_stack = MEM_mallocN( + chunk_list_reference_remaining_len * sizeof(BTableRef), __func__); + uint table_ref_stack_n = 0; - const size_t table_len = chunk_list_reference_remaining_len * BCHUNK_HASH_TABLE_MUL; - BTableRef **table = MEM_callocN(table_len * sizeof(*table), __func__); + const size_t table_len = chunk_list_reference_remaining_len * BCHUNK_HASH_TABLE_MUL; + BTableRef **table = MEM_callocN(table_len * sizeof(*table), __func__); - /* table_make - inline - * include one matching chunk, to allow for repeating values */ - { + /* table_make - inline + * include one matching chunk, to allow for repeating values */ + { #ifdef USE_HASH_TABLE_ACCUMULATE - const size_t hash_store_len = info->accum_read_ahead_len; - hash_key *hash_store = MEM_mallocN(sizeof(hash_key) * hash_store_len, __func__); + const size_t hash_store_len = info->accum_read_ahead_len; + hash_key *hash_store = MEM_mallocN(sizeof(hash_key) * hash_store_len, __func__); #endif - const BChunkRef *cref; - size_t chunk_list_reference_bytes_remaining = - chunk_list_reference->total_size - chunk_list_reference_skip_bytes; + const BChunkRef *cref; + size_t chunk_list_reference_bytes_remaining = chunk_list_reference->total_size - + chunk_list_reference_skip_bytes; - if (cref_match_first) { - cref = cref_match_first; - chunk_list_reference_bytes_remaining += cref->link->data_len; - } - else { - cref = chunk_list_reference->chunk_refs.first; - } + if (cref_match_first) { + cref = cref_match_first; + chunk_list_reference_bytes_remaining += cref->link->data_len; + } + else { + cref = chunk_list_reference->chunk_refs.first; + } #ifdef USE_PARANOID_CHECKS - { - size_t test_bytes_len = 0; - const BChunkRef *cr = cref; - while (cr != chunk_list_reference_last) { - test_bytes_len += cr->link->data_len; - cr = cr->next; - } - BLI_assert(test_bytes_len == chunk_list_reference_bytes_remaining); - } + { + size_t test_bytes_len = 0; + const BChunkRef *cr = cref; + while (cr != chunk_list_reference_last) { + test_bytes_len += cr->link->data_len; + cr = cr->next; + } + BLI_assert(test_bytes_len == chunk_list_reference_bytes_remaining); + } #endif - while ((cref != chunk_list_reference_last) && - (chunk_list_reference_bytes_remaining >= info->accum_read_ahead_bytes)) - { - hash_key key = key_from_chunk_ref(info, cref + while ((cref != chunk_list_reference_last) && + (chunk_list_reference_bytes_remaining >= info->accum_read_ahead_bytes)) { + hash_key key = key_from_chunk_ref(info, + cref #ifdef USE_HASH_TABLE_ACCUMULATE - , hash_store, hash_store_len + , + hash_store, + hash_store_len #endif - ); - size_t key_index = (size_t)(key % (hash_key)table_len); - BTableRef *tref_prev = table[key_index]; - BLI_assert(table_ref_stack_n < chunk_list_reference_remaining_len); - BTableRef *tref = &table_ref_stack[table_ref_stack_n++]; - tref->cref = cref; - tref->next = tref_prev; - table[key_index] = tref; + ); + size_t key_index = (size_t)(key % (hash_key)table_len); + BTableRef *tref_prev = table[key_index]; + BLI_assert(table_ref_stack_n < chunk_list_reference_remaining_len); + BTableRef *tref = &table_ref_stack[table_ref_stack_n++]; + tref->cref = cref; + tref->next = tref_prev; + table[key_index] = tref; - chunk_list_reference_bytes_remaining -= cref->link->data_len; - cref = cref->next; - } + chunk_list_reference_bytes_remaining -= cref->link->data_len; + cref = cref->next; + } - BLI_assert(table_ref_stack_n <= chunk_list_reference_remaining_len); + BLI_assert(table_ref_stack_n <= chunk_list_reference_remaining_len); #ifdef USE_HASH_TABLE_ACCUMULATE - MEM_freeN(hash_store); + MEM_freeN(hash_store); #endif - } - /* done making the table */ - - BLI_assert(i_prev <= data_len); - for (size_t i = i_prev; i < data_len; ) { - /* Assumes exiting chunk isnt a match! */ - - const BChunkRef *cref_found = table_lookup( - info, - table, table_len, i_table_start, - data, data_len, i, table_hash_array); - if (cref_found != NULL) { - BLI_assert(i < data_len); - if (i != i_prev) { - bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], i - i_prev); - i_prev = i; - } - - /* now add the reference chunk */ - { - BChunk *chunk_found = cref_found->link; - i += chunk_found->data_len; - bchunk_list_append(info, bs_mem, chunk_list, chunk_found); - } - i_prev = i; - BLI_assert(i_prev <= data_len); - ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - - /* its likely that the next chunk in the list will be a match, so check it! */ - while ((cref_found->next != NULL) && - (cref_found->next != chunk_list_reference_last)) - { - cref_found = cref_found->next; - BChunk *chunk_found = cref_found->link; - - if (bchunk_data_compare(chunk_found, data, data_len, i_prev)) { - /* may be useful to remove table data, assuming we dont have - * repeating memory where it would be useful to re-use chunks. */ - i += chunk_found->data_len; - bchunk_list_append(info, bs_mem, chunk_list, chunk_found); - /* chunk_found may be freed! */ - i_prev = i; - BLI_assert(i_prev <= data_len); - ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - } - else { - break; - } - } - } - else { - i = i + info->chunk_stride; - } - } + } + /* done making the table */ + + BLI_assert(i_prev <= data_len); + for (size_t i = i_prev; i < data_len;) { + /* Assumes exiting chunk isnt a match! */ + + const BChunkRef *cref_found = table_lookup( + info, table, table_len, i_table_start, data, data_len, i, table_hash_array); + if (cref_found != NULL) { + BLI_assert(i < data_len); + if (i != i_prev) { + bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], i - i_prev); + i_prev = i; + } + + /* now add the reference chunk */ + { + BChunk *chunk_found = cref_found->link; + i += chunk_found->data_len; + bchunk_list_append(info, bs_mem, chunk_list, chunk_found); + } + i_prev = i; + BLI_assert(i_prev <= data_len); + ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + + /* its likely that the next chunk in the list will be a match, so check it! */ + while ((cref_found->next != NULL) && (cref_found->next != chunk_list_reference_last)) { + cref_found = cref_found->next; + BChunk *chunk_found = cref_found->link; + + if (bchunk_data_compare(chunk_found, data, data_len, i_prev)) { + /* may be useful to remove table data, assuming we dont have + * repeating memory where it would be useful to re-use chunks. */ + i += chunk_found->data_len; + bchunk_list_append(info, bs_mem, chunk_list, chunk_found); + /* chunk_found may be freed! */ + i_prev = i; + BLI_assert(i_prev <= data_len); + ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + } + else { + break; + } + } + } + else { + i = i + info->chunk_stride; + } + } #ifdef USE_HASH_TABLE_ACCUMULATE - MEM_freeN(table_hash_array); + MEM_freeN(table_hash_array); #endif - MEM_freeN(table); - MEM_freeN(table_ref_stack); + MEM_freeN(table); + MEM_freeN(table_ref_stack); - /* End Table Lookup - * ---------------- */ - } + /* End Table Lookup + * ---------------- */ + } - ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); - ASSERT_CHUNKLIST_DATA(chunk_list, data); + ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev); + ASSERT_CHUNKLIST_DATA(chunk_list, data); - /* ----------------------------------------------------------------------- - * No Duplicates to copy, write new chunks - * - * Trailing chunks, no matches found in table lookup above. - * Write all new data. */ - if (i_prev != data_len) { - bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], data_len - i_prev); - i_prev = data_len; - } + /* ----------------------------------------------------------------------- + * No Duplicates to copy, write new chunks + * + * Trailing chunks, no matches found in table lookup above. + * Write all new data. */ + if (i_prev != data_len) { + bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], data_len - i_prev); + i_prev = data_len; + } - BLI_assert(i_prev == data_len); + BLI_assert(i_prev == data_len); #ifdef USE_FASTPATH_CHUNKS_LAST - if (chunk_list_reference_last != NULL) { - /* write chunk_list_reference_last since it hasn't been written yet */ - const BChunkRef *cref = chunk_list_reference_last; - while (cref != NULL) { - BChunk *chunk = cref->link; - // BLI_assert(bchunk_data_compare(chunk, data, data_len, i_prev)); - i_prev += chunk->data_len; - /* use simple since we assume the references chunks - * have already been sized correctly. */ - bchunk_list_append_only(bs_mem, chunk_list, chunk); - ASSERT_CHUNKLIST_DATA(chunk_list, data); - cref = cref->next; - } - } + if (chunk_list_reference_last != NULL) { + /* write chunk_list_reference_last since it hasn't been written yet */ + const BChunkRef *cref = chunk_list_reference_last; + while (cref != NULL) { + BChunk *chunk = cref->link; + // BLI_assert(bchunk_data_compare(chunk, data, data_len, i_prev)); + i_prev += chunk->data_len; + /* use simple since we assume the references chunks + * have already been sized correctly. */ + bchunk_list_append_only(bs_mem, chunk_list, chunk); + ASSERT_CHUNKLIST_DATA(chunk_list, data); + cref = cref->next; + } + } #endif #undef data_len_original - BLI_assert(i_prev == data_len_original); + BLI_assert(i_prev == data_len_original); - /* check we're the correct size and that we didn't accidentally modify the reference */ - ASSERT_CHUNKLIST_SIZE(chunk_list, data_len_original); - ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size); + /* check we're the correct size and that we didn't accidentally modify the reference */ + ASSERT_CHUNKLIST_SIZE(chunk_list, data_len_original); + ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size); - ASSERT_CHUNKLIST_DATA(chunk_list, data); + ASSERT_CHUNKLIST_DATA(chunk_list, data); - return chunk_list; + return chunk_list; } /* end private API */ /** \} */ - /** \name Main Array Storage API * \{ */ - /** * Create a new array store, which can store any number of arrays * as long as their stride matches. @@ -1417,88 +1415,85 @@ static BChunkList *bchunk_list_from_data_merge( * * \return A new array store, to be freed with #BLI_array_store_destroy. */ -BArrayStore *BLI_array_store_create( - uint stride, - uint chunk_count) +BArrayStore *BLI_array_store_create(uint stride, uint chunk_count) { - BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__); + BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__); - bs->info.chunk_stride = stride; - // bs->info.chunk_count = chunk_count; + bs->info.chunk_stride = stride; + // bs->info.chunk_count = chunk_count; - bs->info.chunk_byte_size = chunk_count * stride; + bs->info.chunk_byte_size = chunk_count * stride; #ifdef USE_MERGE_CHUNKS - bs->info.chunk_byte_size_min = MAX2(1u, chunk_count / BCHUNK_SIZE_MIN_DIV) * stride; - bs->info.chunk_byte_size_max = (chunk_count * BCHUNK_SIZE_MAX_MUL) * stride; + bs->info.chunk_byte_size_min = MAX2(1u, chunk_count / BCHUNK_SIZE_MIN_DIV) * stride; + bs->info.chunk_byte_size_max = (chunk_count * BCHUNK_SIZE_MAX_MUL) * stride; #endif #ifdef USE_HASH_TABLE_ACCUMULATE - bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS - 1; - /* Triangle number, identifying now much read-ahead we need: - * https://en.wikipedia.org/wiki/Triangular_number (+ 1) */ - bs->info.accum_read_ahead_len = (uint)((((bs->info.accum_steps * (bs->info.accum_steps + 1))) / 2) + 1); - bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride; + bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS - 1; + /* Triangle number, identifying now much read-ahead we need: + * https://en.wikipedia.org/wiki/Triangular_number (+ 1) */ + bs->info.accum_read_ahead_len = (uint)( + (((bs->info.accum_steps * (bs->info.accum_steps + 1))) / 2) + 1); + bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride; #else - bs->info.accum_read_ahead_bytes = BCHUNK_HASH_LEN * stride; + bs->info.accum_read_ahead_bytes = BCHUNK_HASH_LEN * stride; #endif - bs->memory.chunk_list = BLI_mempool_create(sizeof(BChunkList), 0, 512, BLI_MEMPOOL_NOP); - bs->memory.chunk_ref = BLI_mempool_create(sizeof(BChunkRef), 0, 512, BLI_MEMPOOL_NOP); - /* allow iteration to simplify freeing, otherwise its not needed - * (we could loop over all states as an alternative). */ - bs->memory.chunk = BLI_mempool_create(sizeof(BChunk), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + bs->memory.chunk_list = BLI_mempool_create(sizeof(BChunkList), 0, 512, BLI_MEMPOOL_NOP); + bs->memory.chunk_ref = BLI_mempool_create(sizeof(BChunkRef), 0, 512, BLI_MEMPOOL_NOP); + /* allow iteration to simplify freeing, otherwise its not needed + * (we could loop over all states as an alternative). */ + bs->memory.chunk = BLI_mempool_create(sizeof(BChunk), 0, 512, BLI_MEMPOOL_ALLOW_ITER); - return bs; + return bs; } static void array_store_free_data(BArrayStore *bs) { - /* free chunk data */ - { - BLI_mempool_iter iter; - BChunk *chunk; - BLI_mempool_iternew(bs->memory.chunk, &iter); - while ((chunk = BLI_mempool_iterstep(&iter))) { - BLI_assert(chunk->users > 0); - MEM_freeN((void *)chunk->data); - } - } - - /* free states */ - for (BArrayState *state = bs->states.first, *state_next; state; state = state_next) { - state_next = state->next; - MEM_freeN(state); - } + /* free chunk data */ + { + BLI_mempool_iter iter; + BChunk *chunk; + BLI_mempool_iternew(bs->memory.chunk, &iter); + while ((chunk = BLI_mempool_iterstep(&iter))) { + BLI_assert(chunk->users > 0); + MEM_freeN((void *)chunk->data); + } + } + + /* free states */ + for (BArrayState *state = bs->states.first, *state_next; state; state = state_next) { + state_next = state->next; + MEM_freeN(state); + } } /** * Free the #BArrayStore, including all states and chunks. */ -void BLI_array_store_destroy( - BArrayStore *bs) +void BLI_array_store_destroy(BArrayStore *bs) { - array_store_free_data(bs); + array_store_free_data(bs); - BLI_mempool_destroy(bs->memory.chunk_list); - BLI_mempool_destroy(bs->memory.chunk_ref); - BLI_mempool_destroy(bs->memory.chunk); + BLI_mempool_destroy(bs->memory.chunk_list); + BLI_mempool_destroy(bs->memory.chunk_ref); + BLI_mempool_destroy(bs->memory.chunk); - MEM_freeN(bs); + MEM_freeN(bs); } /** * Clear all contents, allowing reuse of \a bs. */ -void BLI_array_store_clear( - BArrayStore *bs) +void BLI_array_store_clear(BArrayStore *bs) { - array_store_free_data(bs); + array_store_free_data(bs); - BLI_listbase_clear(&bs->states); + BLI_listbase_clear(&bs->states); - BLI_mempool_clear(bs->memory.chunk_list); - BLI_mempool_clear(bs->memory.chunk_ref); - BLI_mempool_clear(bs->memory.chunk); + BLI_mempool_clear(bs->memory.chunk_list); + BLI_mempool_clear(bs->memory.chunk_ref); + BLI_mempool_clear(bs->memory.chunk); } /** \} */ @@ -1509,37 +1504,34 @@ void BLI_array_store_clear( /** * \return the total amount of memory that would be used by getting the arrays for all states. */ -size_t BLI_array_store_calc_size_expanded_get( - const BArrayStore *bs) +size_t BLI_array_store_calc_size_expanded_get(const BArrayStore *bs) { - size_t size_accum = 0; - for (const BArrayState *state = bs->states.first; state; state = state->next) { - size_accum += state->chunk_list->total_size; - } - return size_accum; + size_t size_accum = 0; + for (const BArrayState *state = bs->states.first; state; state = state->next) { + size_accum += state->chunk_list->total_size; + } + return size_accum; } /** * \return the amount of memory used by all #BChunk.data * (duplicate chunks are only counted once). */ -size_t BLI_array_store_calc_size_compacted_get( - const BArrayStore *bs) +size_t BLI_array_store_calc_size_compacted_get(const BArrayStore *bs) { - size_t size_total = 0; - BLI_mempool_iter iter; - BChunk *chunk; - BLI_mempool_iternew(bs->memory.chunk, &iter); - while ((chunk = BLI_mempool_iterstep(&iter))) { - BLI_assert(chunk->users > 0); - size_total += (size_t)chunk->data_len; - } - return size_total; + size_t size_total = 0; + BLI_mempool_iter iter; + BChunk *chunk; + BLI_mempool_iternew(bs->memory.chunk, &iter); + while ((chunk = BLI_mempool_iterstep(&iter))) { + BLI_assert(chunk->users > 0); + size_total += (size_t)chunk->data_len; + } + return size_total; } /** \} */ - /** \name BArrayState Access * \{ */ @@ -1554,54 +1546,52 @@ size_t BLI_array_store_calc_size_compacted_get( * This may be removed using #BLI_array_store_state_remove, * otherwise it will be removed with #BLI_array_store_destroy. */ -BArrayState *BLI_array_store_state_add( - BArrayStore *bs, - const void *data, const size_t data_len, - const BArrayState *state_reference) +BArrayState *BLI_array_store_state_add(BArrayStore *bs, + const void *data, + const size_t data_len, + const BArrayState *state_reference) { - /* ensure we're aligned to the stride */ - BLI_assert((data_len % bs->info.chunk_stride) == 0); + /* ensure we're aligned to the stride */ + BLI_assert((data_len % bs->info.chunk_stride) == 0); #ifdef USE_PARANOID_CHECKS - if (state_reference) { - BLI_assert(BLI_findindex(&bs->states, state_reference) != -1); - } + if (state_reference) { + BLI_assert(BLI_findindex(&bs->states, state_reference) != -1); + } #endif - BChunkList *chunk_list; - if (state_reference) { - chunk_list = bchunk_list_from_data_merge( - &bs->info, &bs->memory, - (const uchar *)data, data_len, - /* re-use reference chunks */ - state_reference->chunk_list); - } - else { - chunk_list = bchunk_list_new(&bs->memory, data_len); - bchunk_list_fill_from_array( - &bs->info, &bs->memory, - chunk_list, - (const uchar *)data, data_len); - } - - chunk_list->users += 1; - - BArrayState *state = MEM_callocN(sizeof(BArrayState), __func__); - state->chunk_list = chunk_list; - - BLI_addtail(&bs->states, state); + BChunkList *chunk_list; + if (state_reference) { + chunk_list = bchunk_list_from_data_merge(&bs->info, + &bs->memory, + (const uchar *)data, + data_len, + /* re-use reference chunks */ + state_reference->chunk_list); + } + else { + chunk_list = bchunk_list_new(&bs->memory, data_len); + bchunk_list_fill_from_array(&bs->info, &bs->memory, chunk_list, (const uchar *)data, data_len); + } + + chunk_list->users += 1; + + BArrayState *state = MEM_callocN(sizeof(BArrayState), __func__); + state->chunk_list = chunk_list; + + BLI_addtail(&bs->states, state); #ifdef USE_PARANOID_CHECKS - { - size_t data_test_len; - void *data_test = BLI_array_store_state_data_get_alloc(state, &data_test_len); - BLI_assert(data_test_len == data_len); - BLI_assert(memcmp(data_test, data, data_len) == 0); - MEM_freeN(data_test); - } + { + size_t data_test_len; + void *data_test = BLI_array_store_state_data_get_alloc(state, &data_test_len); + BLI_assert(data_test_len == data_len); + BLI_assert(memcmp(data_test, data, data_len) == 0); + MEM_freeN(data_test); + } #endif - return state; + return state; } /** @@ -1609,196 +1599,187 @@ BArrayState *BLI_array_store_state_add( * * The states can be freed in any order. */ -void BLI_array_store_state_remove( - BArrayStore *bs, - BArrayState *state) +void BLI_array_store_state_remove(BArrayStore *bs, BArrayState *state) { #ifdef USE_PARANOID_CHECKS - BLI_assert(BLI_findindex(&bs->states, state) != -1); + BLI_assert(BLI_findindex(&bs->states, state) != -1); #endif - bchunk_list_decref(&bs->memory, state->chunk_list); - BLI_remlink(&bs->states, state); + bchunk_list_decref(&bs->memory, state->chunk_list); + BLI_remlink(&bs->states, state); - MEM_freeN(state); + MEM_freeN(state); } /** * \return the expanded size of the array, * use this to know how much memory to allocate #BLI_array_store_state_data_get's argument. */ -size_t BLI_array_store_state_size_get( - BArrayState *state) +size_t BLI_array_store_state_size_get(BArrayState *state) { - return state->chunk_list->total_size; + return state->chunk_list->total_size; } /** * Fill in existing allocated memory with the contents of \a state. */ -void BLI_array_store_state_data_get( - BArrayState *state, - void *data) +void BLI_array_store_state_data_get(BArrayState *state, void *data) { #ifdef USE_PARANOID_CHECKS - size_t data_test_len = 0; - for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) { - data_test_len += cref->link->data_len; - } - BLI_assert(data_test_len == state->chunk_list->total_size); + size_t data_test_len = 0; + for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) { + data_test_len += cref->link->data_len; + } + BLI_assert(data_test_len == state->chunk_list->total_size); #endif - uchar *data_step = (uchar *)data; - for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) { - BLI_assert(cref->link->users > 0); - memcpy(data_step, cref->link->data, cref->link->data_len); - data_step += cref->link->data_len; - } + uchar *data_step = (uchar *)data; + for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) { + BLI_assert(cref->link->users > 0); + memcpy(data_step, cref->link->data, cref->link->data_len); + data_step += cref->link->data_len; + } } /** * Allocate an array for \a state and return it. */ -void *BLI_array_store_state_data_get_alloc( - BArrayState *state, - size_t *r_data_len) +void *BLI_array_store_state_data_get_alloc(BArrayState *state, size_t *r_data_len) { - void *data = MEM_mallocN(state->chunk_list->total_size, __func__); - BLI_array_store_state_data_get(state, data); - *r_data_len = state->chunk_list->total_size; - return data; + void *data = MEM_mallocN(state->chunk_list->total_size, __func__); + BLI_array_store_state_data_get(state, data); + *r_data_len = state->chunk_list->total_size; + return data; } /** \} */ - /** \name Debugging API (for testing). * \{ */ /* only for test validation */ static size_t bchunk_list_size(const BChunkList *chunk_list) { - size_t total_size = 0; - for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { - total_size += cref->link->data_len; - } - return total_size; + size_t total_size = 0; + for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { + total_size += cref->link->data_len; + } + return total_size; } -bool BLI_array_store_is_valid( - BArrayStore *bs) +bool BLI_array_store_is_valid(BArrayStore *bs) { - bool ok = true; + bool ok = true; - /* Check Length - * ------------ */ + /* Check Length + * ------------ */ - for (BArrayState *state = bs->states.first; state; state = state->next) { - BChunkList *chunk_list = state->chunk_list; - if (!(bchunk_list_size(chunk_list) == chunk_list->total_size)) { - return false; - } + for (BArrayState *state = bs->states.first; state; state = state->next) { + BChunkList *chunk_list = state->chunk_list; + if (!(bchunk_list_size(chunk_list) == chunk_list->total_size)) { + return false; + } - if (BLI_listbase_count(&chunk_list->chunk_refs) != (int)chunk_list->chunk_refs_len) { - return false; - } + if (BLI_listbase_count(&chunk_list->chunk_refs) != (int)chunk_list->chunk_refs_len) { + return false; + } #ifdef USE_MERGE_CHUNKS - /* ensure we merge all chunks that could be merged */ - if (chunk_list->total_size > bs->info.chunk_byte_size_min) { - for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { - if (cref->link->data_len < bs->info.chunk_byte_size_min) { - return false; - } - } - } + /* ensure we merge all chunks that could be merged */ + if (chunk_list->total_size > bs->info.chunk_byte_size_min) { + for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { + if (cref->link->data_len < bs->info.chunk_byte_size_min) { + return false; + } + } + } #endif - } - - { - BLI_mempool_iter iter; - BChunk *chunk; - BLI_mempool_iternew(bs->memory.chunk, &iter); - while ((chunk = BLI_mempool_iterstep(&iter))) { - if (!(MEM_allocN_len(chunk->data) >= chunk->data_len)) { - return false; - } - } - } - - /* Check User Count & Lost References - * ---------------------------------- */ - { - GHashIterator gh_iter; + } + + { + BLI_mempool_iter iter; + BChunk *chunk; + BLI_mempool_iternew(bs->memory.chunk, &iter); + while ((chunk = BLI_mempool_iterstep(&iter))) { + if (!(MEM_allocN_len(chunk->data) >= chunk->data_len)) { + return false; + } + } + } + + /* Check User Count & Lost References + * ---------------------------------- */ + { + GHashIterator gh_iter; #define GHASH_PTR_ADD_USER(gh, pt) \ - { \ - void **val; \ - if (BLI_ghash_ensure_p((gh), (pt), &val)) { \ - *((int *)val) += 1; \ - } \ - else { \ - *((int *)val) = 1; \ - } \ - } ((void)0) - - /* count chunk_list's */ - GHash *chunk_list_map = BLI_ghash_ptr_new(__func__); - GHash *chunk_map = BLI_ghash_ptr_new(__func__); - - int totrefs = 0; - for (BArrayState *state = bs->states.first; state; state = state->next) { - GHASH_PTR_ADD_USER(chunk_list_map, state->chunk_list); - } - GHASH_ITER (gh_iter, chunk_list_map) { - const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter); - const int users = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); - if (!(chunk_list->users == users)) { - ok = false; - goto user_finally; - } - } - if (!(BLI_mempool_len(bs->memory.chunk_list) == (int)BLI_ghash_len(chunk_list_map))) { - ok = false; - goto user_finally; - } - - /* count chunk's */ - GHASH_ITER (gh_iter, chunk_list_map) { - const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter); - for (const BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { - GHASH_PTR_ADD_USER(chunk_map, cref->link); - totrefs += 1; - } - } - if (!(BLI_mempool_len(bs->memory.chunk) == (int)BLI_ghash_len(chunk_map))) { - ok = false; - goto user_finally; - } - if (!(BLI_mempool_len(bs->memory.chunk_ref) == totrefs)) { - ok = false; - goto user_finally; - } - - GHASH_ITER (gh_iter, chunk_map) { - const struct BChunk *chunk = BLI_ghashIterator_getKey(&gh_iter); - const int users = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); - if (!(chunk->users == users)) { - ok = false; - goto user_finally; - } - } + { \ + void **val; \ + if (BLI_ghash_ensure_p((gh), (pt), &val)) { \ + *((int *)val) += 1; \ + } \ + else { \ + *((int *)val) = 1; \ + } \ + } \ + ((void)0) + + /* count chunk_list's */ + GHash *chunk_list_map = BLI_ghash_ptr_new(__func__); + GHash *chunk_map = BLI_ghash_ptr_new(__func__); + + int totrefs = 0; + for (BArrayState *state = bs->states.first; state; state = state->next) { + GHASH_PTR_ADD_USER(chunk_list_map, state->chunk_list); + } + GHASH_ITER (gh_iter, chunk_list_map) { + const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter); + const int users = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); + if (!(chunk_list->users == users)) { + ok = false; + goto user_finally; + } + } + if (!(BLI_mempool_len(bs->memory.chunk_list) == (int)BLI_ghash_len(chunk_list_map))) { + ok = false; + goto user_finally; + } + + /* count chunk's */ + GHASH_ITER (gh_iter, chunk_list_map) { + const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter); + for (const BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) { + GHASH_PTR_ADD_USER(chunk_map, cref->link); + totrefs += 1; + } + } + if (!(BLI_mempool_len(bs->memory.chunk) == (int)BLI_ghash_len(chunk_map))) { + ok = false; + goto user_finally; + } + if (!(BLI_mempool_len(bs->memory.chunk_ref) == totrefs)) { + ok = false; + goto user_finally; + } + + GHASH_ITER (gh_iter, chunk_map) { + const struct BChunk *chunk = BLI_ghashIterator_getKey(&gh_iter); + const int users = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); + if (!(chunk->users == users)) { + ok = false; + goto user_finally; + } + } #undef GHASH_PTR_ADD_USER -user_finally: - BLI_ghash_free(chunk_list_map, NULL, NULL); - BLI_ghash_free(chunk_map, NULL, NULL); - } - + user_finally: + BLI_ghash_free(chunk_list_map, NULL, NULL); + BLI_ghash_free(chunk_map, NULL, NULL); + } - return ok; - /* TODO, dangling pointer checks */ + return ok; + /* TODO, dangling pointer checks */ } /** \} */ diff --git a/source/blender/blenlib/intern/array_store_utils.c b/source/blender/blenlib/intern/array_store_utils.c index d1b936b76f7..64c985a4c63 100644 --- a/source/blender/blenlib/intern/array_store_utils.c +++ b/source/blender/blenlib/intern/array_store_utils.c @@ -24,72 +24,69 @@ #include "BLI_utildefines.h" #include "BLI_array_store.h" -#include "BLI_array_store_utils.h" /* own include */ +#include "BLI_array_store_utils.h" /* own include */ #include "BLI_math_base.h" -BArrayStore *BLI_array_store_at_size_ensure( - struct BArrayStore_AtSize *bs_stride, - const int stride, const int chunk_size) +BArrayStore *BLI_array_store_at_size_ensure(struct BArrayStore_AtSize *bs_stride, + const int stride, + const int chunk_size) { - if (bs_stride->stride_table_len < stride) { - bs_stride->stride_table_len = stride; - bs_stride->stride_table = MEM_recallocN(bs_stride->stride_table, sizeof(*bs_stride->stride_table) * stride); - } - BArrayStore **bs_p = &bs_stride->stride_table[stride - 1]; + if (bs_stride->stride_table_len < stride) { + bs_stride->stride_table_len = stride; + bs_stride->stride_table = MEM_recallocN(bs_stride->stride_table, + sizeof(*bs_stride->stride_table) * stride); + } + BArrayStore **bs_p = &bs_stride->stride_table[stride - 1]; - if ((*bs_p) == NULL) { - /* calculate best chunk-count to fit a power of two */ - unsigned int chunk_count = chunk_size; - { - unsigned int size = chunk_count * stride; - size = power_of_2_max_u(size); - size = MEM_SIZE_OPTIMAL(size); - chunk_count = size / stride; - } + if ((*bs_p) == NULL) { + /* calculate best chunk-count to fit a power of two */ + unsigned int chunk_count = chunk_size; + { + unsigned int size = chunk_count * stride; + size = power_of_2_max_u(size); + size = MEM_SIZE_OPTIMAL(size); + chunk_count = size / stride; + } - (*bs_p) = BLI_array_store_create(stride, chunk_count); - } - return *bs_p; + (*bs_p) = BLI_array_store_create(stride, chunk_count); + } + return *bs_p; } -BArrayStore *BLI_array_store_at_size_get( - struct BArrayStore_AtSize *bs_stride, - const int stride) +BArrayStore *BLI_array_store_at_size_get(struct BArrayStore_AtSize *bs_stride, const int stride) { - BLI_assert(stride > 0 && stride <= bs_stride->stride_table_len); - return bs_stride->stride_table[stride - 1]; + BLI_assert(stride > 0 && stride <= bs_stride->stride_table_len); + return bs_stride->stride_table[stride - 1]; } -void BLI_array_store_at_size_clear( - struct BArrayStore_AtSize *bs_stride) +void BLI_array_store_at_size_clear(struct BArrayStore_AtSize *bs_stride) { - for (int i = 0; i < bs_stride->stride_table_len; i += 1) { - if (bs_stride->stride_table[i]) { - BLI_array_store_destroy(bs_stride->stride_table[i]); - } - } + for (int i = 0; i < bs_stride->stride_table_len; i += 1) { + if (bs_stride->stride_table[i]) { + BLI_array_store_destroy(bs_stride->stride_table[i]); + } + } - MEM_freeN(bs_stride->stride_table); - bs_stride->stride_table = NULL; - bs_stride->stride_table_len = 0; + MEM_freeN(bs_stride->stride_table); + bs_stride->stride_table = NULL; + bs_stride->stride_table_len = 0; } - -void BLI_array_store_at_size_calc_memory_usage( - struct BArrayStore_AtSize *bs_stride, - size_t *r_size_expanded, size_t *r_size_compacted) +void BLI_array_store_at_size_calc_memory_usage(struct BArrayStore_AtSize *bs_stride, + size_t *r_size_expanded, + size_t *r_size_compacted) { - size_t size_compacted = 0; - size_t size_expanded = 0; - for (int i = 0; i < bs_stride->stride_table_len; i++) { - BArrayStore *bs = bs_stride->stride_table[i]; - if (bs) { - size_compacted += BLI_array_store_calc_size_compacted_get(bs); - size_expanded += BLI_array_store_calc_size_expanded_get(bs); - } - } + size_t size_compacted = 0; + size_t size_expanded = 0; + for (int i = 0; i < bs_stride->stride_table_len; i++) { + BArrayStore *bs = bs_stride->stride_table[i]; + if (bs) { + size_compacted += BLI_array_store_calc_size_compacted_get(bs); + size_expanded += BLI_array_store_calc_size_expanded_get(bs); + } + } - *r_size_expanded = size_expanded; - *r_size_compacted = size_compacted; + *r_size_expanded = size_expanded; + *r_size_compacted = size_compacted; } diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c index 568f3f9b9ff..f941c05e570 100644 --- a/source/blender/blenlib/intern/array_utils.c +++ b/source/blender/blenlib/intern/array_utils.c @@ -42,20 +42,18 @@ */ void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) { - const unsigned int arr_stride_uint = (unsigned int)arr_stride; - const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint; - unsigned int i, i_end; - char *arr = arr_v; - char *buf = BLI_array_alloca(buf, arr_stride); - - for (i = 0, i_end = (arr_len - 1) * arr_stride_uint; - i < arr_half_stride; - i += arr_stride_uint, i_end -= arr_stride_uint) - { - memcpy(buf, &arr[i], arr_stride); - memcpy(&arr[i], &arr[i_end], arr_stride); - memcpy(&arr[i_end], buf, arr_stride); - } + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint; + unsigned int i, i_end; + char *arr = arr_v; + char *buf = BLI_array_alloca(buf, arr_stride); + + for (i = 0, i_end = (arr_len - 1) * arr_stride_uint; i < arr_half_stride; + i += arr_stride_uint, i_end -= arr_stride_uint) { + memcpy(buf, &arr[i], arr_stride); + memcpy(&arr[i], &arr[i_end], arr_stride); + memcpy(&arr[i_end], buf, arr_stride); + } } /** @@ -66,22 +64,22 @@ void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) */ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir) { - char *arr = arr_v; - char *buf = BLI_array_alloca(buf, arr_stride); - - if (dir == -1) { - memcpy(buf, arr, arr_stride); - memmove(arr, arr + arr_stride, arr_stride * (arr_len - 1)); - memcpy(arr + (arr_stride * (arr_len - 1)), buf, arr_stride); - } - else if (dir == 1) { - memcpy(buf, arr + (arr_stride * (arr_len - 1)), arr_stride); - memmove(arr + arr_stride, arr, arr_stride * (arr_len - 1)); - memcpy(arr, buf, arr_stride); - } - else { - BLI_assert(0); - } + char *arr = arr_v; + char *buf = BLI_array_alloca(buf, arr_stride); + + if (dir == -1) { + memcpy(buf, arr, arr_stride); + memmove(arr, arr + arr_stride, arr_stride * (arr_len - 1)); + memcpy(arr + (arr_stride * (arr_len - 1)), buf, arr_stride); + } + else if (dir == 1) { + memcpy(buf, arr + (arr_stride * (arr_len - 1)), arr_stride); + memmove(arr + arr_stride, arr, arr_stride * (arr_len - 1)); + memcpy(arr, buf, arr_stride); + } + else { + BLI_assert(0); + } } /** @@ -90,34 +88,36 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d * * Access via #BLI_array_wrap */ -void _bli_array_permute( - void *arr_v, const unsigned int arr_len, const size_t arr_stride, - const unsigned int *order, void *arr_temp) +void _bli_array_permute(void *arr_v, + const unsigned int arr_len, + const size_t arr_stride, + const unsigned int *order, + void *arr_temp) { - const size_t len = arr_len * arr_stride; - const unsigned int arr_stride_uint = (unsigned int)arr_stride; - void *arr_orig; - unsigned int i; - - if (arr_temp == NULL) { - arr_orig = MEM_mallocN(len, __func__); - } - else { - arr_orig = arr_temp; - } - - memcpy(arr_orig, arr_v, len); - - for (i = 0; i < arr_len; i++) { - BLI_assert(order[i] < arr_len); - memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i), - POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]), - arr_stride); - } - - if (arr_temp == NULL) { - MEM_freeN(arr_orig); - } + const size_t len = arr_len * arr_stride; + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + void *arr_orig; + unsigned int i; + + if (arr_temp == NULL) { + arr_orig = MEM_mallocN(len, __func__); + } + else { + arr_orig = arr_temp; + } + + memcpy(arr_orig, arr_v, len); + + for (i = 0; i < arr_len; i++) { + BLI_assert(order[i] < arr_len); + memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i), + POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]), + arr_stride); + } + + if (arr_temp == NULL) { + MEM_freeN(arr_orig); + } } /** @@ -129,13 +129,13 @@ void _bli_array_permute( */ int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p) { - const char *arr_step = (const char *)arr; - for (unsigned int i = 0; i < arr_len; i++, arr_step += arr_stride) { - if (memcmp(arr_step, p, arr_stride) == 0) { - return (int)i; - } - } - return -1; + const char *arr_step = (const char *)arr; + for (unsigned int i = 0; i < arr_len; i++, arr_step += arr_stride) { + if (memcmp(arr_step, p, arr_stride) == 0) { + return (int)i; + } + } + return -1; } /** @@ -143,42 +143,40 @@ int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_strid */ int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p) { - const char *arr_step = (const char *)arr + (arr_stride * arr_len); - for (unsigned int i = arr_len; i-- != 0; ) { - arr_step -= arr_stride; - if (memcmp(arr_step, p, arr_stride) == 0) { - return (int)i; - } - } - return -1; + const char *arr_step = (const char *)arr + (arr_stride * arr_len); + for (unsigned int i = arr_len; i-- != 0;) { + arr_step -= arr_stride; + if (memcmp(arr_step, p, arr_stride) == 0) { + return (int)i; + } + } + return -1; } void _bli_array_binary_and( - void *arr, const void *arr_a, const void *arr_b, - unsigned int arr_len, size_t arr_stride) + void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride) { - char *dst = arr; - const char *src_a = arr_a; - const char *src_b = arr_b; - - size_t i = arr_stride * arr_len; - while (i--) { - *(dst++) = *(src_a++) & *(src_b++); - } + char *dst = arr; + const char *src_a = arr_a; + const char *src_b = arr_b; + + size_t i = arr_stride * arr_len; + while (i--) { + *(dst++) = *(src_a++) & *(src_b++); + } } void _bli_array_binary_or( - void *arr, const void *arr_a, const void *arr_b, - unsigned int arr_len, size_t arr_stride) + void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride) { - char *dst = arr; - const char *src_a = arr_a; - const char *src_b = arr_b; - - size_t i = arr_stride * arr_len; - while (i--) { - *(dst++) = *(src_a++) | *(src_b++); - } + char *dst = arr; + const char *src_a = arr_a; + const char *src_b = arr_b; + + size_t i = arr_stride * arr_len; + while (i--) { + *(dst++) = *(src_a++) | *(src_b++); + } } /** @@ -196,128 +194,126 @@ void _bli_array_binary_or( * \param r_span_len: The length of the span, useful when \a use_wrap is enabled, * where calculating the length isnt a simple subtraction. */ -bool _bli_array_iter_span( - const void *arr, - unsigned int arr_len, size_t arr_stride, - bool use_wrap, bool use_delimit_bounds, - bool (*test_fn)(const void *arr_item, void *user_data), void *user_data, - unsigned int span_step[2], unsigned int *r_span_len) +bool _bli_array_iter_span(const void *arr, + unsigned int arr_len, + size_t arr_stride, + bool use_wrap, + bool use_delimit_bounds, + bool (*test_fn)(const void *arr_item, void *user_data), + void *user_data, + unsigned int span_step[2], + unsigned int *r_span_len) { - if (arr_len == 0) { - return false; - } - else if (use_wrap && (span_step[0] != arr_len) && (span_step[0] > span_step[1])) { - return false; - } - - const unsigned int arr_stride_uint = (unsigned int)arr_stride; - const void *item_prev; - bool test_prev; - - unsigned int i_curr; - - if ((span_step[0] == arr_len) && (span_step[1] == arr_len)) { - if (use_wrap) { - item_prev = POINTER_OFFSET(arr, (arr_len - 1) * arr_stride_uint); - i_curr = 0; - test_prev = test_fn(item_prev, user_data); - } - else if (use_delimit_bounds == false) { - item_prev = arr; - i_curr = 1; - test_prev = test_fn(item_prev, user_data); - } - else { - item_prev = NULL; - i_curr = 0; - test_prev = false; - } - } - else if ((i_curr = span_step[1] + 2) < arr_len) { - item_prev = POINTER_OFFSET(arr, (span_step[1] + 1) * arr_stride_uint); - test_prev = test_fn(item_prev, user_data); - } - else { - return false; - } - BLI_assert(i_curr < arr_len); - - const void *item_curr = POINTER_OFFSET(arr, i_curr * arr_stride_uint); - - while (i_curr < arr_len) { - bool test_curr = test_fn(item_curr, user_data); - if ((test_prev == false) && - (test_curr == true)) - { - unsigned int span_len; - unsigned int i_step_prev = i_curr; - - if (use_wrap) { - unsigned int i_step = i_curr + 1; - if (UNLIKELY(i_step == arr_len)) { - i_step = 0; - } - while (test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) { - i_step_prev = i_step; - i_step++; - if (UNLIKELY(i_step == arr_len)) { - i_step = 0; - } - } - - if (i_step_prev < i_curr) { - span_len = (i_step_prev + (arr_len - i_curr)) + 1; - } - else { - span_len = (i_step_prev - i_curr) + 1; - } - } - else { - unsigned int i_step = i_curr + 1; - while ((i_step != arr_len) && - test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) - { - i_step_prev = i_step; - i_step++; - } - - span_len = (i_step_prev - i_curr) + 1; - - if ((use_delimit_bounds == false) && (i_step_prev == arr_len - 1)) { - return false; - } - } - - span_step[0] = i_curr; - span_step[1] = i_step_prev; - *r_span_len = span_len; - - return true; - } - - test_prev = test_curr; - - item_prev = item_curr; - item_curr = POINTER_OFFSET(item_curr, arr_stride_uint); - i_curr++; - } - - return false; + if (arr_len == 0) { + return false; + } + else if (use_wrap && (span_step[0] != arr_len) && (span_step[0] > span_step[1])) { + return false; + } + + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const void *item_prev; + bool test_prev; + + unsigned int i_curr; + + if ((span_step[0] == arr_len) && (span_step[1] == arr_len)) { + if (use_wrap) { + item_prev = POINTER_OFFSET(arr, (arr_len - 1) * arr_stride_uint); + i_curr = 0; + test_prev = test_fn(item_prev, user_data); + } + else if (use_delimit_bounds == false) { + item_prev = arr; + i_curr = 1; + test_prev = test_fn(item_prev, user_data); + } + else { + item_prev = NULL; + i_curr = 0; + test_prev = false; + } + } + else if ((i_curr = span_step[1] + 2) < arr_len) { + item_prev = POINTER_OFFSET(arr, (span_step[1] + 1) * arr_stride_uint); + test_prev = test_fn(item_prev, user_data); + } + else { + return false; + } + BLI_assert(i_curr < arr_len); + + const void *item_curr = POINTER_OFFSET(arr, i_curr * arr_stride_uint); + + while (i_curr < arr_len) { + bool test_curr = test_fn(item_curr, user_data); + if ((test_prev == false) && (test_curr == true)) { + unsigned int span_len; + unsigned int i_step_prev = i_curr; + + if (use_wrap) { + unsigned int i_step = i_curr + 1; + if (UNLIKELY(i_step == arr_len)) { + i_step = 0; + } + while (test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) { + i_step_prev = i_step; + i_step++; + if (UNLIKELY(i_step == arr_len)) { + i_step = 0; + } + } + + if (i_step_prev < i_curr) { + span_len = (i_step_prev + (arr_len - i_curr)) + 1; + } + else { + span_len = (i_step_prev - i_curr) + 1; + } + } + else { + unsigned int i_step = i_curr + 1; + while ((i_step != arr_len) && + test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) { + i_step_prev = i_step; + i_step++; + } + + span_len = (i_step_prev - i_curr) + 1; + + if ((use_delimit_bounds == false) && (i_step_prev == arr_len - 1)) { + return false; + } + } + + span_step[0] = i_curr; + span_step[1] = i_step_prev; + *r_span_len = span_len; + + return true; + } + + test_prev = test_curr; + + item_prev = item_curr; + item_curr = POINTER_OFFSET(item_curr, arr_stride_uint); + i_curr++; + } + + return false; } /** * Simple utility to check memory is zeroed. */ -bool _bli_array_is_zeroed( - const void *arr_v, - unsigned int arr_len, size_t arr_stride) +bool _bli_array_is_zeroed(const void *arr_v, unsigned int arr_len, size_t arr_stride) { - const char *arr_step = (const char *)arr_v; - size_t i = arr_stride * arr_len; - while (i--) { - if (*(arr_step++)) { - return false; - } - } - return true; + const char *arr_step = (const char *)arr_v; + size_t i = arr_stride * arr_len; + while (i--) { + if (*(arr_step++)) { + return false; + } + } + return true; } diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c index 13998bad81d..c275f679dc6 100644 --- a/source/blender/blenlib/intern/astar.c +++ b/source/blender/blenlib/intern/astar.c @@ -57,7 +57,7 @@ */ void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *custom_data) { - as_graph->nodes[node_index].custom_data = custom_data; + as_graph->nodes[node_index].custom_data = custom_data; } /** @@ -66,22 +66,25 @@ void BLI_astar_node_init(BLI_AStarGraph *as_graph, const int node_index, void *c * \param cost: the 'length' of the link (actual distance between two vertices or face centers e.g.). * \param custom_data: an opaque pointer attached to this link, available e.g. to cost callback function. */ -void BLI_astar_node_link_add( - BLI_AStarGraph *as_graph, const int node1_index, const int node2_index, const float cost, void *custom_data) +void BLI_astar_node_link_add(BLI_AStarGraph *as_graph, + const int node1_index, + const int node2_index, + const float cost, + void *custom_data) { - MemArena *mem = as_graph->mem; - BLI_AStarGNLink *link = BLI_memarena_alloc(mem, sizeof(*link)); - LinkData *ld = BLI_memarena_alloc(mem, sizeof(*ld) * 2); + MemArena *mem = as_graph->mem; + BLI_AStarGNLink *link = BLI_memarena_alloc(mem, sizeof(*link)); + LinkData *ld = BLI_memarena_alloc(mem, sizeof(*ld) * 2); - link->nodes[0] = node1_index; - link->nodes[1] = node2_index; - link->cost = cost; - link->custom_data = custom_data; + link->nodes[0] = node1_index; + link->nodes[1] = node2_index; + link->cost = cost; + link->custom_data = custom_data; - ld[0].data = ld[1].data = link; + ld[0].data = ld[1].data = link; - BLI_addtail(&(as_graph->nodes[node1_index].neighbor_links), &ld[0]); - BLI_addtail(&(as_graph->nodes[node2_index].neighbor_links), &ld[1]); + BLI_addtail(&(as_graph->nodes[node1_index].neighbor_links), &ld[0]); + BLI_addtail(&(as_graph->nodes[node2_index].neighbor_links), &ld[1]); } /** @@ -89,7 +92,7 @@ void BLI_astar_node_link_add( */ int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx) { - return (lnk->nodes[0] == idx) ? lnk->nodes[1] : lnk->nodes[0]; + return (lnk->nodes[0] == idx) ? lnk->nodes[1] : lnk->nodes[0]; } /** @@ -99,26 +102,28 @@ int BLI_astar_node_link_other_node(BLI_AStarGNLink *lnk, const int idx) * * \note BLI_AStarSolution stores nearly all data needed during solution compute. */ -void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data) +void BLI_astar_solution_init(BLI_AStarGraph *as_graph, + BLI_AStarSolution *as_solution, + void *custom_data) { - MemArena *mem = as_solution->mem; - size_t node_num = (size_t)as_graph->node_num; + MemArena *mem = as_solution->mem; + size_t node_num = (size_t)as_graph->node_num; - if (mem == NULL) { - mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - as_solution->mem = mem; - } - /* else memarena should be cleared */ + if (mem == NULL) { + mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + as_solution->mem = mem; + } + /* else memarena should be cleared */ - as_solution->steps = 0; - as_solution->prev_nodes = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_nodes) * node_num); - as_solution->prev_links = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_links) * node_num); + as_solution->steps = 0; + as_solution->prev_nodes = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_nodes) * node_num); + as_solution->prev_links = BLI_memarena_alloc(mem, sizeof(*as_solution->prev_links) * node_num); - as_solution->custom_data = custom_data; + as_solution->custom_data = custom_data; - as_solution->done_nodes = BLI_BITMAP_NEW_MEMARENA(mem, node_num); - as_solution->g_costs = BLI_memarena_alloc(mem, sizeof(*as_solution->g_costs) * node_num); - as_solution->g_steps = BLI_memarena_alloc(mem, sizeof(*as_solution->g_steps) * node_num); + as_solution->done_nodes = BLI_BITMAP_NEW_MEMARENA(mem, node_num); + as_solution->g_costs = BLI_memarena_alloc(mem, sizeof(*as_solution->g_costs) * node_num); + as_solution->g_steps = BLI_memarena_alloc(mem, sizeof(*as_solution->g_steps) * node_num); } /** @@ -129,19 +134,19 @@ void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_sol */ void BLI_astar_solution_clear(BLI_AStarSolution *as_solution) { - if (as_solution->mem) { - BLI_memarena_clear(as_solution->mem); - } + if (as_solution->mem) { + BLI_memarena_clear(as_solution->mem); + } - as_solution->steps = 0; - as_solution->prev_nodes = NULL; - as_solution->prev_links = NULL; + as_solution->steps = 0; + as_solution->prev_nodes = NULL; + as_solution->prev_links = NULL; - as_solution->custom_data = NULL; + as_solution->custom_data = NULL; - as_solution->done_nodes = NULL; - as_solution->g_costs = NULL; - as_solution->g_steps = NULL; + as_solution->done_nodes = NULL; + as_solution->g_costs = NULL; + as_solution->g_steps = NULL; } /** @@ -149,10 +154,10 @@ void BLI_astar_solution_clear(BLI_AStarSolution *as_solution) */ void BLI_astar_solution_free(BLI_AStarSolution *as_solution) { - if (as_solution->mem) { - BLI_memarena_free(as_solution->mem); - as_solution->mem = NULL; - } + if (as_solution->mem) { + BLI_memarena_free(as_solution->mem); + as_solution->mem = NULL; + } } /** @@ -164,26 +169,26 @@ void BLI_astar_solution_free(BLI_AStarSolution *as_solution) */ void BLI_astar_graph_init(BLI_AStarGraph *as_graph, const int node_num, void *custom_data) { - MemArena *mem = as_graph->mem; + MemArena *mem = as_graph->mem; - if (mem == NULL) { - mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - as_graph->mem = mem; - } - /* else memarena should be cleared */ + if (mem == NULL) { + mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + as_graph->mem = mem; + } + /* else memarena should be cleared */ - as_graph->node_num = node_num; - as_graph->nodes = BLI_memarena_calloc(mem, sizeof(*as_graph->nodes) * (size_t)node_num); + as_graph->node_num = node_num; + as_graph->nodes = BLI_memarena_calloc(mem, sizeof(*as_graph->nodes) * (size_t)node_num); - as_graph->custom_data = custom_data; + as_graph->custom_data = custom_data; } void BLI_astar_graph_free(BLI_AStarGraph *as_graph) { - if (as_graph->mem) { - BLI_memarena_free(as_graph->mem); - as_graph->mem = NULL; - } + if (as_graph->mem) { + BLI_memarena_free(as_graph->mem); + as_graph->mem = NULL; + } } /** @@ -193,84 +198,86 @@ void BLI_astar_graph_free(BLI_AStarGraph *as_graph) * If no path is found within given steps, returns false too. * \return true if a path was found, false otherwise. */ -bool BLI_astar_graph_solve( - BLI_AStarGraph *as_graph, const int node_index_src, const int node_index_dst, astar_f_cost f_cost_cb, - BLI_AStarSolution *r_solution, const int max_steps) +bool BLI_astar_graph_solve(BLI_AStarGraph *as_graph, + const int node_index_src, + const int node_index_dst, + astar_f_cost f_cost_cb, + BLI_AStarSolution *r_solution, + const int max_steps) { - HeapSimple *todo_nodes; - - BLI_bitmap *done_nodes = r_solution->done_nodes; - int *prev_nodes = r_solution->prev_nodes; - BLI_AStarGNLink **prev_links = r_solution->prev_links; - float *g_costs = r_solution->g_costs; - int *g_steps = r_solution->g_steps; - - r_solution->steps = 0; - prev_nodes[node_index_src] = -1; - BLI_bitmap_set_all(done_nodes, false, as_graph->node_num); - copy_vn_fl(g_costs, as_graph->node_num, FLT_MAX); - g_costs[node_index_src] = 0.0f; - g_steps[node_index_src] = 0; - - if (node_index_src == node_index_dst) { - return true; - } - - todo_nodes = BLI_heapsimple_new(); - BLI_heapsimple_insert( - todo_nodes, - f_cost_cb(as_graph, r_solution, NULL, -1, node_index_src, node_index_dst), - POINTER_FROM_INT(node_index_src)); - - while (!BLI_heapsimple_is_empty(todo_nodes)) { - const int node_curr_idx = POINTER_AS_INT(BLI_heapsimple_pop_min(todo_nodes)); - BLI_AStarGNode *node_curr = &as_graph->nodes[node_curr_idx]; - LinkData *ld; - - if (BLI_BITMAP_TEST(done_nodes, node_curr_idx)) { - /* Might happen, because we always add nodes to heap when evaluating them, - * without ever removing them. */ - continue; - } - - /* If we are limited in amount of steps to find a path, skip if we reached limit. */ - if (max_steps && g_steps[node_curr_idx] > max_steps) { - continue; - } - - if (node_curr_idx == node_index_dst) { - /* Success! Path found... */ - r_solution->steps = g_steps[node_curr_idx] + 1; - - BLI_heapsimple_free(todo_nodes, NULL); - return true; - } - - BLI_BITMAP_ENABLE(done_nodes, node_curr_idx); - - for (ld = node_curr->neighbor_links.first; ld; ld = ld->next) { - BLI_AStarGNLink *link = ld->data; - const int node_next_idx = BLI_astar_node_link_other_node(link, node_curr_idx); - - if (!BLI_BITMAP_TEST(done_nodes, node_next_idx)) { - float g_cst = g_costs[node_curr_idx] + link->cost; - - if (g_cst < g_costs[node_next_idx]) { - prev_nodes[node_next_idx] = node_curr_idx; - prev_links[node_next_idx] = link; - g_costs[node_next_idx] = g_cst; - g_steps[node_next_idx] = g_steps[node_curr_idx] + 1; - /* We might have this node already in heap, but since this 'instance' - * will be evaluated first, no problem. */ - BLI_heapsimple_insert( - todo_nodes, - f_cost_cb(as_graph, r_solution, link, node_curr_idx, node_next_idx, node_index_dst), - POINTER_FROM_INT(node_next_idx)); - } - } - } - } - - BLI_heapsimple_free(todo_nodes, NULL); - return false; + HeapSimple *todo_nodes; + + BLI_bitmap *done_nodes = r_solution->done_nodes; + int *prev_nodes = r_solution->prev_nodes; + BLI_AStarGNLink **prev_links = r_solution->prev_links; + float *g_costs = r_solution->g_costs; + int *g_steps = r_solution->g_steps; + + r_solution->steps = 0; + prev_nodes[node_index_src] = -1; + BLI_bitmap_set_all(done_nodes, false, as_graph->node_num); + copy_vn_fl(g_costs, as_graph->node_num, FLT_MAX); + g_costs[node_index_src] = 0.0f; + g_steps[node_index_src] = 0; + + if (node_index_src == node_index_dst) { + return true; + } + + todo_nodes = BLI_heapsimple_new(); + BLI_heapsimple_insert(todo_nodes, + f_cost_cb(as_graph, r_solution, NULL, -1, node_index_src, node_index_dst), + POINTER_FROM_INT(node_index_src)); + + while (!BLI_heapsimple_is_empty(todo_nodes)) { + const int node_curr_idx = POINTER_AS_INT(BLI_heapsimple_pop_min(todo_nodes)); + BLI_AStarGNode *node_curr = &as_graph->nodes[node_curr_idx]; + LinkData *ld; + + if (BLI_BITMAP_TEST(done_nodes, node_curr_idx)) { + /* Might happen, because we always add nodes to heap when evaluating them, + * without ever removing them. */ + continue; + } + + /* If we are limited in amount of steps to find a path, skip if we reached limit. */ + if (max_steps && g_steps[node_curr_idx] > max_steps) { + continue; + } + + if (node_curr_idx == node_index_dst) { + /* Success! Path found... */ + r_solution->steps = g_steps[node_curr_idx] + 1; + + BLI_heapsimple_free(todo_nodes, NULL); + return true; + } + + BLI_BITMAP_ENABLE(done_nodes, node_curr_idx); + + for (ld = node_curr->neighbor_links.first; ld; ld = ld->next) { + BLI_AStarGNLink *link = ld->data; + const int node_next_idx = BLI_astar_node_link_other_node(link, node_curr_idx); + + if (!BLI_BITMAP_TEST(done_nodes, node_next_idx)) { + float g_cst = g_costs[node_curr_idx] + link->cost; + + if (g_cst < g_costs[node_next_idx]) { + prev_nodes[node_next_idx] = node_curr_idx; + prev_links[node_next_idx] = link; + g_costs[node_next_idx] = g_cst; + g_steps[node_next_idx] = g_steps[node_curr_idx] + 1; + /* We might have this node already in heap, but since this 'instance' + * will be evaluated first, no problem. */ + BLI_heapsimple_insert( + todo_nodes, + f_cost_cb(as_graph, r_solution, link, node_curr_idx, node_next_idx, node_index_dst), + POINTER_FROM_INT(node_next_idx)); + } + } + } + } + + BLI_heapsimple_free(todo_nodes, NULL); + return false; } diff --git a/source/blender/blenlib/intern/bitmap.c b/source/blender/blenlib/intern/bitmap.c index 8cc359ac7f2..4e26ae23774 100644 --- a/source/blender/blenlib/intern/bitmap.c +++ b/source/blender/blenlib/intern/bitmap.c @@ -32,38 +32,38 @@ /** Set or clear all bits in the bitmap. */ void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits) { - memset(bitmap, set ? UCHAR_MAX : 0, BLI_BITMAP_SIZE(bits)); + memset(bitmap, set ? UCHAR_MAX : 0, BLI_BITMAP_SIZE(bits)); } /** Invert all bits in the bitmap. */ void BLI_bitmap_flip_all(BLI_bitmap *bitmap, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { - bitmap[i] ^= ~(BLI_bitmap)0; - } + size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < num_blocks; i++) { + bitmap[i] ^= ~(BLI_bitmap)0; + } } /** Copy all bits from one bitmap to another. */ void BLI_bitmap_copy_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) { - memcpy(dst, src, BLI_BITMAP_SIZE(bits)); + memcpy(dst, src, BLI_BITMAP_SIZE(bits)); } /** Combine two bitmaps with boolean AND. */ void BLI_bitmap_and_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { - dst[i] &= src[i]; - } + size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < num_blocks; i++) { + dst[i] &= src[i]; + } } /** Combine two bitmaps with boolean OR. */ void BLI_bitmap_or_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) { - size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); - for (size_t i = 0; i < num_blocks; i++) { - dst[i] |= src[i]; - } + size_t num_blocks = _BITMAP_NUM_BLOCKS(bits); + for (size_t i = 0; i < num_blocks; i++) { + dst[i] |= src[i]; + } } diff --git a/source/blender/blenlib/intern/bitmap_draw_2d.c b/source/blender/blenlib/intern/bitmap_draw_2d.c index aa2e93d06a1..17debb38326 100644 --- a/source/blender/blenlib/intern/bitmap_draw_2d.c +++ b/source/blender/blenlib/intern/bitmap_draw_2d.c @@ -47,74 +47,75 @@ * * \note For clipped line drawing, see: http://stackoverflow.com/a/40902741/432509 */ -void BLI_bitmap_draw_2d_line_v2v2i( - const int p1[2], const int p2[2], - bool (*callback)(int, int, void *), void *user_data) +void BLI_bitmap_draw_2d_line_v2v2i(const int p1[2], + const int p2[2], + bool (*callback)(int, int, void *), + void *user_data) { - /* Bresenham's line algorithm. */ - int x1 = p1[0]; - int y1 = p1[1]; - int x2 = p2[0]; - int y2 = p2[1]; - - if (callback(x1, y1, user_data) == 0) { - return; - } - - /* if x1 == x2 or y1 == y2, then it does not matter what we set here */ - const int sign_x = (x2 > x1) ? 1 : -1; - const int sign_y = (y2 > y1) ? 1 : -1; - - const int delta_x = (sign_x == 1) ? (x2 - x1) : (x1 - x2); - const int delta_y = (sign_y == 1) ? (y2 - y1) : (y1 - y2); - - const int delta_x_step = delta_x * 2; - const int delta_y_step = delta_y * 2; - - if (delta_x >= delta_y) { - /* error may go below zero */ - int error = delta_y_step - delta_x; - - while (x1 != x2) { - if (error >= 0) { - if (error || (sign_x == 1)) { - y1 += sign_y; - error -= delta_x_step; - } - /* else do nothing */ - } - /* else do nothing */ - - x1 += sign_x; - error += delta_y_step; - - if (callback(x1, y1, user_data) == 0) { - return; - } - } - } - else { - /* error may go below zero */ - int error = delta_x_step - delta_y; - - while (y1 != y2) { - if (error >= 0) { - if (error || (sign_y == 1)) { - x1 += sign_x; - error -= delta_y_step; - } - /* else do nothing */ - } - /* else do nothing */ - - y1 += sign_y; - error += delta_x_step; - - if (callback(x1, y1, user_data) == 0) { - return; - } - } - } + /* Bresenham's line algorithm. */ + int x1 = p1[0]; + int y1 = p1[1]; + int x2 = p2[0]; + int y2 = p2[1]; + + if (callback(x1, y1, user_data) == 0) { + return; + } + + /* if x1 == x2 or y1 == y2, then it does not matter what we set here */ + const int sign_x = (x2 > x1) ? 1 : -1; + const int sign_y = (y2 > y1) ? 1 : -1; + + const int delta_x = (sign_x == 1) ? (x2 - x1) : (x1 - x2); + const int delta_y = (sign_y == 1) ? (y2 - y1) : (y1 - y2); + + const int delta_x_step = delta_x * 2; + const int delta_y_step = delta_y * 2; + + if (delta_x >= delta_y) { + /* error may go below zero */ + int error = delta_y_step - delta_x; + + while (x1 != x2) { + if (error >= 0) { + if (error || (sign_x == 1)) { + y1 += sign_y; + error -= delta_x_step; + } + /* else do nothing */ + } + /* else do nothing */ + + x1 += sign_x; + error += delta_y_step; + + if (callback(x1, y1, user_data) == 0) { + return; + } + } + } + else { + /* error may go below zero */ + int error = delta_x_step - delta_y; + + while (y1 != y2) { + if (error >= 0) { + if (error || (sign_y == 1)) { + x1 += sign_x; + error -= delta_y_step; + } + /* else do nothing */ + } + /* else do nothing */ + + y1 += sign_y; + error += delta_x_step; + + if (callback(x1, y1, user_data) == 0) { + return; + } + } + } } /** \} */ @@ -141,25 +142,34 @@ void BLI_bitmap_draw_2d_line_v2v2i( /* Macros could be moved to a shared location. */ #define ORDERED_SWAP(ty, a, b) \ - if (a > b) { SWAP(ty, a, b); } ((void)0) + if (a > b) { \ + SWAP(ty, a, b); \ + } \ + ((void)0) #define ORDERED_SWAP_BY(ty, a, b, by) \ - if ((a by) > (b by)) { SWAP(ty, a, b); } ((void)0) + if ((a by) > (b by)) { \ + SWAP(ty, a, b); \ + } \ + ((void)0) #define ORDER_VARS2(ty, a, b) \ - { ORDERED_SWAP(ty, a, b); } ((void)0) + { \ + ORDERED_SWAP(ty, a, b); \ + } \ + ((void)0) #define ORDER_VARS3_BY(ty, a, b, c, by) \ - { \ - ORDERED_SWAP_BY(ty, b, c, by); \ - ORDERED_SWAP_BY(ty, a, c, by); \ - ORDERED_SWAP_BY(ty, a, b, by); \ - } ((void)0) + { \ + ORDERED_SWAP_BY(ty, b, c, by); \ + ORDERED_SWAP_BY(ty, a, c, by); \ + ORDERED_SWAP_BY(ty, a, b, by); \ + } \ + ((void)0) static float inv_slope(const int a[2], const int b[2]) { - return ((float)(a[0] - b[0]) / - (float)(a[1] - b[1])); + return ((float)(a[0] - b[0]) / (float)(a[1] - b[1])); } /** @@ -169,24 +179,23 @@ static float inv_slope(const int a[2], const int b[2]) * * * </pre> */ -static void draw_tri_flat_max( - const int p[2], - const int max_y, - const float inv_slope1, - const float inv_slope2, - void (*callback)(int x, int x_end, int y, void *), - void *user_data) +static void draw_tri_flat_max(const int p[2], + const int max_y, + const float inv_slope1, + const float inv_slope2, + void (*callback)(int x, int x_end, int y, void *), + void *user_data) { - float cur_x1 = (float)p[0]; - float cur_x2 = cur_x1; - /* start-end inclusive */ - const int min_y = p[1]; - const int max_y_end = max_y + 1; - for (int scanline_y = min_y; scanline_y != max_y_end; scanline_y += 1) { - callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data); - cur_x1 += inv_slope1; - cur_x2 += inv_slope2; - } + float cur_x1 = (float)p[0]; + float cur_x2 = cur_x1; + /* start-end inclusive */ + const int min_y = p[1]; + const int max_y_end = max_y + 1; + for (int scanline_y = min_y; scanline_y != max_y_end; scanline_y += 1) { + callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data); + cur_x1 += inv_slope1; + cur_x2 += inv_slope2; + } } /** @@ -196,95 +205,92 @@ static void draw_tri_flat_max( * *---* * </pre> */ -static void draw_tri_flat_min( - const int p[2], - const int min_y, - const float inv_slope1, - const float inv_slope2, - void (*callback)(int x, int x_end, int y, void *), - void *user_data) +static void draw_tri_flat_min(const int p[2], + const int min_y, + const float inv_slope1, + const float inv_slope2, + void (*callback)(int x, int x_end, int y, void *), + void *user_data) { - float cur_x1 = (float)p[0]; - float cur_x2 = cur_x1; - /* start-end inclusive */ - const int max_y = p[1]; - const int min_y_end = min_y - 1; - for (int scanline_y = max_y; scanline_y != min_y_end; scanline_y -= 1) { - callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data); - cur_x1 -= inv_slope1; - cur_x2 -= inv_slope2; - } + float cur_x1 = (float)p[0]; + float cur_x2 = cur_x1; + /* start-end inclusive */ + const int max_y = p[1]; + const int min_y_end = min_y - 1; + for (int scanline_y = max_y; scanline_y != min_y_end; scanline_y -= 1) { + callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data); + cur_x1 -= inv_slope1; + cur_x2 -= inv_slope2; + } } /** * \note Unclipped (clipped version can be added if needed). */ void BLI_bitmap_draw_2d_tri_v2i( - /* all 2d */ - const int p1[2], - const int p2[2], - const int p3[2], - void (*callback)(int x, int x_end, int y, void *), - void *user_data) + /* all 2d */ + const int p1[2], + const int p2[2], + const int p3[2], + void (*callback)(int x, int x_end, int y, void *), + void *user_data) { - /* At first sort the three vertices by y-coordinate ascending so p1 is the top-most vertice */ - ORDER_VARS3_BY(const int *, p1, p2, p3, [1]); - - BLI_assert(p1[1] <= p2[1] && p2[1] <= p3[1]); - - /* Check for trivial case of bottom-flat triangle. */ - if (p2[1] == p3[1]) { - float inv_slope1 = inv_slope(p2, p1); - float inv_slope2 = inv_slope(p3, p1); - ORDER_VARS2(float, inv_slope1, inv_slope2); - BLI_assert(!(inv_slope1 > inv_slope2)); - draw_tri_flat_max( - p1, p2[1], - inv_slope1, inv_slope2, - callback, user_data); - } - else if (p1[1] == p2[1]) { - /* Check for trivial case of top-flat triangle. */ - float inv_slope1 = inv_slope(p3, p1); - float inv_slope2 = inv_slope(p3, p2); - ORDER_VARS2(float, inv_slope2, inv_slope1); - BLI_assert(!(inv_slope1 < inv_slope2)); - draw_tri_flat_min( - p3, p2[1] + 1, /* avoid overlap */ - inv_slope1, inv_slope2, - callback, user_data); - } - else { - /* General case - split the triangle in a top-flat and bottom-flat one. */ - const float inv_slope_p21 = inv_slope(p2, p1); - const float inv_slope_p31 = inv_slope(p3, p1); - const float inv_slope_p32 = inv_slope(p3, p2); - - float inv_slope1_max, inv_slope2_max; - float inv_slope2_min, inv_slope1_min; - - if (inv_slope_p21 < inv_slope_p31) { - inv_slope1_max = inv_slope_p21; - inv_slope2_max = inv_slope_p31; - inv_slope2_min = inv_slope_p31; - inv_slope1_min = inv_slope_p32; - } - else { - inv_slope1_max = inv_slope_p31; - inv_slope2_max = inv_slope_p21; - inv_slope2_min = inv_slope_p32; - inv_slope1_min = inv_slope_p31; - } - - draw_tri_flat_max( - p1, p2[1], - inv_slope1_max, inv_slope2_max, - callback, user_data); - draw_tri_flat_min( - p3, p2[1] + 1, /* avoid overlap */ - inv_slope1_min, inv_slope2_min, - callback, user_data); - } + /* At first sort the three vertices by y-coordinate ascending so p1 is the top-most vertice */ + ORDER_VARS3_BY(const int *, p1, p2, p3, [1]); + + BLI_assert(p1[1] <= p2[1] && p2[1] <= p3[1]); + + /* Check for trivial case of bottom-flat triangle. */ + if (p2[1] == p3[1]) { + float inv_slope1 = inv_slope(p2, p1); + float inv_slope2 = inv_slope(p3, p1); + ORDER_VARS2(float, inv_slope1, inv_slope2); + BLI_assert(!(inv_slope1 > inv_slope2)); + draw_tri_flat_max(p1, p2[1], inv_slope1, inv_slope2, callback, user_data); + } + else if (p1[1] == p2[1]) { + /* Check for trivial case of top-flat triangle. */ + float inv_slope1 = inv_slope(p3, p1); + float inv_slope2 = inv_slope(p3, p2); + ORDER_VARS2(float, inv_slope2, inv_slope1); + BLI_assert(!(inv_slope1 < inv_slope2)); + draw_tri_flat_min(p3, + p2[1] + 1, /* avoid overlap */ + inv_slope1, + inv_slope2, + callback, + user_data); + } + else { + /* General case - split the triangle in a top-flat and bottom-flat one. */ + const float inv_slope_p21 = inv_slope(p2, p1); + const float inv_slope_p31 = inv_slope(p3, p1); + const float inv_slope_p32 = inv_slope(p3, p2); + + float inv_slope1_max, inv_slope2_max; + float inv_slope2_min, inv_slope1_min; + + if (inv_slope_p21 < inv_slope_p31) { + inv_slope1_max = inv_slope_p21; + inv_slope2_max = inv_slope_p31; + inv_slope2_min = inv_slope_p31; + inv_slope1_min = inv_slope_p32; + } + else { + inv_slope1_max = inv_slope_p31; + inv_slope2_max = inv_slope_p21; + inv_slope2_min = inv_slope_p32; + inv_slope1_min = inv_slope_p31; + } + + draw_tri_flat_max(p1, p2[1], inv_slope1_max, inv_slope2_max, callback, user_data); + draw_tri_flat_min(p3, + p2[1] + 1, /* avoid overlap */ + inv_slope1_min, + inv_slope2_min, + callback, + user_data); + } } #undef ORDERED_SWAP @@ -301,39 +307,38 @@ void BLI_bitmap_draw_2d_tri_v2i( /* sort edge-segments on y, then x axis */ static int draw_poly_v2i_n__span_y_sort(const void *a_p, const void *b_p, void *verts_p) { - const int (*verts)[2] = verts_p; - const int *a = a_p; - const int *b = b_p; - const int *co_a = verts[a[0]]; - const int *co_b = verts[b[0]]; - - if (co_a[1] < co_b[1]) { - return -1; - } - else if (co_a[1] > co_b[1]) { - return 1; - } - else if (co_a[0] < co_b[0]) { - return -1; - } - else if (co_a[0] > co_b[0]) { - return 1; - } - else { - /* co_a & co_b are identical, use the line closest to the x-min */ - const int *co = co_a; - co_a = verts[a[1]]; - co_b = verts[b[1]]; - int ord = (((co_b[0] - co[0]) * (co_a[1] - co[1])) - - ((co_a[0] - co[0]) * (co_b[1] - co[1]))); - if (ord > 0) { - return -1; - } - if (ord < 0) { - return 1; - } - } - return 0; + const int(*verts)[2] = verts_p; + const int *a = a_p; + const int *b = b_p; + const int *co_a = verts[a[0]]; + const int *co_b = verts[b[0]]; + + if (co_a[1] < co_b[1]) { + return -1; + } + else if (co_a[1] > co_b[1]) { + return 1; + } + else if (co_a[0] < co_b[0]) { + return -1; + } + else if (co_a[0] > co_b[0]) { + return 1; + } + else { + /* co_a & co_b are identical, use the line closest to the x-min */ + const int *co = co_a; + co_a = verts[a[1]]; + co_b = verts[b[1]]; + int ord = (((co_b[0] - co[0]) * (co_a[1] - co[1])) - ((co_a[0] - co[0]) * (co_b[1] - co[1]))); + if (ord > 0) { + return -1; + } + if (ord < 0) { + return 1; + } + } + return 0; } /** @@ -348,166 +353,164 @@ static int draw_poly_v2i_n__span_y_sort(const void *a_p, const void *b_p, void * * } while (++x != x_end); * \endcode */ -void BLI_bitmap_draw_2d_poly_v2i_n( - const int xmin, const int ymin, const int xmax, const int ymax, - const int verts[][2], const int verts_len, - void (*callback)(int x, int x_end, int y, void *), void *user_data) +void BLI_bitmap_draw_2d_poly_v2i_n(const int xmin, + const int ymin, + const int xmax, + const int ymax, + const int verts[][2], + const int verts_len, + void (*callback)(int x, int x_end, int y, void *), + void *user_data) { - /* Originally by Darel Rex Finley, 2007. - * Optimized by Campbell Barton, 2016 to track sorted intersections. */ - - int (*span_y)[2] = MEM_mallocN(sizeof(*span_y) * (size_t)verts_len, __func__); - int span_y_len = 0; - - for (int i_curr = 0, i_prev = verts_len - 1; i_curr < verts_len; i_prev = i_curr++) { - const int *co_prev = verts[i_prev]; - const int *co_curr = verts[i_curr]; - - if (co_prev[1] != co_curr[1]) { - /* Any segments entirely above or below the area of interest can be skipped. */ - if ((min_ii(co_prev[1], co_curr[1]) >= ymax) || - (max_ii(co_prev[1], co_curr[1]) < ymin)) - { - continue; - } - - int *s = span_y[span_y_len++]; - if (co_prev[1] < co_curr[1]) { - s[0] = i_prev; - s[1] = i_curr; - } - else { - s[0] = i_curr; - s[1] = i_prev; - } - } - } - - BLI_qsort_r(span_y, (size_t)span_y_len, sizeof(*span_y), draw_poly_v2i_n__span_y_sort, (void *)verts); - - struct NodeX { - int span_y_index; - int x; - } *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(verts_len + 1), __func__); - int node_x_len = 0; - - int span_y_index = 0; - if (span_y_len != 0 && verts[span_y[0][0]][1] < ymin) { - while ((span_y_index < span_y_len) && - (verts[span_y[span_y_index][0]][1] < ymin)) - { - BLI_assert(verts[span_y[span_y_index][0]][1] < - verts[span_y[span_y_index][1]][1]); - if (verts[span_y[span_y_index][1]][1] >= ymin) { - struct NodeX *n = &node_x[node_x_len++]; - n->span_y_index = span_y_index; - } - span_y_index += 1; - } - } - - /* Loop through the rows of the image. */ - for (int pixel_y = ymin; pixel_y < ymax; pixel_y++) { - bool is_sorted = true; - bool do_remove = false; - - for (int i = 0, x_ix_prev = INT_MIN; i < node_x_len; i++) { - struct NodeX *n = &node_x[i]; - const int *s = span_y[n->span_y_index]; - const int *co_prev = verts[s[0]]; - const int *co_curr = verts[s[1]]; - - BLI_assert(co_prev[1] < pixel_y && co_curr[1] >= pixel_y); - - const double x = (co_prev[0] - co_curr[0]); - const double y = (co_prev[1] - co_curr[1]); - const double y_px = (pixel_y - co_curr[1]); - const int x_ix = (int)((double)co_curr[0] + ((y_px / y) * x)); - n->x = x_ix; - - if (is_sorted && (x_ix_prev > x_ix)) { - is_sorted = false; - } - if (do_remove == false && co_curr[1] == pixel_y) { - do_remove = true; - } - x_ix_prev = x_ix; - } - - /* Sort the nodes, via a simple "Bubble" sort. */ - if (is_sorted == false) { - int i = 0; - const int node_x_end = node_x_len - 1; - while (i < node_x_end) { - if (node_x[i].x > node_x[i + 1].x) { - SWAP(struct NodeX, node_x[i], node_x[i + 1]); - if (i != 0) { - i -= 1; - } - } - else { - i += 1; - } - } - } - - /* Fill the pixels between node pairs. */ - for (int i = 0; i < node_x_len; i += 2) { - int x_src = node_x[i].x; - int x_dst = node_x[i + 1].x; - - if (x_src >= xmax) { - break; - } - - if (x_dst > xmin) { - if (x_src < xmin) { - x_src = xmin; - } - if (x_dst > xmax) { - x_dst = xmax; - } - /* for single call per x-span */ - if (x_src < x_dst) { - callback(x_src - xmin, x_dst - xmin, pixel_y - ymin, user_data); - } - } - } - - /* Clear finalized nodes in one pass, only when needed - * (avoids excessive array-resizing). */ - if (do_remove == true) { - int i_dst = 0; - for (int i_src = 0; i_src < node_x_len; i_src += 1) { - const int *s = span_y[node_x[i_src].span_y_index]; - const int *co = verts[s[1]]; - if (co[1] != pixel_y) { - if (i_dst != i_src) { - /* x is initialized for the next pixel_y (no need to adjust here) */ - node_x[i_dst].span_y_index = node_x[i_src].span_y_index; - } - i_dst += 1; - } - } - node_x_len = i_dst; - } - - /* Scan for new x-nodes */ - while ((span_y_index < span_y_len) && - (verts[span_y[span_y_index][0]][1] == pixel_y)) - { - /* note, node_x these are just added at the end, - * not ideal but sorting once will resolve. */ - - /* x is initialized for the next pixel_y */ - struct NodeX *n = &node_x[node_x_len++]; - n->span_y_index = span_y_index; - span_y_index += 1; - } - } - - MEM_freeN(span_y); - MEM_freeN(node_x); + /* Originally by Darel Rex Finley, 2007. + * Optimized by Campbell Barton, 2016 to track sorted intersections. */ + + int(*span_y)[2] = MEM_mallocN(sizeof(*span_y) * (size_t)verts_len, __func__); + int span_y_len = 0; + + for (int i_curr = 0, i_prev = verts_len - 1; i_curr < verts_len; i_prev = i_curr++) { + const int *co_prev = verts[i_prev]; + const int *co_curr = verts[i_curr]; + + if (co_prev[1] != co_curr[1]) { + /* Any segments entirely above or below the area of interest can be skipped. */ + if ((min_ii(co_prev[1], co_curr[1]) >= ymax) || (max_ii(co_prev[1], co_curr[1]) < ymin)) { + continue; + } + + int *s = span_y[span_y_len++]; + if (co_prev[1] < co_curr[1]) { + s[0] = i_prev; + s[1] = i_curr; + } + else { + s[0] = i_curr; + s[1] = i_prev; + } + } + } + + BLI_qsort_r( + span_y, (size_t)span_y_len, sizeof(*span_y), draw_poly_v2i_n__span_y_sort, (void *)verts); + + struct NodeX { + int span_y_index; + int x; + } *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(verts_len + 1), __func__); + int node_x_len = 0; + + int span_y_index = 0; + if (span_y_len != 0 && verts[span_y[0][0]][1] < ymin) { + while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] < ymin)) { + BLI_assert(verts[span_y[span_y_index][0]][1] < verts[span_y[span_y_index][1]][1]); + if (verts[span_y[span_y_index][1]][1] >= ymin) { + struct NodeX *n = &node_x[node_x_len++]; + n->span_y_index = span_y_index; + } + span_y_index += 1; + } + } + + /* Loop through the rows of the image. */ + for (int pixel_y = ymin; pixel_y < ymax; pixel_y++) { + bool is_sorted = true; + bool do_remove = false; + + for (int i = 0, x_ix_prev = INT_MIN; i < node_x_len; i++) { + struct NodeX *n = &node_x[i]; + const int *s = span_y[n->span_y_index]; + const int *co_prev = verts[s[0]]; + const int *co_curr = verts[s[1]]; + + BLI_assert(co_prev[1] < pixel_y && co_curr[1] >= pixel_y); + + const double x = (co_prev[0] - co_curr[0]); + const double y = (co_prev[1] - co_curr[1]); + const double y_px = (pixel_y - co_curr[1]); + const int x_ix = (int)((double)co_curr[0] + ((y_px / y) * x)); + n->x = x_ix; + + if (is_sorted && (x_ix_prev > x_ix)) { + is_sorted = false; + } + if (do_remove == false && co_curr[1] == pixel_y) { + do_remove = true; + } + x_ix_prev = x_ix; + } + + /* Sort the nodes, via a simple "Bubble" sort. */ + if (is_sorted == false) { + int i = 0; + const int node_x_end = node_x_len - 1; + while (i < node_x_end) { + if (node_x[i].x > node_x[i + 1].x) { + SWAP(struct NodeX, node_x[i], node_x[i + 1]); + if (i != 0) { + i -= 1; + } + } + else { + i += 1; + } + } + } + + /* Fill the pixels between node pairs. */ + for (int i = 0; i < node_x_len; i += 2) { + int x_src = node_x[i].x; + int x_dst = node_x[i + 1].x; + + if (x_src >= xmax) { + break; + } + + if (x_dst > xmin) { + if (x_src < xmin) { + x_src = xmin; + } + if (x_dst > xmax) { + x_dst = xmax; + } + /* for single call per x-span */ + if (x_src < x_dst) { + callback(x_src - xmin, x_dst - xmin, pixel_y - ymin, user_data); + } + } + } + + /* Clear finalized nodes in one pass, only when needed + * (avoids excessive array-resizing). */ + if (do_remove == true) { + int i_dst = 0; + for (int i_src = 0; i_src < node_x_len; i_src += 1) { + const int *s = span_y[node_x[i_src].span_y_index]; + const int *co = verts[s[1]]; + if (co[1] != pixel_y) { + if (i_dst != i_src) { + /* x is initialized for the next pixel_y (no need to adjust here) */ + node_x[i_dst].span_y_index = node_x[i_src].span_y_index; + } + i_dst += 1; + } + } + node_x_len = i_dst; + } + + /* Scan for new x-nodes */ + while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] == pixel_y)) { + /* note, node_x these are just added at the end, + * not ideal but sorting once will resolve. */ + + /* x is initialized for the next pixel_y */ + struct NodeX *n = &node_x[node_x_len++]; + n->span_y_index = span_y_index; + span_y_index += 1; + } + } + + MEM_freeN(span_y); + MEM_freeN(node_x); } /** \} */ diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c index c90038b78a1..f05523b8897 100644 --- a/source/blender/blenlib/intern/boxpack_2d.c +++ b/source/blender/blenlib/intern/boxpack_2d.c @@ -19,15 +19,15 @@ */ #include <stdlib.h> /* for qsort */ -#include <math.h> /* for fabsf */ +#include <math.h> /* for fabsf */ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -#include "BLI_boxpack_2d.h" /* own include */ +#include "BLI_boxpack_2d.h" /* own include */ -#include "BLI_sort.h" /* qsort_r */ -#define qsort_r BLI_qsort_r +#include "BLI_sort.h" /* qsort_r */ +#define qsort_r BLI_qsort_r #include "BLI_strict_flags.h" @@ -42,31 +42,30 @@ /* slight bias, needed when packing many boxes the _exact_ same size */ #define USE_PACK_BIAS - /* BoxPacker for backing 2D rectangles into a square * * The defined Below are for internal use only */ typedef struct BoxVert { - float x; - float y; + float x; + float y; - int free : 8; /* vert status */ - uint used : 1; - uint _pad : 23; - uint index; + int free : 8; /* vert status */ + uint used : 1; + uint _pad : 23; + uint index; - struct BoxPack *trb; /* top right box */ - struct BoxPack *blb; /* bottom left box */ - struct BoxPack *brb; /* bottom right box */ - struct BoxPack *tlb; /* top left box */ + struct BoxPack *trb; /* top right box */ + struct BoxPack *blb; /* bottom left box */ + struct BoxPack *brb; /* bottom right box */ + struct BoxPack *tlb; /* top left box */ - /* Store last intersecting boxes here - * speedup intersection testing */ - struct BoxPack *isect_cache[4]; + /* Store last intersecting boxes here + * speedup intersection testing */ + struct BoxPack *isect_cache[4]; #ifdef USE_PACK_BIAS - float bias; - int _pad2; + float bias; + int _pad2; #endif } BoxVert; @@ -88,8 +87,8 @@ typedef struct BoxVert { BLI_INLINE int quad_flag(uint q) { - BLI_assert(q < 4); - return (1 << q); + BLI_assert(q < 4); + return (1 << q); } #define BL 0 @@ -102,106 +101,105 @@ BLI_INLINE int quad_flag(uint q) static float box_xmin_get(const BoxPack *box) { - return box->v[BL]->x; + return box->v[BL]->x; } static float box_xmax_get(const BoxPack *box) { - return box->v[TR]->x; + return box->v[TR]->x; } static float box_ymin_get(const BoxPack *box) { - return box->v[BL]->y; + return box->v[BL]->y; } static float box_ymax_get(const BoxPack *box) { - return box->v[TR]->y; + return box->v[TR]->y; } /** \} */ - /** \name Box Placement * \{ */ BLI_INLINE void box_v34x_update(BoxPack *box) { - box->v[TL]->x = box->v[BL]->x; - box->v[BR]->x = box->v[TR]->x; + box->v[TL]->x = box->v[BL]->x; + box->v[BR]->x = box->v[TR]->x; } BLI_INLINE void box_v34y_update(BoxPack *box) { - box->v[TL]->y = box->v[TR]->y; - box->v[BR]->y = box->v[BL]->y; + box->v[TL]->y = box->v[TR]->y; + box->v[BR]->y = box->v[BL]->y; } static void box_xmin_set(BoxPack *box, const float f) { - box->v[TR]->x = f + box->w; - box->v[BL]->x = f; - box_v34x_update(box); + box->v[TR]->x = f + box->w; + box->v[BL]->x = f; + box_v34x_update(box); } static void box_xmax_set(BoxPack *box, const float f) { - box->v[BL]->x = f - box->w; - box->v[TR]->x = f; - box_v34x_update(box); + box->v[BL]->x = f - box->w; + box->v[TR]->x = f; + box_v34x_update(box); } static void box_ymin_set(BoxPack *box, const float f) { - box->v[TR]->y = f + box->h; - box->v[BL]->y = f; - box_v34y_update(box); + box->v[TR]->y = f + box->h; + box->v[BL]->y = f; + box_v34y_update(box); } static void box_ymax_set(BoxPack *box, const float f) { - box->v[BL]->y = f - box->h; - box->v[TR]->y = f; - box_v34y_update(box); + box->v[BL]->y = f - box->h; + box->v[TR]->y = f; + box_v34y_update(box); } /** \} */ - /** \name Box Utils * \{ */ static float box_area(const BoxPack *box) { - return box->w * box->h; + return box->w * box->h; } static bool box_isect(const BoxPack *box_a, const BoxPack *box_b) { - return !(box_xmin_get(box_a) + EPSILON >= box_xmax_get(box_b) || - box_ymin_get(box_a) + EPSILON >= box_ymax_get(box_b) || - box_xmax_get(box_a) - EPSILON <= box_xmin_get(box_b) || - box_ymax_get(box_a) - EPSILON <= box_ymin_get(box_b)); + return !(box_xmin_get(box_a) + EPSILON >= box_xmax_get(box_b) || + box_ymin_get(box_a) + EPSILON >= box_ymax_get(box_b) || + box_xmax_get(box_a) - EPSILON <= box_xmin_get(box_b) || + box_ymax_get(box_a) - EPSILON <= box_ymin_get(box_b)); } /** \} */ - /* compiler should inline */ -static float max_ff(const float a, const float b) { return b > a ? b : a; } +static float max_ff(const float a, const float b) +{ + return b > a ? b : a; +} #ifdef USE_PACK_BIAS /* set when used is enabled */ static void vert_bias_update(BoxVert *v) { - BLI_assert(v->used); - v->bias = (v->x * v->y) * EPSILON_BIAS; + BLI_assert(v->used); + v->bias = (v->x * v->y) * EPSILON_BIAS; } #endif #if 0 -#define BOXDEBUG(b) \ - printf("\tBox Debug i %i, w:%.3f h:%.3f x:%.3f y:%.3f\n", \ - b->index, b->w, b->h, b->x, b->y) +# define BOXDEBUG(b) \ + printf("\tBox Debug i %i, w:%.3f h:%.3f x:%.3f y:%.3f\n", b->index, b->w, b->h, b->x, b->y) #endif /** \name Box/Vert Sorting @@ -210,13 +208,17 @@ static void vert_bias_update(BoxVert *v) /* qsort function - sort largest to smallest */ static int box_areasort(const void *p1, const void *p2) { - const BoxPack *b1 = p1, *b2 = p2; - const float a1 = box_area(b1); - const float a2 = box_area(b2); - - if (a1 < a2) { return 1; } - else if (a1 > a2) { return -1; } - return 0; + const BoxPack *b1 = p1, *b2 = p2; + const float a1 = box_area(b1); + const float a2 = box_area(b2); + + if (a1 < a2) { + return 1; + } + else if (a1 > a2) { + return -1; + } + return 0; } /* qsort vertex sorting function @@ -225,38 +227,48 @@ static int box_areasort(const void *p1, const void *p2) * the bounds of the existing backed area where possible */ struct VertSortContext { - BoxVert *vertarray; - float box_width, box_height; + BoxVert *vertarray; + float box_width, box_height; }; static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p) { - const struct VertSortContext *vs_ctx = vs_ctx_p; - const BoxVert *v1, *v2; - float a1, a2; + const struct VertSortContext *vs_ctx = vs_ctx_p; + const BoxVert *v1, *v2; + float a1, a2; - v1 = &vs_ctx->vertarray[*((const uint *)p1)]; - v2 = &vs_ctx->vertarray[*((const uint *)p2)]; + v1 = &vs_ctx->vertarray[*((const uint *)p1)]; + v2 = &vs_ctx->vertarray[*((const uint *)p2)]; #ifdef USE_FREE_STRIP - /* push free verts to the end so we can strip */ - if (UNLIKELY(v1->free == 0 && v2->free == 0)) { return 0; } - else if (UNLIKELY(v1->free == 0)) { return 1; } - else if (UNLIKELY(v2->free == 0)) { return -1; } + /* push free verts to the end so we can strip */ + if (UNLIKELY(v1->free == 0 && v2->free == 0)) { + return 0; + } + else if (UNLIKELY(v1->free == 0)) { + return 1; + } + else if (UNLIKELY(v2->free == 0)) { + return -1; + } #endif - a1 = max_ff(v1->x + vs_ctx->box_width, v1->y + vs_ctx->box_height); - a2 = max_ff(v2->x + vs_ctx->box_width, v2->y + vs_ctx->box_height); + a1 = max_ff(v1->x + vs_ctx->box_width, v1->y + vs_ctx->box_height); + a2 = max_ff(v2->x + vs_ctx->box_width, v2->y + vs_ctx->box_height); #ifdef USE_PACK_BIAS - a1 += v1->bias; - a2 += v2->bias; + a1 += v1->bias; + a2 += v2->bias; #endif - /* sort largest to smallest */ - if (a1 > a2) { return 1; } - else if (a1 < a2) { return -1; } - return 0; + /* sort largest to smallest */ + if (a1 > a2) { + return 1; + } + else if (a1 < a2) { + return -1; + } + return 0; } /** \} */ @@ -276,394 +288,388 @@ static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p) * */ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r_tot_y) { - uint box_index, verts_pack_len, i, j, k; - uint *vertex_pack_indices; /* an array of indices used for sorting verts */ - bool isect; - float tot_x = 0.0f, tot_y = 0.0f; - - BoxPack *box, *box_test; /*current box and another for intersection tests*/ - BoxVert *vert; /* the current vert */ - - struct VertSortContext vs_ctx; - - if (!len) { - *r_tot_x = tot_x; - *r_tot_y = tot_y; - return; - } - - /* Sort boxes, biggest first */ - qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort); - - /* add verts to the boxes, these are only used internally */ - vert = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts"); - vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices"); - - vs_ctx.vertarray = vert; - - for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) { - - vert->blb = vert->brb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = CORNERFLAGS & ~TRF; - vert->trb = box; - vert->used = false; - vert->index = i++; - box->v[BL] = vert++; - - vert->trb = vert->brb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = CORNERFLAGS & ~BLF; - vert->blb = box; - vert->used = false; - vert->index = i++; - box->v[TR] = vert++; - - vert->trb = vert->blb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = CORNERFLAGS & ~BRF; - vert->brb = box; - vert->used = false; - vert->index = i++; - box->v[TL] = vert++; - - vert->trb = vert->blb = vert->brb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = CORNERFLAGS & ~TLF; - vert->tlb = box; - vert->used = false; - vert->index = i++; - box->v[BR] = vert++; - } - vert = NULL; - - /* Pack the First box! - * then enter the main box-packing loop */ - - box = boxarray; /* get the first box */ - /* First time, no boxes packed */ - box->v[BL]->free = 0; /* Can't use any if these */ - box->v[BR]->free &= ~(BLF | BRF); - box->v[TL]->free &= ~(BLF | TLF); - - tot_x = box->w; - tot_y = box->h; - - /* This sets all the vertex locations */ - box_xmin_set(box, 0.0f); - box_ymin_set(box, 0.0f); - box->x = box->y = 0.0f; - - for (i = 0; i < 4; i++) { - box->v[i]->used = true; + uint box_index, verts_pack_len, i, j, k; + uint *vertex_pack_indices; /* an array of indices used for sorting verts */ + bool isect; + float tot_x = 0.0f, tot_y = 0.0f; + + BoxPack *box, *box_test; /*current box and another for intersection tests*/ + BoxVert *vert; /* the current vert */ + + struct VertSortContext vs_ctx; + + if (!len) { + *r_tot_x = tot_x; + *r_tot_y = tot_y; + return; + } + + /* Sort boxes, biggest first */ + qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort); + + /* add verts to the boxes, these are only used internally */ + vert = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts"); + vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices"); + + vs_ctx.vertarray = vert; + + for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) { + + vert->blb = vert->brb = vert->tlb = vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->free = CORNERFLAGS & ~TRF; + vert->trb = box; + vert->used = false; + vert->index = i++; + box->v[BL] = vert++; + + vert->trb = vert->brb = vert->tlb = vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->free = CORNERFLAGS & ~BLF; + vert->blb = box; + vert->used = false; + vert->index = i++; + box->v[TR] = vert++; + + vert->trb = vert->blb = vert->tlb = vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->free = CORNERFLAGS & ~BRF; + vert->brb = box; + vert->used = false; + vert->index = i++; + box->v[TL] = vert++; + + vert->trb = vert->blb = vert->brb = vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->free = CORNERFLAGS & ~TLF; + vert->tlb = box; + vert->used = false; + vert->index = i++; + box->v[BR] = vert++; + } + vert = NULL; + + /* Pack the First box! + * then enter the main box-packing loop */ + + box = boxarray; /* get the first box */ + /* First time, no boxes packed */ + box->v[BL]->free = 0; /* Can't use any if these */ + box->v[BR]->free &= ~(BLF | BRF); + box->v[TL]->free &= ~(BLF | TLF); + + tot_x = box->w; + tot_y = box->h; + + /* This sets all the vertex locations */ + box_xmin_set(box, 0.0f); + box_ymin_set(box, 0.0f); + box->x = box->y = 0.0f; + + for (i = 0; i < 4; i++) { + box->v[i]->used = true; #ifdef USE_PACK_BIAS - vert_bias_update(box->v[i]); + vert_bias_update(box->v[i]); #endif - } + } - for (i = 0; i < 3; i++) { - vertex_pack_indices[i] = box->v[i + 1]->index; - } - verts_pack_len = 3; - box++; /* next box, needed for the loop below */ - /* ...done packing the first box */ + for (i = 0; i < 3; i++) { + vertex_pack_indices[i] = box->v[i + 1]->index; + } + verts_pack_len = 3; + box++; /* next box, needed for the loop below */ + /* ...done packing the first box */ - /* Main boxpacking loop */ - for (box_index = 1; box_index < len; box_index++, box++) { + /* Main boxpacking loop */ + for (box_index = 1; box_index < len; box_index++, box++) { - /* These floats are used for sorting re-sorting */ - vs_ctx.box_width = box->w; - vs_ctx.box_height = box->h; + /* These floats are used for sorting re-sorting */ + vs_ctx.box_width = box->w; + vs_ctx.box_height = box->h; - qsort_r(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort, &vs_ctx); + qsort_r(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort, &vs_ctx); #ifdef USE_FREE_STRIP - /* strip free vertices */ - i = verts_pack_len - 1; - while ((i != 0) && vs_ctx.vertarray[vertex_pack_indices[i]].free == 0) { - i--; - } - verts_pack_len = i + 1; + /* strip free vertices */ + i = verts_pack_len - 1; + while ((i != 0) && vs_ctx.vertarray[vertex_pack_indices[i]].free == 0) { + i--; + } + verts_pack_len = i + 1; #endif - /* Pack the box in with the others */ - /* sort the verts */ - isect = true; - - for (i = 0; i < verts_pack_len && isect; i++) { - vert = &vs_ctx.vertarray[vertex_pack_indices[i]]; - /* printf("\ttesting vert %i %i %i %f %f\n", i, - * vert->free, verts_pack_len, vert->x, vert->y); */ - - /* This vert has a free quadrant - * Test if we can place the box here - * vert->free & quad_flags[j] - Checks - * */ - - for (j = 0; (j < 4) && isect; j++) { - if (vert->free & quad_flag(j)) { - switch (j) { - case BL: - box_xmax_set(box, vert->x); - box_ymax_set(box, vert->y); - break; - case TR: - box_xmin_set(box, vert->x); - box_ymin_set(box, vert->y); - break; - case TL: - box_xmax_set(box, vert->x); - box_ymin_set(box, vert->y); - break; - case BR: - box_xmin_set(box, vert->x); - box_ymax_set(box, vert->y); - break; - } - - /* Now we need to check that the box intersects - * with any other boxes - * Assume no intersection... */ - isect = false; - - if ( /* Constrain boxes to positive X/Y values */ - box_xmin_get(box) < 0.0f || box_ymin_get(box) < 0.0f || - /* check for last intersected */ - (vert->isect_cache[j] && - box_isect(box, vert->isect_cache[j]))) - { - /* Here we check that the last intersected - * box will intersect with this one using - * isect_cache that can store a pointer to a - * box for each quadrant - * big speedup */ - isect = true; - } - else { - /* do a full search for colliding box - * this is really slow, some spatially divided - * data-structure would be better */ - for (box_test = boxarray; box_test != box; box_test++) { - if (box_isect(box, box_test)) { - /* Store the last intersecting here as cache - * for faster checking next time around */ - vert->isect_cache[j] = box_test; - isect = true; - break; - } - } - } - - if (!isect) { - - /* maintain the total width and height */ - tot_x = max_ff(box_xmax_get(box), tot_x); - tot_y = max_ff(box_ymax_get(box), tot_y); - - /* Place the box */ - vert->free &= (signed char)(~quad_flag(j)); - - switch (j) { - case TR: - box->v[BL] = vert; - vert->trb = box; - break; - case TL: - box->v[BR] = vert; - vert->tlb = box; - break; - case BR: - box->v[TL] = vert; - vert->brb = box; - break; - case BL: - box->v[TR] = vert; - vert->blb = box; - break; - } - - /* Mask free flags for verts that are - * on the bottom or side so we don't get - * boxes outside the given rectangle ares - * - * We can do an else/if here because only the first - * box can be at the very bottom left corner */ - if (box_xmin_get(box) <= 0) { - box->v[TL]->free &= ~(TLF | BLF); - box->v[BL]->free &= ~(TLF | BLF); - } - else if (box_ymin_get(box) <= 0) { - box->v[BL]->free &= ~(BRF | BLF); - box->v[BR]->free &= ~(BRF | BLF); - } - - /* The following block of code does a logical - * check with 2 adjacent boxes, its possible to - * flag verts on one or both of the boxes - * as being used by checking the width or - * height of both boxes */ - if (vert->tlb && vert->trb && (box == vert->tlb || box == vert->trb)) { - if (UNLIKELY(fabsf(vert->tlb->h - vert->trb->h) < EPSILON_MERGE)) { + /* Pack the box in with the others */ + /* sort the verts */ + isect = true; + + for (i = 0; i < verts_pack_len && isect; i++) { + vert = &vs_ctx.vertarray[vertex_pack_indices[i]]; + /* printf("\ttesting vert %i %i %i %f %f\n", i, + * vert->free, verts_pack_len, vert->x, vert->y); */ + + /* This vert has a free quadrant + * Test if we can place the box here + * vert->free & quad_flags[j] - Checks + * */ + + for (j = 0; (j < 4) && isect; j++) { + if (vert->free & quad_flag(j)) { + switch (j) { + case BL: + box_xmax_set(box, vert->x); + box_ymax_set(box, vert->y); + break; + case TR: + box_xmin_set(box, vert->x); + box_ymin_set(box, vert->y); + break; + case TL: + box_xmax_set(box, vert->x); + box_ymin_set(box, vert->y); + break; + case BR: + box_xmin_set(box, vert->x); + box_ymax_set(box, vert->y); + break; + } + + /* Now we need to check that the box intersects + * with any other boxes + * Assume no intersection... */ + isect = false; + + if (/* Constrain boxes to positive X/Y values */ + box_xmin_get(box) < 0.0f || box_ymin_get(box) < 0.0f || + /* check for last intersected */ + (vert->isect_cache[j] && box_isect(box, vert->isect_cache[j]))) { + /* Here we check that the last intersected + * box will intersect with this one using + * isect_cache that can store a pointer to a + * box for each quadrant + * big speedup */ + isect = true; + } + else { + /* do a full search for colliding box + * this is really slow, some spatially divided + * data-structure would be better */ + for (box_test = boxarray; box_test != box; box_test++) { + if (box_isect(box, box_test)) { + /* Store the last intersecting here as cache + * for faster checking next time around */ + vert->isect_cache[j] = box_test; + isect = true; + break; + } + } + } + + if (!isect) { + + /* maintain the total width and height */ + tot_x = max_ff(box_xmax_get(box), tot_x); + tot_y = max_ff(box_ymax_get(box), tot_y); + + /* Place the box */ + vert->free &= (signed char)(~quad_flag(j)); + + switch (j) { + case TR: + box->v[BL] = vert; + vert->trb = box; + break; + case TL: + box->v[BR] = vert; + vert->tlb = box; + break; + case BR: + box->v[TL] = vert; + vert->brb = box; + break; + case BL: + box->v[TR] = vert; + vert->blb = box; + break; + } + + /* Mask free flags for verts that are + * on the bottom or side so we don't get + * boxes outside the given rectangle ares + * + * We can do an else/if here because only the first + * box can be at the very bottom left corner */ + if (box_xmin_get(box) <= 0) { + box->v[TL]->free &= ~(TLF | BLF); + box->v[BL]->free &= ~(TLF | BLF); + } + else if (box_ymin_get(box) <= 0) { + box->v[BL]->free &= ~(BRF | BLF); + box->v[BR]->free &= ~(BRF | BLF); + } + + /* The following block of code does a logical + * check with 2 adjacent boxes, its possible to + * flag verts on one or both of the boxes + * as being used by checking the width or + * height of both boxes */ + if (vert->tlb && vert->trb && (box == vert->tlb || box == vert->trb)) { + if (UNLIKELY(fabsf(vert->tlb->h - vert->trb->h) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->trb->v[TL]) # define B (vert->tlb->v[TR]) # define MASK (BLF | BRF) - BLI_assert(A->used != B->used); - if (A->used) { - A->free &= B->free & ~MASK; - B = A; - } - else { - B->free &= A->free & ~MASK; - A = B; - } - BLI_assert((A->free & MASK) == 0); + BLI_assert(A->used != B->used); + if (A->used) { + A->free &= B->free & ~MASK; + B = A; + } + else { + B->free &= A->free & ~MASK; + A = B; + } + BLI_assert((A->free & MASK) == 0); # undef A # undef B # undef MASK #else - vert->tlb->v[TR]->free &= ~BLF; - vert->trb->v[TL]->free &= ~BRF; + vert->tlb->v[TR]->free &= ~BLF; + vert->trb->v[TL]->free &= ~BRF; #endif - } - else if (vert->tlb->h > vert->trb->h) { - vert->trb->v[TL]->free &= ~(TLF | BLF); - } - else /* if (vert->tlb->h < vert->trb->h) */ { - vert->tlb->v[TR]->free &= ~(TRF | BRF); - } - } - else if (vert->blb && vert->brb && (box == vert->blb || box == vert->brb)) { - if (UNLIKELY(fabsf(vert->blb->h - vert->brb->h) < EPSILON_MERGE)) { + } + else if (vert->tlb->h > vert->trb->h) { + vert->trb->v[TL]->free &= ~(TLF | BLF); + } + else /* if (vert->tlb->h < vert->trb->h) */ { + vert->tlb->v[TR]->free &= ~(TRF | BRF); + } + } + else if (vert->blb && vert->brb && (box == vert->blb || box == vert->brb)) { + if (UNLIKELY(fabsf(vert->blb->h - vert->brb->h) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->blb->v[BR]) # define B (vert->brb->v[BL]) # define MASK (TRF | TLF) - BLI_assert(A->used != B->used); - if (A->used) { - A->free &= B->free & ~MASK; - B = A; - } - else { - B->free &= A->free & ~MASK; - A = B; - } - BLI_assert((A->free & MASK) == 0); + BLI_assert(A->used != B->used); + if (A->used) { + A->free &= B->free & ~MASK; + B = A; + } + else { + B->free &= A->free & ~MASK; + A = B; + } + BLI_assert((A->free & MASK) == 0); # undef A # undef B # undef MASK #else - vert->blb->v[BR]->free &= ~TRF; - vert->brb->v[BL]->free &= ~TLF; + vert->blb->v[BR]->free &= ~TRF; + vert->brb->v[BL]->free &= ~TLF; #endif - } - else if (vert->blb->h > vert->brb->h) { - vert->brb->v[BL]->free &= ~(TLF | BLF); - } - else /* if (vert->blb->h < vert->brb->h) */ { - vert->blb->v[BR]->free &= ~(TRF | BRF); - } - } - /* Horizontal */ - if (vert->tlb && vert->blb && (box == vert->tlb || box == vert->blb)) { - if (UNLIKELY(fabsf(vert->tlb->w - vert->blb->w) < EPSILON_MERGE)) { + } + else if (vert->blb->h > vert->brb->h) { + vert->brb->v[BL]->free &= ~(TLF | BLF); + } + else /* if (vert->blb->h < vert->brb->h) */ { + vert->blb->v[BR]->free &= ~(TRF | BRF); + } + } + /* Horizontal */ + if (vert->tlb && vert->blb && (box == vert->tlb || box == vert->blb)) { + if (UNLIKELY(fabsf(vert->tlb->w - vert->blb->w) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->blb->v[TL]) # define B (vert->tlb->v[BL]) # define MASK (TRF | BRF) - BLI_assert(A->used != B->used); - if (A->used) { - A->free &= B->free & ~MASK; - B = A; - } - else { - B->free &= A->free & ~MASK; - A = B; - } - BLI_assert((A->free & MASK) == 0); + BLI_assert(A->used != B->used); + if (A->used) { + A->free &= B->free & ~MASK; + B = A; + } + else { + B->free &= A->free & ~MASK; + A = B; + } + BLI_assert((A->free & MASK) == 0); # undef A # undef B # undef MASK #else - vert->blb->v[TL]->free &= ~TRF; - vert->tlb->v[BL]->free &= ~BRF; + vert->blb->v[TL]->free &= ~TRF; + vert->tlb->v[BL]->free &= ~BRF; #endif - } - else if (vert->tlb->w > vert->blb->w) { - vert->blb->v[TL]->free &= ~(TLF | TRF); - } - else /* if (vert->tlb->w < vert->blb->w) */ { - vert->tlb->v[BL]->free &= ~(BLF | BRF); - } - } - else if (vert->trb && vert->brb && (box == vert->trb || box == vert->brb)) { - if (UNLIKELY(fabsf(vert->trb->w - vert->brb->w) < EPSILON_MERGE)) { + } + else if (vert->tlb->w > vert->blb->w) { + vert->blb->v[TL]->free &= ~(TLF | TRF); + } + else /* if (vert->tlb->w < vert->blb->w) */ { + vert->tlb->v[BL]->free &= ~(BLF | BRF); + } + } + else if (vert->trb && vert->brb && (box == vert->trb || box == vert->brb)) { + if (UNLIKELY(fabsf(vert->trb->w - vert->brb->w) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->brb->v[TR]) # define B (vert->trb->v[BR]) # define MASK (TLF | BLF) - BLI_assert(A->used != B->used); - if (A->used) { - A->free &= B->free & ~MASK; - B = A; - } - else { - B->free &= A->free & ~MASK; - A = B; - } - BLI_assert((A->free & MASK) == 0); + BLI_assert(A->used != B->used); + if (A->used) { + A->free &= B->free & ~MASK; + B = A; + } + else { + B->free &= A->free & ~MASK; + A = B; + } + BLI_assert((A->free & MASK) == 0); # undef A # undef B # undef MASK #else - vert->brb->v[TR]->free &= ~TLF; - vert->trb->v[BR]->free &= ~BLF; + vert->brb->v[TR]->free &= ~TLF; + vert->trb->v[BR]->free &= ~BLF; #endif - } - else if (vert->trb->w > vert->brb->w) { - vert->brb->v[TR]->free &= ~(TLF | TRF); - } - else /* if (vert->trb->w < vert->brb->w) */ { - vert->trb->v[BR]->free &= ~(BLF | BRF); - } - } - /* End logical check */ - - for (k = 0; k < 4; k++) { - if (box->v[k]->used == false) { - box->v[k]->used = true; + } + else if (vert->trb->w > vert->brb->w) { + vert->brb->v[TR]->free &= ~(TLF | TRF); + } + else /* if (vert->trb->w < vert->brb->w) */ { + vert->trb->v[BR]->free &= ~(BLF | BRF); + } + } + /* End logical check */ + + for (k = 0; k < 4; k++) { + if (box->v[k]->used == false) { + box->v[k]->used = true; #ifdef USE_PACK_BIAS - vert_bias_update(box->v[k]); + vert_bias_update(box->v[k]); #endif - vertex_pack_indices[verts_pack_len] = box->v[k]->index; - verts_pack_len++; - } - } - /* The Box verts are only used internally - * Update the box x and y since thats what external - * functions will see */ - box->x = box_xmin_get(box); - box->y = box_ymin_get(box); - } - } - } - } - } - - *r_tot_x = tot_x; - *r_tot_y = tot_y; - - /* free all the verts, not really needed because they shouldn't be - * touched anymore but accessing the pointers would crash blender */ - for (box_index = 0; box_index < len; box_index++) { - box = boxarray + box_index; - box->v[0] = box->v[1] = box->v[2] = box->v[3] = NULL; - } - MEM_freeN(vertex_pack_indices); - MEM_freeN(vs_ctx.vertarray); + vertex_pack_indices[verts_pack_len] = box->v[k]->index; + verts_pack_len++; + } + } + /* The Box verts are only used internally + * Update the box x and y since thats what external + * functions will see */ + box->x = box_xmin_get(box); + box->y = box_ymin_get(box); + } + } + } + } + } + + *r_tot_x = tot_x; + *r_tot_y = tot_y; + + /* free all the verts, not really needed because they shouldn't be + * touched anymore but accessing the pointers would crash blender */ + for (box_index = 0; box_index < len; box_index++) { + box = boxarray + box_index; + box->v[0] = box->v[1] = box->v[2] = box->v[3] = NULL; + } + MEM_freeN(vertex_pack_indices); + MEM_freeN(vs_ctx.vertarray); } diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c index 50401fe6091..fb4350501cd 100644 --- a/source/blender/blenlib/intern/buffer.c +++ b/source/blender/blenlib/intern/buffer.c @@ -52,38 +52,38 @@ static void *buffer_alloc(BLI_Buffer *buffer, const size_t len) { - return MEM_mallocN(buffer->elem_size * len, "BLI_Buffer.data"); + return MEM_mallocN(buffer->elem_size * len, "BLI_Buffer.data"); } static void *buffer_realloc(BLI_Buffer *buffer, const size_t len) { - return MEM_reallocN_id(buffer->data, buffer->elem_size * len, "BLI_Buffer.data"); + return MEM_reallocN_id(buffer->data, buffer->elem_size * len, "BLI_Buffer.data"); } void BLI_buffer_resize(BLI_Buffer *buffer, const size_t new_count) { - if (UNLIKELY(new_count > buffer->alloc_count)) { - if (buffer->flag & BLI_BUFFER_USE_STATIC) { - void *orig = buffer->data; - - buffer->data = buffer_alloc(buffer, new_count); - memcpy(buffer->data, orig, buffer->elem_size * buffer->count); - buffer->alloc_count = new_count; - buffer->flag &= ~BLI_BUFFER_USE_STATIC; - } - else { - if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) { - buffer->alloc_count *= 2; - } - else { - buffer->alloc_count = new_count; - } - - buffer->data = buffer_realloc(buffer, buffer->alloc_count); - } - } - - buffer->count = new_count; + if (UNLIKELY(new_count > buffer->alloc_count)) { + if (buffer->flag & BLI_BUFFER_USE_STATIC) { + void *orig = buffer->data; + + buffer->data = buffer_alloc(buffer, new_count); + memcpy(buffer->data, orig, buffer->elem_size * buffer->count); + buffer->alloc_count = new_count; + buffer->flag &= ~BLI_BUFFER_USE_STATIC; + } + else { + if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) { + buffer->alloc_count *= 2; + } + else { + buffer->alloc_count = new_count; + } + + buffer->data = buffer_realloc(buffer, buffer->alloc_count); + } + } + + buffer->count = new_count; } /** @@ -93,34 +93,34 @@ void BLI_buffer_resize(BLI_Buffer *buffer, const size_t new_count) */ void BLI_buffer_reinit(BLI_Buffer *buffer, const size_t new_count) { - if (UNLIKELY(new_count > buffer->alloc_count)) { - if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) { - if (buffer->data) { - MEM_freeN(buffer->data); - } - } - - if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) { - buffer->alloc_count *= 2; - } - else { - buffer->alloc_count = new_count; - } - - buffer->flag &= ~BLI_BUFFER_USE_STATIC; - buffer->data = buffer_alloc(buffer, buffer->alloc_count); - } - - buffer->count = new_count; + if (UNLIKELY(new_count > buffer->alloc_count)) { + if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) { + if (buffer->data) { + MEM_freeN(buffer->data); + } + } + + if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) { + buffer->alloc_count *= 2; + } + else { + buffer->alloc_count = new_count; + } + + buffer->flag &= ~BLI_BUFFER_USE_STATIC; + buffer->data = buffer_alloc(buffer, buffer->alloc_count); + } + + buffer->count = new_count; } /* callers use BLI_buffer_free */ void _bli_buffer_free(BLI_Buffer *buffer) { - if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) { - if (buffer->data) { - MEM_freeN(buffer->data); - } - } - memset(buffer, 0, sizeof(*buffer)); + if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) { + if (buffer->data) { + MEM_freeN(buffer->data); + } + } + memset(buffer, 0, sizeof(*buffer)); } diff --git a/source/blender/blenlib/intern/callbacks.c b/source/blender/blenlib/intern/callbacks.c index 0f84cd588a9..c4f93a9831d 100644 --- a/source/blender/blenlib/intern/callbacks.c +++ b/source/blender/blenlib/intern/callbacks.c @@ -28,39 +28,39 @@ static ListBase callback_slots[BLI_CB_EVT_TOT] = {{NULL}}; void BLI_callback_exec(struct Main *bmain, struct ID *self, eCbEvent evt) { - ListBase *lb = &callback_slots[evt]; - bCallbackFuncStore *funcstore; + ListBase *lb = &callback_slots[evt]; + bCallbackFuncStore *funcstore; - for (funcstore = lb->first; funcstore; funcstore = funcstore->next) { - funcstore->func(bmain, self, funcstore->arg); - } + for (funcstore = lb->first; funcstore; funcstore = funcstore->next) { + funcstore->func(bmain, self, funcstore->arg); + } } void BLI_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt) { - ListBase *lb = &callback_slots[evt]; - BLI_addtail(lb, funcstore); + ListBase *lb = &callback_slots[evt]; + BLI_addtail(lb, funcstore); } void BLI_callback_global_init(void) { - /* do nothing */ + /* do nothing */ } /* call on application exit */ void BLI_callback_global_finalize(void) { - eCbEvent evt; - for (evt = 0; evt < BLI_CB_EVT_TOT; evt++) { - ListBase *lb = &callback_slots[evt]; - bCallbackFuncStore *funcstore; - bCallbackFuncStore *funcstore_next; - for (funcstore = lb->first; funcstore; funcstore = funcstore_next) { - funcstore_next = funcstore->next; - BLI_remlink(lb, funcstore); - if (funcstore->alloc) { - MEM_freeN(funcstore); - } - } - } + eCbEvent evt; + for (evt = 0; evt < BLI_CB_EVT_TOT; evt++) { + ListBase *lb = &callback_slots[evt]; + bCallbackFuncStore *funcstore; + bCallbackFuncStore *funcstore_next; + for (funcstore = lb->first; funcstore; funcstore = funcstore_next) { + funcstore_next = funcstore->next; + BLI_remlink(lb, funcstore); + if (funcstore->alloc) { + MEM_freeN(funcstore); + } + } + } } diff --git a/source/blender/blenlib/intern/convexhull_2d.c b/source/blender/blenlib/intern/convexhull_2d.c index 87471ea65a5..b37dc73db29 100644 --- a/source/blender/blenlib/intern/convexhull_2d.c +++ b/source/blender/blenlib/intern/convexhull_2d.c @@ -18,7 +18,6 @@ * \ingroup bli */ - #include <stdlib.h> #include <string.h> @@ -50,7 +49,7 @@ */ static float is_left(const float p0[2], const float p1[2], const float p2[2]) { - return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1]); + return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1]); } /** @@ -63,120 +62,130 @@ static float is_left(const float p0[2], const float p1[2], const float p2[2]) */ int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[]) { - /* the output array r_points[] will be used as the stack */ - int bot = 0; - int top = -1; /* indices for bottom and top of the stack */ - int i; /* array scan index */ - int minmin, minmax; - int maxmin, maxmax; - float xmax; - - /* Get the indices of points with min x-coord and min|max y-coord */ - float xmin = points[0][0]; - for (i = 1; i < n; i++) { - if (points[i][0] != xmin) { - break; - } - } - - minmin = 0; - minmax = i - 1; - if (minmax == n - 1) { /* degenerate case: all x-coords == xmin */ - r_points[++top] = minmin; - if (points[minmax][1] != points[minmin][1]) { - /* a nontrivial segment */ - r_points[++top] = minmax; - } - r_points[++top] = minmin; /* add polygon endpoint */ - return top + 1; - } - - /* Get the indices of points with max x-coord and min|max y-coord */ - - maxmax = n - 1; - xmax = points[n - 1][0]; - for (i = n - 2; i >= 0; i--) { - if (points[i][0] != xmax) { - break; - } - } - maxmin = i + 1; - - /* Compute the lower hull on the stack r_points */ - r_points[++top] = minmin; /* push minmin point onto stack */ - i = minmax; - while (++i <= maxmin) { - /* the lower line joins points[minmin] with points[maxmin] */ - if (is_left(points[minmin], points[maxmin], points[i]) >= 0 && i < maxmin) { - continue; /* ignore points[i] above or on the lower line */ - } - - while (top > 0) { /* there are at least 2 points on the stack */ - /* test if points[i] is left of the line at the stack top */ - if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { - break; /* points[i] is a new hull vertex */ - } - else { - top--; /* pop top point off stack */ - } - } - - r_points[++top] = i; /* push points[i] onto stack */ - } - - /* Next, compute the upper hull on the stack r_points above the bottom hull */ - if (maxmax != maxmin) { /* if distinct xmax points */ - r_points[++top] = maxmax; /* push maxmax point onto stack */ - } - - bot = top; /* the bottom point of the upper hull stack */ - i = maxmin; - while (--i >= minmax) { - /* the upper line joins points[maxmax] with points[minmax] */ - if (is_left(points[maxmax], points[minmax], points[i]) >= 0 && i > minmax) { - continue; /* ignore points[i] below or on the upper line */ - } - - while (top > bot) { /* at least 2 points on the upper stack */ - /* test if points[i] is left of the line at the stack top */ - if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { - break; /* points[i] is a new hull vertex */ - } - else { - top--; /* pop top point off stack */ - } - } - - if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) { - return top + 1; /* special case (mgomes) */ - } - - r_points[++top] = i; /* push points[i] onto stack */ - } - - if (minmax != minmin) { - r_points[++top] = minmin; /* push joining endpoint onto stack */ - } - - return top + 1; + /* the output array r_points[] will be used as the stack */ + int bot = 0; + int top = -1; /* indices for bottom and top of the stack */ + int i; /* array scan index */ + int minmin, minmax; + int maxmin, maxmax; + float xmax; + + /* Get the indices of points with min x-coord and min|max y-coord */ + float xmin = points[0][0]; + for (i = 1; i < n; i++) { + if (points[i][0] != xmin) { + break; + } + } + + minmin = 0; + minmax = i - 1; + if (minmax == n - 1) { /* degenerate case: all x-coords == xmin */ + r_points[++top] = minmin; + if (points[minmax][1] != points[minmin][1]) { + /* a nontrivial segment */ + r_points[++top] = minmax; + } + r_points[++top] = minmin; /* add polygon endpoint */ + return top + 1; + } + + /* Get the indices of points with max x-coord and min|max y-coord */ + + maxmax = n - 1; + xmax = points[n - 1][0]; + for (i = n - 2; i >= 0; i--) { + if (points[i][0] != xmax) { + break; + } + } + maxmin = i + 1; + + /* Compute the lower hull on the stack r_points */ + r_points[++top] = minmin; /* push minmin point onto stack */ + i = minmax; + while (++i <= maxmin) { + /* the lower line joins points[minmin] with points[maxmin] */ + if (is_left(points[minmin], points[maxmin], points[i]) >= 0 && i < maxmin) { + continue; /* ignore points[i] above or on the lower line */ + } + + while (top > 0) { /* there are at least 2 points on the stack */ + /* test if points[i] is left of the line at the stack top */ + if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { + break; /* points[i] is a new hull vertex */ + } + else { + top--; /* pop top point off stack */ + } + } + + r_points[++top] = i; /* push points[i] onto stack */ + } + + /* Next, compute the upper hull on the stack r_points above the bottom hull */ + if (maxmax != maxmin) { /* if distinct xmax points */ + r_points[++top] = maxmax; /* push maxmax point onto stack */ + } + + bot = top; /* the bottom point of the upper hull stack */ + i = maxmin; + while (--i >= minmax) { + /* the upper line joins points[maxmax] with points[minmax] */ + if (is_left(points[maxmax], points[minmax], points[i]) >= 0 && i > minmax) { + continue; /* ignore points[i] below or on the upper line */ + } + + while (top > bot) { /* at least 2 points on the upper stack */ + /* test if points[i] is left of the line at the stack top */ + if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { + break; /* points[i] is a new hull vertex */ + } + else { + top--; /* pop top point off stack */ + } + } + + if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) { + return top + 1; /* special case (mgomes) */ + } + + r_points[++top] = i; /* push points[i] onto stack */ + } + + if (minmax != minmin) { + r_points[++top] = minmin; /* push joining endpoint onto stack */ + } + + return top + 1; } struct PointRef { - const float *pt; /* 2d vector */ + const float *pt; /* 2d vector */ }; static int pointref_cmp_yx(const void *a_, const void *b_) { - const struct PointRef *a = a_; - const struct PointRef *b = b_; - - if (a->pt[1] > b->pt[1]) { return 1; } - else if (a->pt[1] < b->pt[1]) { return -1; } - - if (a->pt[0] > b->pt[0]) { return 1; } - else if (a->pt[0] < b->pt[0]) { return -1; } - - else { return 0; } + const struct PointRef *a = a_; + const struct PointRef *b = b_; + + if (a->pt[1] > b->pt[1]) { + return 1; + } + else if (a->pt[1] < b->pt[1]) { + return -1; + } + + if (a->pt[0] > b->pt[0]) { + return 1; + } + else if (a->pt[0] < b->pt[0]) { + return -1; + } + + else { + return 0; + } } /** @@ -191,41 +200,40 @@ static int pointref_cmp_yx(const void *a_, const void *b_) */ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) { - struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__); - float (*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__); - int *points_map; - int tot, i; + struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__); + float(*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__); + int *points_map; + int tot, i; - for (i = 0; i < n; i++) { - points_ref[i].pt = points[i]; - } + for (i = 0; i < n; i++) { + points_ref[i].pt = points[i]; + } - /* Sort the points by X, then by Y (required by the algorithm) */ - qsort(points_ref, (size_t)n, sizeof(struct PointRef), pointref_cmp_yx); + /* Sort the points by X, then by Y (required by the algorithm) */ + qsort(points_ref, (size_t)n, sizeof(struct PointRef), pointref_cmp_yx); - for (i = 0; i < n; i++) { - memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2])); - } + for (i = 0; i < n; i++) { + memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2])); + } - tot = BLI_convexhull_2d_sorted(points_sort, n, r_points); + tot = BLI_convexhull_2d_sorted(points_sort, n, r_points); - /* map back to the original index values */ - points_map = (int *)points_sort; /* abuse float array for temp storage */ - for (i = 0; i < tot; i++) { - points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points); - } + /* map back to the original index values */ + points_map = (int *)points_sort; /* abuse float array for temp storage */ + for (i = 0; i < tot; i++) { + points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points); + } - memcpy(r_points, points_map, (size_t)tot * sizeof(*points_map)); + memcpy(r_points, points_map, (size_t)tot * sizeof(*points_map)); - MEM_freeN(points_ref); - MEM_freeN(points_sort); + MEM_freeN(points_ref); + MEM_freeN(points_sort); - return tot; + return tot; } /** \} */ - /* -------------------------------------------------------------------- */ /* Helper functions */ @@ -244,49 +252,49 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) */ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) { - unsigned int i, i_prev; - float area_best = FLT_MAX; - float dvec_best[2]; /* best angle, delay atan2 */ - - i_prev = n - 1; - for (i = 0; i < n; i++) { - const float *ev_a = points_hull[i]; - const float *ev_b = points_hull[i_prev]; - float dvec[2]; /* 2d rotation matrix */ - - sub_v2_v2v2(dvec, ev_a, ev_b); - if (normalize_v2(dvec) != 0.0f) { - /* rotation matrix */ - float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; - unsigned int j; - float area; - - for (j = 0; j < n; j++) { - float tvec[2]; - mul_v2_v2_cw(tvec, dvec, points_hull[j]); - - min[0] = min_ff(min[0], tvec[0]); - min[1] = min_ff(min[1], tvec[1]); - - max[0] = max_ff(max[0], tvec[0]); - max[1] = max_ff(max[1], tvec[1]); - - area = (max[0] - min[0]) * (max[1] - min[1]); - if (area > area_best) { - break; - } - } - - if (area < area_best) { - area_best = area; - copy_v2_v2(dvec_best, dvec); - } - } - - i_prev = i; - } - - return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f; + unsigned int i, i_prev; + float area_best = FLT_MAX; + float dvec_best[2]; /* best angle, delay atan2 */ + + i_prev = n - 1; + for (i = 0; i < n; i++) { + const float *ev_a = points_hull[i]; + const float *ev_b = points_hull[i_prev]; + float dvec[2]; /* 2d rotation matrix */ + + sub_v2_v2v2(dvec, ev_a, ev_b); + if (normalize_v2(dvec) != 0.0f) { + /* rotation matrix */ + float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; + unsigned int j; + float area; + + for (j = 0; j < n; j++) { + float tvec[2]; + mul_v2_v2_cw(tvec, dvec, points_hull[j]); + + min[0] = min_ff(min[0], tvec[0]); + min[1] = min_ff(min[1], tvec[1]); + + max[0] = max_ff(max[0], tvec[0]); + max[1] = max_ff(max[1], tvec[1]); + + area = (max[0] - min[0]) * (max[1] - min[1]); + if (area > area_best) { + break; + } + } + + if (area < area_best) { + area_best = area; + copy_v2_v2(dvec_best, dvec); + } + } + + i_prev = i; + } + + return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f; } /** @@ -296,34 +304,34 @@ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned in */ float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n) { - int *index_map; - int tot; + int *index_map; + int tot; - float angle; + float angle; - index_map = MEM_mallocN(sizeof(*index_map) * n * 2, __func__); + index_map = MEM_mallocN(sizeof(*index_map) * n * 2, __func__); - tot = BLI_convexhull_2d(points, (int)n, index_map); + tot = BLI_convexhull_2d(points, (int)n, index_map); - if (tot) { - float (*points_hull)[2]; - int j; + if (tot) { + float(*points_hull)[2]; + int j; - points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)tot, __func__); - for (j = 0; j < tot; j++) { - copy_v2_v2(points_hull[j], points[index_map[j]]); - } + points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)tot, __func__); + for (j = 0; j < tot; j++) { + copy_v2_v2(points_hull[j], points[index_map[j]]); + } - angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)tot); - MEM_freeN(points_hull); - } - else { - angle = 0.0f; - } + angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)tot); + MEM_freeN(points_hull); + } + else { + angle = 0.0f; + } - MEM_freeN(index_map); + MEM_freeN(index_map); - return angle; + return angle; } /** \} */ diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c index 31f8d9d3d57..c648a212fef 100644 --- a/source/blender/blenlib/intern/dynlib.c +++ b/source/blender/blenlib/intern/dynlib.c @@ -30,106 +30,109 @@ #include "BLI_dynlib.h" struct DynamicLibrary { - void *handle; + void *handle; }; #ifdef WIN32 -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x501 /* Windows XP or newer */ -#endif -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include "utf_winfunc.h" -#include "utfconv.h" +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x501 /* Windows XP or newer */ +# endif +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include "utf_winfunc.h" +# include "utfconv.h" DynamicLibrary *BLI_dynlib_open(const char *name) { - DynamicLibrary *lib; - void *handle; + DynamicLibrary *lib; + void *handle; - UTF16_ENCODE(name); - handle = LoadLibraryW(name_16); - UTF16_UN_ENCODE(name); + UTF16_ENCODE(name); + handle = LoadLibraryW(name_16); + UTF16_UN_ENCODE(name); - if (!handle) { - return NULL; - } + if (!handle) { + return NULL; + } - lib = MEM_callocN(sizeof(*lib), "Dynamic Library"); - lib->handle = handle; + lib = MEM_callocN(sizeof(*lib), "Dynamic Library"); + lib->handle = handle; - return lib; + return lib; } void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname) { - return GetProcAddress(lib->handle, symname); + return GetProcAddress(lib->handle, symname); } char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib) { - int err; - - /* if lib is NULL reset the last error code */ - err = GetLastError(); - if (!lib) { - SetLastError(ERROR_SUCCESS); - } - - if (err) { - static char buf[1024]; - - if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, sizeof(buf), NULL)) - { - return buf; - } - } - - return NULL; + int err; + + /* if lib is NULL reset the last error code */ + err = GetLastError(); + if (!lib) { + SetLastError(ERROR_SUCCESS); + } + + if (err) { + static char buf[1024]; + + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buf, + sizeof(buf), + NULL)) { + return buf; + } + } + + return NULL; } void BLI_dynlib_close(DynamicLibrary *lib) { - FreeLibrary(lib->handle); - MEM_freeN(lib); + FreeLibrary(lib->handle); + MEM_freeN(lib); } #else /* Unix */ -#include <dlfcn.h> +# include <dlfcn.h> DynamicLibrary *BLI_dynlib_open(const char *name) { - DynamicLibrary *lib; - void *handle = dlopen(name, RTLD_LAZY); + DynamicLibrary *lib; + void *handle = dlopen(name, RTLD_LAZY); - if (!handle) { - return NULL; - } + if (!handle) { + return NULL; + } - lib = MEM_callocN(sizeof(*lib), "Dynamic Library"); - lib->handle = handle; + lib = MEM_callocN(sizeof(*lib), "Dynamic Library"); + lib->handle = handle; - return lib; + return lib; } void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname) { - return dlsym(lib->handle, symname); + return dlsym(lib->handle, symname); } char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib) { - (void)lib; /* unused */ - return dlerror(); + (void)lib; /* unused */ + return dlerror(); } void BLI_dynlib_close(DynamicLibrary *lib) { - dlclose(lib->handle); - MEM_freeN(lib); + dlclose(lib->handle); + MEM_freeN(lib); } #endif diff --git a/source/blender/blenlib/intern/easing.c b/source/blender/blenlib/intern/easing.c index 99077eddc4e..9532f78bd44 100644 --- a/source/blender/blenlib/intern/easing.c +++ b/source/blender/blenlib/intern/easing.c @@ -34,111 +34,114 @@ #include "BLI_math_base.h" -#include "BLI_easing.h" /* own include */ +#include "BLI_easing.h" /* own include */ #include "BLI_strict_flags.h" /* blend if (amplitude < fabsf(change) */ #define USE_ELASTIC_BLEND -float BLI_easing_back_ease_in(float time, float begin, float change, float duration, float overshoot) +float BLI_easing_back_ease_in( + float time, float begin, float change, float duration, float overshoot) { - time /= duration; - return change * time * time * ((overshoot + 1) * time - overshoot) + begin; + time /= duration; + return change * time * time * ((overshoot + 1) * time - overshoot) + begin; } -float BLI_easing_back_ease_out(float time, float begin, float change, float duration, float overshoot) +float BLI_easing_back_ease_out( + float time, float begin, float change, float duration, float overshoot) { - time = time / duration - 1; - return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin; + time = time / duration - 1; + return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin; } -float BLI_easing_back_ease_in_out(float time, float begin, float change, float duration, float overshoot) +float BLI_easing_back_ease_in_out( + float time, float begin, float change, float duration, float overshoot) { - overshoot *= 1.525f; - if ((time /= duration / 2) < 1.0f) { - return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin; - } - time -= 2.0f; - return change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + begin; - + overshoot *= 1.525f; + if ((time /= duration / 2) < 1.0f) { + return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin; + } + time -= 2.0f; + return change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + begin; } float BLI_easing_bounce_ease_out(float time, float begin, float change, float duration) { - time /= duration; - if (time < (1 / 2.75f)) { - return change * (7.5625f * time * time) + begin; - } - else if (time < (2 / 2.75f)) { - time -= (1.5f / 2.75f); - return change * ((7.5625f * time) * time + 0.75f) + begin; - } - else if (time < (2.5f / 2.75f)) { - time -= (2.25f / 2.75f); - return change * ((7.5625f * time) * time + 0.9375f) + begin; - } - else { - time -= (2.625f / 2.75f); - return change * ((7.5625f * time) * time + 0.984375f) + begin; - } + time /= duration; + if (time < (1 / 2.75f)) { + return change * (7.5625f * time * time) + begin; + } + else if (time < (2 / 2.75f)) { + time -= (1.5f / 2.75f); + return change * ((7.5625f * time) * time + 0.75f) + begin; + } + else if (time < (2.5f / 2.75f)) { + time -= (2.25f / 2.75f); + return change * ((7.5625f * time) * time + 0.9375f) + begin; + } + else { + time -= (2.625f / 2.75f); + return change * ((7.5625f * time) * time + 0.984375f) + begin; + } } float BLI_easing_bounce_ease_in(float time, float begin, float change, float duration) { - return change - BLI_easing_bounce_ease_out(duration - time, 0, change, duration) + begin; + return change - BLI_easing_bounce_ease_out(duration - time, 0, change, duration) + begin; } float BLI_easing_bounce_ease_in_out(float time, float begin, float change, float duration) { - if (time < duration / 2) { - return BLI_easing_bounce_ease_in(time * 2, 0, change, duration) * 0.5f + begin; - } - else { - return BLI_easing_bounce_ease_out(time * 2 - duration, 0, change, duration) * 0.5f + change * 0.5f + begin; - } + if (time < duration / 2) { + return BLI_easing_bounce_ease_in(time * 2, 0, change, duration) * 0.5f + begin; + } + else { + return BLI_easing_bounce_ease_out(time * 2 - duration, 0, change, duration) * 0.5f + + change * 0.5f + begin; + } } float BLI_easing_circ_ease_in(float time, float begin, float change, float duration) { - time /= duration; - return -change * (sqrtf(1 - time * time) - 1) + begin; + time /= duration; + return -change * (sqrtf(1 - time * time) - 1) + begin; } float BLI_easing_circ_ease_out(float time, float begin, float change, float duration) { - time = time / duration - 1; - return change * sqrtf(1 - time * time) + begin; + time = time / duration - 1; + return change * sqrtf(1 - time * time) + begin; } float BLI_easing_circ_ease_in_out(float time, float begin, float change, float duration) { - if ((time /= duration / 2) < 1.0f) { - return -change / 2 * (sqrtf(1 - time * time) - 1) + begin; - } - time -= 2.0f; - return change / 2 * (sqrtf(1 - time * time) + 1) + begin; + if ((time /= duration / 2) < 1.0f) { + return -change / 2 * (sqrtf(1 - time * time) - 1) + begin; + } + time -= 2.0f; + return change / 2 * (sqrtf(1 - time * time) + 1) + begin; } float BLI_easing_cubic_ease_in(float time, float begin, float change, float duration) { - time /= duration; - return change * time * time * time + begin; + time /= duration; + return change * time * time * time + begin; } float BLI_easing_cubic_ease_out(float time, float begin, float change, float duration) { - time = time / duration - 1; - return change * (time * time * time + 1) + begin; + time = time / duration - 1; + return change * (time * time * time + 1) + begin; } float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float duration) { - if ((time /= duration / 2) < 1.0f) { - return change / 2 * time * time * time + begin; - } - time -= 2.0f; - return change / 2 * (time * time * time + 2) + begin; + if ((time /= duration / 2) < 1.0f) { + return change / 2 * time * time * time + begin; + } + time -= 2.0f; + return change / 2 * (time * time * time + 2) + begin; } #ifdef USE_ELASTIC_BLEND @@ -146,123 +149,135 @@ float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float * When the amplitude is less than the change, we need to blend * \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff. */ -static float elastic_blend(float time, float change, float duration, float amplitude, float s, float f) -{ - if (change) { - /* Looks like a magic number, - * but this is a part of the sine curve we need to blend from */ - const float t = fabsf(s); - if (amplitude) { - f *= amplitude / fabsf(change); - } - else { - f = 0.0f; - } - - if (fabsf(time * duration) < t) { - float l = fabsf(time * duration) / t; - f = (f * l) + (1.0f - l); - } - } - - return f; +static float elastic_blend( + float time, float change, float duration, float amplitude, float s, float f) +{ + if (change) { + /* Looks like a magic number, + * but this is a part of the sine curve we need to blend from */ + const float t = fabsf(s); + if (amplitude) { + f *= amplitude / fabsf(change); + } + else { + f = 0.0f; + } + + if (fabsf(time * duration) < t) { + float l = fabsf(time * duration) / t; + f = (f * l) + (1.0f - l); + } + } + + return f; } #endif -float BLI_easing_elastic_ease_in(float time, float begin, float change, float duration, float amplitude, float period) -{ - float s; - float f = 1.0f; - - if (time == 0.0f) { - return begin; - } - - if ((time /= duration) == 1.0f) { - return begin + change; - } - time -= 1.0f; - if (!period) { - period = duration * 0.3f; - } - if (!amplitude || amplitude < fabsf(change)) { - s = period / 4; +float BLI_easing_elastic_ease_in( + float time, float begin, float change, float duration, float amplitude, float period) +{ + float s; + float f = 1.0f; + + if (time == 0.0f) { + return begin; + } + + if ((time /= duration) == 1.0f) { + return begin + change; + } + time -= 1.0f; + if (!period) { + period = duration * 0.3f; + } + if (!amplitude || amplitude < fabsf(change)) { + s = period / 4; #ifdef USE_ELASTIC_BLEND - f = elastic_blend(time, change, duration, amplitude, s, f); + f = elastic_blend(time, change, duration, amplitude, s, f); #endif - amplitude = change; - } - else { - s = period / (2 * (float)M_PI) * asinf(change / amplitude); - } - - return (-f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin; -} - -float BLI_easing_elastic_ease_out(float time, float begin, float change, float duration, float amplitude, float period) -{ - float s; - float f = 1.0f; - - if (time == 0.0f) { - return begin; - } - if ((time /= duration) == 1.0f) { - return begin + change; - } - time = -time; - if (!period) { - period = duration * 0.3f; - } - if (!amplitude || amplitude < fabsf(change)) { - s = period / 4; + amplitude = change; + } + else { + s = period / (2 * (float)M_PI) * asinf(change / amplitude); + } + + return (-f * (amplitude * powf(2, 10 * time) * + sinf((time * duration - s) * (2 * (float)M_PI) / period))) + + begin; +} + +float BLI_easing_elastic_ease_out( + float time, float begin, float change, float duration, float amplitude, float period) +{ + float s; + float f = 1.0f; + + if (time == 0.0f) { + return begin; + } + if ((time /= duration) == 1.0f) { + return begin + change; + } + time = -time; + if (!period) { + period = duration * 0.3f; + } + if (!amplitude || amplitude < fabsf(change)) { + s = period / 4; #ifdef USE_ELASTIC_BLEND - f = elastic_blend(time, change, duration, amplitude, s, f); + f = elastic_blend(time, change, duration, amplitude, s, f); #endif - amplitude = change; - } - else { - s = period / (2 * (float)M_PI) * asinf(change / amplitude); - } - - return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin; -} - -float BLI_easing_elastic_ease_in_out(float time, float begin, float change, float duration, float amplitude, float period) -{ - float s; - float f = 1.0f; - - if (time == 0.0f) { - return begin; - } - if ((time /= duration / 2) == 2.0f) { - return begin + change; - } - time -= 1.0f; - if (!period) { - period = duration * (0.3f * 1.5f); - } - if (!amplitude || amplitude < fabsf(change)) { - s = period / 4; + amplitude = change; + } + else { + s = period / (2 * (float)M_PI) * asinf(change / amplitude); + } + + return (f * (amplitude * powf(2, 10 * time) * + sinf((time * duration - s) * (2 * (float)M_PI) / period))) + + change + begin; +} + +float BLI_easing_elastic_ease_in_out( + float time, float begin, float change, float duration, float amplitude, float period) +{ + float s; + float f = 1.0f; + + if (time == 0.0f) { + return begin; + } + if ((time /= duration / 2) == 2.0f) { + return begin + change; + } + time -= 1.0f; + if (!period) { + period = duration * (0.3f * 1.5f); + } + if (!amplitude || amplitude < fabsf(change)) { + s = period / 4; #ifdef USE_ELASTIC_BLEND - f = elastic_blend(time, change, duration, amplitude, s, f); + f = elastic_blend(time, change, duration, amplitude, s, f); #endif - amplitude = change; - } - else { - s = period / (2 * (float)M_PI) * asinf(change / amplitude); - } - - if (time < 0.0f) { - f *= -0.5f; - return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin; - } - else { - time = -time; - f *= 0.5f; - return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin; - } + amplitude = change; + } + else { + s = period / (2 * (float)M_PI) * asinf(change / amplitude); + } + + if (time < 0.0f) { + f *= -0.5f; + return (f * (amplitude * powf(2, 10 * time) * + sinf((time * duration - s) * (2 * (float)M_PI) / period))) + + begin; + } + else { + time = -time; + f *= 0.5f; + return (f * (amplitude * powf(2, 10 * time) * + sinf((time * duration - s) * (2 * (float)M_PI) / period))) + + change + begin; + } } static const float pow_min = 0.0009765625f; /* = 2^(-10) */ @@ -270,112 +285,110 @@ static const float pow_scale = 1.0f / (1.0f - 0.0009765625f); float BLI_easing_expo_ease_in(float time, float begin, float change, float duration) { - if (time == 0.0) { - return begin; - } - return change * (powf(2, 10 * (time / duration - 1)) - pow_min) * pow_scale + begin; + if (time == 0.0) { + return begin; + } + return change * (powf(2, 10 * (time / duration - 1)) - pow_min) * pow_scale + begin; } float BLI_easing_expo_ease_out(float time, float begin, float change, float duration) { - if (time == 0.0) { - return begin; - } - return change * (1 - (powf(2, -10 * time / duration) - pow_min) * pow_scale) + begin; + if (time == 0.0) { + return begin; + } + return change * (1 - (powf(2, -10 * time / duration) - pow_min) * pow_scale) + begin; } float BLI_easing_expo_ease_in_out(float time, float begin, float change, float duration) { - float duration_half = duration / 2.0f; - float change_half = change / 2.0f; - if (time <= duration_half) { - return BLI_easing_expo_ease_in( - time, begin, change_half, duration_half); - } - else { - return BLI_easing_expo_ease_out( - time - duration_half, begin + change_half, change_half, duration_half); - } + float duration_half = duration / 2.0f; + float change_half = change / 2.0f; + if (time <= duration_half) { + return BLI_easing_expo_ease_in(time, begin, change_half, duration_half); + } + else { + return BLI_easing_expo_ease_out( + time - duration_half, begin + change_half, change_half, duration_half); + } } float BLI_easing_linear_ease(float time, float begin, float change, float duration) { - return change * time / duration + begin; + return change * time / duration + begin; } float BLI_easing_quad_ease_in(float time, float begin, float change, float duration) { - time /= duration; - return change * time * time + begin; + time /= duration; + return change * time * time + begin; } float BLI_easing_quad_ease_out(float time, float begin, float change, float duration) { - time /= duration; - return -change * time * (time - 2) + begin; + time /= duration; + return -change * time * (time - 2) + begin; } float BLI_easing_quad_ease_in_out(float time, float begin, float change, float duration) { - if ((time /= duration / 2) < 1.0f) { - return change / 2 * time * time + begin; - } - time -= 1.0f; - return -change / 2 * (time * (time - 2) - 1) + begin; + if ((time /= duration / 2) < 1.0f) { + return change / 2 * time * time + begin; + } + time -= 1.0f; + return -change / 2 * (time * (time - 2) - 1) + begin; } - float BLI_easing_quart_ease_in(float time, float begin, float change, float duration) { - time /= duration; - return change * time * time * time * time + begin; + time /= duration; + return change * time * time * time * time + begin; } float BLI_easing_quart_ease_out(float time, float begin, float change, float duration) { - time = time / duration - 1; - return -change * (time * time * time * time - 1) + begin; + time = time / duration - 1; + return -change * (time * time * time * time - 1) + begin; } float BLI_easing_quart_ease_in_out(float time, float begin, float change, float duration) { - if ((time /= duration / 2) < 1.0f) { - return change / 2 * time * time * time * time + begin; - } - time -= 2.0f; - return -change / 2 * ( time * time * time * time - 2) + begin; + if ((time /= duration / 2) < 1.0f) { + return change / 2 * time * time * time * time + begin; + } + time -= 2.0f; + return -change / 2 * (time * time * time * time - 2) + begin; } float BLI_easing_quint_ease_in(float time, float begin, float change, float duration) { - time /= duration; - return change * time * time * time * time * time + begin; + time /= duration; + return change * time * time * time * time * time + begin; } float BLI_easing_quint_ease_out(float time, float begin, float change, float duration) { - time = time / duration - 1; - return change * (time * time * time * time * time + 1) + begin; + time = time / duration - 1; + return change * (time * time * time * time * time + 1) + begin; } float BLI_easing_quint_ease_in_out(float time, float begin, float change, float duration) { - if ((time /= duration / 2) < 1.0f) { - return change / 2 * time * time * time * time * time + begin; - } - time -= 2.0f; - return change / 2 * (time * time * time * time * time + 2) + begin; + if ((time /= duration / 2) < 1.0f) { + return change / 2 * time * time * time * time * time + begin; + } + time -= 2.0f; + return change / 2 * (time * time * time * time * time + 2) + begin; } float BLI_easing_sine_ease_in(float time, float begin, float change, float duration) { - return -change * cosf(time / duration * (float)M_PI_2) + change + begin; + return -change * cosf(time / duration * (float)M_PI_2) + change + begin; } float BLI_easing_sine_ease_out(float time, float begin, float change, float duration) { - return change * sinf(time / duration * (float)M_PI_2) + begin; + return change * sinf(time / duration * (float)M_PI_2) + begin; } float BLI_easing_sine_ease_in_out(float time, float begin, float change, float duration) { - return -change / 2 * (cosf((float)M_PI * time / duration) - 1) + begin; + return -change / 2 * (cosf((float)M_PI * time / duration) - 1) + begin; } diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 564090f734e..528f206c02e 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -37,20 +37,20 @@ typedef struct _EdgeHash_Edge Edge; typedef struct _EdgeHash_Entry EdgeHashEntry; typedef struct EdgeHash { - EdgeHashEntry *entries; - int32_t *map; - uint32_t slot_mask; - uint capacity_exp; - uint length; - uint dummy_count; + EdgeHashEntry *entries; + int32_t *map; + uint32_t slot_mask; + uint capacity_exp; + uint length; + uint dummy_count; } EdgeHash; typedef struct EdgeSet { - Edge *entries; - int32_t *map; - uint32_t slot_mask; - uint capacity_exp; - uint length; + Edge *entries; + int32_t *map; + uint32_t slot_mask; + uint capacity_exp; + uint length; } EdgeSet; /* -------------------------------------------------------------------- */ @@ -59,18 +59,23 @@ typedef struct EdgeSet { #define ENTRIES_CAPACITY(container) (uint)(1 << (container)->capacity_exp) #define MAP_CAPACITY(container) (uint)(1 << ((container)->capacity_exp + 1)) -#define CLEAR_MAP(container) memset((container)->map, 0xFF, sizeof(int32_t) * MAP_CAPACITY(container)) -#define UPDATE_SLOT_MASK(container) { (container)->slot_mask = MAP_CAPACITY(container) - 1; } ((void)0) +#define CLEAR_MAP(container) \ + memset((container)->map, 0xFF, sizeof(int32_t) * MAP_CAPACITY(container)) +#define UPDATE_SLOT_MASK(container) \ + { \ + (container)->slot_mask = MAP_CAPACITY(container) - 1; \ + } \ + ((void)0) #define PERTURB_SHIFT 5 #define ITER_SLOTS(CONTAINER, EDGE, SLOT, INDEX) \ - uint32_t hash = calc_edge_hash(EDGE); \ - uint32_t mask = (CONTAINER)->slot_mask; \ - uint32_t perturb = hash; \ - int32_t *map = (CONTAINER)->map; \ - uint32_t SLOT = mask & hash; \ - int INDEX = map[SLOT]; \ - for (;;SLOT = mask & ((5 * SLOT) + 1 + perturb), perturb >>= PERTURB_SHIFT, INDEX = map[SLOT]) + uint32_t hash = calc_edge_hash(EDGE); \ + uint32_t mask = (CONTAINER)->slot_mask; \ + uint32_t perturb = hash; \ + int32_t *map = (CONTAINER)->map; \ + uint32_t SLOT = mask & hash; \ + int INDEX = map[SLOT]; \ + for (;; SLOT = mask & ((5 * SLOT) + 1 + perturb), perturb >>= PERTURB_SHIFT, INDEX = map[SLOT]) #define SLOT_EMPTY -1 #define SLOT_DUMMY -2 @@ -85,38 +90,38 @@ typedef struct EdgeSet { BLI_INLINE uint32_t calc_edge_hash(Edge edge) { - return (edge.v_low << 8) ^ edge.v_high; + return (edge.v_low << 8) ^ edge.v_high; } BLI_INLINE Edge init_edge(uint v0, uint v1) { - /* If there are use cases where we need this it could be removed (or flag to allow), - * for now this helps avoid incorrect usage (creating degenerate geometry). */ - BLI_assert(v0 != v1); - Edge edge; - if (v0 < v1) { - edge.v_low = v0; - edge.v_high = v1; - } - else { - edge.v_low = v1; - edge.v_high = v0; - } - return edge; + /* If there are use cases where we need this it could be removed (or flag to allow), + * for now this helps avoid incorrect usage (creating degenerate geometry). */ + BLI_assert(v0 != v1); + Edge edge; + if (v0 < v1) { + edge.v_low = v0; + edge.v_high = v1; + } + else { + edge.v_low = v1; + edge.v_high = v0; + } + return edge; } BLI_INLINE bool edges_equal(Edge e1, Edge e2) { - return memcmp(&e1, &e2, sizeof(Edge)) == 0; + return memcmp(&e1, &e2, sizeof(Edge)) == 0; } static uint calc_capacity_exp_for_reserve(uint reserve) { - uint result = 1; - while (reserve >>= 1) { - result++; - } - return result; + uint result = 1; + while (reserve >>= 1) { + result++; + } + return result; } /** \} */ @@ -125,89 +130,94 @@ static uint calc_capacity_exp_for_reserve(uint reserve) /** \name Internal Utility API * \{ */ -#define EH_INDEX_HAS_EDGE(eh, index, edge) ((index) >= 0 && edges_equal((edge), (eh)->entries[index].edge)) +#define EH_INDEX_HAS_EDGE(eh, index, edge) \ + ((index) >= 0 && edges_equal((edge), (eh)->entries[index].edge)) static void edgehash_free_values(EdgeHash *eh, EdgeHashFreeFP free_value) { - if (free_value) { - for (uint i = 0; i < eh->length; i++) { - free_value(eh->entries[i].value); - } - } + if (free_value) { + for (uint i = 0; i < eh->length; i++) { + free_value(eh->entries[i].value); + } + } } BLI_INLINE void edgehash_insert_index(EdgeHash *eh, Edge edge, uint entry_index) { - ITER_SLOTS(eh, edge, slot, index) { - if (index == SLOT_EMPTY) { - eh->map[slot] = (int32_t)entry_index; - break; - } - } + ITER_SLOTS(eh, edge, slot, index) + { + if (index == SLOT_EMPTY) { + eh->map[slot] = (int32_t)entry_index; + break; + } + } } BLI_INLINE EdgeHashEntry *edgehash_insert_at_slot(EdgeHash *eh, uint slot, Edge edge, void *value) { - EdgeHashEntry *entry = &eh->entries[eh->length]; - entry->edge = edge; - entry->value = value; - eh->map[slot] = (int32_t)eh->length; - eh->length++; - return entry; + EdgeHashEntry *entry = &eh->entries[eh->length]; + entry->edge = edge; + entry->value = value; + eh->map[slot] = (int32_t)eh->length; + eh->length++; + return entry; } BLI_INLINE bool edgehash_ensure_can_insert(EdgeHash *eh) { - if (UNLIKELY(ENTRIES_CAPACITY(eh) <= eh->length + eh->dummy_count)) { - eh->capacity_exp++; - UPDATE_SLOT_MASK(eh); - eh->dummy_count = 0; - eh->entries = MEM_reallocN(eh->entries, sizeof(EdgeHashEntry) * ENTRIES_CAPACITY(eh)); - eh->map = MEM_reallocN(eh->map, sizeof(int32_t) * MAP_CAPACITY(eh)); - CLEAR_MAP(eh); - for (uint i = 0; i < eh->length; i++) { - edgehash_insert_index(eh, eh->entries[i].edge, i); - } - return true; - } - return false; + if (UNLIKELY(ENTRIES_CAPACITY(eh) <= eh->length + eh->dummy_count)) { + eh->capacity_exp++; + UPDATE_SLOT_MASK(eh); + eh->dummy_count = 0; + eh->entries = MEM_reallocN(eh->entries, sizeof(EdgeHashEntry) * ENTRIES_CAPACITY(eh)); + eh->map = MEM_reallocN(eh->map, sizeof(int32_t) * MAP_CAPACITY(eh)); + CLEAR_MAP(eh); + for (uint i = 0; i < eh->length; i++) { + edgehash_insert_index(eh, eh->entries[i].edge, i); + } + return true; + } + return false; } BLI_INLINE EdgeHashEntry *edgehash_insert(EdgeHash *eh, Edge edge, void *value) { - ITER_SLOTS(eh, edge, slot, index) { - if (index == SLOT_EMPTY) { - return edgehash_insert_at_slot(eh, slot, edge, value); - } - else if (index == SLOT_DUMMY) { - eh->dummy_count--; - return edgehash_insert_at_slot(eh, slot, edge, value); - } - } + ITER_SLOTS(eh, edge, slot, index) + { + if (index == SLOT_EMPTY) { + return edgehash_insert_at_slot(eh, slot, edge, value); + } + else if (index == SLOT_DUMMY) { + eh->dummy_count--; + return edgehash_insert_at_slot(eh, slot, edge, value); + } + } } BLI_INLINE EdgeHashEntry *edgehash_lookup_entry(EdgeHash *eh, uint v0, uint v1) { - Edge edge = init_edge(v0, v1); + Edge edge = init_edge(v0, v1); - ITER_SLOTS(eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - return &eh->entries[index]; - } - else if (index == SLOT_EMPTY) { - return NULL; - } - } + ITER_SLOTS(eh, edge, slot, index) + { + if (EH_INDEX_HAS_EDGE(eh, index, edge)) { + return &eh->entries[index]; + } + else if (index == SLOT_EMPTY) { + return NULL; + } + } } BLI_INLINE void edgehash_change_index(EdgeHash *eh, Edge edge, int new_index) { - ITER_SLOTS(eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - eh->map[slot] = new_index; - break; - } - } + ITER_SLOTS(eh, edge, slot, index) + { + if (EH_INDEX_HAS_EDGE(eh, index, edge)) { + eh->map[slot] = new_index; + break; + } + } } /** \} */ @@ -218,52 +228,51 @@ BLI_INLINE void edgehash_change_index(EdgeHash *eh, Edge edge, int new_index) EdgeHash *BLI_edgehash_new_ex(const char *info, const uint reserve) { - EdgeHash *eh = MEM_mallocN(sizeof(EdgeHash), info); - eh->capacity_exp = calc_capacity_exp_for_reserve(reserve); - UPDATE_SLOT_MASK(eh); - eh->length = 0; - eh->dummy_count = 0; - eh->entries = MEM_calloc_arrayN(sizeof(EdgeHashEntry), ENTRIES_CAPACITY(eh), "eh entries"); - eh->map = MEM_malloc_arrayN(sizeof(int32_t), MAP_CAPACITY(eh), "eh map"); - CLEAR_MAP(eh); - return eh; + EdgeHash *eh = MEM_mallocN(sizeof(EdgeHash), info); + eh->capacity_exp = calc_capacity_exp_for_reserve(reserve); + UPDATE_SLOT_MASK(eh); + eh->length = 0; + eh->dummy_count = 0; + eh->entries = MEM_calloc_arrayN(sizeof(EdgeHashEntry), ENTRIES_CAPACITY(eh), "eh entries"); + eh->map = MEM_malloc_arrayN(sizeof(int32_t), MAP_CAPACITY(eh), "eh map"); + CLEAR_MAP(eh); + return eh; } EdgeHash *BLI_edgehash_new(const char *info) { - return BLI_edgehash_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); + return BLI_edgehash_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); } void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value) { - edgehash_free_values(eh, free_value); - MEM_freeN(eh->map); - MEM_freeN(eh->entries); - MEM_freeN(eh); + edgehash_free_values(eh, free_value); + MEM_freeN(eh->map); + MEM_freeN(eh->entries); + MEM_freeN(eh); } void BLI_edgehash_print(EdgeHash *eh) { - printf("Edgehash at %p:\n", eh); - printf(" Map:\n"); - for (uint i = 0; i < MAP_CAPACITY(eh); i++) { - int index = eh->map[i]; - printf(" %u: %d", i, index); - if (index >= 0) { - EdgeHashEntry entry = eh->entries[index]; - printf(" -> (%u, %u) -> %p", entry.edge.v_low, entry.edge.v_high, entry.value); - } - printf("\n"); - } - printf(" Entries:\n"); - for (uint i = 0; i < ENTRIES_CAPACITY(eh); i++) { - if (i == eh->length) { - printf(" **** below is rest capacity ****\n"); - } - EdgeHashEntry entry = eh->entries[i]; - printf(" %u: (%u, %u) -> %p\n", i, entry.edge.v_low, entry.edge.v_high, entry.value); - - } + printf("Edgehash at %p:\n", eh); + printf(" Map:\n"); + for (uint i = 0; i < MAP_CAPACITY(eh); i++) { + int index = eh->map[i]; + printf(" %u: %d", i, index); + if (index >= 0) { + EdgeHashEntry entry = eh->entries[index]; + printf(" -> (%u, %u) -> %p", entry.edge.v_low, entry.edge.v_high, entry.value); + } + printf("\n"); + } + printf(" Entries:\n"); + for (uint i = 0; i < ENTRIES_CAPACITY(eh); i++) { + if (i == eh->length) { + printf(" **** below is rest capacity ****\n"); + } + EdgeHashEntry entry = eh->entries[i]; + printf(" %u: (%u, %u) -> %p\n", i, entry.edge.v_low, entry.edge.v_high, entry.value); + } } /** @@ -272,9 +281,9 @@ void BLI_edgehash_print(EdgeHash *eh) */ void BLI_edgehash_insert(EdgeHash *eh, uint v0, uint v1, void *value) { - edgehash_ensure_can_insert(eh); - Edge edge = init_edge(v0, v1); - edgehash_insert(eh, edge, value); + edgehash_ensure_can_insert(eh); + Edge edge = init_edge(v0, v1); + edgehash_insert(eh, edge, value); } /** @@ -282,23 +291,24 @@ void BLI_edgehash_insert(EdgeHash *eh, uint v0, uint v1, void *value) */ bool BLI_edgehash_reinsert(EdgeHash *eh, uint v0, uint v1, void *value) { - Edge edge = init_edge(v0, v1); - - ITER_SLOTS(eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - eh->entries[index].value = value; - return false; - } - else if (index == SLOT_EMPTY) { - if (edgehash_ensure_can_insert(eh)) { - edgehash_insert(eh, edge, value); - } - else { - edgehash_insert_at_slot(eh, slot, edge, value); - } - return true; - } - } + Edge edge = init_edge(v0, v1); + + ITER_SLOTS(eh, edge, slot, index) + { + if (EH_INDEX_HAS_EDGE(eh, index, edge)) { + eh->entries[index].value = value; + return false; + } + else if (index == SLOT_EMPTY) { + if (edgehash_ensure_can_insert(eh)) { + edgehash_insert(eh, edge, value); + } + else { + edgehash_insert_at_slot(eh, slot, edge, value); + } + return true; + } + } } /** @@ -306,8 +316,8 @@ bool BLI_edgehash_reinsert(EdgeHash *eh, uint v0, uint v1, void *value) */ void *BLI_edgehash_lookup_default(EdgeHash *eh, uint v0, uint v1, void *default_value) { - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? entry->value : default_value; + EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); + return entry ? entry->value : default_value; } /** @@ -318,8 +328,8 @@ void *BLI_edgehash_lookup_default(EdgeHash *eh, uint v0, uint v1, void *default_ */ void *BLI_edgehash_lookup(EdgeHash *eh, uint v0, uint v1) { - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? entry->value : NULL; + EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); + return entry ? entry->value : NULL; } /** @@ -328,8 +338,8 @@ void *BLI_edgehash_lookup(EdgeHash *eh, uint v0, uint v1) */ void **BLI_edgehash_lookup_p(EdgeHash *eh, uint v0, uint v1) { - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? &entry->value : NULL; + EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); + return entry ? &entry->value : NULL; } /** @@ -348,23 +358,24 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, uint v0, uint v1) */ bool BLI_edgehash_ensure_p(EdgeHash *eh, uint v0, uint v1, void ***r_value) { - Edge edge = init_edge(v0, v1); - - ITER_SLOTS(eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - *r_value = &eh->entries[index].value; - return true; - } - else if (index == SLOT_EMPTY) { - if (edgehash_ensure_can_insert(eh)) { - *r_value = &edgehash_insert(eh, edge, NULL)->value; - } - else { - *r_value = &edgehash_insert_at_slot(eh, slot, edge, NULL)->value; - } - return false; - } - } + Edge edge = init_edge(v0, v1); + + ITER_SLOTS(eh, edge, slot, index) + { + if (EH_INDEX_HAS_EDGE(eh, index, edge)) { + *r_value = &eh->entries[index].value; + return true; + } + else if (index == SLOT_EMPTY) { + if (edgehash_ensure_can_insert(eh)) { + *r_value = &edgehash_insert(eh, edge, NULL)->value; + } + else { + *r_value = &edgehash_insert_at_slot(eh, slot, edge, NULL)->value; + } + return false; + } + } } /** @@ -376,12 +387,12 @@ bool BLI_edgehash_ensure_p(EdgeHash *eh, uint v0, uint v1, void ***r_value) */ bool BLI_edgehash_remove(EdgeHash *eh, uint v0, uint v1, EdgeHashFreeFP free_value) { - uint old_length = eh->length; - void *value = BLI_edgehash_popkey(eh, v0, v1); - if (free_value && value) { - free_value(value); - } - return old_length > eh->length; + uint old_length = eh->length; + void *value = BLI_edgehash_popkey(eh, v0, v1); + if (free_value && value) { + free_value(value); + } + return old_length > eh->length; } /* same as above but return the value, @@ -394,24 +405,25 @@ bool BLI_edgehash_remove(EdgeHash *eh, uint v0, uint v1, EdgeHashFreeFP free_val */ void *BLI_edgehash_popkey(EdgeHash *eh, uint v0, uint v1) { - Edge edge = init_edge(v0, v1); - - ITER_SLOTS(eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - void *value = eh->entries[index].value; - eh->length--; - eh->dummy_count++; - eh->map[slot] = SLOT_DUMMY; - eh->entries[index] = eh->entries[eh->length]; - if ((uint)index < eh->length) { - edgehash_change_index(eh, eh->entries[index].edge, index); - } - return value; - } - else if (index == SLOT_EMPTY) { - return NULL; - } - } + Edge edge = init_edge(v0, v1); + + ITER_SLOTS(eh, edge, slot, index) + { + if (EH_INDEX_HAS_EDGE(eh, index, edge)) { + void *value = eh->entries[index].value; + eh->length--; + eh->dummy_count++; + eh->map[slot] = SLOT_DUMMY; + eh->entries[index] = eh->entries[eh->length]; + if ((uint)index < eh->length) { + edgehash_change_index(eh, eh->entries[index].edge, index); + } + return value; + } + else if (index == SLOT_EMPTY) { + return NULL; + } + } } /** @@ -419,7 +431,7 @@ void *BLI_edgehash_popkey(EdgeHash *eh, uint v0, uint v1) */ bool BLI_edgehash_haskey(EdgeHash *eh, uint v0, uint v1) { - return edgehash_lookup_entry(eh, v0, v1) != NULL; + return edgehash_lookup_entry(eh, v0, v1) != NULL; } /** @@ -427,7 +439,7 @@ bool BLI_edgehash_haskey(EdgeHash *eh, uint v0, uint v1) */ int BLI_edgehash_len(EdgeHash *eh) { - return (int)eh->length; + return (int)eh->length; } /** @@ -435,12 +447,12 @@ int BLI_edgehash_len(EdgeHash *eh) */ void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP free_value, const uint UNUSED(reserve)) { - /* TODO: handle reserve */ - edgehash_free_values(eh, free_value); - eh->length = 0; - eh->dummy_count = 0; - eh->capacity_exp = CAPACITY_EXP_DEFAULT; - CLEAR_MAP(eh); + /* TODO: handle reserve */ + edgehash_free_values(eh, free_value); + eh->length = 0; + eh->dummy_count = 0; + eh->capacity_exp = CAPACITY_EXP_DEFAULT; + CLEAR_MAP(eh); } /** @@ -448,7 +460,7 @@ void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP free_value, const uint U */ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP free_value) { - BLI_edgehash_clear_ex(eh, free_value, 0); + BLI_edgehash_clear_ex(eh, free_value, 0); } /** \} */ @@ -464,9 +476,9 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP free_value) */ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) { - EdgeHashIterator *ehi = MEM_mallocN(sizeof(EdgeHashIterator), __func__); - BLI_edgehashIterator_init(ehi, eh); - return ehi; + EdgeHashIterator *ehi = MEM_mallocN(sizeof(EdgeHashIterator), __func__); + BLI_edgehashIterator_init(ehi, eh); + return ehi; } /** @@ -479,9 +491,9 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) */ void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh) { - ehi->entries = eh->entries; - ehi->length = eh->length; - ehi->index = 0; + ehi->entries = eh->entries; + ehi->length = eh->length; + ehi->index = 0; } /** @@ -489,10 +501,9 @@ void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh) */ void BLI_edgehashIterator_free(EdgeHashIterator *ehi) { - MEM_freeN(ehi); + MEM_freeN(ehi); } - /** \} */ /* -------------------------------------------------------------------- */ @@ -501,66 +512,68 @@ void BLI_edgehashIterator_free(EdgeHashIterator *ehi) * Use edgehash API to give 'set' functionality * \{ */ -#define ES_INDEX_HAS_EDGE(es, index, edge) (index) >= 0 && edges_equal((edge), (es)->entries[index]) +#define ES_INDEX_HAS_EDGE(es, index, edge) \ + (index) >= 0 && edges_equal((edge), (es)->entries[index]) EdgeSet *BLI_edgeset_new_ex(const char *info, const uint reserve) { - EdgeSet *es = MEM_mallocN(sizeof(EdgeSet), info); - es->capacity_exp = calc_capacity_exp_for_reserve(reserve); - UPDATE_SLOT_MASK(es); - es->length = 0; - es->entries = MEM_malloc_arrayN(sizeof(Edge), ENTRIES_CAPACITY(es), "es entries"); - es->map = MEM_malloc_arrayN(sizeof(int32_t), MAP_CAPACITY(es), "es map"); - CLEAR_MAP(es); - return es; + EdgeSet *es = MEM_mallocN(sizeof(EdgeSet), info); + es->capacity_exp = calc_capacity_exp_for_reserve(reserve); + UPDATE_SLOT_MASK(es); + es->length = 0; + es->entries = MEM_malloc_arrayN(sizeof(Edge), ENTRIES_CAPACITY(es), "es entries"); + es->map = MEM_malloc_arrayN(sizeof(int32_t), MAP_CAPACITY(es), "es map"); + CLEAR_MAP(es); + return es; } EdgeSet *BLI_edgeset_new(const char *info) { - return BLI_edgeset_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); + return BLI_edgeset_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); } void BLI_edgeset_free(EdgeSet *es) { - MEM_freeN(es->entries); - MEM_freeN(es->map); - MEM_freeN(es); + MEM_freeN(es->entries); + MEM_freeN(es->map); + MEM_freeN(es); } int BLI_edgeset_len(EdgeSet *es) { - return (int)es->length; + return (int)es->length; } static void edgeset_insert_index(EdgeSet *es, Edge edge, uint entry_index) { - ITER_SLOTS(es, edge, slot, index) { - if (index == SLOT_EMPTY) { - es->map[slot] = (int)entry_index; - break; - } - } + ITER_SLOTS(es, edge, slot, index) + { + if (index == SLOT_EMPTY) { + es->map[slot] = (int)entry_index; + break; + } + } } BLI_INLINE void edgeset_ensure_can_insert(EdgeSet *es) { - if (UNLIKELY(ENTRIES_CAPACITY(es) <= es->length)) { - es->capacity_exp++; - UPDATE_SLOT_MASK(es); - es->entries = MEM_reallocN(es->entries, sizeof(Edge) * ENTRIES_CAPACITY(es)); - es->map = MEM_reallocN(es->map, sizeof(int32_t) * MAP_CAPACITY(es)); - CLEAR_MAP(es); - for (uint i = 0; i < es->length; i++) { - edgeset_insert_index(es, es->entries[i], i); - } - } + if (UNLIKELY(ENTRIES_CAPACITY(es) <= es->length)) { + es->capacity_exp++; + UPDATE_SLOT_MASK(es); + es->entries = MEM_reallocN(es->entries, sizeof(Edge) * ENTRIES_CAPACITY(es)); + es->map = MEM_reallocN(es->map, sizeof(int32_t) * MAP_CAPACITY(es)); + CLEAR_MAP(es); + for (uint i = 0; i < es->length; i++) { + edgeset_insert_index(es, es->entries[i], i); + } + } } BLI_INLINE void edgeset_insert_at_slot(EdgeSet *es, uint slot, Edge edge) { - es->entries[es->length] = edge; - es->map[slot] = (int)es->length; - es->length++; + es->entries[es->length] = edge; + es->map[slot] = (int)es->length; + es->length++; } /** @@ -571,18 +584,19 @@ BLI_INLINE void edgeset_insert_at_slot(EdgeSet *es, uint slot, Edge edge) */ bool BLI_edgeset_add(EdgeSet *es, uint v0, uint v1) { - edgeset_ensure_can_insert(es); - Edge edge = init_edge(v0, v1); + edgeset_ensure_can_insert(es); + Edge edge = init_edge(v0, v1); - ITER_SLOTS(es, edge, slot, index) { - if (ES_INDEX_HAS_EDGE(es, index, edge)) { - return false; - } - else if (index == SLOT_EMPTY) { - edgeset_insert_at_slot(es, slot, edge); - return true; - } - } + ITER_SLOTS(es, edge, slot, index) + { + if (ES_INDEX_HAS_EDGE(es, index, edge)) { + return false; + } + else if (index == SLOT_EMPTY) { + edgeset_insert_at_slot(es, slot, edge); + return true; + } + } } /** @@ -591,43 +605,45 @@ bool BLI_edgeset_add(EdgeSet *es, uint v0, uint v1) */ void BLI_edgeset_insert(EdgeSet *es, uint v0, uint v1) { - edgeset_ensure_can_insert(es); - Edge edge = init_edge(v0, v1); + edgeset_ensure_can_insert(es); + Edge edge = init_edge(v0, v1); - ITER_SLOTS(es, edge, slot, index) { - if (index == SLOT_EMPTY) { - edgeset_insert_at_slot(es, slot, edge); - return; - } - } + ITER_SLOTS(es, edge, slot, index) + { + if (index == SLOT_EMPTY) { + edgeset_insert_at_slot(es, slot, edge); + return; + } + } } bool BLI_edgeset_haskey(EdgeSet *es, uint v0, uint v1) { - Edge edge = init_edge(v0, v1); + Edge edge = init_edge(v0, v1); - ITER_SLOTS(es, edge, slot, index) { - if (ES_INDEX_HAS_EDGE(es, index, edge)) { - return true; - } - else if (index == SLOT_EMPTY) { - return false; - } - } + ITER_SLOTS(es, edge, slot, index) + { + if (ES_INDEX_HAS_EDGE(es, index, edge)) { + return true; + } + else if (index == SLOT_EMPTY) { + return false; + } + } } EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *es) { - EdgeSetIterator *esi = MEM_mallocN(sizeof(EdgeSetIterator), __func__); - esi->edges = es->entries; - esi->length = es->length; - esi->index = 0; - return esi; + EdgeSetIterator *esi = MEM_mallocN(sizeof(EdgeSetIterator), __func__); + esi->edges = es->entries; + esi->length = es->length; + esi->index = 0; + return esi; } void BLI_edgesetIterator_free(EdgeSetIterator *esi) { - MEM_freeN(esi); + MEM_freeN(esi); } /** \} */ diff --git a/source/blender/blenlib/intern/endian_switch.c b/source/blender/blenlib/intern/endian_switch.c index cc2ffa864f5..09d1d3d0774 100644 --- a/source/blender/blenlib/intern/endian_switch.c +++ b/source/blender/blenlib/intern/endian_switch.c @@ -24,81 +24,80 @@ void BLI_endian_switch_int16_array(short *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_int16(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_int16(val++); + } + } } void BLI_endian_switch_uint16_array(unsigned short *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_uint16(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_uint16(val++); + } + } } void BLI_endian_switch_int32_array(int *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_int32(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_int32(val++); + } + } } void BLI_endian_switch_uint32_array(unsigned int *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_uint32(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_uint32(val++); + } + } } void BLI_endian_switch_float_array(float *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_float(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_float(val++); + } + } } void BLI_endian_switch_int64_array(int64_t *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_int64(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_int64(val++); + } + } } void BLI_endian_switch_uint64_array(uint64_t *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_uint64(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_uint64(val++); + } + } } - void BLI_endian_switch_double_array(double *val, const int size) { - if (size > 0) { - int i = size; - while (i--) { - BLI_endian_switch_double(val++); - } - } + if (size > 0) { + int i = size; + while (i--) { + BLI_endian_switch_double(val++); + } + } } diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c index 51a004f846f..40df9711ef1 100644 --- a/source/blender/blenlib/intern/expr_pylike_eval.c +++ b/source/blender/blenlib/intern/expr_pylike_eval.c @@ -58,7 +58,7 @@ #include "BLI_alloca.h" #ifdef _MSC_VER -#pragma fenv_access (on) +# pragma fenv_access(on) #endif /* -------------------------------------------------------------------- */ @@ -66,52 +66,52 @@ * \{ */ typedef enum eOpCode { - /* Double constant: (-> dval) */ - OPCODE_CONST, - /* 1 argument function call: (a -> func1(a)) */ - OPCODE_FUNC1, - /* 2 argument function call: (a b -> func2(a,b)) */ - OPCODE_FUNC2, - /* Parameter access: (-> params[ival]) */ - OPCODE_PARAMETER, - /* Minimum of multiple inputs: (a b c... -> min); ival = arg count */ - OPCODE_MIN, - /* Maximum of multiple inputs: (a b c... -> max); ival = arg count */ - OPCODE_MAX, - /* Jump (pc += jmp_offset) */ - OPCODE_JMP, - /* Pop and jump if zero: (a -> ); JUMP IF NOT a */ - OPCODE_JMP_ELSE, - /* Jump if nonzero, or pop: (a -> a JUMP) IF a ELSE (a -> ) */ - OPCODE_JMP_OR, - /* Jump if zero, or pop: (a -> a JUMP) IF NOT a ELSE (a -> ) */ - OPCODE_JMP_AND, - /* For comparison chaining: (a b -> 0 JUMP) IF NOT func2(a,b) ELSE (a b -> b) */ - OPCODE_CMP_CHAIN, + /* Double constant: (-> dval) */ + OPCODE_CONST, + /* 1 argument function call: (a -> func1(a)) */ + OPCODE_FUNC1, + /* 2 argument function call: (a b -> func2(a,b)) */ + OPCODE_FUNC2, + /* Parameter access: (-> params[ival]) */ + OPCODE_PARAMETER, + /* Minimum of multiple inputs: (a b c... -> min); ival = arg count */ + OPCODE_MIN, + /* Maximum of multiple inputs: (a b c... -> max); ival = arg count */ + OPCODE_MAX, + /* Jump (pc += jmp_offset) */ + OPCODE_JMP, + /* Pop and jump if zero: (a -> ); JUMP IF NOT a */ + OPCODE_JMP_ELSE, + /* Jump if nonzero, or pop: (a -> a JUMP) IF a ELSE (a -> ) */ + OPCODE_JMP_OR, + /* Jump if zero, or pop: (a -> a JUMP) IF NOT a ELSE (a -> ) */ + OPCODE_JMP_AND, + /* For comparison chaining: (a b -> 0 JUMP) IF NOT func2(a,b) ELSE (a b -> b) */ + OPCODE_CMP_CHAIN, } eOpCode; typedef double (*UnaryOpFunc)(double); typedef double (*BinaryOpFunc)(double, double); typedef struct ExprOp { - eOpCode opcode; + eOpCode opcode; - int jmp_offset; + int jmp_offset; - union { - int ival; - double dval; - void *ptr; - UnaryOpFunc func1; - BinaryOpFunc func2; - } arg; + union { + int ival; + double dval; + void *ptr; + UnaryOpFunc func1; + BinaryOpFunc func2; + } arg; } ExprOp; struct ExprPyLike_Parsed { - int ops_count; - int max_stack; + int ops_count; + int max_stack; - ExprOp ops[]; + ExprOp ops[]; }; /** \} */ @@ -123,21 +123,21 @@ struct ExprPyLike_Parsed { /** Free the parsed data; NULL argument is ok. */ void BLI_expr_pylike_free(ExprPyLike_Parsed *expr) { - if (expr != NULL) { - MEM_freeN(expr); - } + if (expr != NULL) { + MEM_freeN(expr); + } } /** Check if the parsing result is valid for evaluation. */ bool BLI_expr_pylike_is_valid(ExprPyLike_Parsed *expr) { - return expr != NULL && expr->ops_count > 0; + return expr != NULL && expr->ops_count > 0; } /** Check if the parsed expression always evaluates to the same value. */ bool BLI_expr_pylike_is_constant(ExprPyLike_Parsed *expr) { - return expr != NULL && expr->ops_count == 1 && expr->ops[0].opcode == OPCODE_CONST; + return expr != NULL && expr->ops_count == 1 && expr->ops[0].opcode == OPCODE_CONST; } /** \} */ @@ -150,117 +150,120 @@ bool BLI_expr_pylike_is_constant(ExprPyLike_Parsed *expr) * Evaluate the expression with the given parameters. * The order and number of parameters must match the names given to parse. */ -eExprPyLike_EvalStatus BLI_expr_pylike_eval( - ExprPyLike_Parsed *expr, - const double *param_values, int param_values_len, - double *r_result) -{ - *r_result = 0.0; - - if (!BLI_expr_pylike_is_valid(expr)) { - return EXPR_PYLIKE_INVALID; - } - -#define FAIL_IF(condition) if (condition) { return EXPR_PYLIKE_FATAL_ERROR; } - - /* Check the stack requirement is at least remotely sane and allocate on the actual stack. */ - FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000); - - double *stack = BLI_array_alloca(stack, expr->max_stack); - - /* Evaluate expression. */ - ExprOp *ops = expr->ops; - int sp = 0, pc; - - feclearexcept(FE_ALL_EXCEPT); - - for (pc = 0; pc >= 0 && pc < expr->ops_count; pc++) { - switch (ops[pc].opcode) { - /* Arithmetic */ - case OPCODE_CONST: - FAIL_IF(sp >= expr->max_stack); - stack[sp++] = ops[pc].arg.dval; - break; - case OPCODE_PARAMETER: - FAIL_IF(sp >= expr->max_stack || ops[pc].arg.ival >= param_values_len); - stack[sp++] = param_values[ops[pc].arg.ival]; - break; - case OPCODE_FUNC1: - FAIL_IF(sp < 1); - stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]); - break; - case OPCODE_FUNC2: - FAIL_IF(sp < 2); - stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]); - sp--; - break; - case OPCODE_MIN: - FAIL_IF(sp < ops[pc].arg.ival); - for (int j = 1; j < ops[pc].arg.ival; j++, sp--) { - CLAMP_MAX(stack[sp - 2], stack[sp - 1]); - } - break; - case OPCODE_MAX: - FAIL_IF(sp < ops[pc].arg.ival); - for (int j = 1; j < ops[pc].arg.ival; j++, sp--) { - CLAMP_MIN(stack[sp - 2], stack[sp - 1]); - } - break; - - /* Jumps */ - case OPCODE_JMP: - pc += ops[pc].jmp_offset; - break; - case OPCODE_JMP_ELSE: - FAIL_IF(sp < 1); - if (!stack[--sp]) { - pc += ops[pc].jmp_offset; - } - break; - case OPCODE_JMP_OR: - case OPCODE_JMP_AND: - FAIL_IF(sp < 1); - if (!stack[sp - 1] == !(ops[pc].opcode == OPCODE_JMP_OR)) { - pc += ops[pc].jmp_offset; - } - else { - sp--; - } - break; - - /* For chaining comparisons, i.e. "a < b < c" as "a < b and b < c" */ - case OPCODE_CMP_CHAIN: - FAIL_IF(sp < 2); - /* If comparison fails, return 0 and jump to end. */ - if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) { - stack[sp - 2] = 0.0; - pc += ops[pc].jmp_offset; - } - /* Otherwise keep b on the stack and proceed. */ - else { - stack[sp - 2] = stack[sp - 1]; - } - sp--; - break; - - default: - return EXPR_PYLIKE_FATAL_ERROR; - } - } - - FAIL_IF(sp != 1 || pc != expr->ops_count); +eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr, + const double *param_values, + int param_values_len, + double *r_result) +{ + *r_result = 0.0; + + if (!BLI_expr_pylike_is_valid(expr)) { + return EXPR_PYLIKE_INVALID; + } + +#define FAIL_IF(condition) \ + if (condition) { \ + return EXPR_PYLIKE_FATAL_ERROR; \ + } + + /* Check the stack requirement is at least remotely sane and allocate on the actual stack. */ + FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000); + + double *stack = BLI_array_alloca(stack, expr->max_stack); + + /* Evaluate expression. */ + ExprOp *ops = expr->ops; + int sp = 0, pc; + + feclearexcept(FE_ALL_EXCEPT); + + for (pc = 0; pc >= 0 && pc < expr->ops_count; pc++) { + switch (ops[pc].opcode) { + /* Arithmetic */ + case OPCODE_CONST: + FAIL_IF(sp >= expr->max_stack); + stack[sp++] = ops[pc].arg.dval; + break; + case OPCODE_PARAMETER: + FAIL_IF(sp >= expr->max_stack || ops[pc].arg.ival >= param_values_len); + stack[sp++] = param_values[ops[pc].arg.ival]; + break; + case OPCODE_FUNC1: + FAIL_IF(sp < 1); + stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]); + break; + case OPCODE_FUNC2: + FAIL_IF(sp < 2); + stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]); + sp--; + break; + case OPCODE_MIN: + FAIL_IF(sp < ops[pc].arg.ival); + for (int j = 1; j < ops[pc].arg.ival; j++, sp--) { + CLAMP_MAX(stack[sp - 2], stack[sp - 1]); + } + break; + case OPCODE_MAX: + FAIL_IF(sp < ops[pc].arg.ival); + for (int j = 1; j < ops[pc].arg.ival; j++, sp--) { + CLAMP_MIN(stack[sp - 2], stack[sp - 1]); + } + break; + + /* Jumps */ + case OPCODE_JMP: + pc += ops[pc].jmp_offset; + break; + case OPCODE_JMP_ELSE: + FAIL_IF(sp < 1); + if (!stack[--sp]) { + pc += ops[pc].jmp_offset; + } + break; + case OPCODE_JMP_OR: + case OPCODE_JMP_AND: + FAIL_IF(sp < 1); + if (!stack[sp - 1] == !(ops[pc].opcode == OPCODE_JMP_OR)) { + pc += ops[pc].jmp_offset; + } + else { + sp--; + } + break; + + /* For chaining comparisons, i.e. "a < b < c" as "a < b and b < c" */ + case OPCODE_CMP_CHAIN: + FAIL_IF(sp < 2); + /* If comparison fails, return 0 and jump to end. */ + if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) { + stack[sp - 2] = 0.0; + pc += ops[pc].jmp_offset; + } + /* Otherwise keep b on the stack and proceed. */ + else { + stack[sp - 2] = stack[sp - 1]; + } + sp--; + break; + + default: + return EXPR_PYLIKE_FATAL_ERROR; + } + } + + FAIL_IF(sp != 1 || pc != expr->ops_count); #undef FAIL_IF - *r_result = stack[0]; + *r_result = stack[0]; - /* Detect floating point evaluation errors. */ - int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID); - if (flags) { - return (flags & FE_INVALID) ? EXPR_PYLIKE_MATH_ERROR : EXPR_PYLIKE_DIV_BY_ZERO; - } + /* Detect floating point evaluation errors. */ + int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID); + if (flags) { + return (flags & FE_INVALID) ? EXPR_PYLIKE_MATH_ERROR : EXPR_PYLIKE_DIV_BY_ZERO; + } - return EXPR_PYLIKE_SUCCESS; + return EXPR_PYLIKE_SUCCESS; } /** \} */ @@ -271,115 +274,109 @@ eExprPyLike_EvalStatus BLI_expr_pylike_eval( static double op_negate(double arg) { - return -arg; + return -arg; } static double op_mul(double a, double b) { - return a * b; + return a * b; } static double op_div(double a, double b) { - return a / b; + return a / b; } static double op_add(double a, double b) { - return a + b; + return a + b; } static double op_sub(double a, double b) { - return a - b; + return a - b; } static double op_radians(double arg) { - return arg * M_PI / 180.0; + return arg * M_PI / 180.0; } static double op_degrees(double arg) { - return arg * 180.0 / M_PI; + return arg * 180.0 / M_PI; } static double op_not(double a) { - return a ? 0.0 : 1.0; + return a ? 0.0 : 1.0; } static double op_eq(double a, double b) { - return a == b ? 1.0 : 0.0; + return a == b ? 1.0 : 0.0; } static double op_ne(double a, double b) { - return a != b ? 1.0 : 0.0; + return a != b ? 1.0 : 0.0; } static double op_lt(double a, double b) { - return a < b ? 1.0 : 0.0; + return a < b ? 1.0 : 0.0; } static double op_le(double a, double b) { - return a <= b ? 1.0 : 0.0; + return a <= b ? 1.0 : 0.0; } static double op_gt(double a, double b) { - return a > b ? 1.0 : 0.0; + return a > b ? 1.0 : 0.0; } static double op_ge(double a, double b) { - return a >= b ? 1.0 : 0.0; + return a >= b ? 1.0 : 0.0; } typedef struct BuiltinConstDef { - const char *name; - double value; + const char *name; + double value; } BuiltinConstDef; static BuiltinConstDef builtin_consts[] = { - { "pi", M_PI }, - { "True", 1.0 }, - { "False", 0.0 }, - { NULL, 0.0 } -}; + {"pi", M_PI}, {"True", 1.0}, {"False", 0.0}, {NULL, 0.0}}; typedef struct BuiltinOpDef { - const char *name; - eOpCode op; - void *funcptr; + const char *name; + eOpCode op; + void *funcptr; } BuiltinOpDef; -static BuiltinOpDef builtin_ops[] = { - { "radians", OPCODE_FUNC1, op_radians }, - { "degrees", OPCODE_FUNC1, op_degrees }, - { "abs", OPCODE_FUNC1, fabs }, - { "fabs", OPCODE_FUNC1, fabs }, - { "floor", OPCODE_FUNC1, floor }, - { "ceil", OPCODE_FUNC1, ceil }, - { "trunc", OPCODE_FUNC1, trunc }, - { "int", OPCODE_FUNC1, trunc }, - { "sin", OPCODE_FUNC1, sin }, - { "cos", OPCODE_FUNC1, cos }, - { "tan", OPCODE_FUNC1, tan }, - { "asin", OPCODE_FUNC1, asin }, - { "acos", OPCODE_FUNC1, acos }, - { "atan", OPCODE_FUNC1, atan }, - { "atan2", OPCODE_FUNC2, atan2 }, - { "exp", OPCODE_FUNC1, exp }, - { "log", OPCODE_FUNC1, log }, - { "sqrt", OPCODE_FUNC1, sqrt }, - { "pow", OPCODE_FUNC2, pow }, - { "fmod", OPCODE_FUNC2, fmod }, - { NULL, OPCODE_CONST, NULL } -}; +static BuiltinOpDef builtin_ops[] = {{"radians", OPCODE_FUNC1, op_radians}, + {"degrees", OPCODE_FUNC1, op_degrees}, + {"abs", OPCODE_FUNC1, fabs}, + {"fabs", OPCODE_FUNC1, fabs}, + {"floor", OPCODE_FUNC1, floor}, + {"ceil", OPCODE_FUNC1, ceil}, + {"trunc", OPCODE_FUNC1, trunc}, + {"int", OPCODE_FUNC1, trunc}, + {"sin", OPCODE_FUNC1, sin}, + {"cos", OPCODE_FUNC1, cos}, + {"tan", OPCODE_FUNC1, tan}, + {"asin", OPCODE_FUNC1, asin}, + {"acos", OPCODE_FUNC1, acos}, + {"atan", OPCODE_FUNC1, atan}, + {"atan2", OPCODE_FUNC2, atan2}, + {"exp", OPCODE_FUNC1, exp}, + {"log", OPCODE_FUNC1, log}, + {"sqrt", OPCODE_FUNC1, sqrt}, + {"pow", OPCODE_FUNC2, pow}, + {"fmod", OPCODE_FUNC2, fmod}, + {NULL, OPCODE_CONST, NULL}}; /** \} */ @@ -389,250 +386,252 @@ static BuiltinOpDef builtin_ops[] = { #define MAKE_CHAR2(a, b) (((a) << 8) | (b)) -#define CHECK_ERROR(condition) if (!(condition)) { return false; } +#define CHECK_ERROR(condition) \ + if (!(condition)) { \ + return false; \ + } /* For simplicity simple token types are represented by their own character; * these are special identifiers for multi-character tokens. */ -#define TOKEN_ID MAKE_CHAR2('I', 'D') -#define TOKEN_NUMBER MAKE_CHAR2('0', '0') -#define TOKEN_GE MAKE_CHAR2('>', '=') -#define TOKEN_LE MAKE_CHAR2('<', '=') -#define TOKEN_NE MAKE_CHAR2('!', '=') -#define TOKEN_EQ MAKE_CHAR2('=', '=') -#define TOKEN_AND MAKE_CHAR2('A', 'N') -#define TOKEN_OR MAKE_CHAR2('O', 'R') -#define TOKEN_NOT MAKE_CHAR2('N', 'O') -#define TOKEN_IF MAKE_CHAR2('I', 'F') -#define TOKEN_ELSE MAKE_CHAR2('E', 'L') +#define TOKEN_ID MAKE_CHAR2('I', 'D') +#define TOKEN_NUMBER MAKE_CHAR2('0', '0') +#define TOKEN_GE MAKE_CHAR2('>', '=') +#define TOKEN_LE MAKE_CHAR2('<', '=') +#define TOKEN_NE MAKE_CHAR2('!', '=') +#define TOKEN_EQ MAKE_CHAR2('=', '=') +#define TOKEN_AND MAKE_CHAR2('A', 'N') +#define TOKEN_OR MAKE_CHAR2('O', 'R') +#define TOKEN_NOT MAKE_CHAR2('N', 'O') +#define TOKEN_IF MAKE_CHAR2('I', 'F') +#define TOKEN_ELSE MAKE_CHAR2('E', 'L') static const char *token_eq_characters = "!=><"; static const char *token_characters = "~`!@#$%^&*+-=/\\?:;<>(){}[]|.,\"'"; typedef struct KeywordTokenDef { - const char *name; - short token; + const char *name; + short token; } KeywordTokenDef; -static KeywordTokenDef keyword_list[] = { - { "and", TOKEN_AND }, - { "or", TOKEN_OR }, - { "not", TOKEN_NOT }, - { "if", TOKEN_IF }, - { "else", TOKEN_ELSE }, - { NULL, TOKEN_ID } -}; +static KeywordTokenDef keyword_list[] = {{"and", TOKEN_AND}, + {"or", TOKEN_OR}, + {"not", TOKEN_NOT}, + {"if", TOKEN_IF}, + {"else", TOKEN_ELSE}, + {NULL, TOKEN_ID}}; typedef struct ExprParseState { - int param_names_len; - const char **param_names; + int param_names_len; + const char **param_names; - /* Original expression */ - const char *expr; - const char *cur; + /* Original expression */ + const char *expr; + const char *cur; - /* Current token */ - short token; - char *tokenbuf; - double tokenval; + /* Current token */ + short token; + char *tokenbuf; + double tokenval; - /* Opcode buffer */ - int ops_count, max_ops, last_jmp; - ExprOp *ops; + /* Opcode buffer */ + int ops_count, max_ops, last_jmp; + ExprOp *ops; - /* Stack space requirement tracking */ - int stack_ptr, max_stack; + /* Stack space requirement tracking */ + int stack_ptr, max_stack; } ExprParseState; /* Reserve space for the specified number of operations in the buffer. */ static ExprOp *parse_alloc_ops(ExprParseState *state, int count) { - if (state->ops_count + count > state->max_ops) { - state->max_ops = power_of_2_max_i(state->ops_count + count); - state->ops = MEM_reallocN(state->ops, state->max_ops * sizeof(ExprOp)); - } + if (state->ops_count + count > state->max_ops) { + state->max_ops = power_of_2_max_i(state->ops_count + count); + state->ops = MEM_reallocN(state->ops, state->max_ops * sizeof(ExprOp)); + } - ExprOp *op = &state->ops[state->ops_count]; - state->ops_count += count; - return op; + ExprOp *op = &state->ops[state->ops_count]; + state->ops_count += count; + return op; } /* Add one operation and track stack usage. */ static ExprOp *parse_add_op(ExprParseState *state, eOpCode code, int stack_delta) { - /* track evaluation stack depth */ - state->stack_ptr += stack_delta; - CLAMP_MIN(state->stack_ptr, 0); - CLAMP_MIN(state->max_stack, state->stack_ptr); + /* track evaluation stack depth */ + state->stack_ptr += stack_delta; + CLAMP_MIN(state->stack_ptr, 0); + CLAMP_MIN(state->max_stack, state->stack_ptr); - /* allocate the new instruction */ - ExprOp *op = parse_alloc_ops(state, 1); - memset(op, 0, sizeof(ExprOp)); - op->opcode = code; - return op; + /* allocate the new instruction */ + ExprOp *op = parse_alloc_ops(state, 1); + memset(op, 0, sizeof(ExprOp)); + op->opcode = code; + return op; } /* Add one jump operation and return an index for parse_set_jump. */ static int parse_add_jump(ExprParseState *state, eOpCode code) { - parse_add_op(state, code, -1); - return state->last_jmp = state->ops_count; + parse_add_op(state, code, -1); + return state->last_jmp = state->ops_count; } /* Set the jump offset in a previously added jump operation. */ static void parse_set_jump(ExprParseState *state, int jump) { - state->last_jmp = state->ops_count; - state->ops[jump - 1].jmp_offset = state->ops_count - jump; + state->last_jmp = state->ops_count; + state->ops[jump - 1].jmp_offset = state->ops_count - jump; } /* Add a function call operation, applying constant folding when possible. */ static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void *funcptr) { - ExprOp *prev_ops = &state->ops[state->ops_count]; - int jmp_gap = state->ops_count - state->last_jmp; + ExprOp *prev_ops = &state->ops[state->ops_count]; + int jmp_gap = state->ops_count - state->last_jmp; - feclearexcept(FE_ALL_EXCEPT); + feclearexcept(FE_ALL_EXCEPT); - switch (code) { - case OPCODE_FUNC1: - CHECK_ERROR(args == 1); + switch (code) { + case OPCODE_FUNC1: + CHECK_ERROR(args == 1); - if (jmp_gap >= 1 && prev_ops[-1].opcode == OPCODE_CONST) { - UnaryOpFunc func = funcptr; + if (jmp_gap >= 1 && prev_ops[-1].opcode == OPCODE_CONST) { + UnaryOpFunc func = funcptr; - double result = func(prev_ops[-1].arg.dval); + double result = func(prev_ops[-1].arg.dval); - if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { - prev_ops[-1].arg.dval = result; - return true; - } - } - break; + if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { + prev_ops[-1].arg.dval = result; + return true; + } + } + break; - case OPCODE_FUNC2: - CHECK_ERROR(args == 2); + case OPCODE_FUNC2: + CHECK_ERROR(args == 2); - if (jmp_gap >= 2 && prev_ops[-2].opcode == OPCODE_CONST && prev_ops[-1].opcode == OPCODE_CONST) { - BinaryOpFunc func = funcptr; + if (jmp_gap >= 2 && prev_ops[-2].opcode == OPCODE_CONST && + prev_ops[-1].opcode == OPCODE_CONST) { + BinaryOpFunc func = funcptr; - double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval); + double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval); - if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { - prev_ops[-2].arg.dval = result; - state->ops_count--; - state->stack_ptr--; - return true; - } - } - break; + if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { + prev_ops[-2].arg.dval = result; + state->ops_count--; + state->stack_ptr--; + return true; + } + } + break; - default: - BLI_assert(false); - return false; - } + default: + BLI_assert(false); + return false; + } - parse_add_op(state, code, 1 - args)->arg.ptr = funcptr; - return true; + parse_add_op(state, code, 1 - args)->arg.ptr = funcptr; + return true; } /* Extract the next token from raw characters. */ static bool parse_next_token(ExprParseState *state) { - /* Skip whitespace. */ - while (isspace(*state->cur)) { - state->cur++; - } - - /* End of string. */ - if (*state->cur == 0) { - state->token = 0; - return true; - } - - /* Floating point numbers. */ - if (isdigit(*state->cur) || (state->cur[0] == '.' && isdigit(state->cur[1]))) { - char *end, *out = state->tokenbuf; - bool is_float = false; - - while (isdigit(*state->cur)) { - *out++ = *state->cur++; - } - - if (*state->cur == '.') { - is_float = true; - *out++ = *state->cur++; - - while (isdigit(*state->cur)) { - *out++ = *state->cur++; - } - } - - if (ELEM(*state->cur, 'e', 'E')) { - is_float = true; - *out++ = *state->cur++; - - if (ELEM(*state->cur, '+', '-')) { - *out++ = *state->cur++; - } - - CHECK_ERROR(isdigit(*state->cur)); - - while (isdigit(*state->cur)) { - *out++ = *state->cur++; - } - } - - *out = 0; - - /* Forbid C-style octal constants. */ - if (!is_float && state->tokenbuf[0] == '0') { - for (char *p = state->tokenbuf + 1; *p; p++) { - if (*p != '0') { - return false; - } - } - } - - state->token = TOKEN_NUMBER; - state->tokenval = strtod(state->tokenbuf, &end); - return (end == out); - } - - /* ?= tokens */ - if (state->cur[1] == '=' && strchr(token_eq_characters, state->cur[0])) { - state->token = MAKE_CHAR2(state->cur[0], state->cur[1]); - state->cur += 2; - return true; - } - - /* Special characters (single character tokens) */ - if (strchr(token_characters, *state->cur)) { - state->token = *state->cur++; - return true; - } - - /* Identifiers */ - if (isalpha(*state->cur) || ELEM(*state->cur, '_')) { - char *out = state->tokenbuf; - - while (isalnum(*state->cur) || ELEM(*state->cur, '_')) { - *out++ = *state->cur++; - } - - *out = 0; - - for (int i = 0; keyword_list[i].name; i++) { - if (STREQ(state->tokenbuf, keyword_list[i].name)) { - state->token = keyword_list[i].token; - return true; - } - } - - state->token = TOKEN_ID; - return true; - } - - return false; + /* Skip whitespace. */ + while (isspace(*state->cur)) { + state->cur++; + } + + /* End of string. */ + if (*state->cur == 0) { + state->token = 0; + return true; + } + + /* Floating point numbers. */ + if (isdigit(*state->cur) || (state->cur[0] == '.' && isdigit(state->cur[1]))) { + char *end, *out = state->tokenbuf; + bool is_float = false; + + while (isdigit(*state->cur)) { + *out++ = *state->cur++; + } + + if (*state->cur == '.') { + is_float = true; + *out++ = *state->cur++; + + while (isdigit(*state->cur)) { + *out++ = *state->cur++; + } + } + + if (ELEM(*state->cur, 'e', 'E')) { + is_float = true; + *out++ = *state->cur++; + + if (ELEM(*state->cur, '+', '-')) { + *out++ = *state->cur++; + } + + CHECK_ERROR(isdigit(*state->cur)); + + while (isdigit(*state->cur)) { + *out++ = *state->cur++; + } + } + + *out = 0; + + /* Forbid C-style octal constants. */ + if (!is_float && state->tokenbuf[0] == '0') { + for (char *p = state->tokenbuf + 1; *p; p++) { + if (*p != '0') { + return false; + } + } + } + + state->token = TOKEN_NUMBER; + state->tokenval = strtod(state->tokenbuf, &end); + return (end == out); + } + + /* ?= tokens */ + if (state->cur[1] == '=' && strchr(token_eq_characters, state->cur[0])) { + state->token = MAKE_CHAR2(state->cur[0], state->cur[1]); + state->cur += 2; + return true; + } + + /* Special characters (single character tokens) */ + if (strchr(token_characters, *state->cur)) { + state->token = *state->cur++; + return true; + } + + /* Identifiers */ + if (isalpha(*state->cur) || ELEM(*state->cur, '_')) { + char *out = state->tokenbuf; + + while (isalnum(*state->cur) || ELEM(*state->cur, '_')) { + *out++ = *state->cur++; + } + + *out = 0; + + for (int i = 0; keyword_list[i].name; i++) { + if (STREQ(state->tokenbuf, keyword_list[i].name)) { + state->token = keyword_list[i].token; + return true; + } + } + + state->token = TOKEN_ID; + return true; + } + + return false; } /** \} */ @@ -645,303 +644,300 @@ static bool parse_expr(ExprParseState *state); static int parse_function_args(ExprParseState *state) { - if (!parse_next_token(state) || state->token != '(' || !parse_next_token(state)) { - return -1; - } + if (!parse_next_token(state) || state->token != '(' || !parse_next_token(state)) { + return -1; + } - int arg_count = 0; + int arg_count = 0; - for (;;) { - if (!parse_expr(state)) { - return -1; - } + for (;;) { + if (!parse_expr(state)) { + return -1; + } - arg_count++; + arg_count++; - switch (state->token) { - case ',': - if (!parse_next_token(state)) { - return -1; - } - break; + switch (state->token) { + case ',': + if (!parse_next_token(state)) { + return -1; + } + break; - case ')': - if (!parse_next_token(state)) { - return -1; - } - return arg_count; + case ')': + if (!parse_next_token(state)) { + return -1; + } + return arg_count; - default: - return -1; - } - } + default: + return -1; + } + } } static bool parse_unary(ExprParseState *state) { - int i; - - switch (state->token) { - case '+': - return parse_next_token(state) && parse_unary(state); - - case '-': - CHECK_ERROR(parse_next_token(state) && parse_unary(state)); - parse_add_func(state, OPCODE_FUNC1, 1, op_negate); - return true; - - case '(': - return parse_next_token(state) && - parse_expr(state) && - state->token == ')' && - parse_next_token(state); - - case TOKEN_NUMBER: - parse_add_op(state, OPCODE_CONST, 1)->arg.dval = state->tokenval; - return parse_next_token(state); - - case TOKEN_ID: - /* Parameters: search in reverse order in case of duplicate names - - * the last one should win. */ - for (i = state->param_names_len - 1; i >= 0; i--) { - if (STREQ(state->tokenbuf, state->param_names[i])) { - parse_add_op(state, OPCODE_PARAMETER, 1)->arg.ival = i; - return parse_next_token(state); - } - } - - /* Ordinary builtin constants. */ - for (i = 0; builtin_consts[i].name; i++) { - if (STREQ(state->tokenbuf, builtin_consts[i].name)) { - parse_add_op(state, OPCODE_CONST, 1)->arg.dval = builtin_consts[i].value; - return parse_next_token(state); - } - } - - /* Ordinary builtin functions. */ - for (i = 0; builtin_ops[i].name; i++) { - if (STREQ(state->tokenbuf, builtin_ops[i].name)) { - int args = parse_function_args(state); - - return parse_add_func(state, builtin_ops[i].op, args, builtin_ops[i].funcptr); - } - } - - /* Specially supported functions. */ - if (STREQ(state->tokenbuf, "min")) { - int cnt = parse_function_args(state); - CHECK_ERROR(cnt > 0); - - parse_add_op(state, OPCODE_MIN, 1 - cnt)->arg.ival = cnt; - return true; - } - - if (STREQ(state->tokenbuf, "max")) { - int cnt = parse_function_args(state); - CHECK_ERROR(cnt > 0); - - parse_add_op(state, OPCODE_MAX, 1 - cnt)->arg.ival = cnt; - return true; - } - - return false; - - default: - return false; - } + int i; + + switch (state->token) { + case '+': + return parse_next_token(state) && parse_unary(state); + + case '-': + CHECK_ERROR(parse_next_token(state) && parse_unary(state)); + parse_add_func(state, OPCODE_FUNC1, 1, op_negate); + return true; + + case '(': + return parse_next_token(state) && parse_expr(state) && state->token == ')' && + parse_next_token(state); + + case TOKEN_NUMBER: + parse_add_op(state, OPCODE_CONST, 1)->arg.dval = state->tokenval; + return parse_next_token(state); + + case TOKEN_ID: + /* Parameters: search in reverse order in case of duplicate names - + * the last one should win. */ + for (i = state->param_names_len - 1; i >= 0; i--) { + if (STREQ(state->tokenbuf, state->param_names[i])) { + parse_add_op(state, OPCODE_PARAMETER, 1)->arg.ival = i; + return parse_next_token(state); + } + } + + /* Ordinary builtin constants. */ + for (i = 0; builtin_consts[i].name; i++) { + if (STREQ(state->tokenbuf, builtin_consts[i].name)) { + parse_add_op(state, OPCODE_CONST, 1)->arg.dval = builtin_consts[i].value; + return parse_next_token(state); + } + } + + /* Ordinary builtin functions. */ + for (i = 0; builtin_ops[i].name; i++) { + if (STREQ(state->tokenbuf, builtin_ops[i].name)) { + int args = parse_function_args(state); + + return parse_add_func(state, builtin_ops[i].op, args, builtin_ops[i].funcptr); + } + } + + /* Specially supported functions. */ + if (STREQ(state->tokenbuf, "min")) { + int cnt = parse_function_args(state); + CHECK_ERROR(cnt > 0); + + parse_add_op(state, OPCODE_MIN, 1 - cnt)->arg.ival = cnt; + return true; + } + + if (STREQ(state->tokenbuf, "max")) { + int cnt = parse_function_args(state); + CHECK_ERROR(cnt > 0); + + parse_add_op(state, OPCODE_MAX, 1 - cnt)->arg.ival = cnt; + return true; + } + + return false; + + default: + return false; + } } static bool parse_mul(ExprParseState *state) { - CHECK_ERROR(parse_unary(state)); + CHECK_ERROR(parse_unary(state)); - for (;;) { - switch (state->token) { - case '*': - CHECK_ERROR(parse_next_token(state) && parse_unary(state)); - parse_add_func(state, OPCODE_FUNC2, 2, op_mul); - break; + for (;;) { + switch (state->token) { + case '*': + CHECK_ERROR(parse_next_token(state) && parse_unary(state)); + parse_add_func(state, OPCODE_FUNC2, 2, op_mul); + break; - case '/': - CHECK_ERROR(parse_next_token(state) && parse_unary(state)); - parse_add_func(state, OPCODE_FUNC2, 2, op_div); - break; + case '/': + CHECK_ERROR(parse_next_token(state) && parse_unary(state)); + parse_add_func(state, OPCODE_FUNC2, 2, op_div); + break; - default: - return true; - } - } + default: + return true; + } + } } static bool parse_add(ExprParseState *state) { - CHECK_ERROR(parse_mul(state)); + CHECK_ERROR(parse_mul(state)); - for (;;) { - switch (state->token) { - case '+': - CHECK_ERROR(parse_next_token(state) && parse_mul(state)); - parse_add_func(state, OPCODE_FUNC2, 2, op_add); - break; + for (;;) { + switch (state->token) { + case '+': + CHECK_ERROR(parse_next_token(state) && parse_mul(state)); + parse_add_func(state, OPCODE_FUNC2, 2, op_add); + break; - case '-': - CHECK_ERROR(parse_next_token(state) && parse_mul(state)); - parse_add_func(state, OPCODE_FUNC2, 2, op_sub); - break; + case '-': + CHECK_ERROR(parse_next_token(state) && parse_mul(state)); + parse_add_func(state, OPCODE_FUNC2, 2, op_sub); + break; - default: - return true; - } - } + default: + return true; + } + } } static BinaryOpFunc parse_get_cmp_func(short token) { - switch (token) { - case TOKEN_EQ: - return op_eq; - case TOKEN_NE: - return op_ne; - case '>': - return op_gt; - case TOKEN_GE: - return op_ge; - case '<': - return op_lt; - case TOKEN_LE: - return op_le; - default: - return NULL; - } + switch (token) { + case TOKEN_EQ: + return op_eq; + case TOKEN_NE: + return op_ne; + case '>': + return op_gt; + case TOKEN_GE: + return op_ge; + case '<': + return op_lt; + case TOKEN_LE: + return op_le; + default: + return NULL; + } } static bool parse_cmp_chain(ExprParseState *state, BinaryOpFunc cur_func) { - BinaryOpFunc next_func = parse_get_cmp_func(state->token); + BinaryOpFunc next_func = parse_get_cmp_func(state->token); - if (next_func) { - parse_add_op(state, OPCODE_CMP_CHAIN, -1)->arg.func2 = cur_func; - int jump = state->last_jmp = state->ops_count; + if (next_func) { + parse_add_op(state, OPCODE_CMP_CHAIN, -1)->arg.func2 = cur_func; + int jump = state->last_jmp = state->ops_count; - CHECK_ERROR(parse_next_token(state) && parse_add(state)); - CHECK_ERROR(parse_cmp_chain(state, next_func)); + CHECK_ERROR(parse_next_token(state) && parse_add(state)); + CHECK_ERROR(parse_cmp_chain(state, next_func)); - parse_set_jump(state, jump); - } - else { - parse_add_func(state, OPCODE_FUNC2, 2, cur_func); - } + parse_set_jump(state, jump); + } + else { + parse_add_func(state, OPCODE_FUNC2, 2, cur_func); + } - return true; + return true; } static bool parse_cmp(ExprParseState *state) { - CHECK_ERROR(parse_add(state)); + CHECK_ERROR(parse_add(state)); - BinaryOpFunc func = parse_get_cmp_func(state->token); + BinaryOpFunc func = parse_get_cmp_func(state->token); - if (func) { - CHECK_ERROR(parse_next_token(state) && parse_add(state)); + if (func) { + CHECK_ERROR(parse_next_token(state) && parse_add(state)); - return parse_cmp_chain(state, func); - } + return parse_cmp_chain(state, func); + } - return true; + return true; } static bool parse_not(ExprParseState *state) { - if (state->token == TOKEN_NOT) { - CHECK_ERROR(parse_next_token(state) && parse_not(state)); - parse_add_func(state, OPCODE_FUNC1, 1, op_not); - return true; - } + if (state->token == TOKEN_NOT) { + CHECK_ERROR(parse_next_token(state) && parse_not(state)); + parse_add_func(state, OPCODE_FUNC1, 1, op_not); + return true; + } - return parse_cmp(state); + return parse_cmp(state); } static bool parse_and(ExprParseState *state) { - CHECK_ERROR(parse_not(state)); + CHECK_ERROR(parse_not(state)); - if (state->token == TOKEN_AND) { - int jump = parse_add_jump(state, OPCODE_JMP_AND); + if (state->token == TOKEN_AND) { + int jump = parse_add_jump(state, OPCODE_JMP_AND); - CHECK_ERROR(parse_next_token(state) && parse_and(state)); + CHECK_ERROR(parse_next_token(state) && parse_and(state)); - parse_set_jump(state, jump); - } + parse_set_jump(state, jump); + } - return true; + return true; } static bool parse_or(ExprParseState *state) { - CHECK_ERROR(parse_and(state)); + CHECK_ERROR(parse_and(state)); - if (state->token == TOKEN_OR) { - int jump = parse_add_jump(state, OPCODE_JMP_OR); + if (state->token == TOKEN_OR) { + int jump = parse_add_jump(state, OPCODE_JMP_OR); - CHECK_ERROR(parse_next_token(state) && parse_or(state)); + CHECK_ERROR(parse_next_token(state) && parse_or(state)); - parse_set_jump(state, jump); - } + parse_set_jump(state, jump); + } - return true; + return true; } static bool parse_expr(ExprParseState *state) { - /* Temporarily set the constant expression evaluation barrier */ - int prev_last_jmp = state->last_jmp; - int start = state->last_jmp = state->ops_count; + /* Temporarily set the constant expression evaluation barrier */ + int prev_last_jmp = state->last_jmp; + int start = state->last_jmp = state->ops_count; - CHECK_ERROR(parse_or(state)); + CHECK_ERROR(parse_or(state)); - if (state->token == TOKEN_IF) { - /* Ternary IF expression in python requires swapping the - * main body with condition, so stash the body opcodes. */ - int size = state->ops_count - start; - int bytes = size * sizeof(ExprOp); + if (state->token == TOKEN_IF) { + /* Ternary IF expression in python requires swapping the + * main body with condition, so stash the body opcodes. */ + int size = state->ops_count - start; + int bytes = size * sizeof(ExprOp); - ExprOp *body = MEM_mallocN(bytes, "driver if body"); - memcpy(body, state->ops + start, bytes); + ExprOp *body = MEM_mallocN(bytes, "driver if body"); + memcpy(body, state->ops + start, bytes); - state->last_jmp = state->ops_count = start; - state->stack_ptr--; + state->last_jmp = state->ops_count = start; + state->stack_ptr--; - /* Parse condition. */ - if (!parse_next_token(state) || !parse_or(state) || - state->token != TOKEN_ELSE || !parse_next_token(state)) - { - MEM_freeN(body); - return false; - } + /* Parse condition. */ + if (!parse_next_token(state) || !parse_or(state) || state->token != TOKEN_ELSE || + !parse_next_token(state)) { + MEM_freeN(body); + return false; + } - int jmp_else = parse_add_jump(state, OPCODE_JMP_ELSE); + int jmp_else = parse_add_jump(state, OPCODE_JMP_ELSE); - /* Add body back. */ - memcpy(parse_alloc_ops(state, size), body, bytes); - MEM_freeN(body); + /* Add body back. */ + memcpy(parse_alloc_ops(state, size), body, bytes); + MEM_freeN(body); - state->stack_ptr++; + state->stack_ptr++; - int jmp_end = parse_add_jump(state, OPCODE_JMP); + int jmp_end = parse_add_jump(state, OPCODE_JMP); - /* Parse the else block. */ - parse_set_jump(state, jmp_else); + /* Parse the else block. */ + parse_set_jump(state, jmp_else); - CHECK_ERROR(parse_expr(state)); + CHECK_ERROR(parse_expr(state)); - parse_set_jump(state, jmp_end); - } - /* If no actual jumps happened, restore previous barrier */ - else if (state->last_jmp == start) { - state->last_jmp = prev_last_jmp; - } + parse_set_jump(state, jmp_end); + } + /* If no actual jumps happened, restore previous barrier */ + else if (state->last_jmp == start) { + state->last_jmp = prev_last_jmp; + } - return true; + return true; } /** \} */ @@ -956,44 +952,46 @@ static bool parse_expr(ExprParseState *state) * Parse the expression for evaluation later. * Returns non-NULL even on failure; use is_valid to check. */ -ExprPyLike_Parsed *BLI_expr_pylike_parse(const char *expression, const char **param_names, int param_names_len) +ExprPyLike_Parsed *BLI_expr_pylike_parse(const char *expression, + const char **param_names, + int param_names_len) { - /* Prepare the parser state. */ - ExprParseState state; - memset(&state, 0, sizeof(state)); + /* Prepare the parser state. */ + ExprParseState state; + memset(&state, 0, sizeof(state)); - state.cur = state.expr = expression; + state.cur = state.expr = expression; - state.param_names_len = param_names_len; - state.param_names = param_names; + state.param_names_len = param_names_len; + state.param_names = param_names; - state.tokenbuf = MEM_mallocN(strlen(expression) + 1, __func__); + state.tokenbuf = MEM_mallocN(strlen(expression) + 1, __func__); - state.max_ops = 16; - state.ops = MEM_mallocN(state.max_ops * sizeof(ExprOp), __func__); + state.max_ops = 16; + state.ops = MEM_mallocN(state.max_ops * sizeof(ExprOp), __func__); - /* Parse the expression. */ - ExprPyLike_Parsed *expr; + /* Parse the expression. */ + ExprPyLike_Parsed *expr; - if (parse_next_token(&state) && parse_expr(&state) && state.token == 0) { - BLI_assert(state.stack_ptr == 1); + if (parse_next_token(&state) && parse_expr(&state) && state.token == 0) { + BLI_assert(state.stack_ptr == 1); - int bytesize = sizeof(ExprPyLike_Parsed) + state.ops_count * sizeof(ExprOp); + int bytesize = sizeof(ExprPyLike_Parsed) + state.ops_count * sizeof(ExprOp); - expr = MEM_mallocN(bytesize, "ExprPyLike_Parsed"); - expr->ops_count = state.ops_count; - expr->max_stack = state.max_stack; + expr = MEM_mallocN(bytesize, "ExprPyLike_Parsed"); + expr->ops_count = state.ops_count; + expr->max_stack = state.max_stack; - memcpy(expr->ops, state.ops, state.ops_count * sizeof(ExprOp)); - } - else { - /* Always return a non-NULL object so that parse failure can be cached. */ - expr = MEM_callocN(sizeof(ExprPyLike_Parsed), "ExprPyLike_Parsed(empty)"); - } + memcpy(expr->ops, state.ops, state.ops_count * sizeof(ExprOp)); + } + else { + /* Always return a non-NULL object so that parse failure can be cached. */ + expr = MEM_callocN(sizeof(ExprPyLike_Parsed), "ExprPyLike_Parsed(empty)"); + } - MEM_freeN(state.tokenbuf); - MEM_freeN(state.ops); - return expr; + MEM_freeN(state.tokenbuf); + MEM_freeN(state.ops); + return expr; } /** \} */ diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index afedd19b6d5..9e07b4d2836 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -21,8 +21,7 @@ * \ingroup bli */ - -#include <stdlib.h> /* malloc */ +#include <stdlib.h> /* malloc */ #include <string.h> #include <sys/types.h> @@ -53,52 +52,52 @@ #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLI_sys_types.h" // for intptr_t support +#include "BLI_sys_types.h" // for intptr_t support -#if 0 /* UNUSED */ +#if 0 /* UNUSED */ /* gzip the file in from and write it to "to". * return -1 if zlib fails, -2 if the originating file does not exist * note: will remove the "from" file */ int BLI_file_gzip(const char *from, const char *to) { - char buffer[10240]; - int file; - int readsize = 0; - int rval = 0, err; - gzFile gzfile; - - /* level 1 is very close to 3 (the default) in terms of file size, - * but about twice as fast, best use for speedy saving - campbell */ - gzfile = BLI_gzopen(to, "wb1"); - if (gzfile == NULL) - return -1; - file = BLI_open(from, O_BINARY | O_RDONLY, 0); - if (file == -1) - return -2; - - while (1) { - readsize = read(file, buffer, sizeof(buffer)); - - if (readsize < 0) { - rval = -2; /* error happened in reading */ - fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno)); - break; - } - else if (readsize == 0) - break; /* done reading */ - - if (gzwrite(gzfile, buffer, readsize) <= 0) { - rval = -1; /* error happened in writing */ - fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err)); - break; - } - } - - gzclose(gzfile); - close(file); - - return rval; + char buffer[10240]; + int file; + int readsize = 0; + int rval = 0, err; + gzFile gzfile; + + /* level 1 is very close to 3 (the default) in terms of file size, + * but about twice as fast, best use for speedy saving - campbell */ + gzfile = BLI_gzopen(to, "wb1"); + if (gzfile == NULL) + return -1; + file = BLI_open(from, O_BINARY | O_RDONLY, 0); + if (file == -1) + return -2; + + while (1) { + readsize = read(file, buffer, sizeof(buffer)); + + if (readsize < 0) { + rval = -2; /* error happened in reading */ + fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno)); + break; + } + else if (readsize == 0) + break; /* done reading */ + + if (gzwrite(gzfile, buffer, readsize) <= 0) { + rval = -1; /* error happened in writing */ + fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err)); + break; + } + } + + gzclose(gzfile); + close(file); + + return rval; } #endif @@ -107,46 +106,46 @@ int BLI_file_gzip(const char *from, const char *to) */ char *BLI_file_ungzip_to_mem(const char *from_file, int *r_size) { - gzFile gzfile; - int readsize, size, alloc_size = 0; - char *mem = NULL; - const int chunk_size = 512 * 1024; - - size = 0; - - gzfile = BLI_gzopen(from_file, "rb"); - for (;; ) { - if (mem == NULL) { - mem = MEM_callocN(chunk_size, "BLI_ungzip_to_mem"); - alloc_size = chunk_size; - } - else { - mem = MEM_reallocN(mem, size + chunk_size); - alloc_size += chunk_size; - } - - readsize = gzread(gzfile, mem + size, chunk_size); - if (readsize > 0) { - size += readsize; - } - else { - break; - } - } - - gzclose(gzfile); - - if (size == 0) { - MEM_freeN(mem); - mem = NULL; - } - else if (alloc_size != size) { - mem = MEM_reallocN(mem, size); - } - - *r_size = size; - - return mem; + gzFile gzfile; + int readsize, size, alloc_size = 0; + char *mem = NULL; + const int chunk_size = 512 * 1024; + + size = 0; + + gzfile = BLI_gzopen(from_file, "rb"); + for (;;) { + if (mem == NULL) { + mem = MEM_callocN(chunk_size, "BLI_ungzip_to_mem"); + alloc_size = chunk_size; + } + else { + mem = MEM_reallocN(mem, size + chunk_size); + alloc_size += chunk_size; + } + + readsize = gzread(gzfile, mem + size, chunk_size); + if (readsize > 0) { + size += readsize; + } + else { + break; + } + } + + gzclose(gzfile); + + if (size == 0) { + MEM_freeN(mem); + mem = NULL; + } + else if (alloc_size != size) { + mem = MEM_reallocN(mem, size); + } + + *r_size = size; + + return mem; } /** @@ -158,27 +157,27 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *r_size) */ bool BLI_file_is_writable(const char *filename) { - bool writable; - if (BLI_access(filename, W_OK) == 0) { - /* file exists and I can write to it */ - writable = true; - } - else if (errno != ENOENT) { - /* most likely file or containing directory cannot be accessed */ - writable = false; - } - else { - /* file doesn't exist -- check I can create it in parent directory */ - char parent[FILE_MAX]; - BLI_split_dirfile(filename, parent, NULL, sizeof(parent), 0); + bool writable; + if (BLI_access(filename, W_OK) == 0) { + /* file exists and I can write to it */ + writable = true; + } + else if (errno != ENOENT) { + /* most likely file or containing directory cannot be accessed */ + writable = false; + } + else { + /* file doesn't exist -- check I can create it in parent directory */ + char parent[FILE_MAX]; + BLI_split_dirfile(filename, parent, NULL, sizeof(parent), 0); #ifdef WIN32 - /* windows does not have X_OK */ - writable = BLI_access(parent, W_OK) == 0; + /* windows does not have X_OK */ + writable = BLI_access(parent, W_OK) == 0; #else - writable = BLI_access(parent, X_OK | W_OK) == 0; + writable = BLI_access(parent, X_OK | W_OK) == 0; #endif - } - return writable; + } + return writable; } /** @@ -187,338 +186,338 @@ bool BLI_file_is_writable(const char *filename) */ bool BLI_file_touch(const char *file) { - FILE *f = BLI_fopen(file, "r+b"); - - if (f != NULL) { - int c = getc(f); - - if (c == EOF) { - /* Empty file, reopen in truncate write mode... */ - fclose(f); - f = BLI_fopen(file, "w+b"); - } - else { - /* Otherwise, rewrite first byte. */ - rewind(f); - putc(c, f); - } - } - else { - f = BLI_fopen(file, "wb"); - } - if (f) { - fclose(f); - return true; - } - return false; + FILE *f = BLI_fopen(file, "r+b"); + + if (f != NULL) { + int c = getc(f); + + if (c == EOF) { + /* Empty file, reopen in truncate write mode... */ + fclose(f); + f = BLI_fopen(file, "w+b"); + } + else { + /* Otherwise, rewrite first byte. */ + rewind(f); + putc(c, f); + } + } + else { + f = BLI_fopen(file, "wb"); + } + if (f) { + fclose(f); + return true; + } + return false; } #ifdef WIN32 static void callLocalErrorCallBack(const char *err) { - printf("%s\n", err); + printf("%s\n", err); } FILE *BLI_fopen(const char *filename, const char *mode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return ufopen(filename, mode); + return ufopen(filename, mode); } void BLI_get_short_name(char short_name[256], const char *filename) { - wchar_t short_name_16[256]; - int i = 0; + wchar_t short_name_16[256]; + int i = 0; - UTF16_ENCODE(filename); + UTF16_ENCODE(filename); - GetShortPathNameW(filename_16, short_name_16, 256); + GetShortPathNameW(filename_16, short_name_16, 256); - for (i = 0; i < 256; i++) { - short_name[i] = (char)short_name_16[i]; - } + for (i = 0; i < 256; i++) { + short_name[i] = (char)short_name_16[i]; + } - UTF16_UN_ENCODE(filename); + UTF16_UN_ENCODE(filename); } void *BLI_gzopen(const char *filename, const char *mode) { - gzFile gzfile; + gzFile gzfile; - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - /* xxx Creates file before transcribing the path */ - if (mode[0] == 'w') { - fclose(ufopen(filename, "a")); - } + /* xxx Creates file before transcribing the path */ + if (mode[0] == 'w') { + fclose(ufopen(filename, "a")); + } - /* temporary #if until we update all libraries to 1.2.7 - * for correct wide char path handling */ -#if ZLIB_VERNUM >= 0x1270 - UTF16_ENCODE(filename); + /* temporary #if until we update all libraries to 1.2.7 + * for correct wide char path handling */ +# if ZLIB_VERNUM >= 0x1270 + UTF16_ENCODE(filename); - gzfile = gzopen_w(filename_16, mode); + gzfile = gzopen_w(filename_16, mode); - UTF16_UN_ENCODE(filename); -#else - { - char short_name[256]; - BLI_get_short_name(short_name, filename); - gzfile = gzopen(short_name, mode); - } -#endif + UTF16_UN_ENCODE(filename); +# else + { + char short_name[256]; + BLI_get_short_name(short_name, filename); + gzfile = gzopen(short_name, mode); + } +# endif - return gzfile; + return gzfile; } -int BLI_open(const char *filename, int oflag, int pmode) +int BLI_open(const char *filename, int oflag, int pmode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return uopen(filename, oflag, pmode); + return uopen(filename, oflag, pmode); } -int BLI_access(const char *filename, int mode) +int BLI_access(const char *filename, int mode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return uaccess(filename, mode); + return uaccess(filename, mode); } static bool delete_unique(const char *path, const bool dir) { - bool err; - - UTF16_ENCODE(path); - - if (dir) { - err = !RemoveDirectoryW(path_16); - if (err) { - printf("Unable to remove directory\n"); - } - } - else { - err = !DeleteFileW(path_16); - if (err) { - callLocalErrorCallBack("Unable to delete file"); - } - } - - UTF16_UN_ENCODE(path); - - return err; + bool err; + + UTF16_ENCODE(path); + + if (dir) { + err = !RemoveDirectoryW(path_16); + if (err) { + printf("Unable to remove directory\n"); + } + } + else { + err = !DeleteFileW(path_16); + if (err) { + callLocalErrorCallBack("Unable to delete file"); + } + } + + UTF16_UN_ENCODE(path); + + return err; } static bool delete_recursive(const char *dir) { - struct direntry *filelist, *fl; - bool err = false; - uint nbr, i; - - i = nbr = BLI_filelist_dir_contents(dir, &filelist); - fl = filelist; - while (i--) { - const char *file = BLI_path_basename(fl->path); - - if (FILENAME_IS_CURRPAR(file)) { - /* Skip! */ - } - else if (S_ISDIR(fl->type)) { - char path[FILE_MAXDIR]; - - /* dir listing produces dir path without trailing slash... */ - BLI_strncpy(path, fl->path, sizeof(path)); - BLI_add_slash(path); - - if (delete_recursive(path)) { - err = true; - } - } - else { - if (delete_unique(fl->path, false)) { - err = true; - } - } - ++fl; - } - - if (!err && delete_unique(dir, true)) { - err = true; - } - - BLI_filelist_free(filelist, nbr); - - return err; + struct direntry *filelist, *fl; + bool err = false; + uint nbr, i; + + i = nbr = BLI_filelist_dir_contents(dir, &filelist); + fl = filelist; + while (i--) { + const char *file = BLI_path_basename(fl->path); + + if (FILENAME_IS_CURRPAR(file)) { + /* Skip! */ + } + else if (S_ISDIR(fl->type)) { + char path[FILE_MAXDIR]; + + /* dir listing produces dir path without trailing slash... */ + BLI_strncpy(path, fl->path, sizeof(path)); + BLI_add_slash(path); + + if (delete_recursive(path)) { + err = true; + } + } + else { + if (delete_unique(fl->path, false)) { + err = true; + } + } + ++fl; + } + + if (!err && delete_unique(dir, true)) { + err = true; + } + + BLI_filelist_free(filelist, nbr); + + return err; } int BLI_delete(const char *file, bool dir, bool recursive) { - int err; + int err; - BLI_assert(!BLI_path_is_rel(file)); + BLI_assert(!BLI_path_is_rel(file)); - if (recursive) { - err = delete_recursive(file); - } - else { - err = delete_unique(file, dir); - } + if (recursive) { + err = delete_recursive(file); + } + else { + err = delete_unique(file, dir); + } - return err; + return err; } /* Not used anywhere! */ -#if 0 +# if 0 int BLI_move(const char *file, const char *to) { - char str[MAXPATHLEN + 12]; - int err; - - /* windows doesn't support moving to a directory - * it has to be 'mv filename filename' and not - * 'mv filename destdir' */ - - BLI_strncpy(str, to, sizeof(str)); - /* points 'to' to a directory ? */ - if (BLI_last_slash(str) == (str + strlen(str) - 1)) { - if (BLI_last_slash(file) != NULL) { - strcat(str, BLI_last_slash(file) + 1); - } - } - - UTF16_ENCODE(file); - UTF16_ENCODE(str); - err = !MoveFileW(file_16, str_16); - UTF16_UN_ENCODE(str); - UTF16_UN_ENCODE(file); - - if (err) { - callLocalErrorCallBack("Unable to move file"); - printf(" Move from '%s' to '%s' failed\n", file, str); - } - - return err; + char str[MAXPATHLEN + 12]; + int err; + + /* windows doesn't support moving to a directory + * it has to be 'mv filename filename' and not + * 'mv filename destdir' */ + + BLI_strncpy(str, to, sizeof(str)); + /* points 'to' to a directory ? */ + if (BLI_last_slash(str) == (str + strlen(str) - 1)) { + if (BLI_last_slash(file) != NULL) { + strcat(str, BLI_last_slash(file) + 1); + } + } + + UTF16_ENCODE(file); + UTF16_ENCODE(str); + err = !MoveFileW(file_16, str_16); + UTF16_UN_ENCODE(str); + UTF16_UN_ENCODE(file); + + if (err) { + callLocalErrorCallBack("Unable to move file"); + printf(" Move from '%s' to '%s' failed\n", file, str); + } + + return err; } -#endif +# endif int BLI_copy(const char *file, const char *to) { - char str[MAXPATHLEN + 12]; - int err; - - /* windows doesn't support copying to a directory - * it has to be 'cp filename filename' and not - * 'cp filename destdir' */ - - BLI_strncpy(str, to, sizeof(str)); - /* points 'to' to a directory ? */ - if (BLI_last_slash(str) == (str + strlen(str) - 1)) { - if (BLI_last_slash(file) != NULL) { - strcat(str, BLI_last_slash(file) + 1); - } - } - - UTF16_ENCODE(file); - UTF16_ENCODE(str); - err = !CopyFileW(file_16, str_16, false); - UTF16_UN_ENCODE(str); - UTF16_UN_ENCODE(file); - - if (err) { - callLocalErrorCallBack("Unable to copy file!"); - printf(" Copy from '%s' to '%s' failed\n", file, str); - } - - return err; + char str[MAXPATHLEN + 12]; + int err; + + /* windows doesn't support copying to a directory + * it has to be 'cp filename filename' and not + * 'cp filename destdir' */ + + BLI_strncpy(str, to, sizeof(str)); + /* points 'to' to a directory ? */ + if (BLI_last_slash(str) == (str + strlen(str) - 1)) { + if (BLI_last_slash(file) != NULL) { + strcat(str, BLI_last_slash(file) + 1); + } + } + + UTF16_ENCODE(file); + UTF16_ENCODE(str); + err = !CopyFileW(file_16, str_16, false); + UTF16_UN_ENCODE(str); + UTF16_UN_ENCODE(file); + + if (err) { + callLocalErrorCallBack("Unable to copy file!"); + printf(" Copy from '%s' to '%s' failed\n", file, str); + } + + return err; } -#if 0 +# if 0 int BLI_create_symlink(const char *file, const char *to) { - /* See patch from T30870, should this ever become needed. */ - callLocalErrorCallBack("Linking files is unsupported on Windows"); - (void)file; - (void)to; - return 1; + /* See patch from T30870, should this ever become needed. */ + callLocalErrorCallBack("Linking files is unsupported on Windows"); + (void)file; + (void)to; + return 1; } -#endif +# endif /** \return true on success (i.e. given path now exists on FS), false otherwise. */ bool BLI_dir_create_recursive(const char *dirname) { - char *lslash; - char tmp[MAXPATHLEN]; - bool ret = true; - - /* First remove possible slash at the end of the dirname. - * This routine otherwise tries to create - * blah1/blah2/ (with slash) after creating - * blah1/blah2 (without slash) */ - - BLI_strncpy(tmp, dirname, sizeof(tmp)); - BLI_del_slash(tmp); - - /* check special case "c:\foo", don't try create "c:", harmless but prints an error below */ - if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') { - return true; - } - - if (BLI_is_dir(tmp)) { - return true; - } - else if (BLI_exists(tmp)) { - return false; - } - - lslash = (char *)BLI_last_slash(tmp); - - if (lslash) { - /* Split about the last slash and recurse */ - *lslash = 0; - if (!BLI_dir_create_recursive(tmp)) { - ret = false; - } - } - - if (ret && dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */ - if (umkdir(dirname) == -1) { - printf("Unable to create directory %s\n", dirname); - ret = false; - } - } - return ret; + char *lslash; + char tmp[MAXPATHLEN]; + bool ret = true; + + /* First remove possible slash at the end of the dirname. + * This routine otherwise tries to create + * blah1/blah2/ (with slash) after creating + * blah1/blah2 (without slash) */ + + BLI_strncpy(tmp, dirname, sizeof(tmp)); + BLI_del_slash(tmp); + + /* check special case "c:\foo", don't try create "c:", harmless but prints an error below */ + if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') { + return true; + } + + if (BLI_is_dir(tmp)) { + return true; + } + else if (BLI_exists(tmp)) { + return false; + } + + lslash = (char *)BLI_last_slash(tmp); + + if (lslash) { + /* Split about the last slash and recurse */ + *lslash = 0; + if (!BLI_dir_create_recursive(tmp)) { + ret = false; + } + } + + if (ret && dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */ + if (umkdir(dirname) == -1) { + printf("Unable to create directory %s\n", dirname); + ret = false; + } + } + return ret; } int BLI_rename(const char *from, const char *to) { - if (!BLI_exists(from)) { - return 0; - } - - /* make sure the filenames are different (case insensitive) before removing */ - if (BLI_exists(to) && BLI_strcasecmp(from, to)) { - if (BLI_delete(to, false, false)) { - return 1; - } - } - - return urename(from, to); + if (!BLI_exists(from)) { + return 0; + } + + /* make sure the filenames are different (case insensitive) before removing */ + if (BLI_exists(to) && BLI_strcasecmp(from, to)) { + if (BLI_delete(to, false, false)) { + return 1; + } + } + + return urename(from, to); } #else /* The UNIX world */ /* results from recursive_operation and its callbacks */ enum { - /* operation succeeded */ - RecursiveOp_Callback_OK = 0, + /* operation succeeded */ + RecursiveOp_Callback_OK = 0, - /* operation requested not to perform recursive digging for current path */ - RecursiveOp_Callback_StopRecurs = 1, + /* operation requested not to perform recursive digging for current path */ + RecursiveOp_Callback_StopRecurs = 1, - /* error occured in callback and recursive walking should stop immediately */ - RecursiveOp_Callback_Error = 2, + /* error occured in callback and recursive walking should stop immediately */ + RecursiveOp_Callback_Error = 2, }; typedef int (*RecursiveOp_Callback)(const char *from, const char *to); @@ -526,30 +525,28 @@ typedef int (*RecursiveOp_Callback)(const char *from, const char *to); /* appending of filename to dir (ensures for buffer size before appending) */ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, const char *file) { - size_t len = strlen(dir) + strlen(file) + 1; + size_t len = strlen(dir) + strlen(file) + 1; - if (*dst == NULL) { - *dst = MEM_mallocN(len + 1, "join_dirfile_alloc path"); - } - else if (*alloc_len < len) { - *dst = MEM_reallocN(*dst, len + 1); - } + if (*dst == NULL) { + *dst = MEM_mallocN(len + 1, "join_dirfile_alloc path"); + } + else if (*alloc_len < len) { + *dst = MEM_reallocN(*dst, len + 1); + } - *alloc_len = len; + *alloc_len = len; - BLI_join_dirfile(*dst, len + 1, dir, file); + BLI_join_dirfile(*dst, len + 1, dir, file); } static char *strip_last_slash(const char *dir) { - char *result = BLI_strdup(dir); - BLI_del_slash(result); + char *result = BLI_strdup(dir); + BLI_del_slash(result); - return result; + return result; } - - /** * Scans \a startfrom, generating a corresponding destination name for each item found by * prefixing it with startto, recursively scanning subdirectories, and invoking the specified @@ -563,190 +560,192 @@ static char *strip_last_slash(const char *dir) * \param callback_dir_post: optional, to be invoked after leaving a subdirectory. * \return */ -static int recursive_operation(const char *startfrom, const char *startto, +static int recursive_operation(const char *startfrom, + const char *startto, RecursiveOp_Callback callback_dir_pre, - RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post) + RecursiveOp_Callback callback_file, + RecursiveOp_Callback callback_dir_post) { - struct stat st; - char *from = NULL, *to = NULL; - char *from_path = NULL, *to_path = NULL; - struct dirent **dirlist = NULL; - size_t from_alloc_len = -1, to_alloc_len = -1; - int i, n = 0, ret = 0; - - do { /* once */ - /* ensure there's no trailing slash in file path */ - from = strip_last_slash(startfrom); - if (startto) { - to = strip_last_slash(startto); - } - - ret = lstat(from, &st); - if (ret < 0) { - /* source wasn't found, nothing to operate with */ - break; - } - - if (!S_ISDIR(st.st_mode)) { - /* source isn't a directory, can't do recursive walking for it, - * so just call file callback and leave */ - if (callback_file != NULL) { - ret = callback_file(from, to); - if (ret != RecursiveOp_Callback_OK) { - ret = -1; - } - } - break; - } - - n = scandir(startfrom, &dirlist, NULL, alphasort); - if (n < 0) { - /* error opening directory for listing */ - perror("scandir"); - ret = -1; - break; - } - - if (callback_dir_pre != NULL) { - ret = callback_dir_pre(from, to); - if (ret != RecursiveOp_Callback_OK) { - if (ret == RecursiveOp_Callback_StopRecurs) { - /* callback requested not to perform recursive walking, not an error */ - ret = 0; - } - else { - ret = -1; - } - break; - } - } - - for (i = 0; i < n; i++) { - const struct dirent * const dirent = dirlist[i]; - - if (FILENAME_IS_CURRPAR(dirent->d_name)) { - continue; - } - - join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name); - if (to) { - join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name); - } - - bool is_dir; - -#ifdef __HAIKU__ - { - struct stat st_dir; - char filename[FILE_MAX]; - BLI_path_join(filename, sizeof(filename), startfrom, dirent->d_name, NULL); - lstat(filename, &st_dir); - is_dir = S_ISDIR(st_dir.st_mode); - } -#else - is_dir = (dirent->d_type == DT_DIR); -#endif - - if (is_dir) { - /* recursively dig into a subfolder */ - ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post); - } - else if (callback_file != NULL) { - ret = callback_file(from_path, to_path); - if (ret != RecursiveOp_Callback_OK) { - ret = -1; - } - } - - if (ret != 0) { - break; - } - } - if (ret != 0) { - break; - } - - if (callback_dir_post != NULL) { - ret = callback_dir_post(from, to); - if (ret != RecursiveOp_Callback_OK) { - ret = -1; - } - } - } while (false); - - if (dirlist != NULL) { - for (i = 0; i < n; i++) { - free(dirlist[i]); - } - free(dirlist); - } - if (from_path != NULL) { - MEM_freeN(from_path); - } - if (to_path != NULL) { - MEM_freeN(to_path); - } - if (from != NULL) { - MEM_freeN(from); - } - if (to != NULL) { - MEM_freeN(to); - } - - return ret; + struct stat st; + char *from = NULL, *to = NULL; + char *from_path = NULL, *to_path = NULL; + struct dirent **dirlist = NULL; + size_t from_alloc_len = -1, to_alloc_len = -1; + int i, n = 0, ret = 0; + + do { /* once */ + /* ensure there's no trailing slash in file path */ + from = strip_last_slash(startfrom); + if (startto) { + to = strip_last_slash(startto); + } + + ret = lstat(from, &st); + if (ret < 0) { + /* source wasn't found, nothing to operate with */ + break; + } + + if (!S_ISDIR(st.st_mode)) { + /* source isn't a directory, can't do recursive walking for it, + * so just call file callback and leave */ + if (callback_file != NULL) { + ret = callback_file(from, to); + if (ret != RecursiveOp_Callback_OK) { + ret = -1; + } + } + break; + } + + n = scandir(startfrom, &dirlist, NULL, alphasort); + if (n < 0) { + /* error opening directory for listing */ + perror("scandir"); + ret = -1; + break; + } + + if (callback_dir_pre != NULL) { + ret = callback_dir_pre(from, to); + if (ret != RecursiveOp_Callback_OK) { + if (ret == RecursiveOp_Callback_StopRecurs) { + /* callback requested not to perform recursive walking, not an error */ + ret = 0; + } + else { + ret = -1; + } + break; + } + } + + for (i = 0; i < n; i++) { + const struct dirent *const dirent = dirlist[i]; + + if (FILENAME_IS_CURRPAR(dirent->d_name)) { + continue; + } + + join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name); + if (to) { + join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name); + } + + bool is_dir; + +# ifdef __HAIKU__ + { + struct stat st_dir; + char filename[FILE_MAX]; + BLI_path_join(filename, sizeof(filename), startfrom, dirent->d_name, NULL); + lstat(filename, &st_dir); + is_dir = S_ISDIR(st_dir.st_mode); + } +# else + is_dir = (dirent->d_type == DT_DIR); +# endif + + if (is_dir) { + /* recursively dig into a subfolder */ + ret = recursive_operation( + from_path, to_path, callback_dir_pre, callback_file, callback_dir_post); + } + else if (callback_file != NULL) { + ret = callback_file(from_path, to_path); + if (ret != RecursiveOp_Callback_OK) { + ret = -1; + } + } + + if (ret != 0) { + break; + } + } + if (ret != 0) { + break; + } + + if (callback_dir_post != NULL) { + ret = callback_dir_post(from, to); + if (ret != RecursiveOp_Callback_OK) { + ret = -1; + } + } + } while (false); + + if (dirlist != NULL) { + for (i = 0; i < n; i++) { + free(dirlist[i]); + } + free(dirlist); + } + if (from_path != NULL) { + MEM_freeN(from_path); + } + if (to_path != NULL) { + MEM_freeN(to_path); + } + if (from != NULL) { + MEM_freeN(from); + } + if (to != NULL) { + MEM_freeN(to); + } + + return ret; } static int delete_callback_post(const char *from, const char *UNUSED(to)) { - if (rmdir(from)) { - perror("rmdir"); + if (rmdir(from)) { + perror("rmdir"); - return RecursiveOp_Callback_Error; - } + return RecursiveOp_Callback_Error; + } - return RecursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } static int delete_single_file(const char *from, const char *UNUSED(to)) { - if (unlink(from)) { - perror("unlink"); + if (unlink(from)) { + perror("unlink"); - return RecursiveOp_Callback_Error; - } + return RecursiveOp_Callback_Error; + } - return RecursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } FILE *BLI_fopen(const char *filename, const char *mode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return fopen(filename, mode); + return fopen(filename, mode); } void *BLI_gzopen(const char *filename, const char *mode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return gzopen(filename, mode); + return gzopen(filename, mode); } int BLI_open(const char *filename, int oflag, int pmode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return open(filename, oflag, pmode); + return open(filename, oflag, pmode); } -int BLI_access(const char *filename, int mode) +int BLI_access(const char *filename, int mode) { - BLI_assert(!BLI_path_is_rel(filename)); + BLI_assert(!BLI_path_is_rel(filename)); - return access(filename, mode); + return access(filename, mode); } - /** * Deletes the specified file or directory (depending on dir), optionally * doing recursive delete of directory contents. @@ -755,17 +754,17 @@ int BLI_access(const char *filename, int mode) */ int BLI_delete(const char *file, bool dir, bool recursive) { - BLI_assert(!BLI_path_is_rel(file)); - - if (recursive) { - return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post); - } - else if (dir) { - return rmdir(file); - } - else { - return remove(file); - } + BLI_assert(!BLI_path_is_rel(file)); + + if (recursive) { + return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post); + } + else if (dir) { + return rmdir(file); + } + else { + return remove(file); + } } /** @@ -773,17 +772,17 @@ int BLI_delete(const char *file, bool dir, bool recursive) */ static bool check_the_same(const char *path_a, const char *path_b) { - struct stat st_a, st_b; + struct stat st_a, st_b; - if (lstat(path_a, &st_a)) { - return false; - } + if (lstat(path_a, &st_a)) { + return false; + } - if (lstat(path_b, &st_b)) { - return false; - } + if (lstat(path_b, &st_b)) { + return false; + } - return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino; + return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino; } /** @@ -791,298 +790,295 @@ static bool check_the_same(const char *path_a, const char *path_b) */ static int set_permissions(const char *file, const struct stat *st) { - if (chown(file, st->st_uid, st->st_gid)) { - perror("chown"); - return -1; - } + if (chown(file, st->st_uid, st->st_gid)) { + perror("chown"); + return -1; + } - if (chmod(file, st->st_mode)) { - perror("chmod"); - return -1; - } + if (chmod(file, st->st_mode)) { + perror("chmod"); + return -1; + } - return 0; + return 0; } /* pre-recursive callback for copying operation * creates a destination directory where all source content fill be copied to */ static int copy_callback_pre(const char *from, const char *to) { - struct stat st; - - if (check_the_same(from, to)) { - fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); - return RecursiveOp_Callback_Error; - } - - if (lstat(from, &st)) { - perror("stat"); - return RecursiveOp_Callback_Error; - } - - /* create a directory */ - if (mkdir(to, st.st_mode)) { - perror("mkdir"); - return RecursiveOp_Callback_Error; - } - - /* set proper owner and group on new directory */ - if (chown(to, st.st_uid, st.st_gid)) { - perror("chown"); - return RecursiveOp_Callback_Error; - } - - return RecursiveOp_Callback_OK; + struct stat st; + + if (check_the_same(from, to)) { + fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); + return RecursiveOp_Callback_Error; + } + + if (lstat(from, &st)) { + perror("stat"); + return RecursiveOp_Callback_Error; + } + + /* create a directory */ + if (mkdir(to, st.st_mode)) { + perror("mkdir"); + return RecursiveOp_Callback_Error; + } + + /* set proper owner and group on new directory */ + if (chown(to, st.st_uid, st.st_gid)) { + perror("chown"); + return RecursiveOp_Callback_Error; + } + + return RecursiveOp_Callback_OK; } static int copy_single_file(const char *from, const char *to) { - FILE *from_stream, *to_stream; - struct stat st; - char buf[4096]; - size_t len; - - if (check_the_same(from, to)) { - fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); - return RecursiveOp_Callback_Error; - } - - if (lstat(from, &st)) { - perror("lstat"); - return RecursiveOp_Callback_Error; - } - - if (S_ISLNK(st.st_mode)) { - /* symbolic links should be copied in special way */ - char *link_buffer; - int need_free; - ssize_t link_len; - - /* get large enough buffer to read link content */ - if ((st.st_size + 1) < sizeof(buf)) { - link_buffer = buf; - need_free = 0; - } - else { - link_buffer = MEM_callocN(st.st_size + 2, "copy_single_file link_buffer"); - need_free = 1; - } - - link_len = readlink(from, link_buffer, st.st_size + 1); - if (link_len < 0) { - perror("readlink"); - - if (need_free) { - MEM_freeN(link_buffer); - } - - return RecursiveOp_Callback_Error; - } - - link_buffer[link_len] = '\0'; - - if (symlink(link_buffer, to)) { - perror("symlink"); - if (need_free) { - MEM_freeN(link_buffer); - } - return RecursiveOp_Callback_Error; - } - - if (need_free) { - MEM_freeN(link_buffer); - } - - return RecursiveOp_Callback_OK; - } - else if (S_ISCHR(st.st_mode) || - S_ISBLK(st.st_mode) || - S_ISFIFO(st.st_mode) || - S_ISSOCK(st.st_mode)) - { - /* copy special type of file */ - if (mknod(to, st.st_mode, st.st_rdev)) { - perror("mknod"); - return RecursiveOp_Callback_Error; - } - - if (set_permissions(to, &st)) { - return RecursiveOp_Callback_Error; - } - - return RecursiveOp_Callback_OK; - } - else if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "Copying of this kind of files isn't supported yet\n"); - return RecursiveOp_Callback_Error; - } - - from_stream = fopen(from, "rb"); - if (!from_stream) { - perror("fopen"); - return RecursiveOp_Callback_Error; - } - - to_stream = fopen(to, "wb"); - if (!to_stream) { - perror("fopen"); - fclose(from_stream); - return RecursiveOp_Callback_Error; - } - - while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) { - fwrite(buf, 1, len, to_stream); - } - - fclose(to_stream); - fclose(from_stream); - - if (set_permissions(to, &st)) { - return RecursiveOp_Callback_Error; - } - - return RecursiveOp_Callback_OK; + FILE *from_stream, *to_stream; + struct stat st; + char buf[4096]; + size_t len; + + if (check_the_same(from, to)) { + fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); + return RecursiveOp_Callback_Error; + } + + if (lstat(from, &st)) { + perror("lstat"); + return RecursiveOp_Callback_Error; + } + + if (S_ISLNK(st.st_mode)) { + /* symbolic links should be copied in special way */ + char *link_buffer; + int need_free; + ssize_t link_len; + + /* get large enough buffer to read link content */ + if ((st.st_size + 1) < sizeof(buf)) { + link_buffer = buf; + need_free = 0; + } + else { + link_buffer = MEM_callocN(st.st_size + 2, "copy_single_file link_buffer"); + need_free = 1; + } + + link_len = readlink(from, link_buffer, st.st_size + 1); + if (link_len < 0) { + perror("readlink"); + + if (need_free) { + MEM_freeN(link_buffer); + } + + return RecursiveOp_Callback_Error; + } + + link_buffer[link_len] = '\0'; + + if (symlink(link_buffer, to)) { + perror("symlink"); + if (need_free) { + MEM_freeN(link_buffer); + } + return RecursiveOp_Callback_Error; + } + + if (need_free) { + MEM_freeN(link_buffer); + } + + return RecursiveOp_Callback_OK; + } + else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode) || + S_ISSOCK(st.st_mode)) { + /* copy special type of file */ + if (mknod(to, st.st_mode, st.st_rdev)) { + perror("mknod"); + return RecursiveOp_Callback_Error; + } + + if (set_permissions(to, &st)) { + return RecursiveOp_Callback_Error; + } + + return RecursiveOp_Callback_OK; + } + else if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "Copying of this kind of files isn't supported yet\n"); + return RecursiveOp_Callback_Error; + } + + from_stream = fopen(from, "rb"); + if (!from_stream) { + perror("fopen"); + return RecursiveOp_Callback_Error; + } + + to_stream = fopen(to, "wb"); + if (!to_stream) { + perror("fopen"); + fclose(from_stream); + return RecursiveOp_Callback_Error; + } + + while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) { + fwrite(buf, 1, len, to_stream); + } + + fclose(to_stream); + fclose(from_stream); + + if (set_permissions(to, &st)) { + return RecursiveOp_Callback_Error; + } + + return RecursiveOp_Callback_OK; } /* Not used anywhere! */ -#if 0 +# if 0 static int move_callback_pre(const char *from, const char *to) { - int ret = rename(from, to); + int ret = rename(from, to); - if (ret) - return copy_callback_pre(from, to); + if (ret) + return copy_callback_pre(from, to); - return RecursiveOp_Callback_StopRecurs; + return RecursiveOp_Callback_StopRecurs; } static int move_single_file(const char *from, const char *to) { - int ret = rename(from, to); + int ret = rename(from, to); - if (ret) - return copy_single_file(from, to); + if (ret) + return copy_single_file(from, to); - return RecursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } /* if *file represents a directory, moves all its contents into *to, else renames * file itself to *to. */ int BLI_move(const char *file, const char *to) { - int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL); + int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL); - if (ret && ret != -1) { - return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post); - } + if (ret && ret != -1) { + return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post); + } - return ret; + return ret; } -#endif +# endif static const char *check_destination(const char *file, const char *to) { - struct stat st; + struct stat st; - if (!stat(to, &st)) { - if (S_ISDIR(st.st_mode)) { - char *str, *path; - const char *filename; - size_t len = 0; + if (!stat(to, &st)) { + if (S_ISDIR(st.st_mode)) { + char *str, *path; + const char *filename; + size_t len = 0; - str = strip_last_slash(file); - filename = BLI_last_slash(str); + str = strip_last_slash(file); + filename = BLI_last_slash(str); - if (!filename) { - MEM_freeN(str); - return (char *)to; - } + if (!filename) { + MEM_freeN(str); + return (char *)to; + } - /* skip slash */ - filename += 1; + /* skip slash */ + filename += 1; - len = strlen(to) + strlen(filename) + 1; - path = MEM_callocN(len + 1, "check_destination path"); - BLI_join_dirfile(path, len + 1, to, filename); + len = strlen(to) + strlen(filename) + 1; + path = MEM_callocN(len + 1, "check_destination path"); + BLI_join_dirfile(path, len + 1, to, filename); - MEM_freeN(str); + MEM_freeN(str); - return path; - } - } + return path; + } + } - return to; + return to; } int BLI_copy(const char *file, const char *to) { - const char *actual_to = check_destination(file, to); - int ret; + const char *actual_to = check_destination(file, to); + int ret; - ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL); + ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL); - if (actual_to != to) { - MEM_freeN((void *)actual_to); - } + if (actual_to != to) { + MEM_freeN((void *)actual_to); + } - return ret; + return ret; } -#if 0 +# if 0 int BLI_create_symlink(const char *file, const char *to) { - return symlink(to, file); + return symlink(to, file); } -#endif +# endif /** \return true on success (i.e. given path now exists on FS), false otherwise. */ bool BLI_dir_create_recursive(const char *dirname) { - char *lslash; - size_t size; -#ifdef MAXPATHLEN - char static_buf[MAXPATHLEN]; -#endif - char *tmp; - bool ret = true; - - if (BLI_is_dir(dirname)) { - return true; - } - else if (BLI_exists(dirname)) { - return false; - } - -#ifdef MAXPATHLEN - size = MAXPATHLEN; - tmp = static_buf; -#else - size = strlen(dirname) + 1; - tmp = MEM_callocN(size, __func__); -#endif - - BLI_strncpy(tmp, dirname, size); - - /* Avoids one useless recursion in case of '/foo/bar/' path... */ - BLI_del_slash(tmp); - - lslash = (char *)BLI_last_slash(tmp); - if (lslash) { - /* Split about the last slash and recurse */ - *lslash = 0; - if (!BLI_dir_create_recursive(tmp)) { - ret = false; - } - } - -#ifndef MAXPATHLEN - MEM_freeN(tmp); -#endif - - if (ret) { - ret = (mkdir(dirname, 0777) == 0); - } - return ret; + char *lslash; + size_t size; +# ifdef MAXPATHLEN + char static_buf[MAXPATHLEN]; +# endif + char *tmp; + bool ret = true; + + if (BLI_is_dir(dirname)) { + return true; + } + else if (BLI_exists(dirname)) { + return false; + } + +# ifdef MAXPATHLEN + size = MAXPATHLEN; + tmp = static_buf; +# else + size = strlen(dirname) + 1; + tmp = MEM_callocN(size, __func__); +# endif + + BLI_strncpy(tmp, dirname, size); + + /* Avoids one useless recursion in case of '/foo/bar/' path... */ + BLI_del_slash(tmp); + + lslash = (char *)BLI_last_slash(tmp); + if (lslash) { + /* Split about the last slash and recurse */ + *lslash = 0; + if (!BLI_dir_create_recursive(tmp)) { + ret = false; + } + } + +# ifndef MAXPATHLEN + MEM_freeN(tmp); +# endif + + if (ret) { + ret = (mkdir(dirname, 0777) == 0); + } + return ret; } /** @@ -1090,17 +1086,17 @@ bool BLI_dir_create_recursive(const char *dirname) */ int BLI_rename(const char *from, const char *to) { - if (!BLI_exists(from)) { - return 1; - } + if (!BLI_exists(from)) { + return 1; + } - if (BLI_exists(to)) { - if (BLI_delete(to, false, false)) { - return 1; - } - } + if (BLI_exists(to)) { + if (BLI_delete(to, false, false)) { + return 1; + } + } - return rename(from, to); + return rename(from, to); } #endif diff --git a/source/blender/blenlib/intern/fnmatch.c b/source/blender/blenlib/intern/fnmatch.c index c0675e8c4d6..3df09976972 100644 --- a/source/blender/blenlib/intern/fnmatch.c +++ b/source/blender/blenlib/intern/fnmatch.c @@ -19,13 +19,12 @@ #ifdef WIN32 - /* Maintained by GLIBC. */ /* clang-format off */ /* Enable GNU extensions in fnmatch.h. */ #ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 +# define _GNU_SOURCE 1 #endif #include <errno.h> @@ -69,170 +68,170 @@ fnmatch (const char *pattern, const char *string, int flags) # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) while ((c = *p++) != '\0') - { - c = FOLD (c); - - switch (c) - { - case '?': - if (*n == '\0') - return FNM_NOMATCH; - else if ((flags & FNM_FILE_NAME) && *n == '/') - return FNM_NOMATCH; - else if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; - break; - - case '\\': - if (!(flags & FNM_NOESCAPE)) - { - c = *p++; - if (c == '\0') - /* Trailing \ loses. */ - return FNM_NOMATCH; - c = FOLD (c); - } - if (FOLD (*n) != c) - return FNM_NOMATCH; - break; - - case '*': - if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; - - for (c = *p++; c == '?' || c == '*'; c = *p++) - { - if ((flags & FNM_FILE_NAME) && *n == '/') - /* A slash does not match a wildcard under FNM_FILE_NAME. */ - return FNM_NOMATCH; - else if (c == '?') - { - /* A ? needs to match one character. */ - if (*n == '\0') - /* There isn't another character; no match. */ - return FNM_NOMATCH; - else - /* One character of the string is consumed in matching - this ? wildcard, so *??? won't match if there are - less than three characters. */ - ++n; - } - } - - if (c == '\0') - return 0; - - { - char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - c1 = FOLD (c1); - for (--p; *n != '\0'; ++n) - if ((c == '[' || FOLD (*n) == c1) && - fnmatch (p, n, flags & ~FNM_PERIOD) == 0) - return 0; - return FNM_NOMATCH; - } - - case '[': - { - /* Nonzero if the sense of the character class is inverted. */ - register int not; - - if (*n == '\0') - return FNM_NOMATCH; - - if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; - - not = (*p == '!' || *p == '^'); - if (not) - ++p; - - c = *p++; - for (;;) - { - register char cstart = c, cend = c; - - if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return FNM_NOMATCH; - cstart = cend = *p++; - } - - cstart = cend = FOLD (cstart); - - if (c == '\0') - /* [ (unterminated) loses. */ - return FNM_NOMATCH; - - c = *p++; - c = FOLD (c); - - if ((flags & FNM_FILE_NAME) && c == '/') - /* [/] can never match. */ - return FNM_NOMATCH; - - if (c == '-' && *p != ']') - { - cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return FNM_NOMATCH; - cend = FOLD (cend); - - c = *p++; - } - - if (FOLD (*n) >= cstart && FOLD (*n) <= cend) - goto matched; - - if (c == ']') - break; - } - if (!not) - return FNM_NOMATCH; - break; - - matched:; - /* Skip the rest of the [...] that already matched. */ - while (c != ']') - { - if (c == '\0') - /* [... (unterminated) loses. */ - return FNM_NOMATCH; - - c = *p++; - if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return FNM_NOMATCH; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; - } - } - if (not) - return FNM_NOMATCH; - } - break; - - default: - if (c != FOLD (*n)) - return FNM_NOMATCH; - } - - ++n; - } + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (FOLD (*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if ((flags & FNM_FILE_NAME) && *n == '/') + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') + { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD (c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD (*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } + + cstart = cend = FOLD (cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD (cend); + + c = *p++; + } + + if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD (*n)) + return FNM_NOMATCH; + } + + ++n; + } if (*n == '\0') - return 0; + return 0; if ((flags & FNM_LEADING_DIR) && *n == '/') - /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ - return 0; + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; return FNM_NOMATCH; diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 36051e3e7f0..a8b8f01fa22 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -50,371 +50,363 @@ static FT_Library library; static FT_Error err; - static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd) { - const float scale = vfd->scale; - const float eps = 0.0001f; - const float eps_sq = eps * eps; - /* Blender */ - struct Nurb *nu; - struct VChar *che; - struct BezTriple *bezt; - - /* Freetype2 */ - FT_GlyphSlot glyph; - FT_UInt glyph_index; - FT_Outline ftoutline; - float dx, dy; - int j, k, l, l_first = 0; - - /* - * Generate the character 3D data - * - * Get the FT Glyph index and load the Glyph */ - glyph_index = FT_Get_Char_Index(face, charcode); - err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); - - /* If loading succeeded, convert the FT glyph to the internal format */ - if (!err) { - /* initialize as -1 to add 1 on first loop each time */ - int contour_prev; - int *onpoints; - - /* First we create entry for the new character to the character list */ - che = (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char"); - - /* Take some data for modifying purposes */ - glyph = face->glyph; - ftoutline = glyph->outline; - - /* Set the width and character code */ - che->index = charcode; - che->width = glyph->advance.x * scale; - - BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che); - - /* Start converting the FT data */ - onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints"); - - /* get number of on-curve points for beziertriples (including conic virtual on-points) */ - for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) { - const int n = ftoutline.contours[j] - contour_prev; - contour_prev = ftoutline.contours[j]; - - for (k = 0; k < n; k++) { - l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k; - if (k == 0) { - l_first = l; - } - - if (ftoutline.tags[l] == FT_Curve_Tag_On) { - onpoints[j]++; - } - - { - const int l_next = (k < n - 1) ? (l + 1) : l_first; - if (ftoutline.tags[l] == FT_Curve_Tag_Conic && - ftoutline.tags[l_next] == FT_Curve_Tag_Conic) - { - onpoints[j]++; - } - } - } - } - - /* contour loop, bezier & conic styles merged */ - for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) { - const int n = ftoutline.contours[j] - contour_prev; - contour_prev = ftoutline.contours[j]; - - /* add new curve */ - nu = (Nurb *)MEM_callocN(sizeof(struct Nurb), "objfnt_nurb"); - bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt"); - BLI_addtail(&che->nurbsbase, nu); - - nu->type = CU_BEZIER; - nu->pntsu = onpoints[j]; - nu->resolu = 8; - nu->flag = CU_2D; - nu->flagu = CU_NURB_CYCLIC; - nu->bezt = bezt; - - /* individual curve loop, start-end */ - for (k = 0; k < n; k++) { - l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k; - if (k == 0) { - l_first = l; - } - - /* virtual conic on-curve points */ - { - const int l_next = (k < n - 1) ? (l + 1) : l_first; - if (ftoutline.tags[l] == FT_Curve_Tag_Conic && - ftoutline.tags[l_next] == FT_Curve_Tag_Conic) - { - dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f; - dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f; - - /* left handle */ - bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f; - bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f; - - /* midpoint (virtual on-curve point) */ - bezt->vec[1][0] = dx; - bezt->vec[1][1] = dy; - - /* right handle */ - bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f; - bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f; - - bezt->h1 = bezt->h2 = HD_ALIGN; - bezt->radius = 1.0f; - bezt++; - } - } - - /* on-curve points */ - if (ftoutline.tags[l] == FT_Curve_Tag_On) { - const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j]; - const int l_next = (k < n - 1) ? (l + 1) : l_first; - - /* left handle */ - if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) { - bezt->vec[0][0] = ftoutline.points[l_prev].x * scale; - bezt->vec[0][1] = ftoutline.points[l_prev].y * scale; - bezt->h1 = HD_FREE; - } - else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) { - bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale / 3.0f; - bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale / 3.0f; - bezt->h1 = HD_FREE; - } - else { - bezt->vec[0][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f; - bezt->vec[0][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f; - bezt->h1 = HD_VECT; - } - - /* midpoint (on-curve point) */ - bezt->vec[1][0] = ftoutline.points[l].x * scale; - bezt->vec[1][1] = ftoutline.points[l].y * scale; - - /* right handle */ - if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) { - bezt->vec[2][0] = ftoutline.points[l_next].x * scale; - bezt->vec[2][1] = ftoutline.points[l_next].y * scale; - bezt->h2 = HD_FREE; - } - else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) { - bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale / 3.0f; - bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale / 3.0f; - bezt->h2 = HD_FREE; - } - else { - bezt->vec[2][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f; - bezt->vec[2][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f; - bezt->h2 = HD_VECT; - } - - /* get the handles that are aligned, tricky... - * - check if one of them is a vector handle. - * - dist_squared_to_line_v2, check if the three beztriple points are on one line - * - len_squared_v2v2, see if there's a distance between the three points - * - len_squared_v2v2 again, to check the angle between the handles - */ - if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) && - (dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) < (0.001f * 0.001f)) && - (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) && - (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) && - (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) && - (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > - max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]), - len_squared_v2v2(bezt->vec[1], bezt->vec[2])))) - { - bezt->h1 = bezt->h2 = HD_ALIGN; - } - bezt->radius = 1.0f; - bezt++; - } - } - } - - MEM_freeN(onpoints); - - return che; - } - - return NULL; + const float scale = vfd->scale; + const float eps = 0.0001f; + const float eps_sq = eps * eps; + /* Blender */ + struct Nurb *nu; + struct VChar *che; + struct BezTriple *bezt; + + /* Freetype2 */ + FT_GlyphSlot glyph; + FT_UInt glyph_index; + FT_Outline ftoutline; + float dx, dy; + int j, k, l, l_first = 0; + + /* + * Generate the character 3D data + * + * Get the FT Glyph index and load the Glyph */ + glyph_index = FT_Get_Char_Index(face, charcode); + err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); + + /* If loading succeeded, convert the FT glyph to the internal format */ + if (!err) { + /* initialize as -1 to add 1 on first loop each time */ + int contour_prev; + int *onpoints; + + /* First we create entry for the new character to the character list */ + che = (VChar *)MEM_callocN(sizeof(struct VChar), "objfnt_char"); + + /* Take some data for modifying purposes */ + glyph = face->glyph; + ftoutline = glyph->outline; + + /* Set the width and character code */ + che->index = charcode; + che->width = glyph->advance.x * scale; + + BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che); + + /* Start converting the FT data */ + onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints"); + + /* get number of on-curve points for beziertriples (including conic virtual on-points) */ + for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) { + const int n = ftoutline.contours[j] - contour_prev; + contour_prev = ftoutline.contours[j]; + + for (k = 0; k < n; k++) { + l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k; + if (k == 0) { + l_first = l; + } + + if (ftoutline.tags[l] == FT_Curve_Tag_On) { + onpoints[j]++; + } + + { + const int l_next = (k < n - 1) ? (l + 1) : l_first; + if (ftoutline.tags[l] == FT_Curve_Tag_Conic && + ftoutline.tags[l_next] == FT_Curve_Tag_Conic) { + onpoints[j]++; + } + } + } + } + + /* contour loop, bezier & conic styles merged */ + for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) { + const int n = ftoutline.contours[j] - contour_prev; + contour_prev = ftoutline.contours[j]; + + /* add new curve */ + nu = (Nurb *)MEM_callocN(sizeof(struct Nurb), "objfnt_nurb"); + bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt"); + BLI_addtail(&che->nurbsbase, nu); + + nu->type = CU_BEZIER; + nu->pntsu = onpoints[j]; + nu->resolu = 8; + nu->flag = CU_2D; + nu->flagu = CU_NURB_CYCLIC; + nu->bezt = bezt; + + /* individual curve loop, start-end */ + for (k = 0; k < n; k++) { + l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k; + if (k == 0) { + l_first = l; + } + + /* virtual conic on-curve points */ + { + const int l_next = (k < n - 1) ? (l + 1) : l_first; + if (ftoutline.tags[l] == FT_Curve_Tag_Conic && + ftoutline.tags[l_next] == FT_Curve_Tag_Conic) { + dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f; + dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f; + + /* left handle */ + bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f; + bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f; + + /* midpoint (virtual on-curve point) */ + bezt->vec[1][0] = dx; + bezt->vec[1][1] = dy; + + /* right handle */ + bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f; + bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f; + + bezt->h1 = bezt->h2 = HD_ALIGN; + bezt->radius = 1.0f; + bezt++; + } + } + + /* on-curve points */ + if (ftoutline.tags[l] == FT_Curve_Tag_On) { + const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j]; + const int l_next = (k < n - 1) ? (l + 1) : l_first; + + /* left handle */ + if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) { + bezt->vec[0][0] = ftoutline.points[l_prev].x * scale; + bezt->vec[0][1] = ftoutline.points[l_prev].y * scale; + bezt->h1 = HD_FREE; + } + else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) { + bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale / + 3.0f; + bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale / + 3.0f; + bezt->h1 = HD_FREE; + } + else { + bezt->vec[0][0] = ftoutline.points[l].x * scale - + (ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f; + bezt->vec[0][1] = ftoutline.points[l].y * scale - + (ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f; + bezt->h1 = HD_VECT; + } + + /* midpoint (on-curve point) */ + bezt->vec[1][0] = ftoutline.points[l].x * scale; + bezt->vec[1][1] = ftoutline.points[l].y * scale; + + /* right handle */ + if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) { + bezt->vec[2][0] = ftoutline.points[l_next].x * scale; + bezt->vec[2][1] = ftoutline.points[l_next].y * scale; + bezt->h2 = HD_FREE; + } + else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) { + bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale / + 3.0f; + bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale / + 3.0f; + bezt->h2 = HD_FREE; + } + else { + bezt->vec[2][0] = ftoutline.points[l].x * scale - + (ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f; + bezt->vec[2][1] = ftoutline.points[l].y * scale - + (ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f; + bezt->h2 = HD_VECT; + } + + /* get the handles that are aligned, tricky... + * - check if one of them is a vector handle. + * - dist_squared_to_line_v2, check if the three beztriple points are on one line + * - len_squared_v2v2, see if there's a distance between the three points + * - len_squared_v2v2 again, to check the angle between the handles + */ + if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) && + (dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) < + (0.001f * 0.001f)) && + (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) && + (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) && + (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) && + (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > + max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]), + len_squared_v2v2(bezt->vec[1], bezt->vec[2])))) { + bezt->h1 = bezt->h2 = HD_ALIGN; + } + bezt->radius = 1.0f; + bezt++; + } + } + } + + MEM_freeN(onpoints); + + return che; + } + + return NULL; } static VChar *objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode) { - VChar *che; - - /* Freetype2 */ - FT_Face face; - - /* Load the font to memory */ - if (vfont->temp_pf) { - err = FT_New_Memory_Face(library, - vfont->temp_pf->data, - vfont->temp_pf->size, - 0, - &face); - if (err) { - return NULL; - } - } - else { - err = true; - return NULL; - } - - /* Read the char */ - che = freetypechar_to_vchar(face, charcode, vfont->data); - - /* And everything went ok */ - return che; + VChar *che; + + /* Freetype2 */ + FT_Face face; + + /* Load the font to memory */ + if (vfont->temp_pf) { + err = FT_New_Memory_Face(library, vfont->temp_pf->data, vfont->temp_pf->size, 0, &face); + if (err) { + return NULL; + } + } + else { + err = true; + return NULL; + } + + /* Read the char */ + che = freetypechar_to_vchar(face, charcode, vfont->data); + + /* And everything went ok */ + return che; } - static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) { - /* Variables */ - FT_Face face; - const FT_ULong charcode_reserve = 256; - FT_ULong charcode = 0, lcode; - FT_UInt glyph_index; - const char *fontname; - VFontData *vfd; - - /* load the freetype font */ - err = FT_New_Memory_Face(library, - pf->data, - pf->size, - 0, - &face); - - if (err) { - return NULL; - } - - /* allocate blender font */ - vfd = MEM_callocN(sizeof(*vfd), "FTVFontData"); - - /* get the name */ - fontname = FT_Get_Postscript_Name(face); - BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name)); - - /* Extract the first 256 character from TTF */ - lcode = charcode = FT_Get_First_Char(face, &glyph_index); - - /* No charmap found from the ttf so we need to figure it out */ - if (glyph_index == 0) { - FT_CharMap found = NULL; - FT_CharMap charmap; - int n; - - for (n = 0; n < face->num_charmaps; n++) { - charmap = face->charmaps[n]; - if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { - found = charmap; - break; - } - } - - err = FT_Set_Charmap(face, found); - - if (err) { - return NULL; - } - - lcode = charcode = FT_Get_First_Char(face, &glyph_index); - } - - /* Blender default BFont is not "complete". */ - const bool complete_font = (face->ascender != 0) && (face->descender != 0) && - (face->ascender != face->descender); - - if (complete_font) { - /* We can get descender as well, but we simple store descender in relation to the ascender. - * Also note that descender is stored as a negative number. */ - vfd->ascender = (float)face->ascender / (face->ascender - face->descender); - } - else { - vfd->ascender = 0.8f; - vfd->em_height = 1.0f; - } - - /* Adjust font size */ - if (face->bbox.yMax != face->bbox.yMin) { - vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin)); - - if (complete_font) { - vfd->em_height = (float)(face->ascender - face->descender) / (face->bbox.yMax - face->bbox.yMin); - } - } - else { - vfd->scale = 1.0f / 1000.0f; - } - - /* Load characters */ - vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve); - - while (charcode < charcode_reserve) { - /* Generate the font data */ - freetypechar_to_vchar(face, charcode, vfd); - - /* Next glyph */ - charcode = FT_Get_Next_Char(face, charcode, &glyph_index); - - /* Check that we won't start infinite loop */ - if (charcode <= lcode) { - break; - } - lcode = charcode; - } - - return vfd; + /* Variables */ + FT_Face face; + const FT_ULong charcode_reserve = 256; + FT_ULong charcode = 0, lcode; + FT_UInt glyph_index; + const char *fontname; + VFontData *vfd; + + /* load the freetype font */ + err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face); + + if (err) { + return NULL; + } + + /* allocate blender font */ + vfd = MEM_callocN(sizeof(*vfd), "FTVFontData"); + + /* get the name */ + fontname = FT_Get_Postscript_Name(face); + BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name)); + + /* Extract the first 256 character from TTF */ + lcode = charcode = FT_Get_First_Char(face, &glyph_index); + + /* No charmap found from the ttf so we need to figure it out */ + if (glyph_index == 0) { + FT_CharMap found = NULL; + FT_CharMap charmap; + int n; + + for (n = 0; n < face->num_charmaps; n++) { + charmap = face->charmaps[n]; + if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { + found = charmap; + break; + } + } + + err = FT_Set_Charmap(face, found); + + if (err) { + return NULL; + } + + lcode = charcode = FT_Get_First_Char(face, &glyph_index); + } + + /* Blender default BFont is not "complete". */ + const bool complete_font = (face->ascender != 0) && (face->descender != 0) && + (face->ascender != face->descender); + + if (complete_font) { + /* We can get descender as well, but we simple store descender in relation to the ascender. + * Also note that descender is stored as a negative number. */ + vfd->ascender = (float)face->ascender / (face->ascender - face->descender); + } + else { + vfd->ascender = 0.8f; + vfd->em_height = 1.0f; + } + + /* Adjust font size */ + if (face->bbox.yMax != face->bbox.yMin) { + vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin)); + + if (complete_font) { + vfd->em_height = (float)(face->ascender - face->descender) / + (face->bbox.yMax - face->bbox.yMin); + } + } + else { + vfd->scale = 1.0f / 1000.0f; + } + + /* Load characters */ + vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve); + + while (charcode < charcode_reserve) { + /* Generate the font data */ + freetypechar_to_vchar(face, charcode, vfd); + + /* Next glyph */ + charcode = FT_Get_Next_Char(face, charcode, &glyph_index); + + /* Check that we won't start infinite loop */ + if (charcode <= lcode) { + break; + } + lcode = charcode; + } + + return vfd; } - static int check_freetypefont(PackedFile *pf) { - FT_Face face; - FT_GlyphSlot glyph; - FT_UInt glyph_index; - int success = 0; - - err = FT_New_Memory_Face(library, - pf->data, - pf->size, - 0, - &face); - if (err) { - success = 0; - //XXX error("This is not a valid font"); - } - else { - glyph_index = FT_Get_Char_Index(face, 'A'); - err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); - if (err) { - success = 0; - } - else { - glyph = face->glyph; - if (glyph->format == ft_glyph_format_outline) { - success = 1; - } - else { - //XXX error("Selected Font has no outline data"); - success = 0; - } - } - } - - return success; + FT_Face face; + FT_GlyphSlot glyph; + FT_UInt glyph_index; + int success = 0; + + err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face); + if (err) { + success = 0; + //XXX error("This is not a valid font"); + } + else { + glyph_index = FT_Get_Char_Index(face, 'A'); + err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); + if (err) { + success = 0; + } + else { + glyph = face->glyph; + if (glyph->format == ft_glyph_format_outline) { + success = 1; + } + else { + //XXX error("Selected Font has no outline data"); + success = 0; + } + } + } + + return success; } /** @@ -427,66 +419,67 @@ static int check_freetypefont(PackedFile *pf) */ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf) { - VFontData *vfd = NULL; - int success = 0; + VFontData *vfd = NULL; + int success = 0; - /* init Freetype */ - err = FT_Init_FreeType(&library); - if (err) { - /* XXX error("Failed to load the Freetype font library"); */ - return NULL; - } + /* init Freetype */ + err = FT_Init_FreeType(&library); + if (err) { + /* XXX error("Failed to load the Freetype font library"); */ + return NULL; + } - success = check_freetypefont(pf); + success = check_freetypefont(pf); - if (success) { - vfd = objfnt_to_ftvfontdata(pf); - } + if (success) { + vfd = objfnt_to_ftvfontdata(pf); + } - /* free Freetype */ - FT_Done_FreeType(library); + /* free Freetype */ + FT_Done_FreeType(library); - return vfd; + return vfd; } static void *vfontdata_copy_characters_value_cb(const void *src) { - return BLI_vfontchar_copy(src, 0); + return BLI_vfontchar_copy(src, 0); } VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag)) { - VFontData *vfont_dst = MEM_dupallocN(vfont_src); + VFontData *vfont_dst = MEM_dupallocN(vfont_src); - if (vfont_src->characters != NULL) { - vfont_dst->characters = BLI_ghash_copy(vfont_src->characters, NULL, vfontdata_copy_characters_value_cb); - } + if (vfont_src->characters != NULL) { + vfont_dst->characters = BLI_ghash_copy( + vfont_src->characters, NULL, vfontdata_copy_characters_value_cb); + } - return vfont_dst; + return vfont_dst; } VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) { - VChar *che = NULL; + VChar *che = NULL; - if (!vfont) { - return NULL; - } + if (!vfont) { + return NULL; + } - /* Init Freetype */ - err = FT_Init_FreeType(&library); - if (err) { - /* XXX error("Failed to load the Freetype font library"); */ - return NULL; - } + /* Init Freetype */ + err = FT_Init_FreeType(&library); + if (err) { + /* XXX error("Failed to load the Freetype font library"); */ + return NULL; + } - /* Load the character */ - che = objchr_to_ftvfontdata(vfont, character); + /* Load the character */ + che = objchr_to_ftvfontdata(vfont, character); - /* Free Freetype */ - FT_Done_FreeType(library); + /* Free Freetype */ + FT_Done_FreeType(library); - return che; + return che; } /* Yeah, this is very bad... But why is this in BLI in the first place, since it uses Nurb data? @@ -496,15 +489,14 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag)) { - VChar *vchar_dst = MEM_dupallocN(vchar_src); + VChar *vchar_dst = MEM_dupallocN(vchar_src); - BLI_listbase_clear(&vchar_dst->nurbsbase); - BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase); + BLI_listbase_clear(&vchar_dst->nurbsbase); + BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase); - return vchar_dst; + return vchar_dst; } - /* * from: http://www.freetype.org/freetype2/docs/glyphs/glyphs-6.html#section-1 * diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index 40890222e55..6d0fdfacb10 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -37,14 +37,14 @@ typedef struct _GSQueueElem GSQueueElem; struct _GSQueueElem { - GSQueueElem *next; - char data[0]; + GSQueueElem *next; + char data[0]; }; struct _GSQueue { - GSQueueElem *head; - GSQueueElem *tail; - size_t elem_size; + GSQueueElem *head; + GSQueueElem *tail; + size_t elem_size; }; /** @@ -55,11 +55,11 @@ struct _GSQueue { */ GSQueue *BLI_gsqueue_new(size_t elem_size) { - GSQueue *gq = MEM_mallocN(sizeof(*gq), "gqueue_new"); - gq->head = gq->tail = NULL; - gq->elem_size = elem_size; + GSQueue *gq = MEM_mallocN(sizeof(*gq), "gqueue_new"); + gq->head = gq->tail = NULL; + gq->elem_size = elem_size; - return gq; + return gq; } /** @@ -67,7 +67,7 @@ GSQueue *BLI_gsqueue_new(size_t elem_size) */ bool BLI_gsqueue_is_empty(GSQueue *gq) { - return (gq->head == NULL); + return (gq->head == NULL); } /** @@ -75,14 +75,14 @@ bool BLI_gsqueue_is_empty(GSQueue *gq) */ int BLI_gsqueue_len(GSQueue *gq) { - GSQueueElem *elem; - int size = 0; + GSQueueElem *elem; + int size = 0; - for (elem = gq->head; elem; elem = elem->next) { - size++; - } + for (elem = gq->head; elem; elem = elem->next) { + size++; + } - return size; + return size; } /** @@ -94,7 +94,7 @@ int BLI_gsqueue_len(GSQueue *gq) */ void BLI_gsqueue_peek(GSQueue *gq, void *r_item) { - memcpy(r_item, &gq->head->data, gq->elem_size); + memcpy(r_item, &gq->head->data, gq->elem_size); } /** @@ -107,18 +107,18 @@ void BLI_gsqueue_peek(GSQueue *gq, void *r_item) */ void BLI_gsqueue_pop(GSQueue *gq, void *r_item) { - GSQueueElem *elem = gq->head; - if (elem == gq->tail) { - gq->head = gq->tail = NULL; - } - else { - gq->head = gq->head->next; - } - - if (r_item) { - memcpy(r_item, elem->data, gq->elem_size); - } - MEM_freeN(elem); + GSQueueElem *elem = gq->head; + if (elem == gq->tail) { + gq->head = gq->tail = NULL; + } + else { + gq->head = gq->head->next; + } + + if (r_item) { + memcpy(r_item, elem->data, gq->elem_size); + } + MEM_freeN(elem); } /** @@ -129,24 +129,24 @@ void BLI_gsqueue_pop(GSQueue *gq, void *r_item) */ void BLI_gsqueue_push(GSQueue *gq, const void *item) { - GSQueueElem *elem; - - /* compare: prevent events added double in row */ - if (!BLI_gsqueue_is_empty(gq)) { - if (0 == memcmp(item, gq->head->data, gq->elem_size)) { - return; - } - } - elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); - memcpy(elem->data, item, gq->elem_size); - elem->next = NULL; - - if (BLI_gsqueue_is_empty(gq)) { - gq->tail = gq->head = elem; - } - else { - gq->tail = gq->tail->next = elem; - } + GSQueueElem *elem; + + /* compare: prevent events added double in row */ + if (!BLI_gsqueue_is_empty(gq)) { + if (0 == memcmp(item, gq->head->data, gq->elem_size)) { + return; + } + } + elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); + memcpy(elem->data, item, gq->elem_size); + elem->next = NULL; + + if (BLI_gsqueue_is_empty(gq)) { + gq->tail = gq->head = elem; + } + else { + gq->tail = gq->tail->next = elem; + } } /** @@ -158,16 +158,16 @@ void BLI_gsqueue_push(GSQueue *gq, const void *item) */ void BLI_gsqueue_push_back(GSQueue *gq, const void *item) { - GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); - memcpy(elem->data, item, gq->elem_size); - elem->next = gq->head; - - if (BLI_gsqueue_is_empty(gq)) { - gq->head = gq->tail = elem; - } - else { - gq->head = elem; - } + GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); + memcpy(elem->data, item, gq->elem_size); + elem->next = gq->head; + + if (BLI_gsqueue_is_empty(gq)) { + gq->head = gq->tail = elem; + } + else { + gq->head = elem; + } } /** @@ -175,8 +175,8 @@ void BLI_gsqueue_push_back(GSQueue *gq, const void *item) */ void BLI_gsqueue_free(GSQueue *gq) { - while (gq->head) { - BLI_gsqueue_pop(gq, NULL); - } - MEM_freeN(gq); + while (gq->head) { + BLI_gsqueue_pop(gq, NULL); + } + MEM_freeN(gq); } diff --git a/source/blender/blenlib/intern/hash_md5.c b/source/blender/blenlib/intern/hash_md5.c index 1a8e78d4227..d3ba5ee1a3b 100644 --- a/source/blender/blenlib/intern/hash_md5.c +++ b/source/blender/blenlib/intern/hash_md5.c @@ -29,7 +29,7 @@ #include <stdio.h> #include <sys/types.h> -#include "BLI_hash_md5.h" /* own include */ +#include "BLI_hash_md5.h" /* own include */ #if defined HAVE_LIMITS_H || defined _LIBC # include <limits.h> @@ -58,34 +58,33 @@ #endif #if UINT_MAX == UINT_MAX_32_BITS - typedef unsigned int md5_uint32; +typedef unsigned int md5_uint32; #else # if USHRT_MAX == UINT_MAX_32_BITS - typedef unsigned short md5_uint32; +typedef unsigned short md5_uint32; # else # if ULONG_MAX == UINT_MAX_32_BITS - typedef unsigned long md5_uint32; +typedef unsigned long md5_uint32; # else - /* The following line is intended to evoke an error. Using #error is not portable enough. */ - "Cannot determine unsigned 32-bit data type." +/* The following line is intended to evoke an error. Using #error is not portable enough. */ +"Cannot determine unsigned 32-bit data type." # endif # endif #endif - /* Following code is low level, upon which are built up the functions * 'BLI_hash_md5_stream' and 'BLI_hash_md5_buffer'. */ /* Structure to save state of computation between the single steps. */ struct md5_ctx { - md5_uint32 A; - md5_uint32 B; - md5_uint32 C; - md5_uint32 D; + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; }; #ifdef __BIG_ENDIAN__ -# define SWAP(n) (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +# define SWAP(n) (((n) << 24) | (((n)&0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif @@ -99,10 +98,10 @@ static const unsigned char fillbuf[64] = {0x80, 0 /* , 0, 0, ... */}; */ static void md5_init_ctx(struct md5_ctx *ctx) { - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; } /** @@ -118,7 +117,7 @@ static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ct */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) +#define FG(b, c, d) FF(d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) @@ -126,137 +125,137 @@ static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ct * Hope the C compiler is smart enough. */ #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - md5_uint32 correct_words[16]; - const md5_uint32 *words = buffer; - size_t nwords = len / sizeof(md5_uint32); - const md5_uint32 *endp = words + nwords; - md5_uint32 A = ctx->A; - md5_uint32 B = ctx->B; - md5_uint32 C = ctx->C; - md5_uint32 D = ctx->D; - - /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ - while (words < endp) { - md5_uint32 *cwp = correct_words; - md5_uint32 A_save = A; - md5_uint32 B_save = B; - md5_uint32 C_save = C; - md5_uint32 D_save = D; - - /* First round: using the given function, the context and a constant the next context is - * computed. Because the algorithms processing unit is a 32-bit word and it is determined - * to work on words in little endian byte order we perhaps have to change the byte order - * before the computation. To reduce the work for the next steps we store the swapped words - * in the array CORRECT_WORDS. - */ -#define OP(a, b, c, d, s, T) \ - a += FF(b, c, d) + (*cwp++ = SWAP(*words)) + T; \ - ++words; \ - CYCLIC(a, s); \ - a += b; \ - (void)0 - - /* Before we start, one word to the strange constants. They are defined in RFC 1321 as: - * T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - - /* Round 1. */ - OP(A, B, C, D, 7, 0xd76aa478); - OP(D, A, B, C, 12, 0xe8c7b756); - OP(C, D, A, B, 17, 0x242070db); - OP(B, C, D, A, 22, 0xc1bdceee); - OP(A, B, C, D, 7, 0xf57c0faf); - OP(D, A, B, C, 12, 0x4787c62a); - OP(C, D, A, B, 17, 0xa8304613); - OP(B, C, D, A, 22, 0xfd469501); - OP(A, B, C, D, 7, 0x698098d8); - OP(D, A, B, C, 12, 0x8b44f7af); - OP(C, D, A, B, 17, 0xffff5bb1); - OP(B, C, D, A, 22, 0x895cd7be); - OP(A, B, C, D, 7, 0x6b901122); - OP(D, A, B, C, 12, 0xfd987193); - OP(C, D, A, B, 17, 0xa679438e); - OP(B, C, D, A, 22, 0x49b40821); + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof(md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ + while (words < endp) { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant the next context is + * computed. Because the algorithms processing unit is a 32-bit word and it is determined + * to work on words in little endian byte order we perhaps have to change the byte order + * before the computation. To reduce the work for the next steps we store the swapped words + * in the array CORRECT_WORDS. + */ +#define OP(a, b, c, d, s, T) \ + a += FF(b, c, d) + (*cwp++ = SWAP(*words)) + T; \ + ++words; \ + CYCLIC(a, s); \ + a += b; \ + (void)0 + + /* Before we start, one word to the strange constants. They are defined in RFC 1321 as: + * T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP(A, B, C, D, 7, 0xd76aa478); + OP(D, A, B, C, 12, 0xe8c7b756); + OP(C, D, A, B, 17, 0x242070db); + OP(B, C, D, A, 22, 0xc1bdceee); + OP(A, B, C, D, 7, 0xf57c0faf); + OP(D, A, B, C, 12, 0x4787c62a); + OP(C, D, A, B, 17, 0xa8304613); + OP(B, C, D, A, 22, 0xfd469501); + OP(A, B, C, D, 7, 0x698098d8); + OP(D, A, B, C, 12, 0x8b44f7af); + OP(C, D, A, B, 17, 0xffff5bb1); + OP(B, C, D, A, 22, 0x895cd7be); + OP(A, B, C, D, 7, 0x6b901122); + OP(D, A, B, C, 12, 0xfd987193); + OP(C, D, A, B, 17, 0xa679438e); + OP(B, C, D, A, 22, 0x49b40821); #undef OP - /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. - * Redefine the macro to take an additional first argument specifying the function to use. - */ -#define OP(f, a, b, c, d, k, s, T) \ - a += f(b, c, d) + correct_words[k] + T; \ - CYCLIC(a, s); \ - a += b; \ - (void)0 - - /* Round 2. */ - OP(FG, A, B, C, D, 1, 5, 0xf61e2562); - OP(FG, D, A, B, C, 6, 9, 0xc040b340); - OP(FG, C, D, A, B, 11, 14, 0x265e5a51); - OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP(FG, A, B, C, D, 5, 5, 0xd62f105d); - OP(FG, D, A, B, C, 10, 9, 0x02441453); - OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP(FG, D, A, B, C, 14, 9, 0xc33707d6); - OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP(FG, B, C, D, A, 8, 20, 0x455a14ed); - OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP(FG, C, D, A, B, 7, 14, 0x676f02d9); - OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP(FH, A, B, C, D, 5, 4, 0xfffa3942); - OP(FH, D, A, B, C, 8, 11, 0x8771f681); - OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP(FH, B, C, D, A, 14, 23, 0xfde5380c); - OP(FH, A, B, C, D, 1, 4, 0xa4beea44); - OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP(FH, B, C, D, A, 6, 23, 0x04881d05); - OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP(FI, A, B, C, D, 0, 6, 0xf4292244); - OP(FI, D, A, B, C, 7, 10, 0x432aff97); - OP(FI, C, D, A, B, 14, 15, 0xab9423a7); - OP(FI, B, C, D, A, 5, 21, 0xfc93a039); - OP(FI, A, B, C, D, 12, 6, 0x655b59c3); - OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP(FI, C, D, A, B, 10, 15, 0xffeff47d); - OP(FI, B, C, D, A, 1, 21, 0x85845dd1); - OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP(FI, C, D, A, B, 6, 15, 0xa3014314); - OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP(FI, A, B, C, D, 4, 6, 0xf7537e82); - OP(FI, D, A, B, C, 11, 10, 0xbd3af235); - OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP(FI, B, C, D, A, 9, 21, 0xeb86d391); + /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. + * Redefine the macro to take an additional first argument specifying the function to use. + */ +#define OP(f, a, b, c, d, k, s, T) \ + a += f(b, c, d) + correct_words[k] + T; \ + CYCLIC(a, s); \ + a += b; \ + (void)0 + + /* Round 2. */ + OP(FG, A, B, C, D, 1, 5, 0xf61e2562); + OP(FG, D, A, B, C, 6, 9, 0xc040b340); + OP(FG, C, D, A, B, 11, 14, 0x265e5a51); + OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP(FG, A, B, C, D, 5, 5, 0xd62f105d); + OP(FG, D, A, B, C, 10, 9, 0x02441453); + OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP(FG, D, A, B, C, 14, 9, 0xc33707d6); + OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP(FG, B, C, D, A, 8, 20, 0x455a14ed); + OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP(FG, C, D, A, B, 7, 14, 0x676f02d9); + OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP(FH, A, B, C, D, 5, 4, 0xfffa3942); + OP(FH, D, A, B, C, 8, 11, 0x8771f681); + OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP(FH, B, C, D, A, 14, 23, 0xfde5380c); + OP(FH, A, B, C, D, 1, 4, 0xa4beea44); + OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP(FH, B, C, D, A, 6, 23, 0x04881d05); + OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP(FI, A, B, C, D, 0, 6, 0xf4292244); + OP(FI, D, A, B, C, 7, 10, 0x432aff97); + OP(FI, C, D, A, B, 14, 15, 0xab9423a7); + OP(FI, B, C, D, A, 5, 21, 0xfc93a039); + OP(FI, A, B, C, D, 12, 6, 0x655b59c3); + OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP(FI, C, D, A, B, 10, 15, 0xffeff47d); + OP(FI, B, C, D, A, 1, 21, 0x85845dd1); + OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP(FI, C, D, A, B, 6, 15, 0xa3014314); + OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP(FI, A, B, C, D, 4, 6, 0xf7537e82); + OP(FI, D, A, B, C, 11, 10, 0xbd3af235); + OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP(FI, B, C, D, A, 9, 21, 0xeb86d391); #undef OP - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; #undef FF #undef FG @@ -272,13 +271,13 @@ static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ct */ static void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf) { - md5_uint32 *digest = resbuf; - digest[0] = SWAP(ctx->A); - digest[1] = SWAP(ctx->B); - digest[2] = SWAP(ctx->C); - digest[3] = SWAP(ctx->D); + md5_uint32 *digest = resbuf; + digest[0] = SWAP(ctx->A); + digest[1] = SWAP(ctx->B); + digest[2] = SWAP(ctx->C); + digest[3] = SWAP(ctx->D); - return resbuf; + return resbuf; } /* Top level public functions. */ @@ -289,75 +288,75 @@ static void *md5_read_ctx(const struct md5_ctx *ctx, void *resbuf) */ int BLI_hash_md5_stream(FILE *stream, void *resblock) { -#define BLOCKSIZE 4096 /* Important: must be a multiple of 64. */ - struct md5_ctx ctx; - md5_uint32 len[2]; - char buffer[BLOCKSIZE + 72]; - size_t pad, sum; - - /* Initialize the computation context. */ - md5_init_ctx(&ctx); - - len[0] = 0; - len[1] = 0; - - /* Iterate over full file contents. */ - while (1) { - /* We read the file in blocks of BLOCKSIZE bytes. - * One call of the computation function processes the whole buffer - * so that with the next round of the loop another block can be read. - */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - do { - n = fread(buffer, 1, BLOCKSIZE - sum, stream); - sum += n; - } while (sum < BLOCKSIZE && n != 0); - - if (n == 0 && ferror(stream)) { - return 1; - } - - /* RFC 1321 specifies the possible length of the file up to 2^64 bits. - * Here we only compute the number of bytes. Do a double word increment. - */ - len[0] += sum; - if (len[0] < sum) { - ++len[1]; - } - - /* If end of file is reached, end the loop. */ - if (n == 0) { - break; - } - - /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0. */ - md5_process_block(buffer, BLOCKSIZE, &ctx); - } - - /* We can copy 64 bytes because the buffer is always big enough. - * 'fillbuf' contains the needed bits. */ - memcpy(&buffer[sum], fillbuf, 64); - - /* Compute amount of padding bytes needed. Alignment is done to (N + PAD) % 64 == 56. - * There is always at least one byte padded, i.e. if the alignment is correctly aligned, - * 64 padding bytes are added. - */ - pad = sum & 63; - pad = pad >= 56 ? 64 + 56 - pad : 56 - pad; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(md5_uint32 *) &buffer[sum + pad] = SWAP(len[0] << 3); - *(md5_uint32 *) &buffer[sum + pad + 4] = SWAP((len[1] << 3) | (len[0] >> 29)); - - /* Process last bytes. */ - md5_process_block(buffer, sum + pad + 8, &ctx); - - /* Construct result in desired memory. */ - md5_read_ctx(&ctx, resblock); - return 0; +#define BLOCKSIZE 4096 /* Important: must be a multiple of 64. */ + struct md5_ctx ctx; + md5_uint32 len[2]; + char buffer[BLOCKSIZE + 72]; + size_t pad, sum; + + /* Initialize the computation context. */ + md5_init_ctx(&ctx); + + len[0] = 0; + len[1] = 0; + + /* Iterate over full file contents. */ + while (1) { + /* We read the file in blocks of BLOCKSIZE bytes. + * One call of the computation function processes the whole buffer + * so that with the next round of the loop another block can be read. + */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + do { + n = fread(buffer, 1, BLOCKSIZE - sum, stream); + sum += n; + } while (sum < BLOCKSIZE && n != 0); + + if (n == 0 && ferror(stream)) { + return 1; + } + + /* RFC 1321 specifies the possible length of the file up to 2^64 bits. + * Here we only compute the number of bytes. Do a double word increment. + */ + len[0] += sum; + if (len[0] < sum) { + ++len[1]; + } + + /* If end of file is reached, end the loop. */ + if (n == 0) { + break; + } + + /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0. */ + md5_process_block(buffer, BLOCKSIZE, &ctx); + } + + /* We can copy 64 bytes because the buffer is always big enough. + * 'fillbuf' contains the needed bits. */ + memcpy(&buffer[sum], fillbuf, 64); + + /* Compute amount of padding bytes needed. Alignment is done to (N + PAD) % 64 == 56. + * There is always at least one byte padded, i.e. if the alignment is correctly aligned, + * 64 padding bytes are added. + */ + pad = sum & 63; + pad = pad >= 56 ? 64 + 56 - pad : 56 - pad; + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *)&buffer[sum + pad] = SWAP(len[0] << 3); + *(md5_uint32 *)&buffer[sum + pad + 4] = SWAP((len[1] << 3) | (len[0] >> 29)); + + /* Process last bytes. */ + md5_process_block(buffer, sum + pad + 8, &ctx); + + /* Construct result in desired memory. */ + md5_read_ctx(&ctx, resblock); + return 0; } /** Compute MD5 message digest for 'len' bytes beginning at 'buffer'. @@ -366,53 +365,53 @@ int BLI_hash_md5_stream(FILE *stream, void *resblock) */ void *BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock) { - struct md5_ctx ctx; - char restbuf[64 + 72]; - size_t blocks = len & ~63; - size_t pad, rest; - - /* Initialize the computation context. */ - md5_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_block(buffer, blocks, &ctx); - - /* REST bytes are not processed yet. */ - rest = len - blocks; - /* Copy to own buffer. */ - memcpy(restbuf, &buffer[blocks], rest); - /* Append needed fill bytes at end of buffer. - * We can copy 64 bytes because the buffer is always big enough. */ - memcpy(&restbuf[rest], fillbuf, 64); - - /* PAD bytes are used for padding to correct alignment. - * Note that always at least one byte is padded. */ - pad = rest >= 56 ? 64 + 56 - rest : 56 - rest; - - /* Put length of buffer in *bits* in last eight bytes. */ - *(md5_uint32 *) &restbuf[rest + pad] = (md5_uint32) SWAP(len << 3); - *(md5_uint32 *) &restbuf[rest + pad + 4] = (md5_uint32) SWAP(len >> 29); - - /* Process last bytes. */ - md5_process_block(restbuf, rest + pad + 8, &ctx); - - /* Put result in desired memory area. */ - return md5_read_ctx(&ctx, resblock); + struct md5_ctx ctx; + char restbuf[64 + 72]; + size_t blocks = len & ~63; + size_t pad, rest; + + /* Initialize the computation context. */ + md5_init_ctx(&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_block(buffer, blocks, &ctx); + + /* REST bytes are not processed yet. */ + rest = len - blocks; + /* Copy to own buffer. */ + memcpy(restbuf, &buffer[blocks], rest); + /* Append needed fill bytes at end of buffer. + * We can copy 64 bytes because the buffer is always big enough. */ + memcpy(&restbuf[rest], fillbuf, 64); + + /* PAD bytes are used for padding to correct alignment. + * Note that always at least one byte is padded. */ + pad = rest >= 56 ? 64 + 56 - rest : 56 - rest; + + /* Put length of buffer in *bits* in last eight bytes. */ + *(md5_uint32 *)&restbuf[rest + pad] = (md5_uint32)SWAP(len << 3); + *(md5_uint32 *)&restbuf[rest + pad + 4] = (md5_uint32)SWAP(len >> 29); + + /* Process last bytes. */ + md5_process_block(restbuf, rest + pad + 8, &ctx); + + /* Put result in desired memory area. */ + return md5_read_ctx(&ctx, resblock); } char *BLI_hash_md5_to_hexdigest(void *resblock, char r_hex_digest[33]) { - static const char hex_map[17] = "0123456789abcdef"; - const unsigned char *p; - char *q; - short len; - - for (q = r_hex_digest, p = (const unsigned char *)resblock, len = 0; len < 16; ++p, ++len) { - const unsigned char c = *p; - *q++ = hex_map[c >> 4]; - *q++ = hex_map[c & 15]; - } - *q = '\0'; - - return r_hex_digest; + static const char hex_map[17] = "0123456789abcdef"; + const unsigned char *p; + char *q; + short len; + + for (q = r_hex_digest, p = (const unsigned char *)resblock, len = 0; len < 16; ++p, ++len) { + const unsigned char c = *p; + *q++ = hex_map[c >> 4]; + *q++ = hex_map[c & 15]; + } + *q = '\0'; + + return r_hex_digest; } diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c index ff604110f2b..ee4a6329f64 100644 --- a/source/blender/blenlib/intern/hash_mm2a.c +++ b/source/blender/blenlib/intern/hash_mm2a.c @@ -32,109 +32,111 @@ #include "BLI_compiler_attrs.h" -#include "BLI_hash_mm2a.h" /* own include */ +#include "BLI_hash_mm2a.h" /* own include */ /* Helpers. */ #define MM2A_M 0x5bd1e995 -#define MM2A_MIX(h, k) \ -{ \ - (k) *= MM2A_M; \ - (k) ^= (k) >> 24; \ - (k) *= MM2A_M; \ - (h) = ((h) * MM2A_M) ^ (k); \ -} (void)0 - -#define MM2A_MIX_FINALIZE(h) \ -{ \ - (h) ^= (h) >> 13; \ - (h) *= MM2A_M; \ - (h) ^= (h) >> 15; \ -} (void)0 +#define MM2A_MIX(h, k) \ + { \ + (k) *= MM2A_M; \ + (k) ^= (k) >> 24; \ + (k) *= MM2A_M; \ + (h) = ((h)*MM2A_M) ^ (k); \ + } \ + (void)0 + +#define MM2A_MIX_FINALIZE(h) \ + { \ + (h) ^= (h) >> 13; \ + (h) *= MM2A_M; \ + (h) ^= (h) >> 15; \ + } \ + (void)0 static void mm2a_mix_tail(BLI_HashMurmur2A *mm2, const unsigned char **data, size_t *len) { - while (*len && ((*len < 4) || mm2->count)) { - mm2->tail |= (uint32_t)(**data) << (mm2->count * 8); - - mm2->count++; - (*len)--; - (*data)++; - - if (mm2->count == 4) { - MM2A_MIX(mm2->hash, mm2->tail); - mm2->tail = 0; - mm2->count = 0; - } - } + while (*len && ((*len < 4) || mm2->count)) { + mm2->tail |= (uint32_t)(**data) << (mm2->count * 8); + + mm2->count++; + (*len)--; + (*data)++; + + if (mm2->count == 4) { + MM2A_MIX(mm2->hash, mm2->tail); + mm2->tail = 0; + mm2->count = 0; + } + } } void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed) { - mm2->hash = seed; - mm2->tail = 0; - mm2->count = 0; - mm2->size = 0; + mm2->hash = seed; + mm2->tail = 0; + mm2->count = 0; + mm2->size = 0; } void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len) { - mm2->size += (uint32_t)len; + mm2->size += (uint32_t)len; - mm2a_mix_tail(mm2, &data, &len); + mm2a_mix_tail(mm2, &data, &len); - for (; len >= 4; data += 4, len -= 4) { - uint32_t k = *(const uint32_t *)data; + for (; len >= 4; data += 4, len -= 4) { + uint32_t k = *(const uint32_t *)data; - MM2A_MIX(mm2->hash, k); - } + MM2A_MIX(mm2->hash, k); + } - mm2a_mix_tail(mm2, &data, &len); + mm2a_mix_tail(mm2, &data, &len); } void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data) { - BLI_hash_mm2a_add(mm2, (const unsigned char *)&data, sizeof(data)); + BLI_hash_mm2a_add(mm2, (const unsigned char *)&data, sizeof(data)); } uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2) { - MM2A_MIX(mm2->hash, mm2->tail); - MM2A_MIX(mm2->hash, mm2->size); + MM2A_MIX(mm2->hash, mm2->tail); + MM2A_MIX(mm2->hash, mm2->size); - MM2A_MIX_FINALIZE(mm2->hash); + MM2A_MIX_FINALIZE(mm2->hash); - return mm2->hash; + return mm2->hash; } /* Non-incremental version, quicker for small keys. */ uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed) { - /* Initialize the hash to a 'random' value */ - uint32_t h = seed ^ len; - - /* Mix 4 bytes at a time into the hash */ - for (; len >= 4; data += 4, len -= 4) { - uint32_t k = *(uint32_t *)data; - - MM2A_MIX(h, k); - } - - /* Handle the last few bytes of the input array */ - switch (len) { - case 3: - h ^= data[2] << 16; - ATTR_FALLTHROUGH; - case 2: - h ^= data[1] << 8; - ATTR_FALLTHROUGH; - case 1: - h ^= data[0]; - h *= MM2A_M; - } - - /* Do a few final mixes of the hash to ensure the last few bytes are well-incorporated. */ - MM2A_MIX_FINALIZE(h); - - return h; + /* Initialize the hash to a 'random' value */ + uint32_t h = seed ^ len; + + /* Mix 4 bytes at a time into the hash */ + for (; len >= 4; data += 4, len -= 4) { + uint32_t k = *(uint32_t *)data; + + MM2A_MIX(h, k); + } + + /* Handle the last few bytes of the input array */ + switch (len) { + case 3: + h ^= data[2] << 16; + ATTR_FALLTHROUGH; + case 2: + h ^= data[1] << 8; + ATTR_FALLTHROUGH; + case 1: + h ^= data[0]; + h *= MM2A_M; + } + + /* Do a few final mixes of the hash to ensure the last few bytes are well-incorporated. */ + MM2A_MIX_FINALIZE(h); + + return h; } diff --git a/source/blender/blenlib/intern/hash_mm3.c b/source/blender/blenlib/intern/hash_mm3.c index c788a6ae7c8..0dfb7ff414c 100644 --- a/source/blender/blenlib/intern/hash_mm3.c +++ b/source/blender/blenlib/intern/hash_mm3.c @@ -28,20 +28,20 @@ #include "BLI_compiler_compat.h" #include "BLI_compiler_attrs.h" -#include "BLI_hash_mm3.h" /* own include */ +#include "BLI_hash_mm3.h" /* own include */ #if defined(_MSC_VER) # include <stdlib.h> -# define ROTL32(x,y) _rotl(x,y) +# define ROTL32(x, y) _rotl(x, y) # define BIG_CONSTANT(x) (x) /* Other compilers */ -#else /* defined(_MSC_VER) */ +#else /* defined(_MSC_VER) */ static inline uint32_t rotl32(uint32_t x, int8_t r) { - return (x << r) | (x >> (32 - r)); + return (x << r) | (x >> (32 - r)); } -# define ROTL32(x,y) rotl32(x,y) +# define ROTL32(x, y) rotl32(x, y) # define BIG_CONSTANT(x) (x##LLU) #endif /* !defined(_MSC_VER) */ @@ -49,92 +49,92 @@ static inline uint32_t rotl32(uint32_t x, int8_t r) * handle aligned reads, do the conversion here */ -BLI_INLINE uint32_t getblock32(const uint32_t * p, int i) +BLI_INLINE uint32_t getblock32(const uint32_t *p, int i) { - return p[i]; + return p[i]; } -BLI_INLINE uint64_t getblock64(const uint64_t * p, int i) +BLI_INLINE uint64_t getblock64(const uint64_t *p, int i) { - return p[i]; + return p[i]; } /* Finalization mix - force all bits of a hash block to avalanche */ BLI_INLINE uint32_t fmix32(uint32_t h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; - return h; + return h; } BLI_INLINE uint64_t fmix64(uint64_t k) { - k ^= k >> 33; - k *= BIG_CONSTANT(0xff51afd7ed558ccd); - k ^= k >> 33; - k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); - k ^= k >> 33; + k ^= k >> 33; + k *= BIG_CONSTANT(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); + k ^= k >> 33; - return k; + return k; } uint32_t BLI_hash_mm3(const unsigned char *in, size_t len, uint32_t seed) { - const uint8_t *data = (const uint8_t *)in; - const int nblocks = len / 4; + const uint8_t *data = (const uint8_t *)in; + const int nblocks = len / 4; - uint32_t h1 = seed; + uint32_t h1 = seed; - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - /* body */ + /* body */ - const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); + const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); - for (int i = -nblocks; i; i++) { - uint32_t k1 = getblock32(blocks, i); + for (int i = -nblocks; i; i++) { + uint32_t k1 = getblock32(blocks, i); - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; - h1 ^= k1; - h1 = ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } + h1 ^= k1; + h1 = ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } - /* tail */ + /* tail */ - const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); + const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); - uint32_t k1 = 0; + uint32_t k1 = 0; - switch (len & 3) { - case 3: - k1 ^= tail[2] << 16; - ATTR_FALLTHROUGH; - case 2: - k1 ^= tail[1] << 8; - ATTR_FALLTHROUGH; - case 1: - k1 ^= tail[0]; - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - } + switch (len & 3) { + case 3: + k1 ^= tail[2] << 16; + ATTR_FALLTHROUGH; + case 2: + k1 ^= tail[1] << 8; + ATTR_FALLTHROUGH; + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; + } - /* finalization */ + /* finalization */ - h1 ^= len; + h1 ^= len; - h1 = fmix32(h1); + h1 = fmix32(h1); - return h1; + return h1; } diff --git a/source/blender/blenlib/intern/jitter_2d.c b/source/blender/blenlib/intern/jitter_2d.c index bbf1948be4d..aed43657b3f 100644 --- a/source/blender/blenlib/intern/jitter_2d.c +++ b/source/blender/blenlib/intern/jitter_2d.c @@ -31,148 +31,157 @@ #include "BLI_strict_flags.h" - void BLI_jitterate1(float (*jit1)[2], float (*jit2)[2], int num, float rad1) { - int i, j, k; - float vecx, vecy, dvecx, dvecy, x, y, len; - - for (i = num - 1; i >= 0; i--) { - dvecx = dvecy = 0.0; - x = jit1[i][0]; - y = jit1[i][1]; - for (j = num - 1; j >= 0; j--) { - if (i != j) { - vecx = jit1[j][0] - x - 1.0f; - vecy = jit1[j][1] - y - 1.0f; - for (k = 3; k > 0; k--) { - if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { - len = sqrtf(vecx * vecx + vecy * vecy); - if (len > 0 && len < rad1) { - len = len / rad1; - dvecx += vecx / len; - dvecy += vecy / len; - } - } - vecx += 1.0f; - - if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { - len = sqrtf(vecx * vecx + vecy * vecy); - if (len > 0 && len < rad1) { - len = len / rad1; - dvecx += vecx / len; - dvecy += vecy / len; - } - } - vecx += 1.0f; - - if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { - len = sqrtf(vecx * vecx + vecy * vecy); - if (len > 0 && len < rad1) { - len = len / rad1; - dvecx += vecx / len; - dvecy += vecy / len; - } - } - vecx -= 2.0f; - vecy += 1.0f; - } - } - } - - x -= dvecx / 18.0f; - y -= dvecy / 18.0f; - x -= floorf(x); - y -= floorf(y); - jit2[i][0] = x; - jit2[i][1] = y; - } - memcpy(jit1, jit2, 2 * (unsigned int)num * sizeof(float)); + int i, j, k; + float vecx, vecy, dvecx, dvecy, x, y, len; + + for (i = num - 1; i >= 0; i--) { + dvecx = dvecy = 0.0; + x = jit1[i][0]; + y = jit1[i][1]; + for (j = num - 1; j >= 0; j--) { + if (i != j) { + vecx = jit1[j][0] - x - 1.0f; + vecy = jit1[j][1] - y - 1.0f; + for (k = 3; k > 0; k--) { + if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { + len = sqrtf(vecx * vecx + vecy * vecy); + if (len > 0 && len < rad1) { + len = len / rad1; + dvecx += vecx / len; + dvecy += vecy / len; + } + } + vecx += 1.0f; + + if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { + len = sqrtf(vecx * vecx + vecy * vecy); + if (len > 0 && len < rad1) { + len = len / rad1; + dvecx += vecx / len; + dvecy += vecy / len; + } + } + vecx += 1.0f; + + if (fabsf(vecx) < rad1 && fabsf(vecy) < rad1) { + len = sqrtf(vecx * vecx + vecy * vecy); + if (len > 0 && len < rad1) { + len = len / rad1; + dvecx += vecx / len; + dvecy += vecy / len; + } + } + vecx -= 2.0f; + vecy += 1.0f; + } + } + } + + x -= dvecx / 18.0f; + y -= dvecy / 18.0f; + x -= floorf(x); + y -= floorf(y); + jit2[i][0] = x; + jit2[i][1] = y; + } + memcpy(jit1, jit2, 2 * (unsigned int)num * sizeof(float)); } void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float rad2) { - int i, j; - float vecx, vecy, dvecx, dvecy, x, y; - - for (i = num - 1; i >= 0; i--) { - dvecx = dvecy = 0.0; - x = jit1[i][0]; - y = jit1[i][1]; - for (j = num - 1; j >= 0; j--) { - if (i != j) { - vecx = jit1[j][0] - x - 1.0f; - vecy = jit1[j][1] - y - 1.0f; - - if (fabsf(vecx) < rad2) { dvecx += vecx * rad2; } - vecx += 1.0f; - if (fabsf(vecx) < rad2) { dvecx += vecx * rad2; } - vecx += 1.0f; - if (fabsf(vecx) < rad2) { dvecx += vecx * rad2; } - - if (fabsf(vecy) < rad2) { dvecy += vecy * rad2; } - vecy += 1.0f; - if (fabsf(vecy) < rad2) { dvecy += vecy * rad2; } - vecy += 1.0f; - if (fabsf(vecy) < rad2) { dvecy += vecy * rad2; } - - } - } - - x -= dvecx / 2.0f; - y -= dvecy / 2.0f; - x -= floorf(x); - y -= floorf(y); - jit2[i][0] = x; - jit2[i][1] = y; - } - memcpy(jit1, jit2, (unsigned int)num * sizeof(float[2])); + int i, j; + float vecx, vecy, dvecx, dvecy, x, y; + + for (i = num - 1; i >= 0; i--) { + dvecx = dvecy = 0.0; + x = jit1[i][0]; + y = jit1[i][1]; + for (j = num - 1; j >= 0; j--) { + if (i != j) { + vecx = jit1[j][0] - x - 1.0f; + vecy = jit1[j][1] - y - 1.0f; + + if (fabsf(vecx) < rad2) { + dvecx += vecx * rad2; + } + vecx += 1.0f; + if (fabsf(vecx) < rad2) { + dvecx += vecx * rad2; + } + vecx += 1.0f; + if (fabsf(vecx) < rad2) { + dvecx += vecx * rad2; + } + + if (fabsf(vecy) < rad2) { + dvecy += vecy * rad2; + } + vecy += 1.0f; + if (fabsf(vecy) < rad2) { + dvecy += vecy * rad2; + } + vecy += 1.0f; + if (fabsf(vecy) < rad2) { + dvecy += vecy * rad2; + } + } + } + + x -= dvecx / 2.0f; + y -= dvecy / 2.0f; + x -= floorf(x); + y -= floorf(y); + jit2[i][0] = x; + jit2[i][1] = y; + } + memcpy(jit1, jit2, (unsigned int)num * sizeof(float[2])); } - void BLI_jitter_init(float (*jitarr)[2], int num) { - float (*jit2)[2]; - float num_fl, num_fl_sqrt; - float x, rad1, rad2, rad3; - RNG *rng; - int i; - - if (num == 0) { - return; - } - - num_fl = (float)num; - num_fl_sqrt = sqrtf(num_fl); - - jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit"); - rad1 = 1.0f / num_fl_sqrt; - rad2 = 1.0f / num_fl; - rad3 = num_fl_sqrt / num_fl; - - rng = BLI_rng_new(31415926 + (unsigned int)num); - - x = 0; - for (i = 0; i < num; i++) { - jitarr[i][0] = x + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); - jitarr[i][1] = (float)i / num_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); - x += rad3; - x -= floorf(x); - } - - BLI_rng_free(rng); - - for (i = 0; i < 24; i++) { - BLI_jitterate1(jitarr, jit2, num, rad1); - BLI_jitterate1(jitarr, jit2, num, rad1); - BLI_jitterate2(jitarr, jit2, num, rad2); - } - - MEM_freeN(jit2); - - /* finally, move jittertab to be centered around (0, 0) */ - for (i = 0; i < num; i++) { - jitarr[i][0] -= 0.5f; - jitarr[i][1] -= 0.5f; - } + float(*jit2)[2]; + float num_fl, num_fl_sqrt; + float x, rad1, rad2, rad3; + RNG *rng; + int i; + + if (num == 0) { + return; + } + + num_fl = (float)num; + num_fl_sqrt = sqrtf(num_fl); + + jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit"); + rad1 = 1.0f / num_fl_sqrt; + rad2 = 1.0f / num_fl; + rad3 = num_fl_sqrt / num_fl; + + rng = BLI_rng_new(31415926 + (unsigned int)num); + + x = 0; + for (i = 0; i < num; i++) { + jitarr[i][0] = x + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); + jitarr[i][1] = (float)i / num_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng)); + x += rad3; + x -= floorf(x); + } + + BLI_rng_free(rng); + + for (i = 0; i < 24; i++) { + BLI_jitterate1(jitarr, jit2, num, rad1); + BLI_jitterate1(jitarr, jit2, num, rad1); + BLI_jitterate2(jitarr, jit2, num, rad2); + } + + MEM_freeN(jit2); + + /* finally, move jittertab to be centered around (0, 0) */ + for (i = 0; i < num; i++) { + jitarr[i][0] -= 0.5f; + jitarr[i][1] -= 0.5f; + } } diff --git a/source/blender/blenlib/intern/kdtree_1d.c b/source/blender/blenlib/intern/kdtree_1d.c index 95d440d3644..b5d5707df29 100644 --- a/source/blender/blenlib/intern/kdtree_1d.c +++ b/source/blender/blenlib/intern/kdtree_1d.c @@ -22,4 +22,4 @@ #define KDTREE_PREFIX_ID BLI_kdtree_1d #define KDTree KDTree_1d #define KDTreeNearest KDTreeNearest_1d -# include "kdtree_impl.h" +#include "kdtree_impl.h" diff --git a/source/blender/blenlib/intern/kdtree_2d.c b/source/blender/blenlib/intern/kdtree_2d.c index 8ad55e2d964..a9d1c953bff 100644 --- a/source/blender/blenlib/intern/kdtree_2d.c +++ b/source/blender/blenlib/intern/kdtree_2d.c @@ -22,4 +22,4 @@ #define KDTREE_PREFIX_ID BLI_kdtree_2d #define KDTree KDTree_2d #define KDTreeNearest KDTreeNearest_2d -# include "kdtree_impl.h" +#include "kdtree_impl.h" diff --git a/source/blender/blenlib/intern/kdtree_3d.c b/source/blender/blenlib/intern/kdtree_3d.c index 2f85755b676..7b24a249e18 100644 --- a/source/blender/blenlib/intern/kdtree_3d.c +++ b/source/blender/blenlib/intern/kdtree_3d.c @@ -22,4 +22,4 @@ #define KDTREE_PREFIX_ID BLI_kdtree_3d #define KDTree KDTree_3d #define KDTreeNearest KDTreeNearest_3d -# include "kdtree_impl.h" +#include "kdtree_impl.h" diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index 1bce3473bde..a4b1833e657 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -25,36 +25,36 @@ #include "BLI_utildefines.h" #include "BLI_strict_flags.h" -#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1 ## MACRO_ARG2 +#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 #define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) #define BLI_kdtree_nd_(id) _CONCAT(KDTREE_PREFIX_ID, _##id) typedef struct KDTreeNode_head { - uint left, right; - float co[KD_DIMS]; - int index; + uint left, right; + float co[KD_DIMS]; + int index; } KDTreeNode_head; typedef struct KDTreeNode { - uint left, right; - float co[KD_DIMS]; - int index; - uint d; /* range is only (0..KD_DIMS - 1) */ + uint left, right; + float co[KD_DIMS]; + int index; + uint d; /* range is only (0..KD_DIMS - 1) */ } KDTreeNode; struct KDTree { - KDTreeNode *nodes; - uint nodes_len; - uint root; + KDTreeNode *nodes; + uint nodes_len; + uint root; #ifdef DEBUG - bool is_balanced; /* ensure we call balance first */ - uint nodes_len_capacity; /* max size of the tree */ + bool is_balanced; /* ensure we call balance first */ + uint nodes_len_capacity; /* max size of the tree */ #endif }; -#define KD_STACK_INIT 100 /* initial size for array (on the stack) */ -#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */ -#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */ +#define KD_STACK_INIT 100 /* initial size for array (on the stack) */ +#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */ +#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */ #define KD_NODE_UNSET ((uint)-1) @@ -67,23 +67,25 @@ struct KDTree { static void copy_vn_vn(float v0[KD_DIMS], const float v1[KD_DIMS]) { - for (uint j = 0; j < KD_DIMS; j++) { - v0[j] = v1[j]; - } + for (uint j = 0; j < KD_DIMS; j++) { + v0[j] = v1[j]; + } } static float len_squared_vnvn(const float v0[KD_DIMS], const float v1[KD_DIMS]) { - float d = 0.0f; - for (uint j = 0; j < KD_DIMS; j++) { - d += SQUARE(v0[j] - v1[j]); - } - return d; + float d = 0.0f; + for (uint j = 0; j < KD_DIMS; j++) { + d += SQUARE(v0[j] - v1[j]); + } + return d; } -static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], const float co_search[KD_DIMS], const void *UNUSED(user_data)) +static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], + const float co_search[KD_DIMS], + const void *UNUSED(user_data)) { - return len_squared_vnvn(co_kdtree, co_search); + return len_squared_vnvn(co_kdtree, co_search); } /** \} */ @@ -93,27 +95,27 @@ static float len_squared_vnvn_cb(const float co_kdtree[KD_DIMS], const float co_ */ KDTree *BLI_kdtree_nd_(new)(uint nodes_len_capacity) { - KDTree *tree; + KDTree *tree; - tree = MEM_mallocN(sizeof(KDTree), "KDTree"); - tree->nodes = MEM_mallocN(sizeof(KDTreeNode) * nodes_len_capacity, "KDTreeNode"); - tree->nodes_len = 0; - tree->root = KD_NODE_ROOT_IS_INIT; + tree = MEM_mallocN(sizeof(KDTree), "KDTree"); + tree->nodes = MEM_mallocN(sizeof(KDTreeNode) * nodes_len_capacity, "KDTreeNode"); + tree->nodes_len = 0; + tree->root = KD_NODE_ROOT_IS_INIT; #ifdef DEBUG - tree->is_balanced = false; - tree->nodes_len_capacity = nodes_len_capacity; + tree->is_balanced = false; + tree->nodes_len_capacity = nodes_len_capacity; #endif - return tree; + return tree; } void BLI_kdtree_nd_(free)(KDTree *tree) { - if (tree) { - MEM_freeN(tree->nodes); - MEM_freeN(tree); - } + if (tree) { + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } } /** @@ -121,209 +123,212 @@ void BLI_kdtree_nd_(free)(KDTree *tree) */ void BLI_kdtree_nd_(insert)(KDTree *tree, int index, const float co[KD_DIMS]) { - KDTreeNode *node = &tree->nodes[tree->nodes_len++]; + KDTreeNode *node = &tree->nodes[tree->nodes_len++]; #ifdef DEBUG - BLI_assert(tree->nodes_len <= tree->nodes_len_capacity); + BLI_assert(tree->nodes_len <= tree->nodes_len_capacity); #endif - /* note, array isn't calloc'd, - * need to initialize all struct members */ + /* note, array isn't calloc'd, + * need to initialize all struct members */ - node->left = node->right = KD_NODE_UNSET; - copy_vn_vn(node->co, co); - node->index = index; - node->d = 0; + node->left = node->right = KD_NODE_UNSET; + copy_vn_vn(node->co, co); + node->index = index; + node->d = 0; #ifdef DEBUG - tree->is_balanced = false; + tree->is_balanced = false; #endif } static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const uint ofs) { - KDTreeNode *node; - float co; - uint left, right, median, i, j; - - if (nodes_len <= 0) { - return KD_NODE_UNSET; - } - else if (nodes_len == 1) { - return 0 + ofs; - } - - /* quicksort style sorting around median */ - left = 0; - right = nodes_len - 1; - median = nodes_len / 2; - - while (right > left) { - co = nodes[right].co[axis]; - i = left - 1; - j = right; - - while (1) { - while (nodes[++i].co[axis] < co) { /* pass */ } - while (nodes[--j].co[axis] > co && j > left) { /* pass */ } - - if (i >= j) { - break; - } - - SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[j]); - } - - SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[right]); - if (i >= median) { - right = i - 1; - } - if (i <= median) { - left = i + 1; - } - } - - /* set node and sort subnodes */ - node = &nodes[median]; - node->d = axis; - axis = (axis + 1) % KD_DIMS; - node->left = kdtree_balance(nodes, median, axis, ofs); - node->right = kdtree_balance(nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs); - - return median + ofs; + KDTreeNode *node; + float co; + uint left, right, median, i, j; + + if (nodes_len <= 0) { + return KD_NODE_UNSET; + } + else if (nodes_len == 1) { + return 0 + ofs; + } + + /* quicksort style sorting around median */ + left = 0; + right = nodes_len - 1; + median = nodes_len / 2; + + while (right > left) { + co = nodes[right].co[axis]; + i = left - 1; + j = right; + + while (1) { + while (nodes[++i].co[axis] < co) { /* pass */ + } + while (nodes[--j].co[axis] > co && j > left) { /* pass */ + } + + if (i >= j) { + break; + } + + SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[j]); + } + + SWAP(KDTreeNode_head, *(KDTreeNode_head *)&nodes[i], *(KDTreeNode_head *)&nodes[right]); + if (i >= median) { + right = i - 1; + } + if (i <= median) { + left = i + 1; + } + } + + /* set node and sort subnodes */ + node = &nodes[median]; + node->d = axis; + axis = (axis + 1) % KD_DIMS; + node->left = kdtree_balance(nodes, median, axis, ofs); + node->right = kdtree_balance( + nodes + median + 1, (nodes_len - (median + 1)), axis, (median + 1) + ofs); + + return median + ofs; } void BLI_kdtree_nd_(balance)(KDTree *tree) { - if (tree->root != KD_NODE_ROOT_IS_INIT) { - for (uint i = 0; i < tree->nodes_len; i++) { - tree->nodes[i].left = KD_NODE_UNSET; - tree->nodes[i].right = KD_NODE_UNSET; - } - } + if (tree->root != KD_NODE_ROOT_IS_INIT) { + for (uint i = 0; i < tree->nodes_len; i++) { + tree->nodes[i].left = KD_NODE_UNSET; + tree->nodes[i].right = KD_NODE_UNSET; + } + } - tree->root = kdtree_balance(tree->nodes, tree->nodes_len, 0, 0); + tree->root = kdtree_balance(tree->nodes, tree->nodes_len, 0, 0); #ifdef DEBUG - tree->is_balanced = true; + tree->is_balanced = true; #endif } static uint *realloc_nodes(uint *stack, uint *stack_len_capacity, const bool is_alloc) { - uint *stack_new = MEM_mallocN((*stack_len_capacity + KD_NEAR_ALLOC_INC) * sizeof(uint), "KDTree.treestack"); - memcpy(stack_new, stack, *stack_len_capacity * sizeof(uint)); - // memset(stack_new + *stack_len_capacity, 0, sizeof(uint) * KD_NEAR_ALLOC_INC); - if (is_alloc) { - MEM_freeN(stack); - } - *stack_len_capacity += KD_NEAR_ALLOC_INC; - return stack_new; + uint *stack_new = MEM_mallocN((*stack_len_capacity + KD_NEAR_ALLOC_INC) * sizeof(uint), + "KDTree.treestack"); + memcpy(stack_new, stack, *stack_len_capacity * sizeof(uint)); + // memset(stack_new + *stack_len_capacity, 0, sizeof(uint) * KD_NEAR_ALLOC_INC); + if (is_alloc) { + MEM_freeN(stack); + } + *stack_len_capacity += KD_NEAR_ALLOC_INC; + return stack_new; } /** * Find nearest returns index, and -1 if no node is found. */ -int BLI_kdtree_nd_(find_nearest)( - const KDTree *tree, const float co[KD_DIMS], - KDTreeNearest *r_nearest) +int BLI_kdtree_nd_(find_nearest)(const KDTree *tree, + const float co[KD_DIMS], + KDTreeNearest *r_nearest) { - const KDTreeNode *nodes = tree->nodes; - const KDTreeNode *root, *min_node; - uint *stack, stack_default[KD_STACK_INIT]; - float min_dist, cur_dist; - uint stack_len_capacity, cur = 0; + const KDTreeNode *nodes = tree->nodes; + const KDTreeNode *root, *min_node; + uint *stack, stack_default[KD_STACK_INIT]; + float min_dist, cur_dist; + uint stack_len_capacity, cur = 0; #ifdef DEBUG - BLI_assert(tree->is_balanced == true); + BLI_assert(tree->is_balanced == true); #endif - if (UNLIKELY(tree->root == KD_NODE_UNSET)) { - return -1; - } - - stack = stack_default; - stack_len_capacity = KD_STACK_INIT; - - root = &nodes[tree->root]; - min_node = root; - min_dist = len_squared_vnvn(root->co, co); - - if (co[root->d] < root->co[root->d]) { - if (root->right != KD_NODE_UNSET) { - stack[cur++] = root->right; - } - if (root->left != KD_NODE_UNSET) { - stack[cur++] = root->left; - } - } - else { - if (root->left != KD_NODE_UNSET) { - stack[cur++] = root->left; - } - if (root->right != KD_NODE_UNSET) { - stack[cur++] = root->right; - } - } - - while (cur--) { - const KDTreeNode *node = &nodes[stack[cur]]; - - cur_dist = node->co[node->d] - co[node->d]; - - if (cur_dist < 0.0f) { - cur_dist = -cur_dist * cur_dist; - - if (-cur_dist < min_dist) { - cur_dist = len_squared_vnvn(node->co, co); - if (cur_dist < min_dist) { - min_dist = cur_dist; - min_node = node; - } - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - else { - cur_dist = cur_dist * cur_dist; - - if (cur_dist < min_dist) { - cur_dist = len_squared_vnvn(node->co, co); - if (cur_dist < min_dist) { - min_dist = cur_dist; - min_node = node; - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { - stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); - } - } - - if (r_nearest) { - r_nearest->index = min_node->index; - r_nearest->dist = sqrtf(min_dist); - copy_vn_vn(r_nearest->co, min_node->co); - } - - if (stack != stack_default) { - MEM_freeN(stack); - } - - return min_node->index; + if (UNLIKELY(tree->root == KD_NODE_UNSET)) { + return -1; + } + + stack = stack_default; + stack_len_capacity = KD_STACK_INIT; + + root = &nodes[tree->root]; + min_node = root; + min_dist = len_squared_vnvn(root->co, co); + + if (co[root->d] < root->co[root->d]) { + if (root->right != KD_NODE_UNSET) { + stack[cur++] = root->right; + } + if (root->left != KD_NODE_UNSET) { + stack[cur++] = root->left; + } + } + else { + if (root->left != KD_NODE_UNSET) { + stack[cur++] = root->left; + } + if (root->right != KD_NODE_UNSET) { + stack[cur++] = root->right; + } + } + + while (cur--) { + const KDTreeNode *node = &nodes[stack[cur]]; + + cur_dist = node->co[node->d] - co[node->d]; + + if (cur_dist < 0.0f) { + cur_dist = -cur_dist * cur_dist; + + if (-cur_dist < min_dist) { + cur_dist = len_squared_vnvn(node->co, co); + if (cur_dist < min_dist) { + min_dist = cur_dist; + min_node = node; + } + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + else { + cur_dist = cur_dist * cur_dist; + + if (cur_dist < min_dist) { + cur_dist = len_squared_vnvn(node->co, co); + if (cur_dist < min_dist) { + min_dist = cur_dist; + min_node = node; + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { + stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); + } + } + + if (r_nearest) { + r_nearest->index = min_node->index; + r_nearest->dist = sqrtf(min_dist); + copy_vn_vn(r_nearest->co, min_node->co); + } + + if (stack != stack_default) { + MEM_freeN(stack); + } + + return min_node->index; } - /** * A version of #BLI_kdtree_3d_find_nearest which runs a callback * to filter out values. @@ -332,131 +337,136 @@ int BLI_kdtree_nd_(find_nearest)( * Return codes: (1: accept, 0: skip, -1: immediate exit). */ int BLI_kdtree_nd_(find_nearest_cb)( - const KDTree *tree, const float co[KD_DIMS], - int (*filter_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), void *user_data, - KDTreeNearest *r_nearest) + const KDTree *tree, + const float co[KD_DIMS], + int (*filter_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), + void *user_data, + KDTreeNearest *r_nearest) { - const KDTreeNode *nodes = tree->nodes; - const KDTreeNode *min_node = NULL; + const KDTreeNode *nodes = tree->nodes; + const KDTreeNode *min_node = NULL; - uint *stack, stack_default[KD_STACK_INIT]; - float min_dist = FLT_MAX, cur_dist; - uint stack_len_capacity, cur = 0; + uint *stack, stack_default[KD_STACK_INIT]; + float min_dist = FLT_MAX, cur_dist; + uint stack_len_capacity, cur = 0; #ifdef DEBUG - BLI_assert(tree->is_balanced == true); + BLI_assert(tree->is_balanced == true); #endif - if (UNLIKELY(tree->root == KD_NODE_UNSET)) { - return -1; - } + if (UNLIKELY(tree->root == KD_NODE_UNSET)) { + return -1; + } - stack = stack_default; - stack_len_capacity = ARRAY_SIZE(stack_default); + stack = stack_default; + stack_len_capacity = ARRAY_SIZE(stack_default); #define NODE_TEST_NEAREST(node) \ -{ \ - const float dist_sq = len_squared_vnvn((node)->co, co); \ - if (dist_sq < min_dist) { \ - const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \ - if (result == 1) { \ - min_dist = dist_sq; \ - min_node = node; \ - } \ - else if (result == 0) { \ - /* pass */ \ - } \ - else { \ - BLI_assert(result == -1); \ - goto finally; \ - } \ - } \ -} ((void)0) - - stack[cur++] = tree->root; - - while (cur--) { - const KDTreeNode *node = &nodes[stack[cur]]; - - cur_dist = node->co[node->d] - co[node->d]; - - if (cur_dist < 0.0f) { - cur_dist = -cur_dist * cur_dist; - - if (-cur_dist < min_dist) { - NODE_TEST_NEAREST(node); - - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - else { - cur_dist = cur_dist * cur_dist; - - if (cur_dist < min_dist) { - NODE_TEST_NEAREST(node); - - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { - stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); - } - } + { \ + const float dist_sq = len_squared_vnvn((node)->co, co); \ + if (dist_sq < min_dist) { \ + const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \ + if (result == 1) { \ + min_dist = dist_sq; \ + min_node = node; \ + } \ + else if (result == 0) { \ + /* pass */ \ + } \ + else { \ + BLI_assert(result == -1); \ + goto finally; \ + } \ + } \ + } \ + ((void)0) + + stack[cur++] = tree->root; + + while (cur--) { + const KDTreeNode *node = &nodes[stack[cur]]; + + cur_dist = node->co[node->d] - co[node->d]; + + if (cur_dist < 0.0f) { + cur_dist = -cur_dist * cur_dist; + + if (-cur_dist < min_dist) { + NODE_TEST_NEAREST(node); + + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + else { + cur_dist = cur_dist * cur_dist; + + if (cur_dist < min_dist) { + NODE_TEST_NEAREST(node); + + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { + stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); + } + } #undef NODE_TEST_NEAREST - finally: - if (stack != stack_default) { - MEM_freeN(stack); - } - - if (min_node) { - if (r_nearest) { - r_nearest->index = min_node->index; - r_nearest->dist = sqrtf(min_dist); - copy_vn_vn(r_nearest->co, min_node->co); - } - - return min_node->index; - } - else { - return -1; - } + if (stack != stack_default) { + MEM_freeN(stack); + } + + if (min_node) { + if (r_nearest) { + r_nearest->index = min_node->index; + r_nearest->dist = sqrtf(min_dist); + copy_vn_vn(r_nearest->co, min_node->co); + } + + return min_node->index; + } + else { + return -1; + } } -static void nearest_ordered_insert( - KDTreeNearest *nearest, uint *nearest_len, const uint nearest_len_capacity, - const int index, const float dist, const float co[KD_DIMS]) +static void nearest_ordered_insert(KDTreeNearest *nearest, + uint *nearest_len, + const uint nearest_len_capacity, + const int index, + const float dist, + const float co[KD_DIMS]) { - uint i; - - if (*nearest_len < nearest_len_capacity) { - (*nearest_len)++; - } - - for (i = *nearest_len - 1; i > 0; i--) { - if (dist >= nearest[i - 1].dist) { - break; - } - else { - nearest[i] = nearest[i - 1]; - } - } - - nearest[i].index = index; - nearest[i].dist = dist; - copy_vn_vn(nearest[i].co, co); + uint i; + + if (*nearest_len < nearest_len_capacity) { + (*nearest_len)++; + } + + for (i = *nearest_len - 1; i > 0; i--) { + if (dist >= nearest[i - 1].dist) { + break; + } + else { + nearest[i] = nearest[i - 1]; + } + } + + nearest[i].index = index; + nearest[i].dist = dist; + copy_vn_vn(nearest[i].co, co); } /** @@ -465,158 +475,162 @@ static void nearest_ordered_insert( * \param r_nearest: An array of nearest, sized at least \a nearest_len_capacity. */ int BLI_kdtree_nd_(find_nearest_n_with_len_squared_cb)( - const KDTree *tree, const float co[KD_DIMS], - KDTreeNearest r_nearest[], - const uint nearest_len_capacity, - float (*len_sq_fn)(const float co_search[KD_DIMS], const float co_test[KD_DIMS], const void *user_data), - const void *user_data) + const KDTree *tree, + const float co[KD_DIMS], + KDTreeNearest r_nearest[], + const uint nearest_len_capacity, + float (*len_sq_fn)(const float co_search[KD_DIMS], + const float co_test[KD_DIMS], + const void *user_data), + const void *user_data) { - const KDTreeNode *nodes = tree->nodes; - const KDTreeNode *root; - uint *stack, stack_default[KD_STACK_INIT]; - float cur_dist; - uint stack_len_capacity, cur = 0; - uint i, nearest_len = 0; + const KDTreeNode *nodes = tree->nodes; + const KDTreeNode *root; + uint *stack, stack_default[KD_STACK_INIT]; + float cur_dist; + uint stack_len_capacity, cur = 0; + uint i, nearest_len = 0; #ifdef DEBUG - BLI_assert(tree->is_balanced == true); + BLI_assert(tree->is_balanced == true); #endif - if (UNLIKELY((tree->root == KD_NODE_UNSET) || nearest_len_capacity == 0)) { - return 0; - } - - if (len_sq_fn == NULL) { - len_sq_fn = len_squared_vnvn_cb; - BLI_assert(user_data == NULL); - } - - stack = stack_default; - stack_len_capacity = ARRAY_SIZE(stack_default); - - root = &nodes[tree->root]; - - cur_dist = len_sq_fn(co, root->co, user_data); - nearest_ordered_insert(r_nearest, &nearest_len, nearest_len_capacity, root->index, cur_dist, root->co); - - if (co[root->d] < root->co[root->d]) { - if (root->right != KD_NODE_UNSET) { - stack[cur++] = root->right; - } - if (root->left != KD_NODE_UNSET) { - stack[cur++] = root->left; - } - } - else { - if (root->left != KD_NODE_UNSET) { - stack[cur++] = root->left; - } - if (root->right != KD_NODE_UNSET) { - stack[cur++] = root->right; - } - } - - while (cur--) { - const KDTreeNode *node = &nodes[stack[cur]]; - - cur_dist = node->co[node->d] - co[node->d]; - - if (cur_dist < 0.0f) { - cur_dist = -cur_dist * cur_dist; - - if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) { - cur_dist = len_sq_fn(co, node->co, user_data); - - if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { - nearest_ordered_insert(r_nearest, &nearest_len, nearest_len_capacity, node->index, cur_dist, node->co); - } - - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - else { - cur_dist = cur_dist * cur_dist; - - if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { - cur_dist = len_sq_fn(co, node->co, user_data); - if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { - nearest_ordered_insert(r_nearest, &nearest_len, nearest_len_capacity, node->index, cur_dist, node->co); - } - - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { - stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); - } - } - - for (i = 0; i < nearest_len; i++) { - r_nearest[i].dist = sqrtf(r_nearest[i].dist); - } - - if (stack != stack_default) { - MEM_freeN(stack); - } - - return (int)nearest_len; + if (UNLIKELY((tree->root == KD_NODE_UNSET) || nearest_len_capacity == 0)) { + return 0; + } + + if (len_sq_fn == NULL) { + len_sq_fn = len_squared_vnvn_cb; + BLI_assert(user_data == NULL); + } + + stack = stack_default; + stack_len_capacity = ARRAY_SIZE(stack_default); + + root = &nodes[tree->root]; + + cur_dist = len_sq_fn(co, root->co, user_data); + nearest_ordered_insert( + r_nearest, &nearest_len, nearest_len_capacity, root->index, cur_dist, root->co); + + if (co[root->d] < root->co[root->d]) { + if (root->right != KD_NODE_UNSET) { + stack[cur++] = root->right; + } + if (root->left != KD_NODE_UNSET) { + stack[cur++] = root->left; + } + } + else { + if (root->left != KD_NODE_UNSET) { + stack[cur++] = root->left; + } + if (root->right != KD_NODE_UNSET) { + stack[cur++] = root->right; + } + } + + while (cur--) { + const KDTreeNode *node = &nodes[stack[cur]]; + + cur_dist = node->co[node->d] - co[node->d]; + + if (cur_dist < 0.0f) { + cur_dist = -cur_dist * cur_dist; + + if (nearest_len < nearest_len_capacity || -cur_dist < r_nearest[nearest_len - 1].dist) { + cur_dist = len_sq_fn(co, node->co, user_data); + + if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { + nearest_ordered_insert( + r_nearest, &nearest_len, nearest_len_capacity, node->index, cur_dist, node->co); + } + + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + else { + cur_dist = cur_dist * cur_dist; + + if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { + cur_dist = len_sq_fn(co, node->co, user_data); + if (nearest_len < nearest_len_capacity || cur_dist < r_nearest[nearest_len - 1].dist) { + nearest_ordered_insert( + r_nearest, &nearest_len, nearest_len_capacity, node->index, cur_dist, node->co); + } + + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { + stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); + } + } + + for (i = 0; i < nearest_len; i++) { + r_nearest[i].dist = sqrtf(r_nearest[i].dist); + } + + if (stack != stack_default) { + MEM_freeN(stack); + } + + return (int)nearest_len; } -int BLI_kdtree_nd_(find_nearest_n)( - const KDTree *tree, const float co[KD_DIMS], - KDTreeNearest r_nearest[], - const uint nearest_len_capacity) +int BLI_kdtree_nd_(find_nearest_n)(const KDTree *tree, + const float co[KD_DIMS], + KDTreeNearest r_nearest[], + const uint nearest_len_capacity) { - return BLI_kdtree_nd_(find_nearest_n_with_len_squared_cb)( - tree, co, r_nearest, nearest_len_capacity, - NULL, NULL); + return BLI_kdtree_nd_(find_nearest_n_with_len_squared_cb)( + tree, co, r_nearest, nearest_len_capacity, NULL, NULL); } static int nearest_cmp_dist(const void *a, const void *b) { - const KDTreeNearest *kda = a; - const KDTreeNearest *kdb = b; - - if (kda->dist < kdb->dist) { - return -1; - } - else if (kda->dist > kdb->dist) { - return 1; - } - else { - return 0; - } + const KDTreeNearest *kda = a; + const KDTreeNearest *kdb = b; + + if (kda->dist < kdb->dist) { + return -1; + } + else if (kda->dist > kdb->dist) { + return 1; + } + else { + return 0; + } } -static void nearest_add_in_range( - KDTreeNearest **r_nearest, - uint nearest_index, - uint *nearest_len_capacity, - const int index, const float dist, const float co[KD_DIMS]) +static void nearest_add_in_range(KDTreeNearest **r_nearest, + uint nearest_index, + uint *nearest_len_capacity, + const int index, + const float dist, + const float co[KD_DIMS]) { - KDTreeNearest *to; + KDTreeNearest *to; - if (UNLIKELY(nearest_index >= *nearest_len_capacity)) { - *r_nearest = MEM_reallocN_id( - *r_nearest, - (*nearest_len_capacity += KD_FOUND_ALLOC_INC) * sizeof(KDTreeNode), - __func__); - } + if (UNLIKELY(nearest_index >= *nearest_len_capacity)) { + *r_nearest = MEM_reallocN_id( + *r_nearest, (*nearest_len_capacity += KD_FOUND_ALLOC_INC) * sizeof(KDTreeNode), __func__); + } - to = (*r_nearest) + nearest_index; + to = (*r_nearest) + nearest_index; - to->index = index; - to->dist = sqrtf(dist); - copy_vn_vn(to->co, co); + to->index = index; + to->dist = sqrtf(dist); + copy_vn_vn(to->co, co); } /** @@ -625,89 +639,93 @@ static void nearest_add_in_range( * \param r_nearest: Allocated array of nearest nearest_len (caller is responsible for freeing). */ int BLI_kdtree_nd_(range_search_with_len_squared_cb)( - const KDTree *tree, const float co[KD_DIMS], - KDTreeNearest **r_nearest, const float range, - float (*len_sq_fn)(const float co_search[KD_DIMS], const float co_test[KD_DIMS], const void *user_data), - const void *user_data) + const KDTree *tree, + const float co[KD_DIMS], + KDTreeNearest **r_nearest, + const float range, + float (*len_sq_fn)(const float co_search[KD_DIMS], + const float co_test[KD_DIMS], + const void *user_data), + const void *user_data) { - const KDTreeNode *nodes = tree->nodes; - uint *stack, stack_default[KD_STACK_INIT]; - KDTreeNearest *nearest = NULL; - const float range_sq = range * range; - float dist_sq; - uint stack_len_capacity, cur = 0; - uint nearest_len = 0, nearest_len_capacity = 0; + const KDTreeNode *nodes = tree->nodes; + uint *stack, stack_default[KD_STACK_INIT]; + KDTreeNearest *nearest = NULL; + const float range_sq = range * range; + float dist_sq; + uint stack_len_capacity, cur = 0; + uint nearest_len = 0, nearest_len_capacity = 0; #ifdef DEBUG - BLI_assert(tree->is_balanced == true); + BLI_assert(tree->is_balanced == true); #endif - if (UNLIKELY(tree->root == KD_NODE_UNSET)) { - return 0; - } - - if (len_sq_fn == NULL) { - len_sq_fn = len_squared_vnvn_cb; - BLI_assert(user_data == NULL); - } - - stack = stack_default; - stack_len_capacity = ARRAY_SIZE(stack_default); - - stack[cur++] = tree->root; - - while (cur--) { - const KDTreeNode *node = &nodes[stack[cur]]; - - if (co[node->d] + range < node->co[node->d]) { - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - else if (co[node->d] - range > node->co[node->d]) { - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - else { - dist_sq = len_sq_fn(co, node->co, user_data); - if (dist_sq <= range_sq) { - nearest_add_in_range(&nearest, nearest_len++, &nearest_len_capacity, node->index, dist_sq, node->co); - } - - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - - if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { - stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); - } - } - - if (stack != stack_default) { - MEM_freeN(stack); - } - - if (nearest_len) { - qsort(nearest, nearest_len, sizeof(KDTreeNearest), nearest_cmp_dist); - } - - *r_nearest = nearest; - - return (int)nearest_len; + if (UNLIKELY(tree->root == KD_NODE_UNSET)) { + return 0; + } + + if (len_sq_fn == NULL) { + len_sq_fn = len_squared_vnvn_cb; + BLI_assert(user_data == NULL); + } + + stack = stack_default; + stack_len_capacity = ARRAY_SIZE(stack_default); + + stack[cur++] = tree->root; + + while (cur--) { + const KDTreeNode *node = &nodes[stack[cur]]; + + if (co[node->d] + range < node->co[node->d]) { + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + else if (co[node->d] - range > node->co[node->d]) { + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + else { + dist_sq = len_sq_fn(co, node->co, user_data); + if (dist_sq <= range_sq) { + nearest_add_in_range( + &nearest, nearest_len++, &nearest_len_capacity, node->index, dist_sq, node->co); + } + + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + + if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { + stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); + } + } + + if (stack != stack_default) { + MEM_freeN(stack); + } + + if (nearest_len) { + qsort(nearest, nearest_len, sizeof(KDTreeNearest), nearest_cmp_dist); + } + + *r_nearest = nearest; + + return (int)nearest_len; } -int BLI_kdtree_nd_(range_search)( - const KDTree *tree, const float co[KD_DIMS], - KDTreeNearest **r_nearest, const float range) +int BLI_kdtree_nd_(range_search)(const KDTree *tree, + const float co[KD_DIMS], + KDTreeNearest **r_nearest, + const float range) { - return BLI_kdtree_nd_(range_search_with_len_squared_cb)( - tree, co, r_nearest, range, - NULL, NULL); + return BLI_kdtree_nd_(range_search_with_len_squared_cb)(tree, co, r_nearest, range, NULL, NULL); } /** @@ -719,66 +737,69 @@ int BLI_kdtree_nd_(range_search)( * \note the order of calls isn't sorted based on distance. */ void BLI_kdtree_nd_(range_search_cb)( - const KDTree *tree, const float co[KD_DIMS], float range, - bool (*search_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), void *user_data) + const KDTree *tree, + const float co[KD_DIMS], + float range, + bool (*search_cb)(void *user_data, int index, const float co[KD_DIMS], float dist_sq), + void *user_data) { - const KDTreeNode *nodes = tree->nodes; + const KDTreeNode *nodes = tree->nodes; - uint *stack, stack_default[KD_STACK_INIT]; - float range_sq = range * range, dist_sq; - uint stack_len_capacity, cur = 0; + uint *stack, stack_default[KD_STACK_INIT]; + float range_sq = range * range, dist_sq; + uint stack_len_capacity, cur = 0; #ifdef DEBUG - BLI_assert(tree->is_balanced == true); + BLI_assert(tree->is_balanced == true); #endif - if (UNLIKELY(tree->root == KD_NODE_UNSET)) { - return; - } - - stack = stack_default; - stack_len_capacity = ARRAY_SIZE(stack_default); - - stack[cur++] = tree->root; - - while (cur--) { - const KDTreeNode *node = &nodes[stack[cur]]; - - if (co[node->d] + range < node->co[node->d]) { - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - } - else if (co[node->d] - range > node->co[node->d]) { - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - else { - dist_sq = len_squared_vnvn(node->co, co); - if (dist_sq <= range_sq) { - if (search_cb(user_data, node->index, node->co, dist_sq) == false) { - goto finally; - } - } - - if (node->left != KD_NODE_UNSET) { - stack[cur++] = node->left; - } - if (node->right != KD_NODE_UNSET) { - stack[cur++] = node->right; - } - } - - if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { - stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); - } - } + if (UNLIKELY(tree->root == KD_NODE_UNSET)) { + return; + } + + stack = stack_default; + stack_len_capacity = ARRAY_SIZE(stack_default); + + stack[cur++] = tree->root; + + while (cur--) { + const KDTreeNode *node = &nodes[stack[cur]]; + + if (co[node->d] + range < node->co[node->d]) { + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + } + else if (co[node->d] - range > node->co[node->d]) { + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + else { + dist_sq = len_squared_vnvn(node->co, co); + if (dist_sq <= range_sq) { + if (search_cb(user_data, node->index, node->co, dist_sq) == false) { + goto finally; + } + } + + if (node->left != KD_NODE_UNSET) { + stack[cur++] = node->left; + } + if (node->right != KD_NODE_UNSET) { + stack[cur++] = node->right; + } + } + + if (UNLIKELY(cur + KD_DIMS > stack_len_capacity)) { + stack = realloc_nodes(stack, &stack_len_capacity, stack_default != stack); + } + } finally: - if (stack != stack_default) { - MEM_freeN(stack); - } + if (stack != stack_default) { + MEM_freeN(stack); + } } /** @@ -787,12 +808,12 @@ finally: */ static uint *kdtree_order(const KDTree *tree) { - const KDTreeNode *nodes = tree->nodes; - uint *order = MEM_mallocN(sizeof(uint) * tree->nodes_len, __func__); - for (uint i = 0; i < tree->nodes_len; i++) { - order[nodes[i].index] = i; - } - return order; + const KDTreeNode *nodes = tree->nodes; + uint *order = MEM_mallocN(sizeof(uint) * tree->nodes_len, __func__); + for (uint i = 0; i < tree->nodes_len; i++) { + order[nodes[i].index] = i; + } + return order; } /* -------------------------------------------------------------------- */ @@ -800,45 +821,45 @@ static uint *kdtree_order(const KDTree *tree) * \{ */ struct DeDuplicateParams { - /* Static */ - const KDTreeNode *nodes; - float range; - float range_sq; - int *duplicates; - int *duplicates_found; - - /* Per Search */ - float search_co[KD_DIMS]; - int search; + /* Static */ + const KDTreeNode *nodes; + float range; + float range_sq; + int *duplicates; + int *duplicates_found; + + /* Per Search */ + float search_co[KD_DIMS]; + int search; }; static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i) { - const KDTreeNode *node = &p->nodes[i]; - if (p->search_co[node->d] + p->range <= node->co[node->d]) { - if (node->left != KD_NODE_UNSET) { - deduplicate_recursive(p, node->left); - } - } - else if (p->search_co[node->d] - p->range >= node->co[node->d]) { - if (node->right != KD_NODE_UNSET) { - deduplicate_recursive(p, node->right); - } - } - else { - if ((p->search != node->index) && (p->duplicates[node->index] == -1)) { - if (len_squared_vnvn(node->co, p->search_co) <= p->range_sq) { - p->duplicates[node->index] = (int)p->search; - *p->duplicates_found += 1; - } - } - if (node->left != KD_NODE_UNSET) { - deduplicate_recursive(p, node->left); - } - if (node->right != KD_NODE_UNSET) { - deduplicate_recursive(p, node->right); - } - } + const KDTreeNode *node = &p->nodes[i]; + if (p->search_co[node->d] + p->range <= node->co[node->d]) { + if (node->left != KD_NODE_UNSET) { + deduplicate_recursive(p, node->left); + } + } + else if (p->search_co[node->d] - p->range >= node->co[node->d]) { + if (node->right != KD_NODE_UNSET) { + deduplicate_recursive(p, node->right); + } + } + else { + if ((p->search != node->index) && (p->duplicates[node->index] == -1)) { + if (len_squared_vnvn(node->co, p->search_co) <= p->range_sq) { + p->duplicates[node->index] = (int)p->search; + *p->duplicates_found += 1; + } + } + if (node->left != KD_NODE_UNSET) { + deduplicate_recursive(p, node->left); + } + if (node->right != KD_NODE_UNSET) { + deduplicate_recursive(p, node->right); + } + } } /** @@ -859,54 +880,55 @@ static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i) * * \note Merging is always a single step (target indices wont be marked for merging). */ -int BLI_kdtree_nd_(calc_duplicates_fast)( - const KDTree *tree, const float range, bool use_index_order, - int *duplicates) +int BLI_kdtree_nd_(calc_duplicates_fast)(const KDTree *tree, + const float range, + bool use_index_order, + int *duplicates) { - int found = 0; - struct DeDuplicateParams p = { - .nodes = tree->nodes, - .range = range, - .range_sq = SQUARE(range), - .duplicates = duplicates, - .duplicates_found = &found, - }; - - if (use_index_order) { - uint *order = kdtree_order(tree); - for (uint i = 0; i < tree->nodes_len; i++) { - const uint node_index = order[i]; - const int index = (int)i; - if (ELEM(duplicates[index], -1, index)) { - p.search = index; - copy_vn_vn(p.search_co, tree->nodes[node_index].co); - int found_prev = found; - deduplicate_recursive(&p, tree->root); - if (found != found_prev) { - /* Prevent chains of doubles. */ - duplicates[index] = index; - } - } - } - MEM_freeN(order); - } - else { - for (uint i = 0; i < tree->nodes_len; i++) { - const uint node_index = i; - const int index = p.nodes[node_index].index; - if (ELEM(duplicates[index], -1, index)) { - p.search = index; - copy_vn_vn(p.search_co, tree->nodes[node_index].co); - int found_prev = found; - deduplicate_recursive(&p, tree->root); - if (found != found_prev) { - /* Prevent chains of doubles. */ - duplicates[index] = index; - } - } - } - } - return found; + int found = 0; + struct DeDuplicateParams p = { + .nodes = tree->nodes, + .range = range, + .range_sq = SQUARE(range), + .duplicates = duplicates, + .duplicates_found = &found, + }; + + if (use_index_order) { + uint *order = kdtree_order(tree); + for (uint i = 0; i < tree->nodes_len; i++) { + const uint node_index = order[i]; + const int index = (int)i; + if (ELEM(duplicates[index], -1, index)) { + p.search = index; + copy_vn_vn(p.search_co, tree->nodes[node_index].co); + int found_prev = found; + deduplicate_recursive(&p, tree->root); + if (found != found_prev) { + /* Prevent chains of doubles. */ + duplicates[index] = index; + } + } + } + MEM_freeN(order); + } + else { + for (uint i = 0; i < tree->nodes_len; i++) { + const uint node_index = i; + const int index = p.nodes[node_index].index; + if (ELEM(duplicates[index], -1, index)) { + p.search = index; + copy_vn_vn(p.search_co, tree->nodes[node_index].co); + int found_prev = found; + deduplicate_recursive(&p, tree->root); + if (found != found_prev) { + /* Prevent chains of doubles. */ + duplicates[index] = index; + } + } + } + } + return found; } /** \} */ @@ -917,27 +939,27 @@ int BLI_kdtree_nd_(calc_duplicates_fast)( static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p) { - const KDTreeNode *n0 = n0_p; - const KDTreeNode *n1 = n1_p; - for (uint j = 0; j < KD_DIMS; j++) { - if (n0->co[j] < n1->co[j]) { - return -1; - } - else if (n0->co[j] > n1->co[j]) { - return 1; - } - } - /* Sort by pointer so the first added will be used. - * assignment below ignores const correctness, - * however the values aren't used for sorting and are to be discarded. */ - if (n0 < n1) { - ((KDTreeNode *)n1)->d = KD_DIMS; /* tag invalid */ - return -1; - } - else { - ((KDTreeNode *)n0)->d = KD_DIMS; /* tag invalid */ - return 1; - } + const KDTreeNode *n0 = n0_p; + const KDTreeNode *n1 = n1_p; + for (uint j = 0; j < KD_DIMS; j++) { + if (n0->co[j] < n1->co[j]) { + return -1; + } + else if (n0->co[j] > n1->co[j]) { + return 1; + } + } + /* Sort by pointer so the first added will be used. + * assignment below ignores const correctness, + * however the values aren't used for sorting and are to be discarded. */ + if (n0 < n1) { + ((KDTreeNode *)n1)->d = KD_DIMS; /* tag invalid */ + return -1; + } + else { + ((KDTreeNode *)n0)->d = KD_DIMS; /* tag invalid */ + return 1; + } } /** @@ -948,20 +970,20 @@ static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p) int BLI_kdtree_nd_(deduplicate)(KDTree *tree) { #ifdef DEBUG - tree->is_balanced = false; + tree->is_balanced = false; #endif - qsort(tree->nodes, (size_t)tree->nodes_len, sizeof(*tree->nodes), kdtree_node_cmp_deduplicate); - uint j = 0; - for (uint i = 0; i < tree->nodes_len; i++) { - if (tree->nodes[i].d != KD_DIMS) { - if (i != j) { - tree->nodes[j] = tree->nodes[i]; - } - j++; - } - } - tree->nodes_len = j; - return (int)tree->nodes_len; + qsort(tree->nodes, (size_t)tree->nodes_len, sizeof(*tree->nodes), kdtree_node_cmp_deduplicate); + uint j = 0; + for (uint i = 0; i < tree->nodes_len; i++) { + if (tree->nodes[i].d != KD_DIMS) { + if (i != j) { + tree->nodes[j] = tree->nodes[i]; + } + j++; + } + } + tree->nodes_len = j; + return (int)tree->nodes_len; } /** \} */ diff --git a/source/blender/blenlib/intern/lasso_2d.c b/source/blender/blenlib/intern/lasso_2d.c index a8eb9f09041..f1e9b1e655f 100644 --- a/source/blender/blenlib/intern/lasso_2d.c +++ b/source/blender/blenlib/intern/lasso_2d.c @@ -30,63 +30,76 @@ void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves) { - unsigned int a; - - rect->xmin = rect->xmax = mcords[0][0]; - rect->ymin = rect->ymax = mcords[0][1]; - - for (a = 1; a < moves; a++) { - if (mcords[a][0] < rect->xmin) { rect->xmin = mcords[a][0]; } - else if (mcords[a][0] > rect->xmax) { rect->xmax = mcords[a][0]; } - if (mcords[a][1] < rect->ymin) { rect->ymin = mcords[a][1]; } - else if (mcords[a][1] > rect->ymax) { rect->ymax = mcords[a][1]; } - } + unsigned int a; + + rect->xmin = rect->xmax = mcords[0][0]; + rect->ymin = rect->ymax = mcords[0][1]; + + for (a = 1; a < moves; a++) { + if (mcords[a][0] < rect->xmin) { + rect->xmin = mcords[a][0]; + } + else if (mcords[a][0] > rect->xmax) { + rect->xmax = mcords[a][0]; + } + if (mcords[a][1] < rect->ymin) { + rect->ymin = mcords[a][1]; + } + else if (mcords[a][1] > rect->ymax) { + rect->ymax = mcords[a][1]; + } + } } - -bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves, - const int sx, const int sy, +bool BLI_lasso_is_point_inside(const int mcords[][2], + const unsigned int moves, + const int sx, + const int sy, const int error_value) { - if (sx == error_value || moves == 0) { - return false; - } - else { - int pt[2] = {sx, sy}; - return isect_point_poly_v2_int(pt, mcords, moves, true); - } + if (sx == error_value || moves == 0) { + return false; + } + else { + int pt[2] = {sx, sy}; + return isect_point_poly_v2_int(pt, mcords, moves, true); + } } /* edge version for lasso select. we assume boundbox check was done */ -bool BLI_lasso_is_edge_inside(const int mcords[][2], const unsigned int moves, - int x0, int y0, int x1, int y1, +bool BLI_lasso_is_edge_inside(const int mcords[][2], + const unsigned int moves, + int x0, + int y0, + int x1, + int y1, const int error_value) { - if (x0 == error_value || x1 == error_value || moves == 0) { - return false; - } + if (x0 == error_value || x1 == error_value || moves == 0) { + return false; + } - const int v1[2] = {x0, y0}, v2[2] = {x1, y1}; + const int v1[2] = {x0, y0}, v2[2] = {x1, y1}; - /* check points in lasso */ - if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) { - return true; - } - if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) { - return true; - } + /* check points in lasso */ + if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) { + return true; + } + if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) { + return true; + } - /* no points in lasso, so we have to intersect with lasso edge */ + /* no points in lasso, so we have to intersect with lasso edge */ - if (isect_seg_seg_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) { - return true; - } - for (unsigned int a = 0; a < moves - 1; a++) { - if (isect_seg_seg_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) { - return true; - } - } + if (isect_seg_seg_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) { + return true; + } + for (unsigned int a = 0; a < moves - 1; a++) { + if (isect_seg_seg_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) { + return true; + } + } - return false; + return false; } diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h index 3da4c5ccd41..fac1ca8e983 100644 --- a/source/blender/blenlib/intern/list_sort_impl.h +++ b/source/blender/blenlib/intern/list_sort_impl.h @@ -68,25 +68,24 @@ # define THUNK_PREPEND2(thunk, a, b) a, b #endif -#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1 ## MACRO_ARG2 +#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2 #define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) #define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id) /* local identifiers */ -#define SortInfo _SORT_PREFIX(SortInfo) -#define CompareFn _SORT_PREFIX(CompareFn) -#define init_sort_info _SORT_PREFIX(init_sort_info) -#define merge_lists _SORT_PREFIX(merge_lists) -#define sweep_up _SORT_PREFIX(sweep_up) -#define insert_list _SORT_PREFIX(insert_list) - -typedef int (* CompareFn)( +#define SortInfo _SORT_PREFIX(SortInfo) +#define CompareFn _SORT_PREFIX(CompareFn) +#define init_sort_info _SORT_PREFIX(init_sort_info) +#define merge_lists _SORT_PREFIX(merge_lists) +#define sweep_up _SORT_PREFIX(sweep_up) +#define insert_list _SORT_PREFIX(insert_list) + +typedef int (*CompareFn)( #ifdef SORT_IMPL_USE_THUNK - void *thunk, + void *thunk, #endif - const void *, - const void *); - + const void *, + const void *); /* -------------------------------------------------------------------- */ /* MIT license from original source */ @@ -125,69 +124,67 @@ typedef int (* CompareFn)( * we can reduce the depth by 1. */ #define FLOOR_LOG2(x) \ - (((x) >= 2) + ((x) >= 4) + ((x) >= 8) + ((x) >= 16) + ((x) >= 32) + ((x) >= 64) + ((x) >= 128)) -#define MAX_RANKS \ - ((sizeof(size_t) * 8) - FLOOR_LOG2(sizeof(list_node)) - 1) + (((x) >= 2) + ((x) >= 4) + ((x) >= 8) + ((x) >= 16) + ((x) >= 32) + ((x) >= 64) + ((x) >= 128)) +#define MAX_RANKS ((sizeof(size_t) * 8) - FLOOR_LOG2(sizeof(list_node)) - 1) struct SortInfo { - unsigned int min_rank, n_ranks; - CompareFn func; + unsigned int min_rank, n_ranks; + CompareFn func; #ifdef SORT_IMPL_USE_THUNK - void *thunk; + void *thunk; #endif - /** - * Invariant: `ranks[i] == NULL || length(ranks[i]) >= 2**(i+1)`. - * - * ~ 128 bytes on 32bit, ~ 512 bytes on 64bit */ - list_node *ranks[MAX_RANKS]; + /** + * Invariant: `ranks[i] == NULL || length(ranks[i]) >= 2**(i+1)`. + * + * ~ 128 bytes on 32bit, ~ 512 bytes on 64bit */ + list_node *ranks[MAX_RANKS]; }; -BLI_INLINE void init_sort_info( - struct SortInfo *si, - CompareFn func +BLI_INLINE void init_sort_info(struct SortInfo *si, + CompareFn func #ifdef SORT_IMPL_USE_THUNK - , - void *thunk + , + void *thunk #endif - ) +) { - si->min_rank = si->n_ranks = 0; - si->func = func; - /* we don't need to initialize si->ranks, - * since we never lookup past si->n_ranks. */ + si->min_rank = si->n_ranks = 0; + si->func = func; + /* we don't need to initialize si->ranks, + * since we never lookup past si->n_ranks. */ #ifdef SORT_IMPL_USE_THUNK - si->thunk = thunk; + si->thunk = thunk; #endif } -BLI_INLINE list_node *merge_lists( - list_node *first, list_node *second, - CompareFn func +BLI_INLINE list_node *merge_lists(list_node *first, + list_node *second, + CompareFn func #ifdef SORT_IMPL_USE_THUNK - , - void *thunk + , + void *thunk #endif - ) +) { - /* merge the two lists */ - list_node *list = NULL; - list_node **pos = &list; - while (first && second) { - if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) { - *pos = second; - second = second->next; - } - else { - *pos = first; - first = first->next; - } - pos = &((*pos)->next); - } - *pos = first ? first : second; - return list; + /* merge the two lists */ + list_node *list = NULL; + list_node **pos = &list; + while (first && second) { + if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) { + *pos = second; + second = second->next; + } + else { + *pos = first; + first = first->next; + } + pos = &((*pos)->next); + } + *pos = first ? first : second; + return list; } /** @@ -196,12 +193,12 @@ BLI_INLINE list_node *merge_lists( */ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned int upto) { - unsigned int i; - for (i = si->min_rank; i < upto; i++) { - list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); - si->ranks[i] = NULL; - } - return list; + unsigned int i; + for (i = si->min_rank; i < upto; i++) { + list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); + si->ranks[i] = NULL; + } + return list; } /** @@ -233,44 +230,41 @@ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned in * `2**(rank+1) <= length(list) < 2**(rank+2)` * (therefore: `length(list) >= 2`) */ -BLI_INLINE void insert_list( - struct SortInfo *si, - list_node *list, - unsigned int rank) +BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int rank) { - unsigned int i; - - if (rank > si->n_ranks) { - if (UNLIKELY(rank > MAX_RANKS)) { - // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank); - rank = MAX_RANKS; - } - list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk)); - for (i = si->n_ranks; i < rank; ++i) { - si->ranks[i] = NULL; - } - } - else { - if (rank) { - list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk)); - } - for (i = rank; i < si->n_ranks && si->ranks[i]; ++i) { - list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); - si->ranks[i] = NULL; - } - } - - /* Will _never_ happen: so we can just devolve into quadratic ;-) */ - if (UNLIKELY(i == MAX_RANKS)) { - i--; - } - - if (i >= si->n_ranks) { - si->n_ranks = i + 1; - } - - si->min_rank = i; - si->ranks[i] = list; + unsigned int i; + + if (rank > si->n_ranks) { + if (UNLIKELY(rank > MAX_RANKS)) { + // printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank); + rank = MAX_RANKS; + } + list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk)); + for (i = si->n_ranks; i < rank; ++i) { + si->ranks[i] = NULL; + } + } + else { + if (rank) { + list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk)); + } + for (i = rank; i < si->n_ranks && si->ranks[i]; ++i) { + list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk)); + si->ranks[i] = NULL; + } + } + + /* Will _never_ happen: so we can just devolve into quadratic ;-) */ + if (UNLIKELY(i == MAX_RANKS)) { + i--; + } + + if (i >= si->n_ranks) { + si->n_ranks = i + 1; + } + + si->min_rank = i; + si->ranks[i] = list; } #undef MAX_RANKS @@ -279,43 +273,41 @@ BLI_INLINE void insert_list( /** * Main sort function. */ -BLI_INLINE list_node *list_sort_do( - list_node *list, - CompareFn func +BLI_INLINE list_node *list_sort_do(list_node *list, + CompareFn func #ifdef SORT_IMPL_USE_THUNK - , - void *thunk + , + void *thunk #endif - ) +) { - struct SortInfo si; + struct SortInfo si; - init_sort_info( - &si, - func + init_sort_info(&si, + func #ifdef SORT_IMPL_USE_THUNK - , - thunk + , + thunk #endif - ); + ); - while (list && list->next) { - list_node *next = list->next; - list_node *tail = next->next; + while (list && list->next) { + list_node *next = list->next; + list_node *tail = next->next; - if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) { - next->next = list; - next = list; - list = list->next; - } - next->next = NULL; + if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) { + next->next = list; + next = list; + list = list->next; + } + next->next = NULL; - insert_list(&si, list, 0); + insert_list(&si, list, 0); - list = tail; - } + list = tail; + } - return sweep_up(&si, list, si.n_ranks); + return sweep_up(&si, list, si.n_ranks); } #undef _CONCAT_AUX diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index e34f9d0ab10..ff9e21319da 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -28,7 +28,6 @@ #include <string.h> #include <stdlib.h> - #include "MEM_guardedalloc.h" #include "DNA_listBase.h" @@ -44,20 +43,20 @@ */ void BLI_movelisttolist(ListBase *dst, ListBase *src) { - if (src->first == NULL) { - return; - } + if (src->first == NULL) { + return; + } - if (dst->first == NULL) { - dst->first = src->first; - dst->last = src->last; - } - else { - ((Link *)dst->last)->next = src->first; - ((Link *)src->first)->prev = dst->last; - dst->last = src->last; - } - src->first = src->last = NULL; + if (dst->first == NULL) { + dst->first = src->first; + dst->last = src->last; + } + else { + ((Link *)dst->last)->next = src->first; + ((Link *)src->first)->prev = dst->last; + dst->last = src->last; + } + src->first = src->last = NULL; } /** @@ -65,21 +64,21 @@ void BLI_movelisttolist(ListBase *dst, ListBase *src) */ void BLI_movelisttolist_reverse(ListBase *dst, ListBase *src) { - if (src->first == NULL) { - return; - } + if (src->first == NULL) { + return; + } - if (dst->first == NULL) { - dst->first = src->first; - dst->last = src->last; - } - else { - ((Link *)src->last)->next = dst->first; - ((Link *)dst->first)->prev = src->last; - dst->first = src->first; - } + if (dst->first == NULL) { + dst->first = src->first; + dst->last = src->last; + } + else { + ((Link *)src->last)->next = dst->first; + ((Link *)dst->first)->prev = src->last; + dst->first = src->first; + } - src->first = src->last = NULL; + src->first = src->last = NULL; } /** @@ -87,73 +86,71 @@ void BLI_movelisttolist_reverse(ListBase *dst, ListBase *src) */ void BLI_addhead(ListBase *listbase, void *vlink) { - Link *link = vlink; + Link *link = vlink; - if (link == NULL) { - return; - } + if (link == NULL) { + return; + } - link->next = listbase->first; - link->prev = NULL; + link->next = listbase->first; + link->prev = NULL; - if (listbase->first) { - ((Link *)listbase->first)->prev = link; - } - if (listbase->last == NULL) { - listbase->last = link; - } - listbase->first = link; + if (listbase->first) { + ((Link *)listbase->first)->prev = link; + } + if (listbase->last == NULL) { + listbase->last = link; + } + listbase->first = link; } - /** * Appends \a vlink (assumed to begin with a Link) onto listbase. */ void BLI_addtail(ListBase *listbase, void *vlink) { - Link *link = vlink; + Link *link = vlink; - if (link == NULL) { - return; - } + if (link == NULL) { + return; + } - link->next = NULL; - link->prev = listbase->last; + link->next = NULL; + link->prev = listbase->last; - if (listbase->last) { - ((Link *)listbase->last)->next = link; - } - if (listbase->first == NULL) { - listbase->first = link; - } - listbase->last = link; + if (listbase->last) { + ((Link *)listbase->last)->next = link; + } + if (listbase->first == NULL) { + listbase->first = link; + } + listbase->last = link; } - /** * Removes \a vlink from \a listbase. Assumes it is linked into there! */ void BLI_remlink(ListBase *listbase, void *vlink) { - Link *link = vlink; + Link *link = vlink; - if (link == NULL) { - return; - } + if (link == NULL) { + return; + } - if (link->next) { - link->next->prev = link->prev; - } - if (link->prev) { - link->prev->next = link->next; - } + if (link->next) { + link->next->prev = link->prev; + } + if (link->prev) { + link->prev->next = link->next; + } - if (listbase->last == link) { - listbase->last = link->prev; - } - if (listbase->first == link) { - listbase->first = link->next; - } + if (listbase->last == link) { + listbase->last = link->prev; + } + if (listbase->first == link) { + listbase->first = link->next; + } } /** @@ -161,13 +158,13 @@ void BLI_remlink(ListBase *listbase, void *vlink) */ bool BLI_remlink_safe(ListBase *listbase, void *vlink) { - if (BLI_findindex(listbase, vlink) != -1) { - BLI_remlink(listbase, vlink); - return true; - } - else { - return false; - } + if (BLI_findindex(listbase, vlink) != -1) { + BLI_remlink(listbase, vlink); + return true; + } + else { + return false; + } } /** @@ -175,55 +172,55 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink) */ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) { - Link *linka = vlinka; - Link *linkb = vlinkb; - - if (!linka || !linkb) { - return; - } - - if (linkb->next == linka) { - SWAP(Link *, linka, linkb); - } - - if (linka->next == linkb) { - linka->next = linkb->next; - linkb->prev = linka->prev; - linka->prev = linkb; - linkb->next = linka; - } - else { /* Non-contiguous items, we can safely swap. */ - SWAP(Link *, linka->prev, linkb->prev); - SWAP(Link *, linka->next, linkb->next); - } - - /* Update neighbors of linka and linkb. */ - if (linka->prev) { - linka->prev->next = linka; - } - if (linka->next) { - linka->next->prev = linka; - } - if (linkb->prev) { - linkb->prev->next = linkb; - } - if (linkb->next) { - linkb->next->prev = linkb; - } - - if (listbase->last == linka) { - listbase->last = linkb; - } - else if (listbase->last == linkb) { - listbase->last = linka; - } - - if (listbase->first == linka) { - listbase->first = linkb; - } - else if (listbase->first == linkb) { - listbase->first = linka; - } + Link *linka = vlinka; + Link *linkb = vlinkb; + + if (!linka || !linkb) { + return; + } + + if (linkb->next == linka) { + SWAP(Link *, linka, linkb); + } + + if (linka->next == linkb) { + linka->next = linkb->next; + linkb->prev = linka->prev; + linka->prev = linkb; + linkb->next = linka; + } + else { /* Non-contiguous items, we can safely swap. */ + SWAP(Link *, linka->prev, linkb->prev); + SWAP(Link *, linka->next, linkb->next); + } + + /* Update neighbors of linka and linkb. */ + if (linka->prev) { + linka->prev->next = linka; + } + if (linka->next) { + linka->next->prev = linka; + } + if (linkb->prev) { + linkb->prev->next = linkb; + } + if (linkb->next) { + linkb->next->prev = linkb; + } + + if (listbase->last == linka) { + listbase->last = linkb; + } + else if (listbase->last == linkb) { + listbase->last = linka; + } + + if (listbase->first == linka) { + listbase->first = linkb; + } + else if (listbase->first == linkb) { + listbase->first = linka; + } } /** @@ -231,27 +228,27 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) */ void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb) { - Link *linka = vlinka; - Link *linkb = vlinkb; - Link linkc = {NULL}; + Link *linka = vlinka; + Link *linkb = vlinkb; + Link linkc = {NULL}; - if (!linka || !linkb) { - return; - } + if (!linka || !linkb) { + return; + } - /* Temporary link to use as placeholder of the links positions */ - BLI_insertlinkafter(listbasea, linka, &linkc); + /* Temporary link to use as placeholder of the links positions */ + BLI_insertlinkafter(listbasea, linka, &linkc); - /* Bring linka into linkb position */ - BLI_remlink(listbasea, linka); - BLI_insertlinkafter(listbaseb, linkb, linka); + /* Bring linka into linkb position */ + BLI_remlink(listbasea, linka); + BLI_insertlinkafter(listbaseb, linkb, linka); - /* Bring linkb into linka position */ - BLI_remlink(listbaseb, linkb); - BLI_insertlinkafter(listbasea, &linkc, linkb); + /* Bring linkb into linka position */ + BLI_remlink(listbaseb, linkb); + BLI_insertlinkafter(listbasea, &linkc, linkb); - /* Remove temporary link */ - BLI_remlink(listbasea, &linkc); + /* Remove temporary link */ + BLI_remlink(listbasea, &linkc); } /** @@ -259,24 +256,23 @@ void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vli */ void *BLI_pophead(ListBase *listbase) { - Link *link; - if ((link = listbase->first)) { - BLI_remlink(listbase, link); - } - return link; + Link *link; + if ((link = listbase->first)) { + BLI_remlink(listbase, link); + } + return link; } - /** * Removes the tail from \a listbase and returns it. */ void *BLI_poptail(ListBase *listbase) { - Link *link; - if ((link = listbase->last)) { - BLI_remlink(listbase, link); - } - return link; + Link *link; + if ((link = listbase->last)) { + BLI_remlink(listbase, link); + } + return link; } /** @@ -284,14 +280,14 @@ void *BLI_poptail(ListBase *listbase) */ void BLI_freelinkN(ListBase *listbase, void *vlink) { - Link *link = vlink; + Link *link = vlink; - if (link == NULL) { - return; - } + if (link == NULL) { + return; + } - BLI_remlink(listbase, link); - MEM_freeN(link); + BLI_remlink(listbase, link); + MEM_freeN(link); } /** @@ -299,13 +295,13 @@ void BLI_freelinkN(ListBase *listbase, void *vlink) */ static void listbase_double_from_single(Link *iter, ListBase *listbase) { - Link *prev = NULL; - listbase->first = iter; - do { - iter->prev = prev; - prev = iter; - } while ((iter = iter->next)); - listbase->last = prev; + Link *prev = NULL; + listbase->first = iter; + do { + iter->prev = prev; + prev = iter; + } while ((iter = iter->next)); + listbase->last = prev; } #define SORT_IMPL_LINKTYPE Link @@ -331,20 +327,22 @@ static void listbase_double_from_single(Link *iter, ListBase *listbase) */ void BLI_listbase_sort(ListBase *listbase, int (*cmp)(const void *, const void *)) { - if (listbase->first != listbase->last) { - Link *head = listbase->first; - head = listbase_sort_fn(head, cmp); - listbase_double_from_single(head, listbase); - } + if (listbase->first != listbase->last) { + Link *head = listbase->first; + head = listbase_sort_fn(head, cmp); + listbase_double_from_single(head, listbase); + } } -void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) +void BLI_listbase_sort_r(ListBase *listbase, + int (*cmp)(void *, const void *, const void *), + void *thunk) { - if (listbase->first != listbase->last) { - Link *head = listbase->first; - head = listbase_sort_fn_r(head, cmp, thunk); - listbase_double_from_single(head, listbase); - } + if (listbase->first != listbase->last) { + Link *head = listbase->first; + head = listbase_sort_fn_r(head, cmp, thunk); + listbase_double_from_single(head, listbase); + } } /** @@ -353,41 +351,41 @@ void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, co */ void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) { - Link *prevlink = vprevlink; - Link *newlink = vnewlink; + Link *prevlink = vprevlink; + Link *newlink = vnewlink; - /* newlink before nextlink */ - if (newlink == NULL) { - return; - } + /* newlink before nextlink */ + if (newlink == NULL) { + return; + } - /* empty list */ - if (listbase->first == NULL) { - listbase->first = newlink; - listbase->last = newlink; - return; - } + /* empty list */ + if (listbase->first == NULL) { + listbase->first = newlink; + listbase->last = newlink; + return; + } - /* insert at head of list */ - if (prevlink == NULL) { - newlink->prev = NULL; - newlink->next = listbase->first; - newlink->next->prev = newlink; - listbase->first = newlink; - return; - } + /* insert at head of list */ + if (prevlink == NULL) { + newlink->prev = NULL; + newlink->next = listbase->first; + newlink->next->prev = newlink; + listbase->first = newlink; + return; + } - /* at end of list */ - if (listbase->last == prevlink) { - listbase->last = newlink; - } + /* at end of list */ + if (listbase->last == prevlink) { + listbase->last = newlink; + } - newlink->next = prevlink->next; - newlink->prev = prevlink; - prevlink->next = newlink; - if (newlink->next) { - newlink->next->prev = newlink; - } + newlink->next = prevlink->next; + newlink->prev = prevlink; + prevlink->next = newlink; + if (newlink->next) { + newlink->next->prev = newlink; + } } /** @@ -396,44 +394,43 @@ void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) */ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) { - Link *nextlink = vnextlink; - Link *newlink = vnewlink; + Link *nextlink = vnextlink; + Link *newlink = vnewlink; - /* newlink before nextlink */ - if (newlink == NULL) { - return; - } + /* newlink before nextlink */ + if (newlink == NULL) { + return; + } - /* empty list */ - if (listbase->first == NULL) { - listbase->first = newlink; - listbase->last = newlink; - return; - } + /* empty list */ + if (listbase->first == NULL) { + listbase->first = newlink; + listbase->last = newlink; + return; + } - /* insert at end of list */ - if (nextlink == NULL) { - newlink->prev = listbase->last; - newlink->next = NULL; - ((Link *)listbase->last)->next = newlink; - listbase->last = newlink; - return; - } + /* insert at end of list */ + if (nextlink == NULL) { + newlink->prev = listbase->last; + newlink->next = NULL; + ((Link *)listbase->last)->next = newlink; + listbase->last = newlink; + return; + } - /* at beginning of list */ - if (listbase->first == nextlink) { - listbase->first = newlink; - } + /* at beginning of list */ + if (listbase->first == nextlink) { + listbase->first = newlink; + } - newlink->next = nextlink; - newlink->prev = nextlink->prev; - nextlink->prev = newlink; - if (newlink->prev) { - newlink->prev->next = newlink; - } + newlink->next = nextlink; + newlink->prev = nextlink->prev; + nextlink->prev = newlink; + if (newlink->prev) { + newlink->prev->next = newlink; + } } - /** * Insert a link in place of another, without changing it's position in the list. * @@ -443,28 +440,28 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) */ void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink) { - Link *l_old = vreplacelink; - Link *l_new = vnewlink; + Link *l_old = vreplacelink; + Link *l_new = vnewlink; - /* update adjacent links */ - if (l_old->next != NULL) { - l_old->next->prev = l_new; - } - if (l_old->prev != NULL) { - l_old->prev->next = l_new; - } + /* update adjacent links */ + if (l_old->next != NULL) { + l_old->next->prev = l_new; + } + if (l_old->prev != NULL) { + l_old->prev->next = l_new; + } - /* set direct links */ - l_new->next = l_old->next; - l_new->prev = l_old->prev; + /* set direct links */ + l_new->next = l_old->next; + l_new->prev = l_old->prev; - /* update list */ - if (listbase->first == l_old) { - listbase->first = l_new; - } - if (listbase->last == l_old) { - listbase->last = l_new; - } + /* update list */ + if (listbase->first == l_old) { + listbase->first = l_new; + } + if (listbase->last == l_old) { + listbase->last = l_new; + } } /** @@ -477,50 +474,49 @@ void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlin */ bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) { - Link *link = vlink; - Link *hook = link; - const bool is_up = step < 0; + Link *link = vlink; + Link *hook = link; + const bool is_up = step < 0; - if (step == 0) { - return false; - } - BLI_assert(BLI_findindex(listbase, link) != -1); + if (step == 0) { + return false; + } + BLI_assert(BLI_findindex(listbase, link) != -1); - /* find link to insert before/after */ - for (int i = 0; i < ABS(step); i++) { - hook = is_up ? hook->prev : hook->next; - if (!hook) { - return false; - } - } + /* find link to insert before/after */ + for (int i = 0; i < ABS(step); i++) { + hook = is_up ? hook->prev : hook->next; + if (!hook) { + return false; + } + } - /* reinsert link */ - BLI_remlink(listbase, vlink); - if (is_up) { - BLI_insertlinkbefore(listbase, hook, vlink); - } - else { - BLI_insertlinkafter(listbase, hook, vlink); - } - return true; + /* reinsert link */ + BLI_remlink(listbase, vlink); + if (is_up) { + BLI_insertlinkbefore(listbase, hook, vlink); + } + else { + BLI_insertlinkafter(listbase, hook, vlink); + } + return true; } - /** * Removes and disposes of the entire contents of listbase using direct free(3). */ void BLI_freelist(ListBase *listbase) { - Link *link, *next; + Link *link, *next; - link = listbase->first; - while (link) { - next = link->next; - free(link); - link = next; - } + link = listbase->first; + while (link) { + next = link->next; + free(link); + link = next; + } - BLI_listbase_clear(listbase); + BLI_listbase_clear(listbase); } /** @@ -528,16 +524,16 @@ void BLI_freelist(ListBase *listbase) */ void BLI_freelistN(ListBase *listbase) { - Link *link, *next; + Link *link, *next; - link = listbase->first; - while (link) { - next = link->next; - MEM_freeN(link); - link = next; - } + link = listbase->first; + while (link) { + next = link->next; + MEM_freeN(link); + link = next; + } - BLI_listbase_clear(listbase); + BLI_listbase_clear(listbase); } /** @@ -547,14 +543,14 @@ void BLI_freelistN(ListBase *listbase) */ int BLI_listbase_count_at_most(const ListBase *listbase, const int count_max) { - Link *link; - int count = 0; + Link *link; + int count = 0; - for (link = listbase->first; link && count != count_max; link = link->next) { - count++; - } + for (link = listbase->first; link && count != count_max; link = link->next) { + count++; + } - return count; + return count; } /** @@ -562,14 +558,14 @@ int BLI_listbase_count_at_most(const ListBase *listbase, const int count_max) */ int BLI_listbase_count(const ListBase *listbase) { - Link *link; - int count = 0; + Link *link; + int count = 0; - for (link = listbase->first; link; link = link->next) { - count++; - } + for (link = listbase->first; link; link = link->next) { + count++; + } - return count; + return count; } /** @@ -577,17 +573,17 @@ int BLI_listbase_count(const ListBase *listbase) */ void *BLI_findlink(const ListBase *listbase, int number) { - Link *link = NULL; + Link *link = NULL; - if (number >= 0) { - link = listbase->first; - while (link != NULL && number != 0) { - number--; - link = link->next; - } - } + if (number >= 0) { + link = listbase->first; + while (link != NULL && number != 0) { + number--; + link = link->next; + } + } - return link; + return link; } /** @@ -595,17 +591,17 @@ void *BLI_findlink(const ListBase *listbase, int number) */ void *BLI_rfindlink(const ListBase *listbase, int number) { - Link *link = NULL; + Link *link = NULL; - if (number >= 0) { - link = listbase->last; - while (link != NULL && number != 0) { - number--; - link = link->prev; - } - } + if (number >= 0) { + link = listbase->last; + while (link != NULL && number != 0) { + number--; + link = link->prev; + } + } - return link; + return link; } /** @@ -613,24 +609,24 @@ void *BLI_rfindlink(const ListBase *listbase, int number) */ int BLI_findindex(const ListBase *listbase, const void *vlink) { - Link *link = NULL; - int number = 0; + Link *link = NULL; + int number = 0; - if (vlink == NULL) { - return -1; - } + if (vlink == NULL) { + return -1; + } - link = listbase->first; - while (link) { - if (link == vlink) { - return number; - } + link = listbase->first; + while (link) { + if (link == vlink) { + return number; + } - number++; - link = link->next; - } + number++; + link = link->next; + } - return -1; + return -1; } /** @@ -639,22 +635,22 @@ int BLI_findindex(const ListBase *listbase, const void *vlink) */ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset) { - Link *link = NULL; - const char *id_iter; + Link *link = NULL; + const char *id_iter; - if (id == NULL) { - return NULL; - } + if (id == NULL) { + return NULL; + } - for (link = listbase->first; link; link = link->next) { - id_iter = ((const char *)link) + offset; + for (link = listbase->first; link; link = link->next) { + id_iter = ((const char *)link) + offset; - if (id[0] == id_iter[0] && STREQ(id, id_iter)) { - return link; - } - } + if (id[0] == id_iter[0] && STREQ(id, id_iter)) { + return link; + } + } - return NULL; + return NULL; } /* same as above but find reverse */ /** @@ -663,18 +659,18 @@ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset) */ void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset) { - Link *link = NULL; - const char *id_iter; + Link *link = NULL; + const char *id_iter; - for (link = listbase->last; link; link = link->prev) { - id_iter = ((const char *)link) + offset; + for (link = listbase->last; link; link = link->prev) { + id_iter = ((const char *)link) + offset; - if (id[0] == id_iter[0] && STREQ(id, id_iter)) { - return link; - } - } + if (id[0] == id_iter[0] && STREQ(id, id_iter)) { + return link; + } + } - return NULL; + return NULL; } /** @@ -683,19 +679,19 @@ void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset */ void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset) { - Link *link = NULL; - const char *id_iter; + Link *link = NULL; + const char *id_iter; - for (link = listbase->first; link; link = link->next) { - /* exact copy of BLI_findstring(), except for this line */ - id_iter = *((const char **)(((const char *)link) + offset)); + for (link = listbase->first; link; link = link->next) { + /* exact copy of BLI_findstring(), except for this line */ + id_iter = *((const char **)(((const char *)link) + offset)); - if (id[0] == id_iter[0] && STREQ(id, id_iter)) { - return link; - } - } + if (id[0] == id_iter[0] && STREQ(id, id_iter)) { + return link; + } + } - return NULL; + return NULL; } /* same as above but find reverse */ /** @@ -704,19 +700,19 @@ void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int off */ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int offset) { - Link *link = NULL; - const char *id_iter; + Link *link = NULL; + const char *id_iter; - for (link = listbase->last; link; link = link->prev) { - /* exact copy of BLI_rfindstring(), except for this line */ - id_iter = *((const char **)(((const char *)link) + offset)); + for (link = listbase->last; link; link = link->prev) { + /* exact copy of BLI_rfindstring(), except for this line */ + id_iter = *((const char **)(((const char *)link) + offset)); - if (id[0] == id_iter[0] && STREQ(id, id_iter)) { - return link; - } - } + if (id[0] == id_iter[0] && STREQ(id, id_iter)) { + return link; + } + } - return NULL; + return NULL; } /** @@ -725,19 +721,19 @@ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int of */ void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset) { - Link *link = NULL; - const void *ptr_iter; + Link *link = NULL; + const void *ptr_iter; - for (link = listbase->first; link; link = link->next) { - /* exact copy of BLI_findstring(), except for this line */ - ptr_iter = *((const void **)(((const char *)link) + offset)); + for (link = listbase->first; link; link = link->next) { + /* exact copy of BLI_findstring(), except for this line */ + ptr_iter = *((const void **)(((const char *)link) + offset)); - if (ptr == ptr_iter) { - return link; - } - } + if (ptr == ptr_iter) { + return link; + } + } - return NULL; + return NULL; } /* same as above but find reverse */ /** @@ -746,59 +742,65 @@ void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset) */ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset) { - Link *link = NULL; - const void *ptr_iter; + Link *link = NULL; + const void *ptr_iter; - for (link = listbase->last; link; link = link->prev) { - /* exact copy of BLI_rfindstring(), except for this line */ - ptr_iter = *((const void **)(((const char *)link) + offset)); + for (link = listbase->last; link; link = link->prev) { + /* exact copy of BLI_rfindstring(), except for this line */ + ptr_iter = *((const void **)(((const char *)link) + offset)); - if (ptr == ptr_iter) { - return link; - } - } + if (ptr == ptr_iter) { + return link; + } + } - return NULL; + return NULL; } /** * Finds the first element of listbase which contains the specified bytes * at the specified offset, returning NULL if not found. */ -void *BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) +void *BLI_listbase_bytes_find(const ListBase *listbase, + const void *bytes, + const size_t bytes_size, + const int offset) { - Link *link = NULL; - const void *ptr_iter; + Link *link = NULL; + const void *ptr_iter; - for (link = listbase->first; link; link = link->next) { - ptr_iter = (const void *)(((const char *)link) + offset); + for (link = listbase->first; link; link = link->next) { + ptr_iter = (const void *)(((const char *)link) + offset); - if (memcmp(bytes, ptr_iter, bytes_size) == 0) { - return link; - } - } + if (memcmp(bytes, ptr_iter, bytes_size) == 0) { + return link; + } + } - return NULL; + return NULL; } /* same as above but find reverse */ /** * Finds the last element of listbase which contains the specified bytes * at the specified offset, returning NULL if not found. */ -void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) +void *BLI_listbase_bytes_rfind(const ListBase *listbase, + const void *bytes, + const size_t bytes_size, + const int offset) { - Link *link = NULL; - const void *ptr_iter; + Link *link = NULL; + const void *ptr_iter; - for (link = listbase->last; link; link = link->prev) { - ptr_iter = (const void *)(((const char *)link) + offset); + for (link = listbase->last; link; link = link->prev) { + ptr_iter = (const void *)(((const char *)link) + offset); - if (memcmp(bytes, ptr_iter, bytes_size) == 0) { - return link; - } - } + if (memcmp(bytes, ptr_iter, bytes_size) == 0) { + return link; + } + } - return NULL; + return NULL; } /** @@ -807,22 +809,22 @@ void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, cons */ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset) { - Link *link = NULL; - const char *id_iter; - int i = 0; + Link *link = NULL; + const char *id_iter; + int i = 0; - link = listbase->first; - while (link) { - id_iter = ((const char *)link) + offset; + link = listbase->first; + while (link) { + id_iter = ((const char *)link) + offset; - if (id[0] == id_iter[0] && STREQ(id, id_iter)) { - return i; - } - i++; - link = link->next; - } + if (id[0] == id_iter[0] && STREQ(id, id_iter)) { + return i; + } + i++; + link = link->next; + } - return -1; + return -1; } /** @@ -830,37 +832,37 @@ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offs */ void BLI_duplicatelist(ListBase *dst, const ListBase *src) { - struct Link *dst_link, *src_link; + struct Link *dst_link, *src_link; - /* in this order, to ensure it works if dst == src */ - src_link = src->first; - dst->first = dst->last = NULL; + /* in this order, to ensure it works if dst == src */ + src_link = src->first; + dst->first = dst->last = NULL; - while (src_link) { - dst_link = MEM_dupallocN(src_link); - BLI_addtail(dst, dst_link); + while (src_link) { + dst_link = MEM_dupallocN(src_link); + BLI_addtail(dst, dst_link); - src_link = src_link->next; - } + src_link = src_link->next; + } } void BLI_listbase_reverse(ListBase *lb) { - struct Link *curr = lb->first; - struct Link *prev = NULL; - struct Link *next = NULL; - while (curr) { - next = curr->next; - curr->next = prev; - curr->prev = next; - prev = curr; - curr = next; - } + struct Link *curr = lb->first; + struct Link *prev = NULL; + struct Link *next = NULL; + while (curr) { + next = curr->next; + curr->next = prev; + curr->prev = next; + prev = curr; + curr = next; + } - /* swap first/last */ - curr = lb->first; - lb->first = lb->last; - lb->last = curr; + /* swap first/last */ + curr = lb->first; + lb->first = lb->last; + lb->last = curr; } /** @@ -868,15 +870,15 @@ void BLI_listbase_reverse(ListBase *lb) */ void BLI_listbase_rotate_first(ListBase *lb, void *vlink) { - /* make circular */ - ((Link *)lb->first)->prev = lb->last; - ((Link *)lb->last)->next = lb->first; + /* make circular */ + ((Link *)lb->first)->prev = lb->last; + ((Link *)lb->last)->next = lb->first; - lb->first = vlink; - lb->last = ((Link *)vlink)->prev; + lb->first = vlink; + lb->last = ((Link *)vlink)->prev; - ((Link *)lb->first)->prev = NULL; - ((Link *)lb->last)->next = NULL; + ((Link *)lb->first)->prev = NULL; + ((Link *)lb->last)->next = NULL; } /** @@ -884,29 +886,29 @@ void BLI_listbase_rotate_first(ListBase *lb, void *vlink) */ void BLI_listbase_rotate_last(ListBase *lb, void *vlink) { - /* make circular */ - ((Link *)lb->first)->prev = lb->last; - ((Link *)lb->last)->next = lb->first; + /* make circular */ + ((Link *)lb->first)->prev = lb->last; + ((Link *)lb->last)->next = lb->first; - lb->first = ((Link *)vlink)->next; - lb->last = vlink; + lb->first = ((Link *)vlink)->next; + lb->last = vlink; - ((Link *)lb->first)->prev = NULL; - ((Link *)lb->last)->next = NULL; + ((Link *)lb->first)->prev = NULL; + ((Link *)lb->last)->next = NULL; } /* create a generic list node containing link to provided data */ LinkData *BLI_genericNodeN(void *data) { - LinkData *ld; + LinkData *ld; - if (data == NULL) { - return NULL; - } + if (data == NULL) { + return NULL; + } - /* create new link, and make it hold the given data */ - ld = MEM_callocN(sizeof(LinkData), __func__); - ld->data = data; + /* create new link, and make it hold the given data */ + ld = MEM_callocN(sizeof(LinkData), __func__); + ld->data = data; - return ld; + return ld; } diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index ed75cac2d0c..30267661ae7 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -30,52 +30,52 @@ int pow_i(int base, int exp) { - int result = 1; - BLI_assert(exp >= 0); - while (exp) { - if (exp & 1) { - result *= base; - } - exp >>= 1; - base *= base; - } + int result = 1; + BLI_assert(exp >= 0); + while (exp) { + if (exp & 1) { + result *= base; + } + exp >>= 1; + base *= base; + } - return result; + return result; } /* from python 3.1 floatobject.c * ndigits must be between 0 and 21 */ double double_round(double x, int ndigits) { - double pow1, pow2, y, z; - if (ndigits >= 0) { - pow1 = pow(10.0, (double)ndigits); - pow2 = 1.0; - y = (x * pow1) * pow2; - /* if y overflows, then rounded value is exactly x */ - if (!isfinite(y)) { - return x; - } - } - else { - pow1 = pow(10.0, (double)-ndigits); - pow2 = 1.0; /* unused; silences a gcc compiler warning */ - y = x / pow1; - } + double pow1, pow2, y, z; + if (ndigits >= 0) { + pow1 = pow(10.0, (double)ndigits); + pow2 = 1.0; + y = (x * pow1) * pow2; + /* if y overflows, then rounded value is exactly x */ + if (!isfinite(y)) { + return x; + } + } + else { + pow1 = pow(10.0, (double)-ndigits); + pow2 = 1.0; /* unused; silences a gcc compiler warning */ + y = x / pow1; + } - z = round(y); - if (fabs(y - z) == 0.5) { - /* halfway between two integers; use round-half-even */ - z = 2.0 * round(y / 2.0); - } + z = round(y); + if (fabs(y - z) == 0.5) { + /* halfway between two integers; use round-half-even */ + z = 2.0 * round(y / 2.0); + } - if (ndigits >= 0) { - z = (z / pow2) / pow1; - } - else { - z *= pow1; - } + if (ndigits >= 0) { + z = (z / pow2) / pow1; + } + else { + z *= pow1; + } - /* if computation resulted in overflow, raise OverflowError */ - return z; + /* if computation resulted in overflow, raise OverflowError */ + return z; } diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index b8a5a138eb4..f1ceaca4eb1 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -40,196 +40,269 @@ /* copied from BLI_utildefines.h */ #ifdef __GNUC__ -# define UNLIKELY(x) __builtin_expect(!!(x), 0) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) #else -# define UNLIKELY(x) (x) +# define UNLIKELY(x) (x) #endif /* powf is really slow for raising to integer powers. */ MINLINE float pow2f(float x) { - return x * x; + return x * x; } MINLINE float pow3f(float x) { - return pow2f(x) * x; + return pow2f(x) * x; } MINLINE float pow4f(float x) { - return pow2f(pow2f(x)); + return pow2f(pow2f(x)); } MINLINE float pow7f(float x) { - return pow2f(pow3f(x)) * x; + return pow2f(pow3f(x)) * x; } MINLINE float sqrt3f(float f) { - if (UNLIKELY(f == 0.0f)) { return 0.0f; } - else if (UNLIKELY(f < 0.0f)) { return -(float)(exp(log(-f) / 3.0)); } - else { return (float)(exp(log( f) / 3.0)); } + if (UNLIKELY(f == 0.0f)) { + return 0.0f; + } + else if (UNLIKELY(f < 0.0f)) { + return -(float)(exp(log(-f) / 3.0)); + } + else { + return (float)(exp(log(f) / 3.0)); + } } MINLINE double sqrt3d(double d) { - if (UNLIKELY(d == 0.0)) { return 0.0; } - else if (UNLIKELY(d < 0.0)) { return -exp(log(-d) / 3.0); } - else { return exp(log( d) / 3.0); } + if (UNLIKELY(d == 0.0)) { + return 0.0; + } + else if (UNLIKELY(d < 0.0)) { + return -exp(log(-d) / 3.0); + } + else { + return exp(log(d) / 3.0); + } } MINLINE float sqrtf_signed(float f) { - return (f >= 0.0f) ? sqrtf(f) : -sqrtf(-f); + return (f >= 0.0f) ? sqrtf(f) : -sqrtf(-f); } MINLINE float saacos(float fac) { - if (UNLIKELY(fac <= -1.0f)) { return (float)M_PI; } - else if (UNLIKELY(fac >= 1.0f)) { return 0.0f; } - else { return acosf(fac); } + if (UNLIKELY(fac <= -1.0f)) { + return (float)M_PI; + } + else if (UNLIKELY(fac >= 1.0f)) { + return 0.0f; + } + else { + return acosf(fac); + } } MINLINE float saasin(float fac) { - if (UNLIKELY(fac <= -1.0f)) { return (float)-M_PI / 2.0f; } - else if (UNLIKELY(fac >= 1.0f)) { return (float) M_PI / 2.0f; } - else { return asinf(fac); } + if (UNLIKELY(fac <= -1.0f)) { + return (float)-M_PI / 2.0f; + } + else if (UNLIKELY(fac >= 1.0f)) { + return (float)M_PI / 2.0f; + } + else { + return asinf(fac); + } } MINLINE float sasqrt(float fac) { - if (UNLIKELY(fac <= 0.0f)) { return 0.0f; } - else { return sqrtf(fac); } + if (UNLIKELY(fac <= 0.0f)) { + return 0.0f; + } + else { + return sqrtf(fac); + } } MINLINE float saacosf(float fac) { - if (UNLIKELY(fac <= -1.0f)) { return (float)M_PI; } - else if (UNLIKELY(fac >= 1.0f)) { return 0.0f; } - else { return acosf(fac); } + if (UNLIKELY(fac <= -1.0f)) { + return (float)M_PI; + } + else if (UNLIKELY(fac >= 1.0f)) { + return 0.0f; + } + else { + return acosf(fac); + } } MINLINE float saasinf(float fac) { - if (UNLIKELY(fac <= -1.0f)) { return (float)-M_PI / 2.0f; } - else if (UNLIKELY(fac >= 1.0f)) { return (float) M_PI / 2.0f; } - else { return asinf(fac); } + if (UNLIKELY(fac <= -1.0f)) { + return (float)-M_PI / 2.0f; + } + else if (UNLIKELY(fac >= 1.0f)) { + return (float)M_PI / 2.0f; + } + else { + return asinf(fac); + } } MINLINE float sasqrtf(float fac) { - if (UNLIKELY(fac <= 0.0f)) { return 0.0f; } - else { return sqrtf(fac); } + if (UNLIKELY(fac <= 0.0f)) { + return 0.0f; + } + else { + return sqrtf(fac); + } } MINLINE float interpf(float target, float origin, float fac) { - return (fac * target) + (1.0f - fac) * origin; + return (fac * target) + (1.0f - fac) * origin; } /* used for zoom values*/ MINLINE float power_of_2(float val) { - return (float)pow(2.0, ceil(log((double)val) / M_LN2)); + return (float)pow(2.0, ceil(log((double)val) / M_LN2)); } MINLINE int is_power_of_2_i(int n) { - return (n & (n - 1)) == 0; + return (n & (n - 1)) == 0; } MINLINE int power_of_2_max_i(int n) { - if (is_power_of_2_i(n)) { - return n; - } + if (is_power_of_2_i(n)) { + return n; + } - do { - n = n & (n - 1); - } while (!is_power_of_2_i(n)); + do { + n = n & (n - 1); + } while (!is_power_of_2_i(n)); - return n * 2; + return n * 2; } MINLINE int power_of_2_min_i(int n) { - while (!is_power_of_2_i(n)) { - n = n & (n - 1); - } + while (!is_power_of_2_i(n)) { + n = n & (n - 1); + } - return n; + return n; } MINLINE unsigned int power_of_2_max_u(unsigned int x) { - x -= 1; - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return x + 1; + x -= 1; + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x + 1; } MINLINE unsigned power_of_2_min_u(unsigned x) { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return x - (x >> 1); + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x - (x >> 1); } /* rounding and clamping */ -#define _round_clamp_fl_impl(arg, ty, min, max) { \ - float r = floorf(arg + 0.5f); \ - if (UNLIKELY(r <= (float)min)) return (ty)min; \ - else if (UNLIKELY(r >= (float)max)) return (ty)max; \ - else return (ty)r; \ +#define _round_clamp_fl_impl(arg, ty, min, max) \ + { \ + float r = floorf(arg + 0.5f); \ + if (UNLIKELY(r <= (float)min)) \ + return (ty)min; \ + else if (UNLIKELY(r >= (float)max)) \ + return (ty)max; \ + else \ + return (ty)r; \ + } + +#define _round_clamp_db_impl(arg, ty, min, max) \ + { \ + double r = floor(arg + 0.5); \ + if (UNLIKELY(r <= (double)min)) \ + return (ty)min; \ + else if (UNLIKELY(r >= (double)max)) \ + return (ty)max; \ + else \ + return (ty)r; \ + } + +#define _round_fl_impl(arg, ty) \ + { \ + return (ty)floorf(arg + 0.5f); \ + } +#define _round_db_impl(arg, ty) \ + { \ + return (ty)floor(arg + 0.5); \ + } + +MINLINE signed char round_fl_to_char(float a){_round_fl_impl(a, signed char)} MINLINE + unsigned char round_fl_to_uchar(float a){_round_fl_impl(a, unsigned char)} MINLINE + short round_fl_to_short(float a){_round_fl_impl(a, short)} MINLINE + unsigned short round_fl_to_ushort(float a){_round_fl_impl(a, unsigned short)} MINLINE + int round_fl_to_int(float a){_round_fl_impl(a, int)} MINLINE + unsigned int round_fl_to_uint(float a){_round_fl_impl(a, unsigned int)} + +MINLINE signed char round_db_to_char(double a){_round_db_impl(a, signed char)} MINLINE + unsigned char round_db_to_uchar(double a){_round_db_impl(a, unsigned char)} MINLINE + short round_db_to_short(double a){_round_db_impl(a, short)} MINLINE + unsigned short round_db_to_ushort(double a){_round_db_impl(a, unsigned short)} MINLINE + int round_db_to_int(double a){_round_db_impl(a, int)} MINLINE + unsigned int round_db_to_uint(double a) +{ + _round_db_impl(a, unsigned int) } -#define _round_clamp_db_impl(arg, ty, min, max) { \ - double r = floor(arg + 0.5); \ - if (UNLIKELY(r <= (double)min)) return (ty)min; \ - else if (UNLIKELY(r >= (double)max)) return (ty)max; \ - else return (ty)r; \ -} - -#define _round_fl_impl(arg, ty) { return (ty)floorf(arg + 0.5f); } -#define _round_db_impl(arg, ty) { return (ty)floor(arg + 0.5); } - -MINLINE signed char round_fl_to_char(float a) { _round_fl_impl(a, signed char) } -MINLINE unsigned char round_fl_to_uchar(float a) { _round_fl_impl(a, unsigned char) } -MINLINE short round_fl_to_short(float a) { _round_fl_impl(a, short) } -MINLINE unsigned short round_fl_to_ushort(float a) { _round_fl_impl(a, unsigned short) } -MINLINE int round_fl_to_int(float a) { _round_fl_impl(a, int) } -MINLINE unsigned int round_fl_to_uint(float a) { _round_fl_impl(a, unsigned int) } - -MINLINE signed char round_db_to_char(double a) { _round_db_impl(a, signed char) } -MINLINE unsigned char round_db_to_uchar(double a) { _round_db_impl(a, unsigned char) } -MINLINE short round_db_to_short(double a) { _round_db_impl(a, short) } -MINLINE unsigned short round_db_to_ushort(double a) { _round_db_impl(a, unsigned short) } -MINLINE int round_db_to_int(double a) { _round_db_impl(a, int) } -MINLINE unsigned int round_db_to_uint(double a) { _round_db_impl(a, unsigned int) } - #undef _round_fl_impl #undef _round_db_impl -MINLINE signed char round_fl_to_char_clamp(float a) { _round_clamp_fl_impl(a, signed char, SCHAR_MIN, SCHAR_MAX) } -MINLINE unsigned char round_fl_to_uchar_clamp(float a) { _round_clamp_fl_impl(a, unsigned char, 0, UCHAR_MAX) } -MINLINE short round_fl_to_short_clamp(float a) { _round_clamp_fl_impl(a, short, SHRT_MIN, SHRT_MAX) } -MINLINE unsigned short round_fl_to_ushort_clamp(float a) { _round_clamp_fl_impl(a, unsigned short, 0, USHRT_MAX) } -MINLINE int round_fl_to_int_clamp(float a) { _round_clamp_fl_impl(a, int, INT_MIN, INT_MAX) } -MINLINE unsigned int round_fl_to_uint_clamp(float a) { _round_clamp_fl_impl(a, unsigned int, 0, UINT_MAX) } - -MINLINE signed char round_db_to_char_clamp(double a) { _round_clamp_db_impl(a, signed char, SCHAR_MIN, SCHAR_MAX) } -MINLINE unsigned char round_db_to_uchar_clamp(double a) { _round_clamp_db_impl(a, unsigned char, 0, UCHAR_MAX) } -MINLINE short round_db_to_short_clamp(double a) { _round_clamp_db_impl(a, short, SHRT_MIN, SHRT_MAX) } -MINLINE unsigned short round_db_to_ushort_clamp(double a) { _round_clamp_db_impl(a, unsigned short, 0, USHRT_MAX) } -MINLINE int round_db_to_int_clamp(double a) { _round_clamp_db_impl(a, int, INT_MIN, INT_MAX) } -MINLINE unsigned int round_db_to_uint_clamp(double a) { _round_clamp_db_impl(a, unsigned int, 0, UINT_MAX) } +MINLINE signed char round_fl_to_char_clamp(float a){ + _round_clamp_fl_impl(a, signed char, SCHAR_MIN, SCHAR_MAX)} MINLINE + unsigned char round_fl_to_uchar_clamp(float a){ + _round_clamp_fl_impl(a, unsigned char, 0, UCHAR_MAX)} MINLINE + short round_fl_to_short_clamp(float a){ + _round_clamp_fl_impl(a, short, SHRT_MIN, SHRT_MAX)} MINLINE + unsigned short round_fl_to_ushort_clamp(float a){ + _round_clamp_fl_impl(a, unsigned short, 0, USHRT_MAX)} MINLINE + int round_fl_to_int_clamp(float a){_round_clamp_fl_impl(a, int, INT_MIN, INT_MAX)} MINLINE + unsigned int round_fl_to_uint_clamp(float a){ + _round_clamp_fl_impl(a, unsigned int, 0, UINT_MAX)} + +MINLINE signed char round_db_to_char_clamp(double a){ + _round_clamp_db_impl(a, signed char, SCHAR_MIN, SCHAR_MAX)} MINLINE + unsigned char round_db_to_uchar_clamp(double a){ + _round_clamp_db_impl(a, unsigned char, 0, UCHAR_MAX)} MINLINE + short round_db_to_short_clamp(double a){ + _round_clamp_db_impl(a, short, SHRT_MIN, SHRT_MAX)} MINLINE + unsigned short round_db_to_ushort_clamp(double a){ + _round_clamp_db_impl(a, unsigned short, 0, USHRT_MAX)} MINLINE + int round_db_to_int_clamp(double a){_round_clamp_db_impl(a, int, INT_MIN, INT_MAX)} MINLINE + unsigned int round_db_to_uint_clamp(double a) +{ + _round_clamp_db_impl(a, unsigned int, 0, UINT_MAX) +} #undef _round_clamp_fl_impl #undef _round_clamp_db_impl @@ -238,7 +311,7 @@ MINLINE unsigned int round_db_to_uint_clamp(double a) { _round_clamp_db_impl(a * with integers, to avoid gradual darkening when rounding down */ MINLINE int divide_round_i(int a, int b) { - return (2 * a + b) / (2 * b); + return (2 * a + b) / (2 * b); } /** @@ -247,9 +320,9 @@ MINLINE int divide_round_i(int a, int b) */ MINLINE int divide_floor_i(int a, int b) { - int d = a / b; - int r = a % b; /* Optimizes into a single division. */ - return r ? d - ((a < 0) ^ (b < 0)) : d; + int d = a / b; + int r = a % b; /* Optimizes into a single division. */ + return r ? d - ((a < 0) ^ (b < 0)) : d; } /** @@ -257,91 +330,91 @@ MINLINE int divide_floor_i(int a, int b) */ MINLINE int mod_i(int i, int n) { - return (i % n + n) % n; + return (i % n + n) % n; } MINLINE float min_ff(float a, float b) { - return (a < b) ? a : b; + return (a < b) ? a : b; } MINLINE float max_ff(float a, float b) { - return (a > b) ? a : b; + return (a > b) ? a : b; } MINLINE int min_ii(int a, int b) { - return (a < b) ? a : b; + return (a < b) ? a : b; } MINLINE int max_ii(int a, int b) { - return (b < a) ? a : b; + return (b < a) ? a : b; } MINLINE float min_fff(float a, float b, float c) { - return min_ff(min_ff(a, b), c); + return min_ff(min_ff(a, b), c); } MINLINE float max_fff(float a, float b, float c) { - return max_ff(max_ff(a, b), c); + return max_ff(max_ff(a, b), c); } MINLINE int min_iii(int a, int b, int c) { - return min_ii(min_ii(a, b), c); + return min_ii(min_ii(a, b), c); } MINLINE int max_iii(int a, int b, int c) { - return max_ii(max_ii(a, b), c); + return max_ii(max_ii(a, b), c); } MINLINE float min_ffff(float a, float b, float c, float d) { - return min_ff(min_fff(a, b, c), d); + return min_ff(min_fff(a, b, c), d); } MINLINE float max_ffff(float a, float b, float c, float d) { - return max_ff(max_fff(a, b, c), d); + return max_ff(max_fff(a, b, c), d); } MINLINE int min_iiii(int a, int b, int c, int d) { - return min_ii(min_iii(a, b, c), d); + return min_ii(min_iii(a, b, c), d); } MINLINE int max_iiii(int a, int b, int c, int d) { - return max_ii(max_iii(a, b, c), d); + return max_ii(max_iii(a, b, c), d); } MINLINE size_t min_zz(size_t a, size_t b) { - return (a < b) ? a : b; + return (a < b) ? a : b; } MINLINE size_t max_zz(size_t a, size_t b) { - return (b < a) ? a : b; + return (b < a) ? a : b; } MINLINE int clamp_i(int value, int min, int max) { - return min_ii(max_ii(value, min), max); + return min_ii(max_ii(value, min), max); } MINLINE float clamp_f(float value, float min, float max) { - if (value > max) { - return max; - } - else if (value < min) { - return min; - } - return value; + if (value > max) { + return max; + } + else if (value < min) { + return min; + } + return value; } MINLINE size_t clamp_z(size_t value, size_t min, size_t max) { - return min_zz(max_zz(value, min), max); + return min_zz(max_zz(value, min), max); } /** @@ -351,7 +424,7 @@ MINLINE size_t clamp_z(size_t value, size_t min, size_t max) */ MINLINE int compare_ff(float a, float b, const float max_diff) { - return fabsf(a - b) <= max_diff; + return fabsf(a - b) <= max_diff; } /** @@ -365,59 +438,74 @@ MINLINE int compare_ff(float a, float b, const float max_diff) */ MINLINE int compare_ff_relative(float a, float b, const float max_diff, const int max_ulps) { - union {float f; int i;} ua, ub; + union { + float f; + int i; + } ua, ub; - BLI_assert(sizeof(float) == sizeof(int)); - BLI_assert(max_ulps < (1 << 22)); + BLI_assert(sizeof(float) == sizeof(int)); + BLI_assert(max_ulps < (1 << 22)); - if (fabsf(a - b) <= max_diff) { - return 1; - } + if (fabsf(a - b) <= max_diff) { + return 1; + } - ua.f = a; - ub.f = b; + ua.f = a; + ub.f = b; - /* Important to compare sign from integers, since (-0.0f < 0) is false - * (though this shall not be an issue in common cases)... */ - return ((ua.i < 0) != (ub.i < 0)) ? 0 : (abs(ua.i - ub.i) <= max_ulps) ? 1 : 0; + /* Important to compare sign from integers, since (-0.0f < 0) is false + * (though this shall not be an issue in common cases)... */ + return ((ua.i < 0) != (ub.i < 0)) ? 0 : (abs(ua.i - ub.i) <= max_ulps) ? 1 : 0; } MINLINE float signf(float f) { - return (f < 0.f) ? -1.f : 1.f; + return (f < 0.f) ? -1.f : 1.f; } MINLINE int signum_i_ex(float a, float eps) { - if (a > eps) { return 1; } - if (a < -eps) { return -1; } - else { return 0; } + if (a > eps) { + return 1; + } + if (a < -eps) { + return -1; + } + else { + return 0; + } } MINLINE int signum_i(float a) { - if (a > 0.0f) { return 1; } - if (a < 0.0f) { return -1; } - else { return 0; } + if (a > 0.0f) { + return 1; + } + if (a < 0.0f) { + return -1; + } + else { + return 0; + } } /** Returns number of (base ten) *significant* digits of integer part of given float * (negative in case of decimal-only floats, 0.01 returns -1 e.g.). */ MINLINE int integer_digits_f(const float f) { - return (f == 0.0f) ? 0 : (int)floor(log10(fabs(f))) + 1; + return (f == 0.0f) ? 0 : (int)floor(log10(fabs(f))) + 1; } /** Returns number of (base ten) *significant* digits of integer part of given double * (negative in case of decimal-only floats, 0.01 returns -1 e.g.). */ MINLINE int integer_digits_d(const double d) { - return (d == 0.0) ? 0 : (int)floor(log10(fabs(d))) + 1; + return (d == 0.0) ? 0 : (int)floor(log10(fabs(d))) + 1; } MINLINE int integer_digits_i(const int i) { - return (int)log10((double)i) + 1; + return (int)log10((double)i) + 1; } /* Internal helpers for SSE2 implementation. @@ -437,112 +525,116 @@ MINLINE int integer_digits_i(const int i) * * We hope that exp and e2coeff gets properly inlined */ -MALWAYS_INLINE __m128 _bli_math_fastpow(const int exp, - const int e2coeff, - const __m128 arg) +MALWAYS_INLINE __m128 _bli_math_fastpow(const int exp, const int e2coeff, const __m128 arg) { - __m128 ret; - ret = _mm_mul_ps(arg, _mm_castsi128_ps(_mm_set1_epi32(e2coeff))); - ret = _mm_cvtepi32_ps(_mm_castps_si128(ret)); - ret = _mm_mul_ps(ret, _mm_castsi128_ps(_mm_set1_epi32(exp))); - ret = _mm_castsi128_ps(_mm_cvtps_epi32(ret)); - return ret; + __m128 ret; + ret = _mm_mul_ps(arg, _mm_castsi128_ps(_mm_set1_epi32(e2coeff))); + ret = _mm_cvtepi32_ps(_mm_castps_si128(ret)); + ret = _mm_mul_ps(ret, _mm_castsi128_ps(_mm_set1_epi32(exp))); + ret = _mm_castsi128_ps(_mm_cvtps_epi32(ret)); + return ret; } /* Improve x ^ 1.0f/5.0f solution with Newton-Raphson method */ -MALWAYS_INLINE __m128 _bli_math_improve_5throot_solution( - const __m128 old_result, - const __m128 x) +MALWAYS_INLINE __m128 _bli_math_improve_5throot_solution(const __m128 old_result, const __m128 x) { - __m128 approx2 = _mm_mul_ps(old_result, old_result); - __m128 approx4 = _mm_mul_ps(approx2, approx2); - __m128 t = _mm_div_ps(x, approx4); - __m128 summ = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(4.0f), old_result), t); /* fma */ - return _mm_mul_ps(summ, _mm_set1_ps(1.0f / 5.0f)); + __m128 approx2 = _mm_mul_ps(old_result, old_result); + __m128 approx4 = _mm_mul_ps(approx2, approx2); + __m128 t = _mm_div_ps(x, approx4); + __m128 summ = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(4.0f), old_result), t); /* fma */ + return _mm_mul_ps(summ, _mm_set1_ps(1.0f / 5.0f)); } /* Calculate powf(x, 2.4). Working domain: 1e-10 < x < 1e+10 */ MALWAYS_INLINE __m128 _bli_math_fastpow24(const __m128 arg) { - /* max, avg and |avg| errors were calculated in gcc without FMA instructions - * The final precision should be better than powf in glibc */ - - /* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize - * avg error. - */ - /* 0x3F4CCCCD = 4/5 */ - /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */ - /* error max = 0.17, avg = 0.0018, |avg| = 0.05 */ - __m128 x = _bli_math_fastpow(0x3F4CCCCD, 0x4F55A7FB, arg); - __m128 arg2 = _mm_mul_ps(arg, arg); - __m128 arg4 = _mm_mul_ps(arg2, arg2); - /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */ - x = _bli_math_improve_5throot_solution(x, arg4); - /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */ - x = _bli_math_improve_5throot_solution(x, arg4); - /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */ - x = _bli_math_improve_5throot_solution(x, arg4); - return _mm_mul_ps(x, _mm_mul_ps(x, x)); + /* max, avg and |avg| errors were calculated in gcc without FMA instructions + * The final precision should be better than powf in glibc */ + + /* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize + * avg error. + */ + /* 0x3F4CCCCD = 4/5 */ + /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */ + /* error max = 0.17, avg = 0.0018, |avg| = 0.05 */ + __m128 x = _bli_math_fastpow(0x3F4CCCCD, 0x4F55A7FB, arg); + __m128 arg2 = _mm_mul_ps(arg, arg); + __m128 arg4 = _mm_mul_ps(arg2, arg2); + /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */ + x = _bli_math_improve_5throot_solution(x, arg4); + /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */ + x = _bli_math_improve_5throot_solution(x, arg4); + /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */ + x = _bli_math_improve_5throot_solution(x, arg4); + return _mm_mul_ps(x, _mm_mul_ps(x, x)); } /* Calculate powf(x, 1.0f / 2.4) */ MALWAYS_INLINE __m128 _bli_math_fastpow512(const __m128 arg) { - /* 5/12 is too small, so compute the 4th root of 20/12 instead. - * 20/12 = 5/3 = 1 + 2/3 = 2 - 1/3. 2/3 is a suitable argument for fastpow. - * weighting coefficient: a^-1/2 = 2 a; a = 2^-2/3 - */ - __m128 xf = _bli_math_fastpow(0x3f2aaaab, 0x5eb504f3, arg); - __m128 xover = _mm_mul_ps(arg, xf); - __m128 xfm1 = _mm_rsqrt_ps(xf); - __m128 x2 = _mm_mul_ps(arg, arg); - __m128 xunder = _mm_mul_ps(x2, xfm1); - /* sqrt2 * over + 2 * sqrt2 * under */ - __m128 xavg = _mm_mul_ps(_mm_set1_ps(1.0f / (3.0f * 0.629960524947437f) * 0.999852f), - _mm_add_ps(xover, xunder)); - xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg)); - xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg)); - return xavg; + /* 5/12 is too small, so compute the 4th root of 20/12 instead. + * 20/12 = 5/3 = 1 + 2/3 = 2 - 1/3. 2/3 is a suitable argument for fastpow. + * weighting coefficient: a^-1/2 = 2 a; a = 2^-2/3 + */ + __m128 xf = _bli_math_fastpow(0x3f2aaaab, 0x5eb504f3, arg); + __m128 xover = _mm_mul_ps(arg, xf); + __m128 xfm1 = _mm_rsqrt_ps(xf); + __m128 x2 = _mm_mul_ps(arg, arg); + __m128 xunder = _mm_mul_ps(x2, xfm1); + /* sqrt2 * over + 2 * sqrt2 * under */ + __m128 xavg = _mm_mul_ps(_mm_set1_ps(1.0f / (3.0f * 0.629960524947437f) * 0.999852f), + _mm_add_ps(xover, xunder)); + xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg)); + xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg)); + return xavg; } -MALWAYS_INLINE __m128 _bli_math_blend_sse(const __m128 mask, - const __m128 a, - const __m128 b) +MALWAYS_INLINE __m128 _bli_math_blend_sse(const __m128 mask, const __m128 a, const __m128 b) { - return _mm_or_ps(_mm_and_ps(mask, a), _mm_andnot_ps(mask, b)); + return _mm_or_ps(_mm_and_ps(mask, a), _mm_andnot_ps(mask, b)); } -#endif /* __SSE2__ */ +#endif /* __SSE2__ */ /* Low level conversion functions */ MINLINE unsigned char unit_float_to_uchar_clamp(float val) { - return (unsigned char)(((val <= 0.0f) ? 0 : ((val > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * val) + 0.5f)))); + return (unsigned char)(( + (val <= 0.0f) ? 0 : ((val > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * val) + 0.5f)))); } -#define unit_float_to_uchar_clamp(val) ((CHECK_TYPE_INLINE(val, float)), unit_float_to_uchar_clamp(val)) +#define unit_float_to_uchar_clamp(val) \ + ((CHECK_TYPE_INLINE(val, float)), unit_float_to_uchar_clamp(val)) MINLINE unsigned short unit_float_to_ushort_clamp(float val) { - return (unsigned short)((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (val * 65535.0f + 0.5f)); + return (unsigned short)((val >= 1.0f - 0.5f / 65535) ? + 65535 : + (val <= 0.0f) ? 0 : (val * 65535.0f + 0.5f)); } -#define unit_float_to_ushort_clamp(val) ((CHECK_TYPE_INLINE(val, float)), unit_float_to_ushort_clamp(val)) +#define unit_float_to_ushort_clamp(val) \ + ((CHECK_TYPE_INLINE(val, float)), unit_float_to_ushort_clamp(val)) MINLINE unsigned char unit_ushort_to_uchar(unsigned short val) { - return (unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8); -} -#define unit_ushort_to_uchar(val) ((CHECK_TYPE_INLINE(val, unsigned short)), unit_ushort_to_uchar(val)) - -#define unit_float_to_uchar_clamp_v3(v1, v2) { \ - (v1)[0] = unit_float_to_uchar_clamp((v2[0])); \ - (v1)[1] = unit_float_to_uchar_clamp((v2[1])); \ - (v1)[2] = unit_float_to_uchar_clamp((v2[2])); \ -} ((void)0) -#define unit_float_to_uchar_clamp_v4(v1, v2) { \ - (v1)[0] = unit_float_to_uchar_clamp((v2[0])); \ - (v1)[1] = unit_float_to_uchar_clamp((v2[1])); \ - (v1)[2] = unit_float_to_uchar_clamp((v2[2])); \ - (v1)[3] = unit_float_to_uchar_clamp((v2[3])); \ -} ((void)0) + return (unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8); +} +#define unit_ushort_to_uchar(val) \ + ((CHECK_TYPE_INLINE(val, unsigned short)), unit_ushort_to_uchar(val)) + +#define unit_float_to_uchar_clamp_v3(v1, v2) \ + { \ + (v1)[0] = unit_float_to_uchar_clamp((v2[0])); \ + (v1)[1] = unit_float_to_uchar_clamp((v2[1])); \ + (v1)[2] = unit_float_to_uchar_clamp((v2[2])); \ + } \ + ((void)0) +#define unit_float_to_uchar_clamp_v4(v1, v2) \ + { \ + (v1)[0] = unit_float_to_uchar_clamp((v2[0])); \ + (v1)[1] = unit_float_to_uchar_clamp((v2[1])); \ + (v1)[2] = unit_float_to_uchar_clamp((v2[2])); \ + (v1)[3] = unit_float_to_uchar_clamp((v2[3])); \ + } \ + ((void)0) #endif /* __MATH_BASE_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index d86b2924e17..ec2408e30a1 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -30,121 +30,133 @@ MINLINE int bitscan_forward_i(int a) { - BLI_assert(a != 0); + BLI_assert(a != 0); #ifdef _MSC_VER - unsigned long ctz; - _BitScanForward(&ctz, a); - return ctz; + unsigned long ctz; + _BitScanForward(&ctz, a); + return ctz; #else - return __builtin_ctz((unsigned int)a); + return __builtin_ctz((unsigned int)a); #endif } MINLINE unsigned int bitscan_forward_uint(unsigned int a) { - return (unsigned int)bitscan_forward_i((int)a); + return (unsigned int)bitscan_forward_i((int)a); } MINLINE int bitscan_forward_clear_i(int *a) { - int i = bitscan_forward_i(*a); - *a &= (*a) - 1; - return i; + int i = bitscan_forward_i(*a); + *a &= (*a) - 1; + return i; } MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a) { - return (unsigned int)bitscan_forward_clear_i((int *)a); + return (unsigned int)bitscan_forward_clear_i((int *)a); } MINLINE int bitscan_reverse_i(int a) { - BLI_assert(a != 0); + BLI_assert(a != 0); #ifdef _MSC_VER - unsigned long clz; - _BitScanReverse(&clz, a); - return clz; + unsigned long clz; + _BitScanReverse(&clz, a); + return clz; #else - return __builtin_clz((unsigned int)a); + return __builtin_clz((unsigned int)a); #endif } MINLINE unsigned int bitscan_reverse_uint(unsigned int a) { - return (unsigned int)bitscan_reverse_i((int)a); + return (unsigned int)bitscan_reverse_i((int)a); } MINLINE int bitscan_reverse_clear_i(int *a) { - int i = bitscan_reverse_i(*a); - /* TODO(sergey): This could probably be optimized. */ - *a &= ~(1 << (sizeof(int) * 8 - i - 1)); - return i; + int i = bitscan_reverse_i(*a); + /* TODO(sergey): This could probably be optimized. */ + *a &= ~(1 << (sizeof(int) * 8 - i - 1)); + return i; } MINLINE unsigned int bitscan_reverse_clear_uint(unsigned int *a) { - return (unsigned int)bitscan_reverse_clear_i((int *)a); + return (unsigned int)bitscan_reverse_clear_i((int *)a); } MINLINE unsigned int highest_order_bit_uint(unsigned int n) { - if (n == 0) { - return 0; - } - return 1 << (sizeof(unsigned int) * 8 - bitscan_reverse_uint(n)); + if (n == 0) { + return 0; + } + return 1 << (sizeof(unsigned int) * 8 - bitscan_reverse_uint(n)); } MINLINE unsigned short highest_order_bit_s(unsigned short n) { - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - return (unsigned short)(n - (n >> 1)); + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return (unsigned short)(n - (n >> 1)); } #ifndef __GNUC__ MINLINE int count_bits_i(unsigned int i) { - /* variable-precision SWAR algorithm. */ - i = i - ((i >> 1) & 0x55555555); - i = (i & 0x33333333) + ((i >> 2) & 0x33333333); - return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; + /* variable-precision SWAR algorithm. */ + i = i - ((i >> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; } #endif MINLINE int float_as_int(float f) { - union { int i; float f; } u; - u.f = f; - return u.i; + union { + int i; + float f; + } u; + u.f = f; + return u.i; } MINLINE unsigned int float_as_uint(float f) { - union { unsigned int i; float f; } u; - u.f = f; - return u.i; + union { + unsigned int i; + float f; + } u; + u.f = f; + return u.i; } MINLINE float int_as_float(int i) { - union { int i; float f; } u; - u.i = i; - return u.f; + union { + int i; + float f; + } u; + u.i = i; + return u.f; } MINLINE float uint_as_float(unsigned int i) { - union { unsigned int i; float f; } u; - u.i = i; - return u.f; + union { + unsigned int i; + float f; + } u; + u.i = i; + return u.f; } MINLINE float xor_fl(float x, int y) { - return int_as_float(float_as_int(x) ^ y); + return int_as_float(float_as_int(x) ^ y); } #endif /* __MATH_BITS_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 54698ddf7ca..bc1699451f3 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -26,7 +26,6 @@ #include <assert.h> - #include "BLI_math.h" #include "BLI_utildefines.h" @@ -34,95 +33,95 @@ void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b) { - float nr, ng, nb; + float nr, ng, nb; - nr = fabsf(h * 6.0f - 3.0f) - 1.0f; - ng = 2.0f - fabsf(h * 6.0f - 2.0f); - nb = 2.0f - fabsf(h * 6.0f - 4.0f); + nr = fabsf(h * 6.0f - 3.0f) - 1.0f; + ng = 2.0f - fabsf(h * 6.0f - 2.0f); + nb = 2.0f - fabsf(h * 6.0f - 4.0f); - CLAMP(nr, 0.0f, 1.0f); - CLAMP(nb, 0.0f, 1.0f); - CLAMP(ng, 0.0f, 1.0f); + CLAMP(nr, 0.0f, 1.0f); + CLAMP(nb, 0.0f, 1.0f); + CLAMP(ng, 0.0f, 1.0f); - *r = ((nr - 1.0f) * s + 1.0f) * v; - *g = ((ng - 1.0f) * s + 1.0f) * v; - *b = ((nb - 1.0f) * s + 1.0f) * v; + *r = ((nr - 1.0f) * s + 1.0f) * v; + *g = ((ng - 1.0f) * s + 1.0f) * v; + *b = ((nb - 1.0f) * s + 1.0f) * v; } void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b) { - float nr, ng, nb, chroma; + float nr, ng, nb, chroma; - nr = fabsf(h * 6.0f - 3.0f) - 1.0f; - ng = 2.0f - fabsf(h * 6.0f - 2.0f); - nb = 2.0f - fabsf(h * 6.0f - 4.0f); + nr = fabsf(h * 6.0f - 3.0f) - 1.0f; + ng = 2.0f - fabsf(h * 6.0f - 2.0f); + nb = 2.0f - fabsf(h * 6.0f - 4.0f); - CLAMP(nr, 0.0f, 1.0f); - CLAMP(nb, 0.0f, 1.0f); - CLAMP(ng, 0.0f, 1.0f); + CLAMP(nr, 0.0f, 1.0f); + CLAMP(nb, 0.0f, 1.0f); + CLAMP(ng, 0.0f, 1.0f); - chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s; + chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s; - *r = (nr - 0.5f) * chroma + l; - *g = (ng - 0.5f) * chroma + l; - *b = (nb - 0.5f) * chroma + l; + *r = (nr - 0.5f) * chroma + l; + *g = (ng - 0.5f) * chroma + l; + *b = (nb - 0.5f) * chroma + l; } /* convenience function for now */ void hsv_to_rgb_v(const float hsv[3], float r_rgb[3]) { - hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]); + hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]); } /* convenience function for now */ void hsl_to_rgb_v(const float hsl[3], float r_rgb[3]) { - hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]); + hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]); } void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int colorspace) { - float y, u, v; + float y, u, v; - switch (colorspace) { - case BLI_YUV_ITU_BT601: - y = 0.299f * r + 0.587f * g + 0.114f * b; - u = -0.147f * r - 0.289f * g + 0.436f * b; - v = 0.615f * r - 0.515f * g - 0.100f * b; - break; - case BLI_YUV_ITU_BT709: - default: - y = 0.2126f * r + 0.7152f * g + 0.0722f * b; - u = -0.09991f * r - 0.33609f * g + 0.436f * b; - v = 0.615f * r - 0.55861f * g - 0.05639f * b; - break; - } + switch (colorspace) { + case BLI_YUV_ITU_BT601: + y = 0.299f * r + 0.587f * g + 0.114f * b; + u = -0.147f * r - 0.289f * g + 0.436f * b; + v = 0.615f * r - 0.515f * g - 0.100f * b; + break; + case BLI_YUV_ITU_BT709: + default: + y = 0.2126f * r + 0.7152f * g + 0.0722f * b; + u = -0.09991f * r - 0.33609f * g + 0.436f * b; + v = 0.615f * r - 0.55861f * g - 0.05639f * b; + break; + } - *ly = y; - *lu = u; - *lv = v; + *ly = y; + *lu = u; + *lv = v; } void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int colorspace) { - float r, g, b; + float r, g, b; - switch (colorspace) { - case BLI_YUV_ITU_BT601: - r = y + 1.140f * v; - g = y - 0.394f * u - 0.581f * v; - b = y + 2.032f * u; - break; - case BLI_YUV_ITU_BT709: - r = y + 1.28033f * v; - g = y - 0.21482f * u - 0.38059f * v; - b = y + 2.12798f * u; - break; - } + switch (colorspace) { + case BLI_YUV_ITU_BT601: + r = y + 1.140f * v; + g = y - 0.394f * u - 0.581f * v; + b = y + 2.032f * u; + break; + case BLI_YUV_ITU_BT709: + r = y + 1.28033f * v; + g = y - 0.21482f * u - 0.38059f * v; + b = y + 2.12798f * u; + break; + } - *lr = r; - *lg = g; - *lb = b; + *lr = r; + *lg = g; + *lb = b; } /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f @@ -130,231 +129,229 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int * Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace) { - float sr, sg, sb; - float y = 128.0f, cr = 128.0f, cb = 128.0f; - - sr = 255.0f * r; - sg = 255.0f * g; - sb = 255.0f * b; - - switch (colorspace) { - case BLI_YCC_ITU_BT601: - y = (0.257f * sr) + (0.504f * sg) + (0.098f * sb) + 16.0f; - cb = (-0.148f * sr) - (0.291f * sg) + (0.439f * sb) + 128.0f; - cr = (0.439f * sr) - (0.368f * sg) - (0.071f * sb) + 128.0f; - break; - case BLI_YCC_ITU_BT709: - y = (0.183f * sr) + (0.614f * sg) + (0.062f * sb) + 16.0f; - cb = (-0.101f * sr) - (0.338f * sg) + (0.439f * sb) + 128.0f; - cr = (0.439f * sr) - (0.399f * sg) - (0.040f * sb) + 128.0f; - break; - case BLI_YCC_JFIF_0_255: - y = (0.299f * sr) + (0.587f * sg) + (0.114f * sb); - cb = (-0.16874f * sr) - (0.33126f * sg) + (0.5f * sb) + 128.0f; - cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f; - break; - default: - assert(!"invalid colorspace"); - break; - } - - *ly = y; - *lcb = cb; - *lcr = cr; + float sr, sg, sb; + float y = 128.0f, cr = 128.0f, cb = 128.0f; + + sr = 255.0f * r; + sg = 255.0f * g; + sb = 255.0f * b; + + switch (colorspace) { + case BLI_YCC_ITU_BT601: + y = (0.257f * sr) + (0.504f * sg) + (0.098f * sb) + 16.0f; + cb = (-0.148f * sr) - (0.291f * sg) + (0.439f * sb) + 128.0f; + cr = (0.439f * sr) - (0.368f * sg) - (0.071f * sb) + 128.0f; + break; + case BLI_YCC_ITU_BT709: + y = (0.183f * sr) + (0.614f * sg) + (0.062f * sb) + 16.0f; + cb = (-0.101f * sr) - (0.338f * sg) + (0.439f * sb) + 128.0f; + cr = (0.439f * sr) - (0.399f * sg) - (0.040f * sb) + 128.0f; + break; + case BLI_YCC_JFIF_0_255: + y = (0.299f * sr) + (0.587f * sg) + (0.114f * sb); + cb = (-0.16874f * sr) - (0.33126f * sg) + (0.5f * sb) + 128.0f; + cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f; + break; + default: + assert(!"invalid colorspace"); + break; + } + + *ly = y; + *lcb = cb; + *lcr = cr; } - /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */ /* RGB outputs are in the range 0 - 1.0f */ /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */ void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace) { - float r = 128.0f, g = 128.0f, b = 128.0f; - - switch (colorspace) { - case BLI_YCC_ITU_BT601: - r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f); - g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f); - b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f); - break; - case BLI_YCC_ITU_BT709: - r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f); - g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f); - b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f); - break; - case BLI_YCC_JFIF_0_255: - r = y + 1.402f * cr - 179.456f; - g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f; - b = y + 1.772f * cb - 226.816f; - break; - default: - BLI_assert(0); - break; - } - *lr = r / 255.0f; - *lg = g / 255.0f; - *lb = b / 255.0f; + float r = 128.0f, g = 128.0f, b = 128.0f; + + switch (colorspace) { + case BLI_YCC_ITU_BT601: + r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f); + g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f); + b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f); + break; + case BLI_YCC_ITU_BT709: + r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f); + g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f); + b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f); + break; + case BLI_YCC_JFIF_0_255: + r = y + 1.402f * cr - 179.456f; + g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f; + b = y + 1.772f * cb - 226.816f; + break; + default: + BLI_assert(0); + break; + } + *lr = r / 255.0f; + *lg = g / 255.0f; + *lb = b / 255.0f; } void hex_to_rgb(char *hexcol, float *r, float *g, float *b) { - unsigned int ri, gi, bi; - - if (hexcol[0] == '#') { - hexcol++; - } - - if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) { - /* six digit hex colors */ - } - else if (sscanf(hexcol, "%01x%01x%01x", &ri, &gi, &bi) == 3) { - /* three digit hex colors (#123 becomes #112233) */ - ri += ri << 4; - gi += gi << 4; - bi += bi << 4; - } - else { - /* avoid using un-initialized vars */ - *r = *g = *b = 0.0f; - return; - } - - *r = (float)ri * (1.0f / 255.0f); - *g = (float)gi * (1.0f / 255.0f); - *b = (float)bi * (1.0f / 255.0f); - CLAMP(*r, 0.0f, 1.0f); - CLAMP(*g, 0.0f, 1.0f); - CLAMP(*b, 0.0f, 1.0f); + unsigned int ri, gi, bi; + + if (hexcol[0] == '#') { + hexcol++; + } + + if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) { + /* six digit hex colors */ + } + else if (sscanf(hexcol, "%01x%01x%01x", &ri, &gi, &bi) == 3) { + /* three digit hex colors (#123 becomes #112233) */ + ri += ri << 4; + gi += gi << 4; + bi += bi << 4; + } + else { + /* avoid using un-initialized vars */ + *r = *g = *b = 0.0f; + return; + } + + *r = (float)ri * (1.0f / 255.0f); + *g = (float)gi * (1.0f / 255.0f); + *b = (float)bi * (1.0f / 255.0f); + CLAMP(*r, 0.0f, 1.0f); + CLAMP(*g, 0.0f, 1.0f); + CLAMP(*b, 0.0f, 1.0f); } void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) { - float k = 0.0f; - float chroma; - float min_gb; + float k = 0.0f; + float chroma; + float min_gb; - if (g < b) { - SWAP(float, g, b); - k = -1.0f; - } - min_gb = b; - if (r < g) { - SWAP(float, r, g); - k = -2.0f / 6.0f - k; - min_gb = min_ff(g, b); - } + if (g < b) { + SWAP(float, g, b); + k = -1.0f; + } + min_gb = b; + if (r < g) { + SWAP(float, r, g); + k = -2.0f / 6.0f - k; + min_gb = min_ff(g, b); + } - chroma = r - min_gb; + chroma = r - min_gb; - *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f)); - *ls = chroma / (r + 1e-20f); - *lv = r; + *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f)); + *ls = chroma / (r + 1e-20f); + *lv = r; } /* convenience function for now */ void rgb_to_hsv_v(const float rgb[3], float r_hsv[3]) { - rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]); } void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll) { - const float cmax = max_fff(r, g, b); - const float cmin = min_fff(r, g, b); - float h, s, l = min_ff(1.0, (cmax + cmin) / 2.0f); - - if (cmax == cmin) { - h = s = 0.0f; // achromatic - } - else { - float d = cmax - cmin; - s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin); - if (cmax == r) { - h = (g - b) / d + (g < b ? 6.0f : 0.0f); - } - else if (cmax == g) { - h = (b - r) / d + 2.0f; - } - else { - h = (r - g) / d + 4.0f; - } - } - h /= 6.0f; - - *lh = h; - *ls = s; - *ll = l; + const float cmax = max_fff(r, g, b); + const float cmin = min_fff(r, g, b); + float h, s, l = min_ff(1.0, (cmax + cmin) / 2.0f); + + if (cmax == cmin) { + h = s = 0.0f; // achromatic + } + else { + float d = cmax - cmin; + s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin); + if (cmax == r) { + h = (g - b) / d + (g < b ? 6.0f : 0.0f); + } + else if (cmax == g) { + h = (b - r) / d + 2.0f; + } + else { + h = (r - g) / d + 4.0f; + } + } + h /= 6.0f; + + *lh = h; + *ls = s; + *ll = l; } void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *ll) { - const float orig_s = *ls; - const float orig_h = *lh; + const float orig_s = *ls; + const float orig_h = *lh; - rgb_to_hsl(r, g, b, lh, ls, ll); + rgb_to_hsl(r, g, b, lh, ls, ll); - if (*ll <= 0.0f) { - *lh = orig_h; - *ls = orig_s; - } - else if (*ls <= 0.0f) { - *lh = orig_h; - *ls = orig_s; - } + if (*ll <= 0.0f) { + *lh = orig_h; + *ls = orig_s; + } + else if (*ls <= 0.0f) { + *lh = orig_h; + *ls = orig_s; + } - if (*lh == 0.0f && orig_h >= 1.0f) { - *lh = 1.0f; - } + if (*lh == 0.0f && orig_h >= 1.0f) { + *lh = 1.0f; + } } void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3]) { - rgb_to_hsl_compat(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]); + rgb_to_hsl_compat(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]); } - /* convenience function for now */ void rgb_to_hsl_v(const float rgb[3], float r_hsl[3]) { - rgb_to_hsl(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]); + rgb_to_hsl(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]); } void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv) { - const float orig_h = *lh; - const float orig_s = *ls; + const float orig_h = *lh; + const float orig_s = *ls; - rgb_to_hsv(r, g, b, lh, ls, lv); + rgb_to_hsv(r, g, b, lh, ls, lv); - if (*lv <= 1e-8) { - /* Very low v values will affect the hs values, correct them in post. */ - *lh = orig_h; - *ls = orig_s; - } - else if (*ls <= 1e-8) { - *lh = orig_h; - } + if (*lv <= 1e-8) { + /* Very low v values will affect the hs values, correct them in post. */ + *lh = orig_h; + *ls = orig_s; + } + else if (*ls <= 1e-8) { + *lh = orig_h; + } - if (*lh == 0.0f && orig_h >= 1.0f) { - *lh = 1.0f; - } + if (*lh == 0.0f && orig_h >= 1.0f) { + *lh = 1.0f; + } } /* convenience function for now */ void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3]) { - rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]); + rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]); } /* clamp hsv to usable values */ void hsv_clamp_v(float hsv[3], float v_max) { - if (UNLIKELY(hsv[0] < 0.0f || hsv[0] > 1.0f)) { - hsv[0] = hsv[0] - floorf(hsv[0]); - } - CLAMP(hsv[1], 0.0f, 1.0f); - CLAMP(hsv[2], 0.0f, v_max); + if (UNLIKELY(hsv[0] < 0.0f || hsv[0] > 1.0f)) { + hsv[0] = hsv[0] - floorf(hsv[0]); + } + CLAMP(hsv[1], 0.0f, 1.0f); + CLAMP(hsv[2], 0.0f, v_max); } /** @@ -365,112 +362,117 @@ void hsv_clamp_v(float hsv[3], float v_max) unsigned int hsv_to_cpack(float h, float s, float v) { - unsigned int r, g, b; - float rf, gf, bf; - unsigned int col; + unsigned int r, g, b; + float rf, gf, bf; + unsigned int col; - hsv_to_rgb(h, s, v, &rf, &gf, &bf); + hsv_to_rgb(h, s, v, &rf, &gf, &bf); - r = (unsigned int) (rf * 255.0f); - g = (unsigned int) (gf * 255.0f); - b = (unsigned int) (bf * 255.0f); + r = (unsigned int)(rf * 255.0f); + g = (unsigned int)(gf * 255.0f); + b = (unsigned int)(bf * 255.0f); - col = (r + (g * 256) + (b * 256 * 256)); - return col; + col = (r + (g * 256) + (b * 256 * 256)); + return col; } unsigned int rgb_to_cpack(float r, float g, float b) { - unsigned int ir, ig, ib; + unsigned int ir, ig, ib; - ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f)); - ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f)); - ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f)); + ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f)); + ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f)); + ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f)); - if (ir > 255) { ir = 255; } - if (ig > 255) { ig = 255; } - if (ib > 255) { ib = 255; } + if (ir > 255) { + ir = 255; + } + if (ig > 255) { + ig = 255; + } + if (ib > 255) { + ib = 255; + } - return (ir + (ig * 256) + (ib * 256 * 256)); + return (ir + (ig * 256) + (ib * 256 * 256)); } void cpack_to_rgb(unsigned int col, float *r, float *g, float *b) { - *r = ((float)(((col) ) & 0xFF)) * (1.0f / 255.0f); - *g = ((float)(((col) >> 8) & 0xFF)) * (1.0f / 255.0f); - *b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f); + *r = ((float)(((col)) & 0xFF)) * (1.0f / 255.0f); + *g = ((float)(((col) >> 8) & 0xFF)) * (1.0f / 255.0f); + *b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f); } void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3]) { - r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); - r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); - r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f); + r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); + r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); + r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f); } void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4]) { - r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); - r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); - r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f); - r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f); + r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); + r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); + r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f); + r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f); } void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3]) { - unit_float_to_uchar_clamp_v3(r_col, col_f); + unit_float_to_uchar_clamp_v3(r_col, col_f); } void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]) { - unit_float_to_uchar_clamp_v4(r_col, col_f); + unit_float_to_uchar_clamp_v4(r_col, col_f); } /* ********************************* color transforms ********************************* */ - float srgb_to_linearrgb(float c) { - if (c < 0.04045f) { - return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f); - } - else { - return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f); - } + if (c < 0.04045f) { + return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f); + } + else { + return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f); + } } float linearrgb_to_srgb(float c) { - if (c < 0.0031308f) { - return (c < 0.0f) ? 0.0f : c * 12.92f; - } - else { - return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f; - } + if (c < 0.0031308f) { + return (c < 0.0f) ? 0.0f : c * 12.92f; + } + else { + return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f; + } } void minmax_rgb(short c[3]) { - if (c[0] > 255) { - c[0] = 255; - } - else if (c[0] < 0) { - c[0] = 0; - } + if (c[0] > 255) { + c[0] = 255; + } + else if (c[0] < 0) { + c[0] = 0; + } - if (c[1] > 255) { - c[1] = 255; - } - else if (c[1] < 0) { - c[1] = 0; - } + if (c[1] > 255) { + c[1] = 255; + } + else if (c[1] < 0) { + c[1] = 0; + } - if (c[2] > 255) { - c[2] = 255; - } - else if (c[2] < 0) { - c[2] = 0; - } + if (c[2] > 255) { + c[2] = 255; + } + else if (c[2] < 0) { + c[2] = 0; + } } /* If the requested RGB shade contains a negative weight for @@ -481,36 +483,37 @@ void minmax_rgb(short c[3]) * components were modified, zero otherwise.*/ int constrain_rgb(float *r, float *g, float *b) { - /* Amount of white needed */ - const float w = -min_ffff(0.0f, *r, *g, *b); + /* Amount of white needed */ + const float w = -min_ffff(0.0f, *r, *g, *b); - /* Add just enough white to make r, g, b all positive. */ - if (w > 0.0f) { - *r += w; - *g += w; - *b += w; + /* Add just enough white to make r, g, b all positive. */ + if (w > 0.0f) { + *r += w; + *g += w; + *b += w; - return 1; /* Color modified to fit RGB gamut */ - } + return 1; /* Color modified to fit RGB gamut */ + } - return 0; /* Color within RGB gamut */ + return 0; /* Color within RGB gamut */ } /* ********************** lift/gamma/gain / ASC-CDL conversion ********************************* */ -void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power) +void lift_gamma_gain_to_asc_cdl( + float *lift, float *gamma, float *gain, float *offset, float *slope, float *power) { - int c; - for (c = 0; c < 3; c++) { - offset[c] = lift[c] * gain[c]; - slope[c] = gain[c] * (1.0f - lift[c]); - if (gamma[c] == 0) { - power[c] = FLT_MAX; - } - else { - power[c] = 1.0f / gamma[c]; - } - } + int c; + for (c = 0; c < 3; c++) { + offset[c] = lift[c] * gain[c]; + slope[c] = gain[c] * (1.0f - lift[c]); + if (gamma[c] == 0) { + power[c] = FLT_MAX; + } + else { + power[c] = 1.0f / gamma[c]; + } + } } /* ************************************* other ************************************************* */ @@ -518,32 +521,31 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o /* Applies an hue offset to a float rgb color */ void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset) { - float hsv[3]; + float hsv[3]; - rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2); - hsv[0] += hue_offset; - if (hsv[0] > 1.0f) { - hsv[0] -= 1.0f; - } - else if (hsv[0] < 0.0f) { - hsv[0] += 1.0f; - } + hsv[0] += hue_offset; + if (hsv[0] > 1.0f) { + hsv[0] -= 1.0f; + } + else if (hsv[0] < 0.0f) { + hsv[0] += 1.0f; + } - hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2); + hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2); } /* Applies an hue offset to a byte rgb color */ void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset) { - float rgb_float[3]; + float rgb_float[3]; - rgb_uchar_to_float(rgb_float, rgb); - rgb_float_set_hue_float_offset(rgb_float, hue_offset); - rgb_float_to_uchar(rgb, rgb_float); + rgb_uchar_to_float(rgb_float, rgb); + rgb_float_set_hue_float_offset(rgb_float, hue_offset); + rgb_float_to_uchar(rgb, rgb_float); } - /* fast sRGB conversion * LUT from linear float to 16-bit short * based on http://mysite.verizon.net/spitzak/conversion/ @@ -554,83 +556,83 @@ unsigned short BLI_color_to_srgb_table[0x10000]; static unsigned short hipart(const float f) { - union { - float f; - unsigned short us[2]; - } tmp; + union { + float f; + unsigned short us[2]; + } tmp; - tmp.f = f; + tmp.f = f; #ifdef __BIG_ENDIAN__ - return tmp.us[0]; + return tmp.us[0]; #else - return tmp.us[1]; + return tmp.us[1]; #endif } static float index_to_float(const unsigned short i) { - union { - float f; - unsigned short us[2]; - } tmp; + union { + float f; + unsigned short us[2]; + } tmp; - /* positive and negative zeros, and all gradual underflow, turn into zero: */ - if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) { - return 0; - } - /* All NaN's and infinity turn into the largest possible legal float: */ - if (i >= 0x7f80 && i < 0x8000) { - return FLT_MAX; - } - if (i >= 0xff80) { - return -FLT_MAX; - } + /* positive and negative zeros, and all gradual underflow, turn into zero: */ + if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) { + return 0; + } + /* All NaN's and infinity turn into the largest possible legal float: */ + if (i >= 0x7f80 && i < 0x8000) { + return FLT_MAX; + } + if (i >= 0xff80) { + return -FLT_MAX; + } #ifdef __BIG_ENDIAN__ - tmp.us[0] = i; - tmp.us[1] = 0x8000; + tmp.us[0] = i; + tmp.us[1] = 0x8000; #else - tmp.us[0] = 0x8000; - tmp.us[1] = i; + tmp.us[0] = 0x8000; + tmp.us[1] = i; #endif - return tmp.f; + return tmp.f; } void BLI_init_srgb_conversion(void) { - static bool initialized = false; - unsigned int i, b; - - if (initialized) { - return; - } - initialized = true; - - /* Fill in the lookup table to convert floats to bytes: */ - for (i = 0; i < 0x10000; i++) { - float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f; - if (f <= 0) { - BLI_color_to_srgb_table[i] = 0; - } - else if (f < 255) { - BLI_color_to_srgb_table[i] = (unsigned short) (f * 0x100 + 0.5f); - } - else { - BLI_color_to_srgb_table[i] = 0xff00; - } - } - - /* Fill in the lookup table to convert bytes to float: */ - for (b = 0; b <= 255; b++) { - float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f)); - BLI_color_from_srgb_table[b] = f; - i = hipart(f); - /* replace entries so byte->float->byte does not change the data: */ - BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100); - } + static bool initialized = false; + unsigned int i, b; + + if (initialized) { + return; + } + initialized = true; + + /* Fill in the lookup table to convert floats to bytes: */ + for (i = 0; i < 0x10000; i++) { + float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f; + if (f <= 0) { + BLI_color_to_srgb_table[i] = 0; + } + else if (f < 255) { + BLI_color_to_srgb_table[i] = (unsigned short)(f * 0x100 + 0.5f); + } + else { + BLI_color_to_srgb_table[i] = 0xff00; + } + } + + /* Fill in the lookup table to convert bytes to float: */ + for (b = 0; b <= 255; b++) { + float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f)); + BLI_color_from_srgb_table[b] = f; + i = hipart(f); + /* replace entries so byte->float->byte does not change the data: */ + BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100); + } } /* ****************************** blackbody ******************************** */ @@ -642,71 +644,70 @@ void BLI_init_srgb_conversion(void) */ static const float blackbody_table_r[6][3] = { - { 2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f }, - { 3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f }, - { 4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f }, - { 4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f }, - { 4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f }, - { 3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f }, + {2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f}, + {3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f}, + {4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f}, + {4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f}, + {4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f}, + {3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f}, }; static const float blackbody_table_g[6][3] = { - { -7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f }, - { -1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f }, - { -1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f }, - { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f }, - { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f }, - { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f }, + {-7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f}, + {-1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f}, + {-1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f}, + {-1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f}, + {-1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f}, + {-5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f}, }; static const float blackbody_table_b[6][4] = { - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { -2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f }, - { -2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f }, - { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f }, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {-2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f}, + {-2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f}, + {6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f}, }; static void blackbody_temperature_to_rgb(float rgb[3], float t) { - if (t >= 12000.0f) { - rgb[0] = 0.826270103f; - rgb[1] = 0.994478524f; - rgb[2] = 1.56626022f; - } - else if (t < 965.0f) { - rgb[0] = 4.70366907f; - rgb[1] = 0.0f; - rgb[2] = 0.0f; - } - else { - int i = (t >= 6365.0f) ? 5 : - (t >= 3315.0f) ? 4 : - (t >= 1902.0f) ? 3 : - (t >= 1449.0f) ? 2 : - (t >= 1167.0f) ? 1 : 0; - - const float *r = blackbody_table_r[i]; - const float *g = blackbody_table_g[i]; - const float *b = blackbody_table_b[i]; - - const float t_inv = 1.0f / t; - rgb[0] = r[0] * t_inv + r[1] * t + r[2]; - rgb[1] = g[0] * t_inv + g[1] * t + g[2]; - rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3]; - } + if (t >= 12000.0f) { + rgb[0] = 0.826270103f; + rgb[1] = 0.994478524f; + rgb[2] = 1.56626022f; + } + else if (t < 965.0f) { + rgb[0] = 4.70366907f; + rgb[1] = 0.0f; + rgb[2] = 0.0f; + } + else { + int i = (t >= 6365.0f) ? + 5 : + (t >= 3315.0f) ? 4 : + (t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0; + + const float *r = blackbody_table_r[i]; + const float *g = blackbody_table_g[i]; + const float *b = blackbody_table_b[i]; + + const float t_inv = 1.0f / t; + rgb[0] = r[0] * t_inv + r[1] * t + r[2]; + rgb[1] = g[0] * t_inv + g[1] * t + g[2]; + rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3]; + } } void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max) { - for (int i = 0; i < width; i++) { - float temperature = min + (max - min) / (float)width * (float)i; + for (int i = 0; i < width; i++) { + float temperature = min + (max - min) / (float)width * (float)i; - float rgb[3]; - blackbody_temperature_to_rgb(rgb, temperature); + float rgb[3]; + blackbody_temperature_to_rgb(rgb, temperature); - copy_v3_v3(&r_table[i * 4], rgb); - r_table[i * 4 + 3] = 0.0f; - } + copy_v3_v3(&r_table[i * 4], rgb); + r_table[i * 4 + 3] = 0.0f; + } } diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c index f3e6ff8b110..7241779b32a 100644 --- a/source/blender/blenlib/intern/math_color_blend_inline.c +++ b/source/blender/blenlib/intern/math_color_blend_inline.c @@ -31,11 +31,11 @@ #include "BLI_utildefines.h" #ifndef __MATH_COLOR_BLEND_INLINE_C__ -#define __MATH_COLOR_BLEND_INLINE_C__ +# define __MATH_COLOR_BLEND_INLINE_C__ /* don't add any saturation to a completely black and white image */ -#define EPS_SATURATION 0.0005f -#define EPS_ALPHA 0.0005f +# define EPS_SATURATION 0.0005f +# define EPS_ALPHA 0.0005f /***************************** Color Blending ******************************** * @@ -49,1123 +49,1154 @@ /* straight alpha byte blending modes */ -MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_mix_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight over operation */ - const int t = src2[3]; - const int mt = 255 - t; - int tmp[4]; - - tmp[0] = (mt * src1[3] * src1[0]) + (t * 255 * src2[0]); - tmp[1] = (mt * src1[3] * src1[1]) + (t * 255 * src2[1]); - tmp[2] = (mt * src1[3] * src1[2]) + (t * 255 * src2[2]); - tmp[3] = (mt * src1[3]) + (t * 255); - - dst[0] = (unsigned char)divide_round_i(tmp[0], tmp[3]); - dst[1] = (unsigned char)divide_round_i(tmp[1], tmp[3]); - dst[2] = (unsigned char)divide_round_i(tmp[2], tmp[3]); - dst[3] = (unsigned char)divide_round_i(tmp[3], 255); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight over operation */ + const int t = src2[3]; + const int mt = 255 - t; + int tmp[4]; + + tmp[0] = (mt * src1[3] * src1[0]) + (t * 255 * src2[0]); + tmp[1] = (mt * src1[3] * src1[1]) + (t * 255 * src2[1]); + tmp[2] = (mt * src1[3] * src1[2]) + (t * 255 * src2[2]); + tmp[3] = (mt * src1[3]) + (t * 255); + + dst[0] = (unsigned char)divide_round_i(tmp[0], tmp[3]); + dst[1] = (unsigned char)divide_round_i(tmp[1], tmp[3]); + dst[2] = (unsigned char)divide_round_i(tmp[2], tmp[3]); + dst[3] = (unsigned char)divide_round_i(tmp[3], 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_add_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight add operation */ - const int t = src2[3]; - int tmp[3]; - - tmp[0] = (src1[0] * 255) + (src2[0] * t); - tmp[1] = (src1[1] * 255) + (src2[1] * t); - tmp[2] = (src1[2] * 255) + (src2[2] * t); - - dst[0] = (unsigned char)min_ii(divide_round_i(tmp[0], 255), 255); - dst[1] = (unsigned char)min_ii(divide_round_i(tmp[1], 255), 255); - dst[2] = (unsigned char)min_ii(divide_round_i(tmp[2], 255), 255); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight add operation */ + const int t = src2[3]; + int tmp[3]; + + tmp[0] = (src1[0] * 255) + (src2[0] * t); + tmp[1] = (src1[1] * 255) + (src2[1] * t); + tmp[2] = (src1[2] * 255) + (src2[2] * t); + + dst[0] = (unsigned char)min_ii(divide_round_i(tmp[0], 255), 255); + dst[1] = (unsigned char)min_ii(divide_round_i(tmp[1], 255), 255); + dst[2] = (unsigned char)min_ii(divide_round_i(tmp[2], 255), 255); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_sub_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight sub operation */ - const int t = src2[3]; - int tmp[3]; - - tmp[0] = (src1[0] * 255) - (src2[0] * t); - tmp[1] = (src1[1] * 255) - (src2[1] * t); - tmp[2] = (src1[2] * 255) - (src2[2] * t); - - dst[0] = (unsigned char)max_ii(divide_round_i(tmp[0], 255), 0); - dst[1] = (unsigned char)max_ii(divide_round_i(tmp[1], 255), 0); - dst[2] = (unsigned char)max_ii(divide_round_i(tmp[2], 255), 0); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight sub operation */ + const int t = src2[3]; + int tmp[3]; + + tmp[0] = (src1[0] * 255) - (src2[0] * t); + tmp[1] = (src1[1] * 255) - (src2[1] * t); + tmp[2] = (src1[2] * 255) - (src2[2] * t); + + dst[0] = (unsigned char)max_ii(divide_round_i(tmp[0], 255), 0); + dst[1] = (unsigned char)max_ii(divide_round_i(tmp[1], 255), 0); + dst[2] = (unsigned char)max_ii(divide_round_i(tmp[2], 255), 0); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_mul_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight multiply operation */ - const int t = src2[3]; - const int mt = 255 - t; - int tmp[3]; - - tmp[0] = (mt * src1[0] * 255) + (t * src1[0] * src2[0]); - tmp[1] = (mt * src1[1] * 255) + (t * src1[1] * src2[1]); - tmp[2] = (mt * src1[2] * 255) + (t * src1[2] * src2[2]); - - dst[0] = (unsigned char)divide_round_i(tmp[0], 255 * 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255 * 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255 * 255); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight multiply operation */ + const int t = src2[3]; + const int mt = 255 - t; + int tmp[3]; + + tmp[0] = (mt * src1[0] * 255) + (t * src1[0] * src2[0]); + tmp[1] = (mt * src1[1] * 255) + (t * src1[1] * src2[1]); + tmp[2] = (mt * src1[2] * 255) + (t * src1[2] * src2[2]); + + dst[0] = (unsigned char)divide_round_i(tmp[0], 255 * 255); + dst[1] = (unsigned char)divide_round_i(tmp[1], 255 * 255); + dst[2] = (unsigned char)divide_round_i(tmp[2], 255 * 255); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_lighten_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight lighten operation */ - const int t = src2[3]; - const int mt = 255 - t; - int tmp[3]; - - tmp[0] = (mt * src1[0]) + (t * max_ii(src1[0], src2[0])); - tmp[1] = (mt * src1[1]) + (t * max_ii(src1[1], src2[1])); - tmp[2] = (mt * src1[2]) + (t * max_ii(src1[2], src2[2])); - - dst[0] = (unsigned char)divide_round_i(tmp[0], 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight lighten operation */ + const int t = src2[3]; + const int mt = 255 - t; + int tmp[3]; + + tmp[0] = (mt * src1[0]) + (t * max_ii(src1[0], src2[0])); + tmp[1] = (mt * src1[1]) + (t * max_ii(src1[1], src2[1])); + tmp[2] = (mt * src1[2]) + (t * max_ii(src1[2], src2[2])); + + dst[0] = (unsigned char)divide_round_i(tmp[0], 255); + dst[1] = (unsigned char)divide_round_i(tmp[1], 255); + dst[2] = (unsigned char)divide_round_i(tmp[2], 255); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_darken_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight darken operation */ - const int t = src2[3]; - const int mt = 255 - t; - int tmp[3]; - - tmp[0] = (mt * src1[0]) + (t * min_ii(src1[0], src2[0])); - tmp[1] = (mt * src1[1]) + (t * min_ii(src1[1], src2[1])); - tmp[2] = (mt * src1[2]) + (t * min_ii(src1[2], src2[2])); - - dst[0] = (unsigned char)divide_round_i(tmp[0], 255); - dst[1] = (unsigned char)divide_round_i(tmp[1], 255); - dst[2] = (unsigned char)divide_round_i(tmp[2], 255); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight darken operation */ + const int t = src2[3]; + const int mt = 255 - t; + int tmp[3]; + + tmp[0] = (mt * src1[0]) + (t * min_ii(src1[0], src2[0])); + tmp[1] = (mt * src1[1]) + (t * min_ii(src1[1], src2[1])); + tmp[2] = (mt * src1[2]) + (t * min_ii(src1[2], src2[2])); + + dst[0] = (unsigned char)divide_round_i(tmp[0], 255); + dst[1] = (unsigned char)divide_round_i(tmp[1], 255); + dst[2] = (unsigned char)divide_round_i(tmp[2], 255); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight so just modify alpha channel */ - const int t = src2[3]; - - dst[0] = src1[0]; - dst[1] = src1[1]; - dst[2] = src1[2]; - dst[3] = (unsigned char)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight so just modify alpha channel */ + const int t = src2[3]; + + dst[0] = src1[0]; + dst[1] = src1[1]; + dst[2] = src1[2]; + dst[3] = (unsigned char)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]) +MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4]) { - if (src2[3] != 0) { - /* straight so just modify alpha channel */ - const int t = src2[3]; - - dst[0] = src1[0]; - dst[1] = src1[1]; - dst[2] = src1[2]; - dst[3] = (unsigned char)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + if (src2[3] != 0) { + /* straight so just modify alpha channel */ + const int t = src2[3]; + + dst[0] = src1[0]; + dst[1] = src1[1]; + dst[2] = src1[2]; + dst[3] = (unsigned char)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_overlay_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = (int)src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src1[i] > 127) { - temp = 255 - ((255 - 2 * (src1[i] - 127)) * (255 - src2[i]) / 255); - } - else { - temp = (2 * src1[i] * src2[i]) >> 8; - } - dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = (int)src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src1[i] > 127) { + temp = 255 - ((255 - 2 * (src1[i] - 127)) * (255 - src2[i]) / 255); + } + else { + temp = (2 * src1[i] * src2[i]) >> 8; + } + dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_hardlight_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = (int)src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src2[i] > 127) { - temp = 255 - ((255 - 2 * (src2[i] - 127)) * (255 - src1[i]) / 255); - } - else { - temp = (2 * src2[i] * src1[i]) >> 8; - } - dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = (int)src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src2[i] > 127) { + temp = 255 - ((255 - 2 * (src2[i] - 127)) * (255 - src1[i]) / 255); + } + else { + temp = (2 * src2[i] * src1[i]) >> 8; + } + dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_burn_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_linearburn_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = max_ii(src1[i] + src2[i] - 255, 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = max_ii(src1[i] + src2[i] - 255, 0); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_dodge_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_screen_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_softlight_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src1[i] < 127) { - temp = ((2 * ((src2[i] / 2) + 64)) * src1[i]) / 255; - } - else { - temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255); - } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src1[i] < 127) { + temp = ((2 * ((src2[i] / 2) + 64)) * src1[i]) / 255; + } + else { + temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255); + } + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_pinlight_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src2[i] > 127) { - temp = max_ii(2 * (src2[i] - 127), src1[i]); - } - else { - temp = min_ii(2 * src2[i], src1[i]); - } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src2[i] > 127) { + temp = max_ii(2 * (src2[i] - 127), src1[i]); + } + else { + temp = min_ii(2 * src2[i], src1[i]); + } + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_linearlight_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src2[i] > 127) { - temp = min_ii(src1[i] + 2 * (src2[i] - 127), 255); - } - else { - temp = max_ii(src1[i] + 2 * src2[i] - 255, 0); - } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src2[i] > 127) { + temp = min_ii(src1[i] + 2 * (src2[i] - 127), 255); + } + else { + temp = max_ii(src1[i] + 2 * src2[i] - 255, 0); + } + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_vividlight_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - int temp; - - if (src2[i] == 255) { - temp = (src1[i] == 0) ? 127 : 255; - } - else if (src2[i] == 0) { - temp = (src1[i] == 255) ? 127 : 0; - } - else if (src2[i] > 127) { - temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255); - } - else { - temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0); - } - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + int temp; + + if (src2[i] == 255) { + temp = (src1[i] == 0) ? 127 : 255; + } + else if (src2[i] == 0) { + temp = (src1[i] == 255) ? 127 : 0; + } + else if (src2[i] > 127) { + temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255); + } + else { + temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0); + } + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - - -MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_difference_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = abs(src1[i] - src2[i]); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = abs(src1[i] - src2[i]); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } - -MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_exclusion_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - int i = 3; - - while (i--) { - const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255); - dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); - } - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + int i = 3; + + while (i--) { + const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255); + dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255); + } + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_color_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); - rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); - - - h1 = h2; - s1 = s2; - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); + rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); + + h1 = h2; + s1 = s2; + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_hue_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); - rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); - - - h1 = h2; - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } - + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); + rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); + + h1 = h2; + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_saturation_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); - rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); - - if (s1 > EPS_SATURATION) { - s1 = s2; - } - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); + rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); + + if (s1 > EPS_SATURATION) { + s1 = s2; + } + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]) +MINLINE void blend_color_luminosity_byte(unsigned char dst[4], + unsigned const char src1[4], + unsigned const char src2[4]) { - const int fac = src2[3]; - if (fac != 0) { - const int mfac = 255 - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); - rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); - - v1 = v2; - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); - dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); - dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); - - } - else { - /* no op */ - copy_v4_v4_uchar(dst, src1); - } - + const int fac = src2[3]; + if (fac != 0) { + const int mfac = 255 - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1); + rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2); + + v1 = v2; + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255); + dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255); + dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255); + } + else { + /* no op */ + copy_v4_v4_uchar(dst, src1); + } } -MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float ft) +MINLINE void blend_color_interpolate_byte(unsigned char dst[4], + const unsigned char src1[4], + const unsigned char src2[4], + float ft) { - /* do color interpolation, but in premultiplied space so that RGB colors - * from zero alpha regions have no influence */ - const int t = (int)(255 * ft); - const int mt = 255 - t; - int tmp = (mt * src1[3] + t * src2[3]); - - if (tmp > 0) { - dst[0] = (unsigned char)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp); - dst[1] = (unsigned char)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp); - dst[2] = (unsigned char)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp); - dst[3] = (unsigned char)divide_round_i(tmp, 255); - } - else { - copy_v4_v4_uchar(dst, src1); - } + /* do color interpolation, but in premultiplied space so that RGB colors + * from zero alpha regions have no influence */ + const int t = (int)(255 * ft); + const int mt = 255 - t; + int tmp = (mt * src1[3] + t * src2[3]); + + if (tmp > 0) { + dst[0] = (unsigned char)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp); + dst[1] = (unsigned char)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp); + dst[2] = (unsigned char)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp); + dst[3] = (unsigned char)divide_round_i(tmp, 255); + } + else { + copy_v4_v4_uchar(dst, src1); + } } /* premultiplied alpha float blending modes */ MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* premul over operation */ - const float t = src2[3]; - const float mt = 1.0f - t; - - dst[0] = mt * src1[0] + src2[0]; - dst[1] = mt * src1[1] + src2[1]; - dst[2] = mt * src1[2] + src2[2]; - dst[3] = mt * src1[3] + t; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* premul over operation */ + const float t = src2[3]; + const float mt = 1.0f - t; + + dst[0] = mt * src1[0] + src2[0]; + dst[1] = mt * src1[1] + src2[1]; + dst[2] = mt * src1[2] + src2[2]; + dst[3] = mt * src1[3] + t; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_add_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* unpremul > add > premul, simplified */ - dst[0] = src1[0] + src2[0] * src1[3]; - dst[1] = src1[1] + src2[1] * src1[3]; - dst[2] = src1[2] + src2[2] * src1[3]; - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* unpremul > add > premul, simplified */ + dst[0] = src1[0] + src2[0] * src1[3]; + dst[1] = src1[1] + src2[1] * src1[3]; + dst[2] = src1[2] + src2[2] * src1[3]; + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_sub_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* unpremul > subtract > premul, simplified */ - dst[0] = max_ff(src1[0] - src2[0] * src1[3], 0.0f); - dst[1] = max_ff(src1[1] - src2[1] * src1[3], 0.0f); - dst[2] = max_ff(src1[2] - src2[2] * src1[3], 0.0f); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* unpremul > subtract > premul, simplified */ + dst[0] = max_ff(src1[0] - src2[0] * src1[3], 0.0f); + dst[1] = max_ff(src1[1] - src2[1] * src1[3], 0.0f); + dst[2] = max_ff(src1[2] - src2[2] * src1[3], 0.0f); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_mul_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* unpremul > multiply > premul, simplified */ - const float t = src2[3]; - const float mt = 1.0f - t; - - dst[0] = mt * src1[0] + src1[0] * src2[0] * src1[3]; - dst[1] = mt * src1[1] + src1[1] * src2[1] * src1[3]; - dst[2] = mt * src1[2] + src1[2] * src2[2] * src1[3]; - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* unpremul > multiply > premul, simplified */ + const float t = src2[3]; + const float mt = 1.0f - t; + + dst[0] = mt * src1[0] + src1[0] * src2[0] * src1[3]; + dst[1] = mt * src1[1] + src1[1] * src2[1] * src1[3]; + dst[2] = mt * src1[2] + src1[2] * src2[2] * src1[3]; + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* remap src2 to have same alpha as src1 premultiplied, take maximum of - * src1 and src2, then blend it with src1 */ - const float t = src2[3]; - const float mt = 1.0f - t; - const float map_alpha = src1[3] / src2[3]; - - dst[0] = mt * src1[0] + t * max_ff(src1[0], src2[0] * map_alpha); - dst[1] = mt * src1[1] + t * max_ff(src1[1], src2[1] * map_alpha); - dst[2] = mt * src1[2] + t * max_ff(src1[2], src2[2] * map_alpha); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* remap src2 to have same alpha as src1 premultiplied, take maximum of + * src1 and src2, then blend it with src1 */ + const float t = src2[3]; + const float mt = 1.0f - t; + const float map_alpha = src1[3] / src2[3]; + + dst[0] = mt * src1[0] + t * max_ff(src1[0], src2[0] * map_alpha); + dst[1] = mt * src1[1] + t * max_ff(src1[1], src2[1] * map_alpha); + dst[2] = mt * src1[2] + t * max_ff(src1[2], src2[2] * map_alpha); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f) { - /* remap src2 to have same alpha as src1 premultiplied, take minimum of - * src1 and src2, then blend it with src1 */ - const float t = src2[3]; - const float mt = 1.0f - t; - const float map_alpha = src1[3] / src2[3]; - - dst[0] = mt * src1[0] + t * min_ff(src1[0], src2[0] * map_alpha); - dst[1] = mt * src1[1] + t * min_ff(src1[1], src2[1] * map_alpha); - dst[2] = mt * src1[2] + t * min_ff(src1[2], src2[2] * map_alpha); - dst[3] = src1[3]; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f) { + /* remap src2 to have same alpha as src1 premultiplied, take minimum of + * src1 and src2, then blend it with src1 */ + const float t = src2[3]; + const float mt = 1.0f - t; + const float map_alpha = src1[3] / src2[3]; + + dst[0] = mt * src1[0] + t * min_ff(src1[0], src2[0] * map_alpha); + dst[1] = mt * src1[1] + t * min_ff(src1[1], src2[1] * map_alpha); + dst[2] = mt * src1[2] + t * min_ff(src1[2], src2[2] * map_alpha); + dst[3] = src1[3]; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f && src1[3] > 0.0f) { - /* subtract alpha and remap RGB channels to match */ - float alpha = max_ff(src1[3] - src2[3], 0.0f); - float map_alpha; - - if (alpha <= EPS_ALPHA) { - alpha = 0.0f; - } - - map_alpha = alpha / src1[3]; - - dst[0] = src1[0] * map_alpha; - dst[1] = src1[1] * map_alpha; - dst[2] = src1[2] * map_alpha; - dst[3] = alpha; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f && src1[3] > 0.0f) { + /* subtract alpha and remap RGB channels to match */ + float alpha = max_ff(src1[3] - src2[3], 0.0f); + float map_alpha; + + if (alpha <= EPS_ALPHA) { + alpha = 0.0f; + } + + map_alpha = alpha / src1[3]; + + dst[0] = src1[0] * map_alpha; + dst[1] = src1[1] * map_alpha; + dst[2] = src1[2] * map_alpha; + dst[3] = alpha; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]) { - if (src2[3] != 0.0f && src1[3] < 1.0f) { - /* add alpha and remap RGB channels to match */ - float alpha = min_ff(src1[3] + src2[3], 1.0f); - float map_alpha; - - if (alpha >= 1.0f - EPS_ALPHA) { - alpha = 1.0f; - } - - map_alpha = (src1[3] > 0.0f) ? alpha / src1[3] : 1.0f; - - dst[0] = src1[0] * map_alpha; - dst[1] = src1[1] * map_alpha; - dst[2] = src1[2] * map_alpha; - dst[3] = alpha; - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + if (src2[3] != 0.0f && src1[3] < 1.0f) { + /* add alpha and remap RGB channels to match */ + float alpha = min_ff(src1[3] + src2[3], 1.0f); + float map_alpha; + + if (alpha >= 1.0f - EPS_ALPHA) { + alpha = 1.0f; + } + + map_alpha = (src1[3] > 0.0f) ? alpha / src1[3] : 1.0f; + + dst[0] = src1[0] * map_alpha; + dst[1] = src1[1] * map_alpha; + dst[2] = src1[2] * map_alpha; + dst[3] = alpha; + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src1[i] > 0.5f) { - temp = 1.0f - (1.0f - 2.0f * (src1[i] - 0.5f)) * (1.0f - src2[i]); - } - else { - temp = 2.0f * src1[i] * src2[i]; - } - dst[i] = min_ff(temp * fac + src1[i] * mfac, 1.0f); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src1[i] > 0.5f) { + temp = 1.0f - (1.0f - 2.0f * (src1[i] - 0.5f)) * (1.0f - src2[i]); + } + else { + temp = 2.0f * src1[i] * src2[i]; + } + dst[i] = min_ff(temp * fac + src1[i] * mfac, 1.0f); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src2[i] > 0.5f) { - temp = 1.0f - ((1.0f - 2.0f * (src2[i] - 0.5f)) * (1.0f - src1[i])); - } - else { - temp = 2.0f * src2[i] * src1[i]; - } - dst[i] = min_ff((temp * fac + src1[i] * mfac) / 1.0f, 1.0f); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src2[i] > 0.5f) { + temp = 1.0f - ((1.0f - 2.0f * (src2[i] - 0.5f)) * (1.0f - src1[i])); + } + else { + temp = 2.0f * src2[i] * src1[i]; + } + dst[i] = min_ff((temp * fac + src1[i] * mfac) / 1.0f, 1.0f); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - const float temp = (src2[i] == 0.0f) ? 0.0f : max_ff(1.0f - ((1.0f - src1[i]) / src2[i]), 0.0f); - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + const float temp = (src2[i] == 0.0f) ? 0.0f : + max_ff(1.0f - ((1.0f - src1[i]) / src2[i]), 0.0f); + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - const float temp = max_ff(src1[i] + src2[i] - 1.0f, 0.0f); - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + const float temp = max_ff(src1[i] + src2[i] - 1.0f, 0.0f); + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - const float temp = (src2[i] >= 1.0f) ? 1.0f : min_ff(src1[i] / (1.0f - src2[i]), 1.0f); - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + const float temp = (src2[i] >= 1.0f) ? 1.0f : min_ff(src1[i] / (1.0f - src2[i]), 1.0f); + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - const float temp = max_ff(1.0f - ((1.0f - src1[i]) * (1.0f - src2[i])), 0.0f); - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + const float temp = max_ff(1.0f - ((1.0f - src1[i]) * (1.0f - src2[i])), 0.0f); + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src1[i] < 0.5f) { - temp = (src2[i] + 0.5f) * src1[i]; - } - else { - temp = 1.0f - ((1.0f - (src2[i] + 0.5f)) * (1.0f - src1[i])); - } - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src1[i] < 0.5f) { + temp = (src2[i] + 0.5f) * src1[i]; + } + else { + temp = 1.0f - ((1.0f - (src2[i] + 0.5f)) * (1.0f - src1[i])); + } + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src2[i] > 0.5f) { - temp = max_ff(2.0f * (src2[i] - 0.5f), src1[i]); - } - else { - temp = min_ff(2.0f * src2[i], src1[i]); - } - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src2[i] > 0.5f) { + temp = max_ff(2.0f * (src2[i] - 0.5f), src1[i]); + } + else { + temp = min_ff(2.0f * src2[i], src1[i]); + } + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src2[i] > 0.5f) { - temp = min_ff(src1[i] + 2.0f * (src2[i] - 0.5f), 1.0f); - } - else { - temp = max_ff(src1[i] + 2.0f * src2[i] - 1.0f, 0.0f); - } - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src2[i] > 0.5f) { + temp = min_ff(src1[i] + 2.0f * (src2[i] - 0.5f), 1.0f); + } + else { + temp = max_ff(src1[i] + 2.0f * src2[i] - 1.0f, 0.0f); + } + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - float temp; - - if (src2[i] == 1.0f) { - temp = (src1[i] == 0.0f) ? 0.5f : 1.0f; - } - else if (src2[i] == 0.0f) { - temp = (src1[i] == 1.0f) ? 0.5f : 0.0f; - } - else if (src2[i] > 0.5f) { - temp = min_ff(((src1[i]) * 1.0f) / (2.0f * (1.0f - src2[i])), 1.0f); - } - else { - temp = max_ff(1.0f - ((1.0f - src1[i]) * 1.0f / (2.0f * src2[i])), 0.0f); - } - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + float temp; + + if (src2[i] == 1.0f) { + temp = (src1[i] == 0.0f) ? 0.5f : 1.0f; + } + else if (src2[i] == 0.0f) { + temp = (src1[i] == 1.0f) ? 0.5f : 0.0f; + } + else if (src2[i] > 0.5f) { + temp = min_ff(((src1[i]) * 1.0f) / (2.0f * (1.0f - src2[i])), 1.0f); + } + else { + temp = max_ff(1.0f - ((1.0f - src1[i]) * 1.0f / (2.0f * src2[i])), 0.0f); + } + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - dst[i] = (fabsf(src1[i] - src2[i]) * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + dst[i] = (fabsf(src1[i] - src2[i]) * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - int i = 3; - - while (i--) { - const float temp = 0.5f - ((2 * (src1[i] - 0.5f) * (src2[i] - 0.5f))); - dst[i] = (temp * fac + src1[i] * mfac); - } - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } - + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + int i = 3; + + while (i--) { + const float temp = 0.5f - ((2 * (src1[i] - 0.5f) * (src2[i] - 0.5f))); + dst[i] = (temp * fac + src1[i] * mfac); + } + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - - rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); - rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); - - h1 = h2; - s1 = s2; - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (r * fac + src1[0] * mfac); - dst[1] = (g * fac + src1[1] * mfac); - dst[2] = (b * fac + src1[2] * mfac); - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + + rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); + rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); + + h1 = h2; + s1 = s2; + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (r * fac + src1[0] * mfac); + dst[1] = (g * fac + src1[1] * mfac); + dst[2] = (b * fac + src1[2] * mfac); + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - - rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); - rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); - - h1 = h2; - - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (r * fac + src1[0] * mfac); - dst[1] = (g * fac + src1[1] * mfac); - dst[2] = (b * fac + src1[2] * mfac); - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + + rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); + rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); + + h1 = h2; + + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (r * fac + src1[0] * mfac); + dst[1] = (g * fac + src1[1] * mfac); + dst[2] = (b * fac + src1[2] * mfac); + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - - rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); - rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); - - if (s1 > EPS_SATURATION) { - s1 = s2; - } - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (r * fac + src1[0] * mfac); - dst[1] = (g * fac + src1[1] * mfac); - dst[2] = (b * fac + src1[2] * mfac); - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + + rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); + rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); + + if (s1 > EPS_SATURATION) { + s1 = s2; + } + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (r * fac + src1[0] * mfac); + dst[1] = (g * fac + src1[1] * mfac); + dst[2] = (b * fac + src1[2] * mfac); + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4]) { - const float fac = src2[3]; - if (fac != 0.0f) { - const float mfac = 1.0f - fac; - float h1, s1, v1; - float h2, s2, v2; - float r, g, b; - - rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); - rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); - - v1 = v2; - hsv_to_rgb(h1, s1, v1, &r, &g, &b); - - dst[0] = (r * fac + src1[0] * mfac); - dst[1] = (g * fac + src1[1] * mfac); - dst[2] = (b * fac + src1[2] * mfac); - } - else { - /* no op */ - copy_v4_v4(dst, src1); - } + const float fac = src2[3]; + if (fac != 0.0f) { + const float mfac = 1.0f - fac; + float h1, s1, v1; + float h2, s2, v2; + float r, g, b; + + rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1); + rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2); + + v1 = v2; + hsv_to_rgb(h1, s1, v1, &r, &g, &b); + + dst[0] = (r * fac + src1[0] * mfac); + dst[1] = (g * fac + src1[1] * mfac); + dst[2] = (b * fac + src1[2] * mfac); + } + else { + /* no op */ + copy_v4_v4(dst, src1); + } } - -MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t) +MINLINE void blend_color_interpolate_float(float dst[4], + const float src1[4], + const float src2[4], + float t) { - /* interpolation, colors are premultiplied so it goes fine */ - const float mt = 1.0f - t; + /* interpolation, colors are premultiplied so it goes fine */ + const float mt = 1.0f - t; - dst[0] = mt * src1[0] + t * src2[0]; - dst[1] = mt * src1[1] + t * src2[1]; - dst[2] = mt * src1[2] + t * src2[2]; - dst[3] = mt * src1[3] + t * src2[3]; + dst[0] = mt * src1[0] + t * src2[0]; + dst[1] = mt * src1[1] + t * src2[1]; + dst[2] = mt * src1[2] + t * src2[2]; + dst[3] = mt * src1[3] + t * src2[3]; } -#undef EPS_SATURATION -#undef EPS_ALPHA +# undef EPS_SATURATION +# undef EPS_ALPHA #endif /* __MATH_COLOR_BLEND_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index bfe060a8826..1309eb12e4d 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -24,7 +24,6 @@ * \ingroup bli */ - #include "BLI_math_base.h" #include "BLI_math_color.h" #include "BLI_utildefines.h" @@ -32,97 +31,94 @@ #include "math.h" #ifndef __MATH_COLOR_INLINE_C__ -#define __MATH_COLOR_INLINE_C__ +# define __MATH_COLOR_INLINE_C__ /******************************** Color Space ********************************/ -#ifdef __SSE2__ +# ifdef __SSE2__ MALWAYS_INLINE __m128 srgb_to_linearrgb_v4_simd(const __m128 c) { - __m128 cmp = _mm_cmplt_ps(c, _mm_set1_ps(0.04045f)); - __m128 lt = _mm_max_ps(_mm_mul_ps(c, _mm_set1_ps(1.0f / 12.92f)), - _mm_set1_ps(0.0f)); - __m128 gtebase = _mm_mul_ps(_mm_add_ps(c, _mm_set1_ps(0.055f)), - _mm_set1_ps(1.0f / 1.055f)); /* fma */ - __m128 gte = _bli_math_fastpow24(gtebase); - return _bli_math_blend_sse(cmp, lt, gte); + __m128 cmp = _mm_cmplt_ps(c, _mm_set1_ps(0.04045f)); + __m128 lt = _mm_max_ps(_mm_mul_ps(c, _mm_set1_ps(1.0f / 12.92f)), _mm_set1_ps(0.0f)); + __m128 gtebase = _mm_mul_ps(_mm_add_ps(c, _mm_set1_ps(0.055f)), + _mm_set1_ps(1.0f / 1.055f)); /* fma */ + __m128 gte = _bli_math_fastpow24(gtebase); + return _bli_math_blend_sse(cmp, lt, gte); } MALWAYS_INLINE __m128 linearrgb_to_srgb_v4_simd(const __m128 c) { - __m128 cmp = _mm_cmplt_ps(c, _mm_set1_ps(0.0031308f)); - __m128 lt = _mm_max_ps(_mm_mul_ps(c, _mm_set1_ps(12.92f)), - _mm_set1_ps(0.0f)); - __m128 gte = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.055f), - _bli_math_fastpow512(c)), - _mm_set1_ps(-0.055f)); - return _bli_math_blend_sse(cmp, lt, gte); + __m128 cmp = _mm_cmplt_ps(c, _mm_set1_ps(0.0031308f)); + __m128 lt = _mm_max_ps(_mm_mul_ps(c, _mm_set1_ps(12.92f)), _mm_set1_ps(0.0f)); + __m128 gte = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.055f), _bli_math_fastpow512(c)), + _mm_set1_ps(-0.055f)); + return _bli_math_blend_sse(cmp, lt, gte); } MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]) { - float r[4] = {srgb[0], srgb[1], srgb[2], 1.0f}; - __m128 *rv = (__m128 *)&r; - *rv = srgb_to_linearrgb_v4_simd(*rv); - linear[0] = r[0]; - linear[1] = r[1]; - linear[2] = r[2]; + float r[4] = {srgb[0], srgb[1], srgb[2], 1.0f}; + __m128 *rv = (__m128 *)&r; + *rv = srgb_to_linearrgb_v4_simd(*rv); + linear[0] = r[0]; + linear[1] = r[1]; + linear[2] = r[2]; } MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]) { - float r[4] = {linear[0], linear[1], linear[2], 1.0f}; - __m128 *rv = (__m128 *)&r; - *rv = linearrgb_to_srgb_v4_simd(*rv); - srgb[0] = r[0]; - srgb[1] = r[1]; - srgb[2] = r[2]; + float r[4] = {linear[0], linear[1], linear[2], 1.0f}; + __m128 *rv = (__m128 *)&r; + *rv = linearrgb_to_srgb_v4_simd(*rv); + srgb[0] = r[0]; + srgb[1] = r[1]; + srgb[2] = r[2]; } -#else /* __SSE2__ */ +# else /* __SSE2__ */ MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]) { - linear[0] = srgb_to_linearrgb(srgb[0]); - linear[1] = srgb_to_linearrgb(srgb[1]); - linear[2] = srgb_to_linearrgb(srgb[2]); + linear[0] = srgb_to_linearrgb(srgb[0]); + linear[1] = srgb_to_linearrgb(srgb[1]); + linear[2] = srgb_to_linearrgb(srgb[2]); } MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]) { - srgb[0] = linearrgb_to_srgb(linear[0]); - srgb[1] = linearrgb_to_srgb(linear[1]); - srgb[2] = linearrgb_to_srgb(linear[2]); + srgb[0] = linearrgb_to_srgb(linear[0]); + srgb[1] = linearrgb_to_srgb(linear[1]); + srgb[2] = linearrgb_to_srgb(linear[2]); } -#endif /* __SSE2__ */ +# endif /* __SSE2__ */ MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]) { - srgb_to_linearrgb_v3_v3(linear, srgb); - linear[3] = srgb[3]; + srgb_to_linearrgb_v3_v3(linear, srgb); + linear[3] = srgb[3]; } MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]) { - linearrgb_to_srgb_v3_v3(srgb, linear); - srgb[3] = linear[3]; + linearrgb_to_srgb_v3_v3(srgb, linear); + srgb[3] = linear[3]; } MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3]) { - float srgb_f[3]; + float srgb_f[3]; - linearrgb_to_srgb_v3_v3(srgb_f, linear); - unit_float_to_uchar_clamp_v3(srgb, srgb_f); + linearrgb_to_srgb_v3_v3(srgb_f, linear); + unit_float_to_uchar_clamp_v3(srgb, srgb_f); } MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4]) { - float srgb_f[4]; + float srgb_f[4]; - linearrgb_to_srgb_v4(srgb_f, linear); - unit_float_to_uchar_clamp_v4(srgb, srgb_f); + linearrgb_to_srgb_v4(srgb_f, linear); + unit_float_to_uchar_clamp_v4(srgb, srgb_f); } /* predivide versions to work on associated/pre-multiplied alpha. if this should @@ -132,48 +128,48 @@ MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[ MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]) { - float alpha, inv_alpha; - - if (srgb[3] == 1.0f || srgb[3] == 0.0f) { - alpha = 1.0f; - inv_alpha = 1.0f; - } - else { - alpha = srgb[3]; - inv_alpha = 1.0f / alpha; - } - - linear[0] = srgb[0] * inv_alpha; - linear[1] = srgb[1] * inv_alpha; - linear[2] = srgb[2] * inv_alpha; - linear[3] = srgb[3]; - srgb_to_linearrgb_v3_v3(linear, linear); - linear[0] *= alpha; - linear[1] *= alpha; - linear[2] *= alpha; + float alpha, inv_alpha; + + if (srgb[3] == 1.0f || srgb[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = srgb[3]; + inv_alpha = 1.0f / alpha; + } + + linear[0] = srgb[0] * inv_alpha; + linear[1] = srgb[1] * inv_alpha; + linear[2] = srgb[2] * inv_alpha; + linear[3] = srgb[3]; + srgb_to_linearrgb_v3_v3(linear, linear); + linear[0] *= alpha; + linear[1] *= alpha; + linear[2] *= alpha; } MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]) { - float alpha, inv_alpha; - - if (linear[3] == 1.0f || linear[3] == 0.0f) { - alpha = 1.0f; - inv_alpha = 1.0f; - } - else { - alpha = linear[3]; - inv_alpha = 1.0f / alpha; - } - - srgb[0] = linear[0] * inv_alpha; - srgb[1] = linear[1] * inv_alpha; - srgb[2] = linear[2] * inv_alpha; - srgb[3] = linear[3]; - linearrgb_to_srgb_v3_v3(srgb, srgb); - srgb[0] *= alpha; - srgb[1] *= alpha; - srgb[2] *= alpha; + float alpha, inv_alpha; + + if (linear[3] == 1.0f || linear[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = linear[3]; + inv_alpha = 1.0f / alpha; + } + + srgb[0] = linear[0] * inv_alpha; + srgb[1] = linear[1] * inv_alpha; + srgb[2] = linear[2] * inv_alpha; + srgb[3] = linear[3]; + linearrgb_to_srgb_v3_v3(srgb, srgb); + srgb[0] *= alpha; + srgb[1] *= alpha; + srgb[2] *= alpha; } /* LUT accelerated conversions */ @@ -184,85 +180,87 @@ extern unsigned short BLI_color_to_srgb_table[0x10000]; MINLINE unsigned short to_srgb_table_lookup(const float f) { - union { - float f; - unsigned short us[2]; - } tmp; - tmp.f = f; -#ifdef __BIG_ENDIAN__ - return BLI_color_to_srgb_table[tmp.us[0]]; -#else - return BLI_color_to_srgb_table[tmp.us[1]]; -#endif + union { + float f; + unsigned short us[2]; + } tmp; + tmp.f = f; +# ifdef __BIG_ENDIAN__ + return BLI_color_to_srgb_table[tmp.us[0]]; +# else + return BLI_color_to_srgb_table[tmp.us[1]]; +# endif } MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4]) { - srgb[0] = to_srgb_table_lookup(linear[0]); - srgb[1] = to_srgb_table_lookup(linear[1]); - srgb[2] = to_srgb_table_lookup(linear[2]); - srgb[3] = unit_float_to_ushort_clamp(linear[3]); + srgb[0] = to_srgb_table_lookup(linear[0]); + srgb[1] = to_srgb_table_lookup(linear[1]); + srgb[2] = to_srgb_table_lookup(linear[2]); + srgb[3] = unit_float_to_ushort_clamp(linear[3]); } MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4]) { - linear[0] = BLI_color_from_srgb_table[srgb[0]]; - linear[1] = BLI_color_from_srgb_table[srgb[1]]; - linear[2] = BLI_color_from_srgb_table[srgb[2]]; - linear[3] = srgb[3] * (1.0f / 255.0f); + linear[0] = BLI_color_from_srgb_table[srgb[0]]; + linear[1] = BLI_color_from_srgb_table[srgb[1]]; + linear[2] = BLI_color_from_srgb_table[srgb[2]]; + linear[3] = srgb[3] * (1.0f / 255.0f); } MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4]) { - float fsrgb[4]; - int i; + float fsrgb[4]; + int i; - if (srgb[3] == 255 || srgb[3] == 0) { - srgb_to_linearrgb_uchar4(linear, srgb); - return; - } + if (srgb[3] == 255 || srgb[3] == 0) { + srgb_to_linearrgb_uchar4(linear, srgb); + return; + } - for (i = 0; i < 4; i++) { - fsrgb[i] = srgb[i] * (1.0f / 255.0f); - } + for (i = 0; i < 4; i++) { + fsrgb[i] = srgb[i] * (1.0f / 255.0f); + } - srgb_to_linearrgb_predivide_v4(linear, fsrgb); + srgb_to_linearrgb_predivide_v4(linear, fsrgb); } -MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a) +MINLINE void rgba_char_args_set( + char col[4], const char r, const char g, const char b, const char a) { - col[0] = r; - col[1] = g; - col[2] = b; - col[3] = a; + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; } -MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a) +MINLINE void rgba_float_args_set( + float col[4], const float r, const float g, const float b, const float a) { - col[0] = r; - col[1] = g; - col[2] = b; - col[3] = a; + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; } -MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a) +MINLINE void rgba_char_args_test_set( + char col[4], const char r, const char g, const char b, const char a) { - if (col[3] == 0) { - col[0] = r; - col[1] = g; - col[2] = b; - col[3] = a; - } + if (col[3] == 0) { + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; + } } MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) { - r_col[0] = ((pack) >> 0) & 0xFF; - r_col[1] = ((pack) >> 8) & 0xFF; - r_col[2] = ((pack) >> 16) & 0xFF; + r_col[0] = ((pack) >> 0) & 0xFF; + r_col[1] = ((pack) >> 8) & 0xFF; + r_col[2] = ((pack) >> 16) & 0xFF; } - /** \name RGB/Grayscale Functions * * \warning @@ -289,120 +287,121 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) */ MINLINE float rgb_to_grayscale(const float rgb[3]) { - return (0.2126f * rgb[0]) + (0.7152f * rgb[1]) + (0.0722f * rgb[2]); + return (0.2126f * rgb[0]) + (0.7152f * rgb[1]) + (0.0722f * rgb[2]); } MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]) { - return (unsigned char)(((54 * (unsigned short)rgb[0]) + - (182 * (unsigned short)rgb[1]) + - (19 * (unsigned short)rgb[2])) / 255); + return (unsigned char)(((54 * (unsigned short)rgb[0]) + (182 * (unsigned short)rgb[1]) + + (19 * (unsigned short)rgb[2])) / + 255); } /** \} */ - - -MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit) +MINLINE int compare_rgb_uchar(const unsigned char col_a[3], + const unsigned char col_b[3], + const int limit) { - const int r = (int)col_a[0] - (int)col_b[0]; - if (ABS(r) < limit) { - const int g = (int)col_a[1] - (int)col_b[1]; - if (ABS(g) < limit) { - const int b = (int)col_a[2] - (int)col_b[2]; - if (ABS(b) < limit) { - return 1; - } - } - } - - return 0; + const int r = (int)col_a[0] - (int)col_b[0]; + if (ABS(r) < limit) { + const int g = (int)col_a[1] - (int)col_b[1]; + if (ABS(g) < limit) { + const int b = (int)col_a[2] - (int)col_b[2]; + if (ABS(b) < limit) { + return 1; + } + } + } + + return 0; } MINLINE float dither_random_value(float s, float t) { - static float vec[2] = {12.9898f, 78.233f}; - float value; + static float vec[2] = {12.9898f, 78.233f}; + float value; - value = sinf(s * vec[0] + t * vec[1]) * 43758.5453f; - return value - floorf(value); + value = sinf(s * vec[0] + t * vec[1]) * 43758.5453f; + return value - floorf(value); } -MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float dither, float s, float t) +MINLINE void float_to_byte_dither_v3( + unsigned char b[3], const float f[3], float dither, float s, float t) { - float dither_value = dither_random_value(s, t) * 0.005f * dither; + float dither_value = dither_random_value(s, t) * 0.005f * dither; - b[0] = unit_float_to_uchar_clamp(dither_value + f[0]); - b[1] = unit_float_to_uchar_clamp(dither_value + f[1]); - b[2] = unit_float_to_uchar_clamp(dither_value + f[2]); + b[0] = unit_float_to_uchar_clamp(dither_value + f[0]); + b[1] = unit_float_to_uchar_clamp(dither_value + f[1]); + b[2] = unit_float_to_uchar_clamp(dither_value + f[2]); } /**************** Alpha Transformations *****************/ MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4]) { - if (premul[3] == 0.0f || premul[3] == 1.0f) { - straight[0] = premul[0]; - straight[1] = premul[1]; - straight[2] = premul[2]; - straight[3] = premul[3]; - } - else { - const float alpha_inv = 1.0f / premul[3]; - straight[0] = premul[0] * alpha_inv; - straight[1] = premul[1] * alpha_inv; - straight[2] = premul[2] * alpha_inv; - straight[3] = premul[3]; - } + if (premul[3] == 0.0f || premul[3] == 1.0f) { + straight[0] = premul[0]; + straight[1] = premul[1]; + straight[2] = premul[2]; + straight[3] = premul[3]; + } + else { + const float alpha_inv = 1.0f / premul[3]; + straight[0] = premul[0] * alpha_inv; + straight[1] = premul[1] * alpha_inv; + straight[2] = premul[2] * alpha_inv; + straight[3] = premul[3]; + } } MINLINE void premul_to_straight_v4(float color[4]) { - premul_to_straight_v4_v4(color, color); + premul_to_straight_v4_v4(color, color); } MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4]) { - const float alpha = straight[3]; - premul[0] = straight[0] * alpha; - premul[1] = straight[1] * alpha; - premul[2] = straight[2] * alpha; - premul[3] = straight[3]; + const float alpha = straight[3]; + premul[0] = straight[0] * alpha; + premul[1] = straight[1] * alpha; + premul[2] = straight[2] * alpha; + premul[3] = straight[3]; } MINLINE void straight_to_premul_v4(float color[4]) { - straight_to_premul_v4_v4(color, color); + straight_to_premul_v4_v4(color, color); } MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]) { - const float alpha = color[3] * (1.0f / 255.0f); - const float fac = alpha * (1.0f / 255.0f); + const float alpha = color[3] * (1.0f / 255.0f); + const float fac = alpha * (1.0f / 255.0f); - result[0] = color[0] * fac; - result[1] = color[1] * fac; - result[2] = color[2] * fac; - result[3] = alpha; + result[0] = color[0] * fac; + result[1] = color[1] * fac; + result[2] = color[2] * fac; + result[3] = alpha; } MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]) { - if (color[3] == 0.0f || color[3] == 1.0f) { - result[0] = unit_float_to_uchar_clamp(color[0]); - result[1] = unit_float_to_uchar_clamp(color[1]); - result[2] = unit_float_to_uchar_clamp(color[2]); - result[3] = unit_float_to_uchar_clamp(color[3]); - } - else { - const float alpha_inv = 1.0f / color[3]; - - /* hopefully this would be optimized */ - result[0] = unit_float_to_uchar_clamp(color[0] * alpha_inv); - result[1] = unit_float_to_uchar_clamp(color[1] * alpha_inv); - result[2] = unit_float_to_uchar_clamp(color[2] * alpha_inv); - result[3] = unit_float_to_uchar_clamp(color[3]); - } + if (color[3] == 0.0f || color[3] == 1.0f) { + result[0] = unit_float_to_uchar_clamp(color[0]); + result[1] = unit_float_to_uchar_clamp(color[1]); + result[2] = unit_float_to_uchar_clamp(color[2]); + result[3] = unit_float_to_uchar_clamp(color[3]); + } + else { + const float alpha_inv = 1.0f / color[3]; + + /* hopefully this would be optimized */ + result[0] = unit_float_to_uchar_clamp(color[0] * alpha_inv); + result[1] = unit_float_to_uchar_clamp(color[1] * alpha_inv); + result[2] = unit_float_to_uchar_clamp(color[2] * alpha_inv); + result[3] = unit_float_to_uchar_clamp(color[3]); + } } #endif /* __MATH_COLOR_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 7c9c3844843..7d7ff3f450f 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -36,54 +36,55 @@ void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]) { - float n1[3], n2[3]; + float n1[3], n2[3]; - n1[0] = v1[0] - v2[0]; - n2[0] = v2[0] - v3[0]; - n1[1] = v1[1] - v2[1]; - n2[1] = v2[1] - v3[1]; - n1[2] = v1[2] - v2[2]; - n2[2] = v2[2] - v3[2]; - n[0] = n1[1] * n2[2] - n1[2] * n2[1]; - n[1] = n1[2] * n2[0] - n1[0] * n2[2]; - n[2] = n1[0] * n2[1] - n1[1] * n2[0]; + n1[0] = v1[0] - v2[0]; + n2[0] = v2[0] - v3[0]; + n1[1] = v1[1] - v2[1]; + n2[1] = v2[1] - v3[1]; + n1[2] = v1[2] - v2[2]; + n2[2] = v2[2] - v3[2]; + n[0] = n1[1] * n2[2] - n1[2] * n2[1]; + n[1] = n1[2] * n2[0] - n1[0] * n2[2]; + n[2] = n1[0] * n2[1] - n1[1] * n2[0]; } float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]) { - float n1[3], n2[3]; + float n1[3], n2[3]; - n1[0] = v1[0] - v2[0]; - n2[0] = v2[0] - v3[0]; - n1[1] = v1[1] - v2[1]; - n2[1] = v2[1] - v3[1]; - n1[2] = v1[2] - v2[2]; - n2[2] = v2[2] - v3[2]; - n[0] = n1[1] * n2[2] - n1[2] * n2[1]; - n[1] = n1[2] * n2[0] - n1[0] * n2[2]; - n[2] = n1[0] * n2[1] - n1[1] * n2[0]; + n1[0] = v1[0] - v2[0]; + n2[0] = v2[0] - v3[0]; + n1[1] = v1[1] - v2[1]; + n2[1] = v2[1] - v3[1]; + n1[2] = v1[2] - v2[2]; + n2[2] = v2[2] - v3[2]; + n[0] = n1[1] * n2[2] - n1[2] * n2[1]; + n[1] = n1[2] * n2[0] - n1[0] * n2[2]; + n[2] = n1[0] * n2[1] - n1[1] * n2[0]; - return normalize_v3(n); + return normalize_v3(n); } -float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +float normal_quad_v3( + float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - /* real cross! */ - float n1[3], n2[3]; + /* real cross! */ + float n1[3], n2[3]; - n1[0] = v1[0] - v3[0]; - n1[1] = v1[1] - v3[1]; - n1[2] = v1[2] - v3[2]; + n1[0] = v1[0] - v3[0]; + n1[1] = v1[1] - v3[1]; + n1[2] = v1[2] - v3[2]; - n2[0] = v2[0] - v4[0]; - n2[1] = v2[1] - v4[1]; - n2[2] = v2[2] - v4[2]; + n2[0] = v2[0] - v4[0]; + n2[1] = v2[1] - v4[1]; + n2[2] = v2[2] - v4[2]; - n[0] = n1[1] * n2[2] - n1[2] * n2[1]; - n[1] = n1[2] * n2[0] - n1[0] * n2[2]; - n[2] = n1[0] * n2[1] - n1[1] * n2[0]; + n[0] = n1[1] * n2[2] - n1[2] * n2[1]; + n[1] = n1[2] * n2[0] - n1[0] * n2[2]; + n[2] = n1[0] * n2[1] - n1[1] * n2[0]; - return normalize_v3(n); + return normalize_v3(n); } /** @@ -93,67 +94,73 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo */ float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr) { - cross_poly_v3(n, verts, nr); - return normalize_v3(n); + cross_poly_v3(n, verts, nr); + return normalize_v3(n); } float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; - return area_poly_v3(verts, 4); + const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; + return area_poly_v3(verts, 4); } -float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +float area_squared_quad_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3]) { - const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; - return area_squared_poly_v3(verts, 4); + const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; + return area_squared_poly_v3(verts, 4); } /* Triangles */ float area_tri_v3(const float v1[3], const float v2[3], const float v3[3]) { - float n[3]; - cross_tri_v3(n, v1, v2, v3); - return len_v3(n) * 0.5f; + float n[3]; + cross_tri_v3(n, v1, v2, v3); + return len_v3(n) * 0.5f; } float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3]) { - float n[3]; - cross_tri_v3(n, v1, v2, v3); - mul_v3_fl(n, 0.5f); - return len_squared_v3(n); + float n[3]; + cross_tri_v3(n, v1, v2, v3); + mul_v3_fl(n, 0.5f); + return len_squared_v3(n); } -float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]) +float area_tri_signed_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float normal[3]) { - float area, n[3]; + float area, n[3]; - cross_tri_v3(n, v1, v2, v3); - area = len_v3(n) * 0.5f; + cross_tri_v3(n, v1, v2, v3); + area = len_v3(n) * 0.5f; - /* negate area for flipped triangles */ - if (dot_v3v3(n, normal) < 0.0f) { - area = -area; - } + /* negate area for flipped triangles */ + if (dot_v3v3(n, normal) < 0.0f) { + area = -area; + } - return area; + return area; } float area_poly_v3(const float verts[][3], unsigned int nr) { - float n[3]; - cross_poly_v3(n, verts, nr); - return len_v3(n) * 0.5f; + float n[3]; + cross_poly_v3(n, verts, nr); + return len_v3(n) * 0.5f; } float area_squared_poly_v3(const float verts[][3], unsigned int nr) { - float n[3]; + float n[3]; - cross_poly_v3(n, verts, nr); - mul_v3_fl(n, 0.5f); - return len_squared_v3(n); + cross_poly_v3(n, verts, nr); + mul_v3_fl(n, 0.5f); + return len_squared_v3(n); } /** @@ -164,69 +171,69 @@ float area_squared_poly_v3(const float verts[][3], unsigned int nr) */ float cross_poly_v2(const float verts[][2], unsigned int nr) { - unsigned int a; - float cross; - const float *co_curr, *co_prev; + unsigned int a; + float cross; + const float *co_curr, *co_prev; - /* The Trapezium Area Rule */ - co_prev = verts[nr - 1]; - co_curr = verts[0]; - cross = 0.0f; - for (a = 0; a < nr; a++) { - cross += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]); - co_prev = co_curr; - co_curr += 2; - } + /* The Trapezium Area Rule */ + co_prev = verts[nr - 1]; + co_curr = verts[0]; + cross = 0.0f; + for (a = 0; a < nr; a++) { + cross += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]); + co_prev = co_curr; + co_curr += 2; + } - return cross; + return cross; } void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr) { - const float *v_prev = verts[nr - 1]; - const float *v_curr = verts[0]; - unsigned int i; + const float *v_prev = verts[nr - 1]; + const float *v_curr = verts[0]; + unsigned int i; - zero_v3(n); + zero_v3(n); - /* Newell's Method */ - for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) { - add_newell_cross_v3_v3v3(n, v_prev, v_curr); - } + /* Newell's Method */ + for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) { + add_newell_cross_v3_v3v3(n, v_prev, v_curr); + } } float area_poly_v2(const float verts[][2], unsigned int nr) { - return fabsf(0.5f * cross_poly_v2(verts, nr)); + return fabsf(0.5f * cross_poly_v2(verts, nr)); } float area_poly_signed_v2(const float verts[][2], unsigned int nr) { - return (0.5f * cross_poly_v2(verts, nr)); + return (0.5f * cross_poly_v2(verts, nr)); } float area_squared_poly_v2(const float verts[][2], unsigned int nr) { - float area = area_poly_signed_v2(verts, nr); - return area * area; + float area = area_poly_signed_v2(verts, nr); + return area * area; } float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]) { - float a[3], b[3], c[3], c_len; + float a[3], b[3], c[3], c_len; - sub_v3_v3v3(a, v2, v1); - sub_v3_v3v3(b, v3, v1); - cross_v3_v3v3(c, a, b); + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v3, v1); + cross_v3_v3v3(c, a, b); - c_len = len_v3(c); + c_len = len_v3(c); - if (c_len > FLT_EPSILON) { - return dot_v3v3(a, b) / c_len; - } - else { - return 0.0f; - } + if (c_len > FLT_EPSILON) { + return dot_v3v3(a, b) / c_len; + } + else { + return 0.0f; + } } /********************************* Planes **********************************/ @@ -237,8 +244,8 @@ float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float */ void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]) { - copy_v3_v3(r_plane, plane_no); - r_plane[3] = -dot_v3v3(r_plane, plane_co); + copy_v3_v3(r_plane, plane_no); + r_plane[3] = -dot_v3v3(r_plane, plane_co); } /** @@ -246,17 +253,19 @@ void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const */ void plane_to_point_vector_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]) { - mul_v3_v3fl(r_plane_co, plane, (-plane[3] / len_squared_v3(plane))); - copy_v3_v3(r_plane_no, plane); + mul_v3_v3fl(r_plane_co, plane, (-plane[3] / len_squared_v3(plane))); + copy_v3_v3(r_plane_no, plane); } /** * version of #plane_to_point_vector_v3 that gets a unit length vector. */ -void plane_to_point_vector_v3_normalized(const float plane[4], float r_plane_co[3], float r_plane_no[3]) +void plane_to_point_vector_v3_normalized(const float plane[4], + float r_plane_co[3], + float r_plane_no[3]) { - const float length = normalize_v3_v3(r_plane_no, plane); - mul_v3_v3fl(r_plane_co, r_plane_no, (-plane[3] / length)); + const float length = normalize_v3_v3(r_plane_no, plane); + mul_v3_v3fl(r_plane_co, r_plane_no, (-plane[3] / length)); } /********************************* Volume **********************************/ @@ -264,96 +273,107 @@ void plane_to_point_vector_v3_normalized(const float plane[4], float r_plane_co[ /** * The volume from a tetrahedron, points can be in any order */ -float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +float volume_tetrahedron_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3]) { - float m[3][3]; - sub_v3_v3v3(m[0], v1, v2); - sub_v3_v3v3(m[1], v2, v3); - sub_v3_v3v3(m[2], v3, v4); - return fabsf(determinant_m3_array(m)) / 6.0f; + float m[3][3]; + sub_v3_v3v3(m[0], v1, v2); + sub_v3_v3v3(m[1], v2, v3); + sub_v3_v3v3(m[2], v3, v4); + return fabsf(determinant_m3_array(m)) / 6.0f; } /** * The volume from a tetrahedron, normal pointing inside gives negative volume */ -float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +float volume_tetrahedron_signed_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3]) { - float m[3][3]; - sub_v3_v3v3(m[0], v1, v2); - sub_v3_v3v3(m[1], v2, v3); - sub_v3_v3v3(m[2], v3, v4); - return determinant_m3_array(m) / 6.0f; + float m[3][3]; + sub_v3_v3v3(m[0], v1, v2); + sub_v3_v3v3(m[1], v2, v3); + sub_v3_v3v3(m[2], v3, v4); + return determinant_m3_array(m) / 6.0f; } - /********************************* Distance **********************************/ /* distance p to line v1-v2 * using Hesse formula, NO LINE PIECE! */ float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2]) { - float closest[2]; + float closest[2]; - closest_to_line_v2(closest, p, l1, l2); + closest_to_line_v2(closest, p, l1, l2); - return len_squared_v2v2(closest, p); + return len_squared_v2v2(closest, p); } float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2]) { - return sqrtf(dist_squared_to_line_v2(p, l1, l2)); + return sqrtf(dist_squared_to_line_v2(p, l1, l2)); } /* distance p to line-piece v1-v2 */ float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]) { - float closest[2]; + float closest[2]; - closest_to_line_segment_v2(closest, p, l1, l2); + closest_to_line_segment_v2(closest, p, l1, l2); - return len_squared_v2v2(closest, p); + return len_squared_v2v2(closest, p); } float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]) { - return sqrtf(dist_squared_to_line_segment_v2(p, l1, l2)); + return sqrtf(dist_squared_to_line_segment_v2(p, l1, l2)); } /* point closest to v1 on line v2-v3 in 2D */ -void closest_to_line_segment_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2]) +void closest_to_line_segment_v2(float r_close[2], + const float p[2], + const float l1[2], + const float l2[2]) { - float lambda, cp[2]; + float lambda, cp[2]; - lambda = closest_to_line_v2(cp, p, l1, l2); + lambda = closest_to_line_v2(cp, p, l1, l2); - /* flip checks for !finite case (when segment is a point) */ - if (!(lambda > 0.0f)) { - copy_v2_v2(r_close, l1); - } - else if (!(lambda < 1.0f)) { - copy_v2_v2(r_close, l2); - } - else { - copy_v2_v2(r_close, cp); - } + /* flip checks for !finite case (when segment is a point) */ + if (!(lambda > 0.0f)) { + copy_v2_v2(r_close, l1); + } + else if (!(lambda < 1.0f)) { + copy_v2_v2(r_close, l2); + } + else { + copy_v2_v2(r_close, cp); + } } /* point closest to v1 on line v2-v3 in 3D */ -void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]) +void closest_to_line_segment_v3(float r_close[3], + const float p[3], + const float l1[3], + const float l2[3]) { - float lambda, cp[3]; + float lambda, cp[3]; - lambda = closest_to_line_v3(cp, p, l1, l2); + lambda = closest_to_line_v3(cp, p, l1, l2); - /* flip checks for !finite case (when segment is a point) */ - if (!(lambda > 0.0f)) { - copy_v3_v3(r_close, l1); - } - else if (!(lambda < 1.0f)) { - copy_v3_v3(r_close, l2); - } - else { - copy_v3_v3(r_close, cp); - } + /* flip checks for !finite case (when segment is a point) */ + if (!(lambda > 0.0f)) { + copy_v3_v3(r_close, l1); + } + else if (!(lambda < 1.0f)) { + copy_v3_v3(r_close, l2); + } + else { + copy_v3_v3(r_close, cp); + } } /** @@ -367,62 +387,62 @@ void closest_to_line_segment_v3(float r_close[3], const float p[3], const float */ void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3]) { - const float len_sq = len_squared_v3(plane); - const float side = plane_point_side_v3(plane, pt); - madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq); + const float len_sq = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq); } void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3]) { - const float side = plane_point_side_v3(plane, pt); - BLI_ASSERT_UNIT_V3(plane); - madd_v3_v3v3fl(r_close, pt, plane, -side); + const float side = plane_point_side_v3(plane, pt); + BLI_ASSERT_UNIT_V3(plane); + madd_v3_v3v3fl(r_close, pt, plane, -side); } void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3]) { - const float len_sq = len_squared_v3(plane); - const float side = dot_v3v3(plane, pt); - madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq); + const float len_sq = len_squared_v3(plane); + const float side = dot_v3v3(plane, pt); + madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq); } void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3]) { - const float side = dot_v3v3(plane, pt); - BLI_ASSERT_UNIT_V3(plane); - madd_v3_v3v3fl(r_close, pt, plane, -side); + const float side = dot_v3v3(plane, pt); + BLI_ASSERT_UNIT_V3(plane); + madd_v3_v3v3fl(r_close, pt, plane, -side); } float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4]) { - const float len_sq = len_squared_v3(plane); - const float side = plane_point_side_v3(plane, pt); - const float fac = side / len_sq; - return copysignf(len_sq * (fac * fac), side); + const float len_sq = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + const float fac = side / len_sq; + return copysignf(len_sq * (fac * fac), side); } float dist_squared_to_plane_v3(const float pt[3], const float plane[4]) { - const float len_sq = len_squared_v3(plane); - const float side = plane_point_side_v3(plane, pt); - const float fac = side / len_sq; - /* only difference to code above - no 'copysignf' */ - return len_sq * (fac * fac); + const float len_sq = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + const float fac = side / len_sq; + /* only difference to code above - no 'copysignf' */ + return len_sq * (fac * fac); } float dist_signed_squared_to_plane3_v3(const float pt[3], const float plane[3]) { - const float len_sq = len_squared_v3(plane); - const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ - const float fac = side / len_sq; - return copysignf(len_sq * (fac * fac), side); + const float len_sq = len_squared_v3(plane); + const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ + const float fac = side / len_sq; + return copysignf(len_sq * (fac * fac), side); } float dist_squared_to_plane3_v3(const float pt[3], const float plane[3]) { - const float len_sq = len_squared_v3(plane); - const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ - const float fac = side / len_sq; - /* only difference to code above - no 'copysignf' */ - return len_sq * (fac * fac); + const float len_sq = len_squared_v3(plane); + const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ + const float fac = side / len_sq; + /* only difference to code above - no 'copysignf' */ + return len_sq * (fac * fac); } /** @@ -430,54 +450,54 @@ float dist_squared_to_plane3_v3(const float pt[3], const float plane[3]) */ float dist_signed_to_plane_v3(const float pt[3], const float plane[4]) { - const float len_sq = len_squared_v3(plane); - const float side = plane_point_side_v3(plane, pt); - const float fac = side / len_sq; - return sqrtf(len_sq) * fac; + const float len_sq = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + const float fac = side / len_sq; + return sqrtf(len_sq) * fac; } float dist_to_plane_v3(const float pt[3], const float plane[4]) { - return fabsf(dist_signed_to_plane_v3(pt, plane)); + return fabsf(dist_signed_to_plane_v3(pt, plane)); } float dist_signed_to_plane3_v3(const float pt[3], const float plane[3]) { - const float len_sq = len_squared_v3(plane); - const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ - const float fac = side / len_sq; - return sqrtf(len_sq) * fac; + const float len_sq = len_squared_v3(plane); + const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */ + const float fac = side / len_sq; + return sqrtf(len_sq) * fac; } float dist_to_plane3_v3(const float pt[3], const float plane[3]) { - return fabsf(dist_signed_to_plane3_v3(pt, plane)); + return fabsf(dist_signed_to_plane3_v3(pt, plane)); } /* distance v1 to line-piece l1-l2 in 3D */ float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]) { - float closest[3]; + float closest[3]; - closest_to_line_segment_v3(closest, p, l1, l2); + closest_to_line_segment_v3(closest, p, l1, l2); - return len_squared_v3v3(closest, p); + return len_squared_v3v3(closest, p); } float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]) { - return sqrtf(dist_squared_to_line_segment_v3(p, l1, l2)); + return sqrtf(dist_squared_to_line_segment_v3(p, l1, l2)); } float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3]) { - float closest[3]; + float closest[3]; - closest_to_line_v3(closest, p, l1, l2); + closest_to_line_v3(closest, p, l1, l2); - return len_squared_v3v3(closest, p); + return len_squared_v3v3(closest, p); } float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]) { - return sqrtf(dist_squared_to_line_v3(p, l1, l2)); + return sqrtf(dist_squared_to_line_v3(p, l1, l2)); } /** @@ -503,55 +523,56 @@ float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]) * x - also outside * </pre> */ -float dist_signed_squared_to_corner_v3v3v3( - const float p[3], - const float v1[3], const float v2[3], const float v3[3], - const float axis_ref[3]) -{ - float dir_a[3], dir_b[3]; - float plane_a[3], plane_b[3]; - float dist_a, dist_b; - float axis[3]; - float s_p_v2[3]; - bool flip = false; - - sub_v3_v3v3(dir_a, v1, v2); - sub_v3_v3v3(dir_b, v3, v2); - - cross_v3_v3v3(axis, dir_a, dir_b); - - if ((len_squared_v3(axis) < FLT_EPSILON)) { - copy_v3_v3(axis, axis_ref); - } - else if (dot_v3v3(axis, axis_ref) < 0.0f) { - /* concave */ - flip = true; - negate_v3(axis); - } - - cross_v3_v3v3(plane_a, dir_a, axis); - cross_v3_v3v3(plane_b, axis, dir_b); +float dist_signed_squared_to_corner_v3v3v3(const float p[3], + const float v1[3], + const float v2[3], + const float v3[3], + const float axis_ref[3]) +{ + float dir_a[3], dir_b[3]; + float plane_a[3], plane_b[3]; + float dist_a, dist_b; + float axis[3]; + float s_p_v2[3]; + bool flip = false; + + sub_v3_v3v3(dir_a, v1, v2); + sub_v3_v3v3(dir_b, v3, v2); + + cross_v3_v3v3(axis, dir_a, dir_b); + + if ((len_squared_v3(axis) < FLT_EPSILON)) { + copy_v3_v3(axis, axis_ref); + } + else if (dot_v3v3(axis, axis_ref) < 0.0f) { + /* concave */ + flip = true; + negate_v3(axis); + } + + cross_v3_v3v3(plane_a, dir_a, axis); + cross_v3_v3v3(plane_b, axis, dir_b); #if 0 - plane_from_point_normal_v3(plane_a, v2, plane_a); - plane_from_point_normal_v3(plane_b, v2, plane_b); + plane_from_point_normal_v3(plane_a, v2, plane_a); + plane_from_point_normal_v3(plane_b, v2, plane_b); - dist_a = dist_signed_squared_to_plane_v3(p, plane_a); - dist_b = dist_signed_squared_to_plane_v3(p, plane_b); + dist_a = dist_signed_squared_to_plane_v3(p, plane_a); + dist_b = dist_signed_squared_to_plane_v3(p, plane_b); #else - /* calculate without the planes 4th component to avoid float precision issues */ - sub_v3_v3v3(s_p_v2, p, v2); + /* calculate without the planes 4th component to avoid float precision issues */ + sub_v3_v3v3(s_p_v2, p, v2); - dist_a = dist_signed_squared_to_plane3_v3(s_p_v2, plane_a); - dist_b = dist_signed_squared_to_plane3_v3(s_p_v2, plane_b); + dist_a = dist_signed_squared_to_plane3_v3(s_p_v2, plane_a); + dist_b = dist_signed_squared_to_plane3_v3(s_p_v2, plane_b); #endif - if (flip) { - return min_ff(dist_a, dist_b); - } - else { - return max_ff(dist_a, dist_b); - } + if (flip) { + return min_ff(dist_a, dist_b); + } + else { + return max_ff(dist_a, dist_b); + } } /** @@ -560,220 +581,220 @@ float dist_signed_squared_to_corner_v3v3v3( * \param ray_direction: Normalized direction of the line. * \param co: Point to which the distance is to be calculated. */ -float dist_squared_to_ray_v3_normalized( - const float ray_origin[3], const float ray_direction[3], - const float co[3]) +float dist_squared_to_ray_v3_normalized(const float ray_origin[3], + const float ray_direction[3], + const float co[3]) { - float origin_to_co[3]; - sub_v3_v3v3(origin_to_co, co, ray_origin); + float origin_to_co[3]; + sub_v3_v3v3(origin_to_co, co, ray_origin); - float origin_to_proj[3]; - project_v3_v3v3_normalized(origin_to_proj, origin_to_co, ray_direction); + float origin_to_proj[3]; + project_v3_v3v3_normalized(origin_to_proj, origin_to_co, ray_direction); - float co_projected_on_ray[3]; - add_v3_v3v3(co_projected_on_ray, ray_origin, origin_to_proj); + float co_projected_on_ray[3]; + add_v3_v3v3(co_projected_on_ray, ray_origin, origin_to_proj); - return len_squared_v3v3(co, co_projected_on_ray); + return len_squared_v3v3(co, co_projected_on_ray); } - /** * Find the closest point in a seg to a ray and return the distance squared. * \param r_point: Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel). * \param r_depth: the distance of r_point projection on ray to the ray_origin. */ -float dist_squared_ray_to_seg_v3( - const float ray_origin[3], const float ray_direction[3], - const float v0[3], const float v1[3], - float r_point[3], float *r_depth) -{ - float lambda, depth; - if (isect_ray_seg_v3( - ray_origin, ray_direction, v0, v1, &lambda)) - { - if (lambda <= 0.0f) { - copy_v3_v3(r_point, v0); - } - else if (lambda >= 1.0f) { - copy_v3_v3(r_point, v1); - } - else { - interp_v3_v3v3(r_point, v0, v1, lambda); - } - } - else { - /* has no nearest point, only distance squared. */ - /* Calculate the distance to the point v0 then */ - copy_v3_v3(r_point, v0); - } - - float dvec[3]; - sub_v3_v3v3(dvec, r_point, ray_origin); - depth = dot_v3v3(dvec, ray_direction); - - if (r_depth) { - *r_depth = depth; - } - - return len_squared_v3(dvec) - SQUARE(depth); +float dist_squared_ray_to_seg_v3(const float ray_origin[3], + const float ray_direction[3], + const float v0[3], + const float v1[3], + float r_point[3], + float *r_depth) +{ + float lambda, depth; + if (isect_ray_seg_v3(ray_origin, ray_direction, v0, v1, &lambda)) { + if (lambda <= 0.0f) { + copy_v3_v3(r_point, v0); + } + else if (lambda >= 1.0f) { + copy_v3_v3(r_point, v1); + } + else { + interp_v3_v3v3(r_point, v0, v1, lambda); + } + } + else { + /* has no nearest point, only distance squared. */ + /* Calculate the distance to the point v0 then */ + copy_v3_v3(r_point, v0); + } + + float dvec[3]; + sub_v3_v3v3(dvec, r_point, ray_origin); + depth = dot_v3v3(dvec, ray_direction); + + if (r_depth) { + *r_depth = depth; + } + + return len_squared_v3(dvec) - SQUARE(depth); } - /* Returns the coordinates of the nearest vertex and * the farthest vertex from a plane (or normal). */ -void aabb_get_near_far_from_plane( - const float plane_no[3], const float bbmin[3], const float bbmax[3], - float bb_near[3], float bb_afar[3]) -{ - if (plane_no[0] < 0.0f) { - bb_near[0] = bbmax[0]; - bb_afar[0] = bbmin[0]; - } - else { - bb_near[0] = bbmin[0]; - bb_afar[0] = bbmax[0]; - } - if (plane_no[1] < 0.0f) { - bb_near[1] = bbmax[1]; - bb_afar[1] = bbmin[1]; - } - else { - bb_near[1] = bbmin[1]; - bb_afar[1] = bbmax[1]; - } - if (plane_no[2] < 0.0f) { - bb_near[2] = bbmax[2]; - bb_afar[2] = bbmin[2]; - } - else { - bb_near[2] = bbmin[2]; - bb_afar[2] = bbmax[2]; - } +void aabb_get_near_far_from_plane(const float plane_no[3], + const float bbmin[3], + const float bbmax[3], + float bb_near[3], + float bb_afar[3]) +{ + if (plane_no[0] < 0.0f) { + bb_near[0] = bbmax[0]; + bb_afar[0] = bbmin[0]; + } + else { + bb_near[0] = bbmin[0]; + bb_afar[0] = bbmax[0]; + } + if (plane_no[1] < 0.0f) { + bb_near[1] = bbmax[1]; + bb_afar[1] = bbmin[1]; + } + else { + bb_near[1] = bbmin[1]; + bb_afar[1] = bbmax[1]; + } + if (plane_no[2] < 0.0f) { + bb_near[2] = bbmax[2]; + bb_afar[2] = bbmin[2]; + } + else { + bb_near[2] = bbmin[2]; + bb_afar[2] = bbmax[2]; + } } /* -------------------------------------------------------------------- */ /** \name dist_squared_to_ray_to_aabb and helpers * \{ */ -void dist_squared_ray_to_aabb_v3_precalc( - struct DistRayAABB_Precalc *neasrest_precalc, - const float ray_origin[3], const float ray_direction[3]) +void dist_squared_ray_to_aabb_v3_precalc(struct DistRayAABB_Precalc *neasrest_precalc, + const float ray_origin[3], + const float ray_direction[3]) { - copy_v3_v3(neasrest_precalc->ray_origin, ray_origin); - copy_v3_v3(neasrest_precalc->ray_direction, ray_direction); + copy_v3_v3(neasrest_precalc->ray_origin, ray_origin); + copy_v3_v3(neasrest_precalc->ray_direction, ray_direction); - for (int i = 0; i < 3; i++) { - neasrest_precalc->ray_inv_dir[i] = - (neasrest_precalc->ray_direction[i] != 0.0f) ? - (1.0f / neasrest_precalc->ray_direction[i]) : FLT_MAX; - } + for (int i = 0; i < 3; i++) { + neasrest_precalc->ray_inv_dir[i] = (neasrest_precalc->ray_direction[i] != 0.0f) ? + (1.0f / neasrest_precalc->ray_direction[i]) : + FLT_MAX; + } } /** * Returns the distance from a ray to a bound-box (projected on ray) */ -float dist_squared_ray_to_aabb_v3( - const struct DistRayAABB_Precalc *data, - const float bb_min[3], const float bb_max[3], - float r_point[3], float *r_depth) -{ - // bool r_axis_closest[3]; - float local_bvmin[3], local_bvmax[3]; - aabb_get_near_far_from_plane( - data->ray_direction, bb_min, bb_max, local_bvmin, local_bvmax); - - const float tmin[3] = { - (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0], - (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1], - (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2], - }; - const float tmax[3] = { - (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0], - (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1], - (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2], - }; - /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ - float va[3], vb[3]; - /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ - float rtmin, rtmax; - int main_axis; - - if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { - rtmax = tmax[0]; - va[0] = vb[0] = local_bvmax[0]; - main_axis = 3; - // r_axis_closest[0] = neasrest_precalc->ray_direction[0] < 0.0f; - } - else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { - rtmax = tmax[1]; - va[1] = vb[1] = local_bvmax[1]; - main_axis = 2; - // r_axis_closest[1] = neasrest_precalc->ray_direction[1] < 0.0f; - } - else { - rtmax = tmax[2]; - va[2] = vb[2] = local_bvmax[2]; - main_axis = 1; - // r_axis_closest[2] = neasrest_precalc->ray_direction[2] < 0.0f; - } - - if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { - rtmin = tmin[0]; - va[0] = vb[0] = local_bvmin[0]; - main_axis -= 3; - // r_axis_closest[0] = neasrest_precalc->ray_direction[0] >= 0.0f; - } - else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { - rtmin = tmin[1]; - va[1] = vb[1] = local_bvmin[1]; - main_axis -= 1; - // r_axis_closest[1] = neasrest_precalc->ray_direction[1] >= 0.0f; - } - else { - rtmin = tmin[2]; - va[2] = vb[2] = local_bvmin[2]; - main_axis -= 2; - // r_axis_closest[2] = neasrest_precalc->ray_direction[2] >= 0.0f; - } - if (main_axis < 0) { - main_axis += 3; - } - - /* if rtmin <= rtmax, ray intersect `AABB` */ - if (rtmin <= rtmax) { - float dvec[3]; - copy_v3_v3(r_point, local_bvmax); - sub_v3_v3v3(dvec, local_bvmax, data->ray_origin); - *r_depth = dot_v3v3(dvec, data->ray_direction); - return 0.0f; - } - - if (data->ray_direction[main_axis] >= 0.0f) { - va[main_axis] = local_bvmin[main_axis]; - vb[main_axis] = local_bvmax[main_axis]; - } - else { - va[main_axis] = local_bvmax[main_axis]; - vb[main_axis] = local_bvmin[main_axis]; - } - - return dist_squared_ray_to_seg_v3( - data->ray_origin, data->ray_direction, va, vb, - r_point, r_depth); -} - -float dist_squared_ray_to_aabb_v3_simple( - const float ray_origin[3], const float ray_direction[3], - const float bbmin[3], const float bbmax[3], - float r_point[3], float *r_depth) -{ - struct DistRayAABB_Precalc data; - dist_squared_ray_to_aabb_v3_precalc(&data, ray_origin, ray_direction); - return dist_squared_ray_to_aabb_v3(&data, bbmin, bbmax, r_point, r_depth); +float dist_squared_ray_to_aabb_v3(const struct DistRayAABB_Precalc *data, + const float bb_min[3], + const float bb_max[3], + float r_point[3], + float *r_depth) +{ + // bool r_axis_closest[3]; + float local_bvmin[3], local_bvmax[3]; + aabb_get_near_far_from_plane(data->ray_direction, bb_min, bb_max, local_bvmin, local_bvmax); + + const float tmin[3] = { + (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0], + (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1], + (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2], + }; + const float tmax[3] = { + (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0], + (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1], + (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2], + }; + /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ + float va[3], vb[3]; + /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ + float rtmin, rtmax; + int main_axis; + + if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { + rtmax = tmax[0]; + va[0] = vb[0] = local_bvmax[0]; + main_axis = 3; + // r_axis_closest[0] = neasrest_precalc->ray_direction[0] < 0.0f; + } + else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { + rtmax = tmax[1]; + va[1] = vb[1] = local_bvmax[1]; + main_axis = 2; + // r_axis_closest[1] = neasrest_precalc->ray_direction[1] < 0.0f; + } + else { + rtmax = tmax[2]; + va[2] = vb[2] = local_bvmax[2]; + main_axis = 1; + // r_axis_closest[2] = neasrest_precalc->ray_direction[2] < 0.0f; + } + + if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { + rtmin = tmin[0]; + va[0] = vb[0] = local_bvmin[0]; + main_axis -= 3; + // r_axis_closest[0] = neasrest_precalc->ray_direction[0] >= 0.0f; + } + else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { + rtmin = tmin[1]; + va[1] = vb[1] = local_bvmin[1]; + main_axis -= 1; + // r_axis_closest[1] = neasrest_precalc->ray_direction[1] >= 0.0f; + } + else { + rtmin = tmin[2]; + va[2] = vb[2] = local_bvmin[2]; + main_axis -= 2; + // r_axis_closest[2] = neasrest_precalc->ray_direction[2] >= 0.0f; + } + if (main_axis < 0) { + main_axis += 3; + } + + /* if rtmin <= rtmax, ray intersect `AABB` */ + if (rtmin <= rtmax) { + float dvec[3]; + copy_v3_v3(r_point, local_bvmax); + sub_v3_v3v3(dvec, local_bvmax, data->ray_origin); + *r_depth = dot_v3v3(dvec, data->ray_direction); + return 0.0f; + } + + if (data->ray_direction[main_axis] >= 0.0f) { + va[main_axis] = local_bvmin[main_axis]; + vb[main_axis] = local_bvmax[main_axis]; + } + else { + va[main_axis] = local_bvmax[main_axis]; + vb[main_axis] = local_bvmin[main_axis]; + } + + return dist_squared_ray_to_seg_v3( + data->ray_origin, data->ray_direction, va, vb, r_point, r_depth); +} + +float dist_squared_ray_to_aabb_v3_simple(const float ray_origin[3], + const float ray_direction[3], + const float bbmin[3], + const float bbmax[3], + float r_point[3], + float *r_depth) +{ + struct DistRayAABB_Precalc data; + dist_squared_ray_to_aabb_v3_precalc(&data, ray_origin, ray_direction); + return dist_squared_ray_to_aabb_v3(&data, bbmin, bbmax, r_point, r_depth); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name dist_squared_to_projected_aabb and helpers * \{ */ @@ -782,290 +803,287 @@ float dist_squared_ray_to_aabb_v3_simple( * \param projmat: Projection Matrix (usually perspective * matrix multiplied by object matrix). */ -void dist_squared_to_projected_aabb_precalc( - struct DistProjectedAABBPrecalc *precalc, - const float projmat[4][4], const float winsize[2], const float mval[2]) +void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, + const float projmat[4][4], + const float winsize[2], + const float mval[2]) { - float win_half[2], relative_mval[2], px[4], py[4]; + float win_half[2], relative_mval[2], px[4], py[4]; - mul_v2_v2fl(win_half, winsize, 0.5f); - sub_v2_v2v2(precalc->mval, mval, win_half); + mul_v2_v2fl(win_half, winsize, 0.5f); + sub_v2_v2v2(precalc->mval, mval, win_half); - relative_mval[0] = precalc->mval[0] / win_half[0]; - relative_mval[1] = precalc->mval[1] / win_half[1]; + relative_mval[0] = precalc->mval[0] / win_half[0]; + relative_mval[1] = precalc->mval[1] / win_half[1]; - copy_m4_m4(precalc->pmat, projmat); - for (int i = 0; i < 4; i++) { - px[i] = precalc->pmat[i][0] - precalc->pmat[i][3] * relative_mval[0]; - py[i] = precalc->pmat[i][1] - precalc->pmat[i][3] * relative_mval[1]; + copy_m4_m4(precalc->pmat, projmat); + for (int i = 0; i < 4; i++) { + px[i] = precalc->pmat[i][0] - precalc->pmat[i][3] * relative_mval[0]; + py[i] = precalc->pmat[i][1] - precalc->pmat[i][3] * relative_mval[1]; - precalc->pmat[i][0] *= win_half[0]; - precalc->pmat[i][1] *= win_half[1]; - } + precalc->pmat[i][0] *= win_half[0]; + precalc->pmat[i][1] *= win_half[1]; + } #if 0 - float projmat_trans[4][4]; - transpose_m4_m4(projmat_trans, projmat); - if (!isect_plane_plane_plane_v3( - projmat_trans[0], projmat_trans[1], projmat_trans[3], - precalc->ray_origin)) - { - /* Orthographic projection. */ - isect_plane_plane_v3( - px, py, - precalc->ray_origin, - precalc->ray_direction); - } - else { - /* Perspective projection. */ - cross_v3_v3v3(precalc->ray_direction, py, px); - //normalize_v3(precalc->ray_direction); - } + float projmat_trans[4][4]; + transpose_m4_m4(projmat_trans, projmat); + if (!isect_plane_plane_plane_v3( + projmat_trans[0], projmat_trans[1], projmat_trans[3], + precalc->ray_origin)) + { + /* Orthographic projection. */ + isect_plane_plane_v3( + px, py, + precalc->ray_origin, + precalc->ray_direction); + } + else { + /* Perspective projection. */ + cross_v3_v3v3(precalc->ray_direction, py, px); + //normalize_v3(precalc->ray_direction); + } #else - if (!isect_plane_plane_v3( - px, py, - precalc->ray_origin, - precalc->ray_direction)) - { - /* Matrix with weird coplanar planes. Undetermined origin.*/ - zero_v3(precalc->ray_origin); - precalc->ray_direction[0] = precalc->pmat[0][3]; - precalc->ray_direction[1] = precalc->pmat[1][3]; - precalc->ray_direction[2] = precalc->pmat[2][3]; - } + if (!isect_plane_plane_v3(px, py, precalc->ray_origin, precalc->ray_direction)) { + /* Matrix with weird coplanar planes. Undetermined origin.*/ + zero_v3(precalc->ray_origin); + precalc->ray_direction[0] = precalc->pmat[0][3]; + precalc->ray_direction[1] = precalc->pmat[1][3]; + precalc->ray_direction[2] = precalc->pmat[2][3]; + } #endif - for (int i = 0; i < 3; i++) { - precalc->ray_inv_dir[i] = - (precalc->ray_direction[i] != 0.0f) ? - (1.0f / precalc->ray_direction[i]) : FLT_MAX; - } + for (int i = 0; i < 3; i++) { + precalc->ray_inv_dir[i] = (precalc->ray_direction[i] != 0.0f) ? + (1.0f / precalc->ray_direction[i]) : + FLT_MAX; + } } /* Returns the distance from a 2d coordinate to a BoundBox (Projected) */ -float dist_squared_to_projected_aabb( - struct DistProjectedAABBPrecalc *data, - const float bbmin[3], const float bbmax[3], - bool r_axis_closest[3]) -{ - float local_bvmin[3], local_bvmax[3]; - aabb_get_near_far_from_plane( - data->ray_direction, bbmin, bbmax, local_bvmin, local_bvmax); - - const float tmin[3] = { - (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0], - (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1], - (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2], - }; - const float tmax[3] = { - (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0], - (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1], - (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2], - }; - /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ - float va[3], vb[3]; - /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ - float rtmin, rtmax; - int main_axis; - - r_axis_closest[0] = false; - r_axis_closest[1] = false; - r_axis_closest[2] = false; - - if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { - rtmax = tmax[0]; - va[0] = vb[0] = local_bvmax[0]; - main_axis = 3; - r_axis_closest[0] = data->ray_direction[0] < 0.0f; - } - else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { - rtmax = tmax[1]; - va[1] = vb[1] = local_bvmax[1]; - main_axis = 2; - r_axis_closest[1] = data->ray_direction[1] < 0.0f; - } - else { - rtmax = tmax[2]; - va[2] = vb[2] = local_bvmax[2]; - main_axis = 1; - r_axis_closest[2] = data->ray_direction[2] < 0.0f; - } - - if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { - rtmin = tmin[0]; - va[0] = vb[0] = local_bvmin[0]; - main_axis -= 3; - r_axis_closest[0] = data->ray_direction[0] >= 0.0f; - } - else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { - rtmin = tmin[1]; - va[1] = vb[1] = local_bvmin[1]; - main_axis -= 1; - r_axis_closest[1] = data->ray_direction[1] >= 0.0f; - } - else { - rtmin = tmin[2]; - va[2] = vb[2] = local_bvmin[2]; - main_axis -= 2; - r_axis_closest[2] = data->ray_direction[2] >= 0.0f; - } - if (main_axis < 0) { - main_axis += 3; - } - - /* if rtmin <= rtmax, ray intersect `AABB` */ - if (rtmin <= rtmax) { - return 0; - } - - if (data->ray_direction[main_axis] >= 0.0f) { - va[main_axis] = local_bvmin[main_axis]; - vb[main_axis] = local_bvmax[main_axis]; - } - else { - va[main_axis] = local_bvmax[main_axis]; - vb[main_axis] = local_bvmin[main_axis]; - } - float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); - - float va2d[2] = { - (dot_m4_v3_row_x(data->pmat, va) + data->pmat[3][0]), - (dot_m4_v3_row_y(data->pmat, va) + data->pmat[3][1]), - }; - float vb2d[2] = { - (va2d[0] + data->pmat[main_axis][0] * scale), - (va2d[1] + data->pmat[main_axis][1] * scale), - }; - - float w_a = mul_project_m4_v3_zfac(data->pmat, va); - if (w_a != 1.0f) { - /* Perspective Projection. */ - float w_b = w_a + data->pmat[main_axis][3] * scale; - va2d[0] /= w_a; - va2d[1] /= w_a; - vb2d[0] /= w_b; - vb2d[1] /= w_b; - } - - float dvec[2], edge[2], lambda, rdist_sq; - sub_v2_v2v2(dvec, data->mval, va2d); - sub_v2_v2v2(edge, vb2d, va2d); - lambda = dot_v2v2(dvec, edge); - if (lambda != 0.0f) { - lambda /= len_squared_v2(edge); - if (lambda <= 0.0f) { - rdist_sq = len_squared_v2v2(data->mval, va2d); - r_axis_closest[main_axis] = true; - } - else if (lambda >= 1.0f) { - rdist_sq = len_squared_v2v2(data->mval, vb2d); - r_axis_closest[main_axis] = false; - } - else { - madd_v2_v2fl(va2d, edge, lambda); - rdist_sq = len_squared_v2v2(data->mval, va2d); - r_axis_closest[main_axis] = lambda < 0.5f; - } - } - else { - rdist_sq = len_squared_v2v2(data->mval, va2d); - } - - return rdist_sq; -} - -float dist_squared_to_projected_aabb_simple( - const float projmat[4][4], const float winsize[2], const float mval[2], - const float bbmin[3], const float bbmax[3]) -{ - struct DistProjectedAABBPrecalc data; - dist_squared_to_projected_aabb_precalc(&data, projmat, winsize, mval); - - bool dummy[3] = {true, true, true}; - return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy); +float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, + const float bbmin[3], + const float bbmax[3], + bool r_axis_closest[3]) +{ + float local_bvmin[3], local_bvmax[3]; + aabb_get_near_far_from_plane(data->ray_direction, bbmin, bbmax, local_bvmin, local_bvmax); + + const float tmin[3] = { + (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0], + (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1], + (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2], + }; + const float tmax[3] = { + (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0], + (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1], + (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2], + }; + /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ + float va[3], vb[3]; + /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ + float rtmin, rtmax; + int main_axis; + + r_axis_closest[0] = false; + r_axis_closest[1] = false; + r_axis_closest[2] = false; + + if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { + rtmax = tmax[0]; + va[0] = vb[0] = local_bvmax[0]; + main_axis = 3; + r_axis_closest[0] = data->ray_direction[0] < 0.0f; + } + else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { + rtmax = tmax[1]; + va[1] = vb[1] = local_bvmax[1]; + main_axis = 2; + r_axis_closest[1] = data->ray_direction[1] < 0.0f; + } + else { + rtmax = tmax[2]; + va[2] = vb[2] = local_bvmax[2]; + main_axis = 1; + r_axis_closest[2] = data->ray_direction[2] < 0.0f; + } + + if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { + rtmin = tmin[0]; + va[0] = vb[0] = local_bvmin[0]; + main_axis -= 3; + r_axis_closest[0] = data->ray_direction[0] >= 0.0f; + } + else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { + rtmin = tmin[1]; + va[1] = vb[1] = local_bvmin[1]; + main_axis -= 1; + r_axis_closest[1] = data->ray_direction[1] >= 0.0f; + } + else { + rtmin = tmin[2]; + va[2] = vb[2] = local_bvmin[2]; + main_axis -= 2; + r_axis_closest[2] = data->ray_direction[2] >= 0.0f; + } + if (main_axis < 0) { + main_axis += 3; + } + + /* if rtmin <= rtmax, ray intersect `AABB` */ + if (rtmin <= rtmax) { + return 0; + } + + if (data->ray_direction[main_axis] >= 0.0f) { + va[main_axis] = local_bvmin[main_axis]; + vb[main_axis] = local_bvmax[main_axis]; + } + else { + va[main_axis] = local_bvmax[main_axis]; + vb[main_axis] = local_bvmin[main_axis]; + } + float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); + + float va2d[2] = { + (dot_m4_v3_row_x(data->pmat, va) + data->pmat[3][0]), + (dot_m4_v3_row_y(data->pmat, va) + data->pmat[3][1]), + }; + float vb2d[2] = { + (va2d[0] + data->pmat[main_axis][0] * scale), + (va2d[1] + data->pmat[main_axis][1] * scale), + }; + + float w_a = mul_project_m4_v3_zfac(data->pmat, va); + if (w_a != 1.0f) { + /* Perspective Projection. */ + float w_b = w_a + data->pmat[main_axis][3] * scale; + va2d[0] /= w_a; + va2d[1] /= w_a; + vb2d[0] /= w_b; + vb2d[1] /= w_b; + } + + float dvec[2], edge[2], lambda, rdist_sq; + sub_v2_v2v2(dvec, data->mval, va2d); + sub_v2_v2v2(edge, vb2d, va2d); + lambda = dot_v2v2(dvec, edge); + if (lambda != 0.0f) { + lambda /= len_squared_v2(edge); + if (lambda <= 0.0f) { + rdist_sq = len_squared_v2v2(data->mval, va2d); + r_axis_closest[main_axis] = true; + } + else if (lambda >= 1.0f) { + rdist_sq = len_squared_v2v2(data->mval, vb2d); + r_axis_closest[main_axis] = false; + } + else { + madd_v2_v2fl(va2d, edge, lambda); + rdist_sq = len_squared_v2v2(data->mval, va2d); + r_axis_closest[main_axis] = lambda < 0.5f; + } + } + else { + rdist_sq = len_squared_v2v2(data->mval, va2d); + } + + return rdist_sq; +} + +float dist_squared_to_projected_aabb_simple(const float projmat[4][4], + const float winsize[2], + const float mval[2], + const float bbmin[3], + const float bbmax[3]) +{ + struct DistProjectedAABBPrecalc data; + dist_squared_to_projected_aabb_precalc(&data, projmat, winsize, mval); + + bool dummy[3] = {true, true, true}; + return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy); } /** \} */ - /* Adapted from "Real-Time Collision Detection" by Christer Ericson, * published by Morgan Kaufmann Publishers, copyright 2005 Elsevier Inc. * * Set 'r' to the point in triangle (a, b, c) closest to point 'p' */ -void closest_on_tri_to_point_v3(float r[3], const float p[3], - const float a[3], const float b[3], const float c[3]) -{ - float ab[3], ac[3], ap[3], d1, d2; - float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va; - float denom, v, w; - - /* Check if P in vertex region outside A */ - sub_v3_v3v3(ab, b, a); - sub_v3_v3v3(ac, c, a); - sub_v3_v3v3(ap, p, a); - d1 = dot_v3v3(ab, ap); - d2 = dot_v3v3(ac, ap); - if (d1 <= 0.0f && d2 <= 0.0f) { - /* barycentric coordinates (1,0,0) */ - copy_v3_v3(r, a); - return; - } - - /* Check if P in vertex region outside B */ - sub_v3_v3v3(bp, p, b); - d3 = dot_v3v3(ab, bp); - d4 = dot_v3v3(ac, bp); - if (d3 >= 0.0f && d4 <= d3) { - /* barycentric coordinates (0,1,0) */ - copy_v3_v3(r, b); - return; - } - /* Check if P in edge region of AB, if so return projection of P onto AB */ - vc = d1 * d4 - d3 * d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { - v = d1 / (d1 - d3); - /* barycentric coordinates (1-v,v,0) */ - madd_v3_v3v3fl(r, a, ab, v); - return; - } - /* Check if P in vertex region outside C */ - sub_v3_v3v3(cp, p, c); - d5 = dot_v3v3(ab, cp); - d6 = dot_v3v3(ac, cp); - if (d6 >= 0.0f && d5 <= d6) { - /* barycentric coordinates (0,0,1) */ - copy_v3_v3(r, c); - return; - } - /* Check if P in edge region of AC, if so return projection of P onto AC */ - vb = d5 * d2 - d1 * d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { - w = d2 / (d2 - d6); - /* barycentric coordinates (1-w,0,w) */ - madd_v3_v3v3fl(r, a, ac, w); - return; - } - /* Check if P in edge region of BC, if so return projection of P onto BC */ - va = d3 * d6 - d5 * d4; - if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { - w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); - /* barycentric coordinates (0,1-w,w) */ - sub_v3_v3v3(r, c, b); - mul_v3_fl(r, w); - add_v3_v3(r, b); - return; - } - - /* P inside face region. Compute Q through its barycentric coordinates (u,v,w) */ - denom = 1.0f / (va + vb + vc); - v = vb * denom; - w = vc * denom; - - /* = u*a + v*b + w*c, u = va * denom = 1.0f - v - w */ - /* ac * w */ - mul_v3_fl(ac, w); - /* a + ab * v */ - madd_v3_v3v3fl(r, a, ab, v); - /* a + ab * v + ac * w */ - add_v3_v3(r, ac); +void closest_on_tri_to_point_v3( + float r[3], const float p[3], const float a[3], const float b[3], const float c[3]) +{ + float ab[3], ac[3], ap[3], d1, d2; + float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va; + float denom, v, w; + + /* Check if P in vertex region outside A */ + sub_v3_v3v3(ab, b, a); + sub_v3_v3v3(ac, c, a); + sub_v3_v3v3(ap, p, a); + d1 = dot_v3v3(ab, ap); + d2 = dot_v3v3(ac, ap); + if (d1 <= 0.0f && d2 <= 0.0f) { + /* barycentric coordinates (1,0,0) */ + copy_v3_v3(r, a); + return; + } + + /* Check if P in vertex region outside B */ + sub_v3_v3v3(bp, p, b); + d3 = dot_v3v3(ab, bp); + d4 = dot_v3v3(ac, bp); + if (d3 >= 0.0f && d4 <= d3) { + /* barycentric coordinates (0,1,0) */ + copy_v3_v3(r, b); + return; + } + /* Check if P in edge region of AB, if so return projection of P onto AB */ + vc = d1 * d4 - d3 * d2; + if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { + v = d1 / (d1 - d3); + /* barycentric coordinates (1-v,v,0) */ + madd_v3_v3v3fl(r, a, ab, v); + return; + } + /* Check if P in vertex region outside C */ + sub_v3_v3v3(cp, p, c); + d5 = dot_v3v3(ab, cp); + d6 = dot_v3v3(ac, cp); + if (d6 >= 0.0f && d5 <= d6) { + /* barycentric coordinates (0,0,1) */ + copy_v3_v3(r, c); + return; + } + /* Check if P in edge region of AC, if so return projection of P onto AC */ + vb = d5 * d2 - d1 * d6; + if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { + w = d2 / (d2 - d6); + /* barycentric coordinates (1-w,0,w) */ + madd_v3_v3v3fl(r, a, ac, w); + return; + } + /* Check if P in edge region of BC, if so return projection of P onto BC */ + va = d3 * d6 - d5 * d4; + if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { + w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + /* barycentric coordinates (0,1-w,w) */ + sub_v3_v3v3(r, c, b); + mul_v3_fl(r, w); + add_v3_v3(r, b); + return; + } + + /* P inside face region. Compute Q through its barycentric coordinates (u,v,w) */ + denom = 1.0f / (va + vb + vc); + v = vb * denom; + w = vc * denom; + + /* = u*a + v*b + w*c, u = va * denom = 1.0f - v - w */ + /* ac * w */ + mul_v3_fl(ac, w); + /* a + ab * v */ + madd_v3_v3v3fl(r, a, ab, v); + /* a + ab * v + ac * w */ + add_v3_v3(r, ac); } /******************************* Intersection ********************************/ @@ -1073,135 +1091,138 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3], /* intersect Line-Line, shorts */ int isect_seg_seg_v2_int(const int v1[2], const int v2[2], const int v3[2], const int v4[2]) { - float div, lambda, mu; + float div, lambda, mu; - div = (float)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); - if (div == 0.0f) { - return ISECT_LINE_LINE_COLINEAR; - } + div = (float)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); + if (div == 0.0f) { + return ISECT_LINE_LINE_COLINEAR; + } - lambda = (float)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + lambda = (float)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - mu = (float)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + mu = (float)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { - if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { - return ISECT_LINE_LINE_EXACT; - } - return ISECT_LINE_LINE_CROSS; - } - return ISECT_LINE_LINE_NONE; + if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { + if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { + return ISECT_LINE_LINE_EXACT; + } + return ISECT_LINE_LINE_CROSS; + } + return ISECT_LINE_LINE_NONE; } /* intersect Line-Line, floats - gives intersection point */ -int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2]) +int isect_line_line_v2_point( + const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2]) { - float s10[2], s32[2]; - float div; + float s10[2], s32[2]; + float div; - sub_v2_v2v2(s10, v1, v0); - sub_v2_v2v2(s32, v3, v2); + sub_v2_v2v2(s10, v1, v0); + sub_v2_v2v2(s32, v3, v2); - div = cross_v2v2(s10, s32); - if (div != 0.0f) { - const float u = cross_v2v2(v1, v0); - const float v = cross_v2v2(v3, v2); + div = cross_v2v2(s10, s32); + if (div != 0.0f) { + const float u = cross_v2v2(v1, v0); + const float v = cross_v2v2(v3, v2); - r_vi[0] = ((s32[0] * u) - (s10[0] * v)) / div; - r_vi[1] = ((s32[1] * u) - (s10[1] * v)) / div; + r_vi[0] = ((s32[0] * u) - (s10[0] * v)) / div; + r_vi[1] = ((s32[1] * u) - (s10[1] * v)) / div; - return ISECT_LINE_LINE_CROSS; - } - else { - return ISECT_LINE_LINE_COLINEAR; - } + return ISECT_LINE_LINE_CROSS; + } + else { + return ISECT_LINE_LINE_COLINEAR; + } } /* intersect Line-Line, floats */ int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) { - float div, lambda, mu; + float div, lambda, mu; - div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]); - if (div == 0.0f) { - return ISECT_LINE_LINE_COLINEAR; - } + div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]); + if (div == 0.0f) { + return ISECT_LINE_LINE_COLINEAR; + } - lambda = ((float)(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + lambda = ((float)(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - mu = ((float)(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + mu = ((float)(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { - if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { - return ISECT_LINE_LINE_EXACT; - } - return ISECT_LINE_LINE_CROSS; - } - return ISECT_LINE_LINE_NONE; + if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { + if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { + return ISECT_LINE_LINE_EXACT; + } + return ISECT_LINE_LINE_CROSS; + } + return ISECT_LINE_LINE_NONE; } /* Returns a point on each segment that is closest to the other. */ -void isect_seg_seg_v3( - const float a0[3], const float a1[3], - const float b0[3], const float b1[3], - float r_a[3], float r_b[3]) -{ - float fac_a, fac_b; - float a_dir[3], b_dir[3], a0b0[3], crs_ab[3]; - sub_v3_v3v3(a_dir, a1, a0); - sub_v3_v3v3(b_dir, b1, b0); - sub_v3_v3v3(a0b0, b0, a0); - cross_v3_v3v3(crs_ab, b_dir, a_dir); - const float nlen = len_squared_v3(crs_ab); - - if (nlen == 0.0f) { - /* Parallel Lines */ - /* In this case return any point that - * is between the closest segments. */ - float a0b1[3], a1b0[3], len_a, len_b, fac1, fac2; - sub_v3_v3v3(a0b1, b1, a0); - sub_v3_v3v3(a1b0, b0, a1); - len_a = len_squared_v3(a_dir); - len_b = len_squared_v3(b_dir); - - if (len_a) { - fac1 = dot_v3v3(a0b0, a_dir); - fac2 = dot_v3v3(a0b1, a_dir); - CLAMP(fac1, 0.0f, len_a); - CLAMP(fac2, 0.0f, len_a); - fac_a = (fac1 + fac2) / (2 * len_a); - } - else { - fac_a = 0.0f; - } - - if (len_b) { - fac1 = -dot_v3v3(a0b0, b_dir); - fac2 = -dot_v3v3(a1b0, b_dir); - CLAMP(fac1, 0.0f, len_b); - CLAMP(fac2, 0.0f, len_b); - fac_b = (fac1 + fac2) / (2 * len_b); - } - else { - fac_b = 0.0f; - } - } - else { - float c[3], cray[3]; - sub_v3_v3v3(c, crs_ab, a0b0); - - cross_v3_v3v3(cray, c, b_dir); - fac_a = dot_v3v3(cray, crs_ab) / nlen; - - cross_v3_v3v3(cray, c, a_dir); - fac_b = dot_v3v3(cray, crs_ab) / nlen; - - CLAMP(fac_a, 0.0f, 1.0f); - CLAMP(fac_b, 0.0f, 1.0f); - } - - madd_v3_v3v3fl(r_a, a0, a_dir, fac_a); - madd_v3_v3v3fl(r_b, b0, b_dir, fac_b); +void isect_seg_seg_v3(const float a0[3], + const float a1[3], + const float b0[3], + const float b1[3], + float r_a[3], + float r_b[3]) +{ + float fac_a, fac_b; + float a_dir[3], b_dir[3], a0b0[3], crs_ab[3]; + sub_v3_v3v3(a_dir, a1, a0); + sub_v3_v3v3(b_dir, b1, b0); + sub_v3_v3v3(a0b0, b0, a0); + cross_v3_v3v3(crs_ab, b_dir, a_dir); + const float nlen = len_squared_v3(crs_ab); + + if (nlen == 0.0f) { + /* Parallel Lines */ + /* In this case return any point that + * is between the closest segments. */ + float a0b1[3], a1b0[3], len_a, len_b, fac1, fac2; + sub_v3_v3v3(a0b1, b1, a0); + sub_v3_v3v3(a1b0, b0, a1); + len_a = len_squared_v3(a_dir); + len_b = len_squared_v3(b_dir); + + if (len_a) { + fac1 = dot_v3v3(a0b0, a_dir); + fac2 = dot_v3v3(a0b1, a_dir); + CLAMP(fac1, 0.0f, len_a); + CLAMP(fac2, 0.0f, len_a); + fac_a = (fac1 + fac2) / (2 * len_a); + } + else { + fac_a = 0.0f; + } + + if (len_b) { + fac1 = -dot_v3v3(a0b0, b_dir); + fac2 = -dot_v3v3(a1b0, b_dir); + CLAMP(fac1, 0.0f, len_b); + CLAMP(fac2, 0.0f, len_b); + fac_b = (fac1 + fac2) / (2 * len_b); + } + else { + fac_b = 0.0f; + } + } + else { + float c[3], cray[3]; + sub_v3_v3v3(c, crs_ab, a0b0); + + cross_v3_v3v3(cray, c, b_dir); + fac_a = dot_v3v3(cray, crs_ab) / nlen; + + cross_v3_v3v3(cray, c, a_dir); + fac_b = dot_v3v3(cray, crs_ab) / nlen; + + CLAMP(fac_a, 0.0f, 1.0f); + CLAMP(fac_b, 0.0f, 1.0f); + } + + madd_v3_v3v3fl(r_a, a0, a_dir, fac_a); + madd_v3_v3v3fl(r_b, b0, b_dir, fac_b); } /** @@ -1217,127 +1238,123 @@ void isect_seg_seg_v3( * - 1: intersection. * - 0: no intersection. */ -int isect_seg_seg_v2_point_ex( - const float v0[2], const float v1[2], - const float v2[2], const float v3[2], - const float endpoint_bias, - float r_vi[2]) +int isect_seg_seg_v2_point_ex(const float v0[2], + const float v1[2], + const float v2[2], + const float v3[2], + const float endpoint_bias, + float r_vi[2]) { - float s10[2], s32[2], s30[2], d; - const float eps = 1e-6f; - const float endpoint_min = -endpoint_bias; - const float endpoint_max = endpoint_bias + 1.0f; + float s10[2], s32[2], s30[2], d; + const float eps = 1e-6f; + const float endpoint_min = -endpoint_bias; + const float endpoint_max = endpoint_bias + 1.0f; - sub_v2_v2v2(s10, v1, v0); - sub_v2_v2v2(s32, v3, v2); - sub_v2_v2v2(s30, v3, v0); + sub_v2_v2v2(s10, v1, v0); + sub_v2_v2v2(s32, v3, v2); + sub_v2_v2v2(s30, v3, v0); - d = cross_v2v2(s10, s32); + d = cross_v2v2(s10, s32); - if (d != 0) { - float u, v; + if (d != 0) { + float u, v; - u = cross_v2v2(s30, s32) / d; - v = cross_v2v2(s10, s30) / d; + u = cross_v2v2(s30, s32) / d; + v = cross_v2v2(s10, s30) / d; - if ((u >= endpoint_min && u <= endpoint_max) && - (v >= endpoint_min && v <= endpoint_max)) - { - /* intersection */ - float vi_test[2]; - float s_vi_v2[2]; + if ((u >= endpoint_min && u <= endpoint_max) && (v >= endpoint_min && v <= endpoint_max)) { + /* intersection */ + float vi_test[2]; + float s_vi_v2[2]; - madd_v2_v2v2fl(vi_test, v0, s10, u); + madd_v2_v2v2fl(vi_test, v0, s10, u); - /* When 'd' approaches zero, float precision lets non-overlapping co-linear segments - * detect as an intersection. So re-calculate 'v' to ensure the point overlaps both. - * see T45123 */ + /* When 'd' approaches zero, float precision lets non-overlapping co-linear segments + * detect as an intersection. So re-calculate 'v' to ensure the point overlaps both. + * see T45123 */ - /* inline since we have most vars already */ + /* inline since we have most vars already */ #if 0 - v = line_point_factor_v2(ix_test, v2, v3); + v = line_point_factor_v2(ix_test, v2, v3); #else - sub_v2_v2v2(s_vi_v2, vi_test, v2); - v = (dot_v2v2(s32, s_vi_v2) / dot_v2v2(s32, s32)); + sub_v2_v2v2(s_vi_v2, vi_test, v2); + v = (dot_v2v2(s32, s_vi_v2) / dot_v2v2(s32, s32)); #endif - if (v >= endpoint_min && v <= endpoint_max) { - copy_v2_v2(r_vi, vi_test); - return 1; - } - } - - /* out of segment intersection */ - return -1; - } - else { - if ((cross_v2v2(s10, s30) == 0.0f) && - (cross_v2v2(s32, s30) == 0.0f)) - { - /* equal lines */ - float s20[2]; - float u_a, u_b; - - if (equals_v2v2(v0, v1)) { - if (len_squared_v2v2(v2, v3) > SQUARE(eps)) { - /* use non-point segment as basis */ - SWAP(const float *, v0, v2); - SWAP(const float *, v1, v3); - - sub_v2_v2v2(s10, v1, v0); - sub_v2_v2v2(s30, v3, v0); - } - else { /* both of segments are points */ - if (equals_v2v2(v0, v2)) { /* points are equal */ - copy_v2_v2(r_vi, v0); - return 1; - } - - /* two different points */ - return -1; - } - } - - sub_v2_v2v2(s20, v2, v0); - - u_a = dot_v2v2(s20, s10) / dot_v2v2(s10, s10); - u_b = dot_v2v2(s30, s10) / dot_v2v2(s10, s10); - - if (u_a > u_b) { - SWAP(float, u_a, u_b); - } - - if (u_a > endpoint_max || u_b < endpoint_min) { - /* non-overlapping segments */ - return -1; - } - else if (max_ff(0.0f, u_a) == min_ff(1.0f, u_b)) { - /* one common point: can return result */ - madd_v2_v2v2fl(r_vi, v0, s10, max_ff(0, u_a)); - return 1; - } - } - - /* lines are collinear */ - return -1; - } + if (v >= endpoint_min && v <= endpoint_max) { + copy_v2_v2(r_vi, vi_test); + return 1; + } + } + + /* out of segment intersection */ + return -1; + } + else { + if ((cross_v2v2(s10, s30) == 0.0f) && (cross_v2v2(s32, s30) == 0.0f)) { + /* equal lines */ + float s20[2]; + float u_a, u_b; + + if (equals_v2v2(v0, v1)) { + if (len_squared_v2v2(v2, v3) > SQUARE(eps)) { + /* use non-point segment as basis */ + SWAP(const float *, v0, v2); + SWAP(const float *, v1, v3); + + sub_v2_v2v2(s10, v1, v0); + sub_v2_v2v2(s30, v3, v0); + } + else { /* both of segments are points */ + if (equals_v2v2(v0, v2)) { /* points are equal */ + copy_v2_v2(r_vi, v0); + return 1; + } + + /* two different points */ + return -1; + } + } + + sub_v2_v2v2(s20, v2, v0); + + u_a = dot_v2v2(s20, s10) / dot_v2v2(s10, s10); + u_b = dot_v2v2(s30, s10) / dot_v2v2(s10, s10); + + if (u_a > u_b) { + SWAP(float, u_a, u_b); + } + + if (u_a > endpoint_max || u_b < endpoint_min) { + /* non-overlapping segments */ + return -1; + } + else if (max_ff(0.0f, u_a) == min_ff(1.0f, u_b)) { + /* one common point: can return result */ + madd_v2_v2v2fl(r_vi, v0, s10, max_ff(0, u_a)); + return 1; + } + } + + /* lines are collinear */ + return -1; + } } int isect_seg_seg_v2_point( - const float v0[2], const float v1[2], - const float v2[2], const float v3[2], - float r_vi[2]) + const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2]) { - const float endpoint_bias = 1e-6f; - return isect_seg_seg_v2_point_ex(v0, v1, v2, v3, endpoint_bias, r_vi); + const float endpoint_bias = 1e-6f; + return isect_seg_seg_v2_point_ex(v0, v1, v2, v3, endpoint_bias, r_vi); } -bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) +bool isect_seg_seg_v2_simple(const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2]) { -#define CCW(A, B, C) \ - ((C[1] - A[1]) * (B[0] - A[0]) > \ - (B[1] - A[1]) * (C[0] - A[0])) +#define CCW(A, B, C) ((C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0])) - return CCW(v1, v3, v4) != CCW(v2, v3, v4) && CCW(v1, v2, v3) != CCW(v1, v2, v4); + return CCW(v1, v3, v4) != CCW(v2, v3, v4) && CCW(v1, v2, v3) != CCW(v1, v2, v4); #undef CCW } @@ -1355,364 +1372,377 @@ bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v * For example, when \a l1 is inside the sphere and \a l2 is outside, * \a r_p1 will always be between \a l1 and \a l2. */ -int isect_line_sphere_v3(const float l1[3], const float l2[3], - const float sp[3], const float r, - float r_p1[3], float r_p2[3]) -{ - /* adapted for use in blender by Campbell Barton - 2011 - * - * atelier iebele abel - 2001 - * atelier@iebele.nl - * http://www.iebele.nl - * - * sphere_line_intersection function adapted from: - * http://astronomy.swin.edu.au/pbourke/geometry/sphereline - * Paul Bourke pbourke@swin.edu.au - */ - - const float ldir[3] = { - l2[0] - l1[0], - l2[1] - l1[1], - l2[2] - l1[2], - }; - - const float a = len_squared_v3(ldir); - - const float b = 2.0f * - (ldir[0] * (l1[0] - sp[0]) + - ldir[1] * (l1[1] - sp[1]) + - ldir[2] * (l1[2] - sp[2])); - - const float c = - len_squared_v3(sp) + - len_squared_v3(l1) - - (2.0f * dot_v3v3(sp, l1)) - - (r * r); - - const float i = b * b - 4.0f * a * c; - - float mu; - - if (i < 0.0f) { - /* no intersections */ - return 0; - } - else if (i == 0.0f) { - /* one intersection */ - mu = -b / (2.0f * a); - madd_v3_v3v3fl(r_p1, l1, ldir, mu); - return 1; - } - else if (i > 0.0f) { - const float i_sqrt = sqrtf(i); /* avoid calc twice */ - - /* first intersection */ - mu = (-b + i_sqrt) / (2.0f * a); - madd_v3_v3v3fl(r_p1, l1, ldir, mu); - - /* second intersection */ - mu = (-b - i_sqrt) / (2.0f * a); - madd_v3_v3v3fl(r_p2, l1, ldir, mu); - return 2; - } - else { - /* math domain error - nan */ - return -1; - } +int isect_line_sphere_v3(const float l1[3], + const float l2[3], + const float sp[3], + const float r, + float r_p1[3], + float r_p2[3]) +{ + /* adapted for use in blender by Campbell Barton - 2011 + * + * atelier iebele abel - 2001 + * atelier@iebele.nl + * http://www.iebele.nl + * + * sphere_line_intersection function adapted from: + * http://astronomy.swin.edu.au/pbourke/geometry/sphereline + * Paul Bourke pbourke@swin.edu.au + */ + + const float ldir[3] = { + l2[0] - l1[0], + l2[1] - l1[1], + l2[2] - l1[2], + }; + + const float a = len_squared_v3(ldir); + + const float b = 2.0f * (ldir[0] * (l1[0] - sp[0]) + ldir[1] * (l1[1] - sp[1]) + + ldir[2] * (l1[2] - sp[2])); + + const float c = len_squared_v3(sp) + len_squared_v3(l1) - (2.0f * dot_v3v3(sp, l1)) - (r * r); + + const float i = b * b - 4.0f * a * c; + + float mu; + + if (i < 0.0f) { + /* no intersections */ + return 0; + } + else if (i == 0.0f) { + /* one intersection */ + mu = -b / (2.0f * a); + madd_v3_v3v3fl(r_p1, l1, ldir, mu); + return 1; + } + else if (i > 0.0f) { + const float i_sqrt = sqrtf(i); /* avoid calc twice */ + + /* first intersection */ + mu = (-b + i_sqrt) / (2.0f * a); + madd_v3_v3v3fl(r_p1, l1, ldir, mu); + + /* second intersection */ + mu = (-b - i_sqrt) / (2.0f * a); + madd_v3_v3v3fl(r_p2, l1, ldir, mu); + return 2; + } + else { + /* math domain error - nan */ + return -1; + } } /* keep in sync with isect_line_sphere_v3 */ -int isect_line_sphere_v2(const float l1[2], const float l2[2], - const float sp[2], const float r, - float r_p1[2], float r_p2[2]) -{ - const float ldir[2] = {l2[0] - l1[0], - l2[1] - l1[1]}; - - const float a = dot_v2v2(ldir, ldir); - - const float b = 2.0f * - (ldir[0] * (l1[0] - sp[0]) + - ldir[1] * (l1[1] - sp[1])); - - const float c = - dot_v2v2(sp, sp) + - dot_v2v2(l1, l1) - - (2.0f * dot_v2v2(sp, l1)) - - (r * r); - - const float i = b * b - 4.0f * a * c; - - float mu; - - if (i < 0.0f) { - /* no intersections */ - return 0; - } - else if (i == 0.0f) { - /* one intersection */ - mu = -b / (2.0f * a); - madd_v2_v2v2fl(r_p1, l1, ldir, mu); - return 1; - } - else if (i > 0.0f) { - const float i_sqrt = sqrtf(i); /* avoid calc twice */ - - /* first intersection */ - mu = (-b + i_sqrt) / (2.0f * a); - madd_v2_v2v2fl(r_p1, l1, ldir, mu); - - /* second intersection */ - mu = (-b - i_sqrt) / (2.0f * a); - madd_v2_v2v2fl(r_p2, l1, ldir, mu); - return 2; - } - else { - /* math domain error - nan */ - return -1; - } +int isect_line_sphere_v2(const float l1[2], + const float l2[2], + const float sp[2], + const float r, + float r_p1[2], + float r_p2[2]) +{ + const float ldir[2] = {l2[0] - l1[0], l2[1] - l1[1]}; + + const float a = dot_v2v2(ldir, ldir); + + const float b = 2.0f * (ldir[0] * (l1[0] - sp[0]) + ldir[1] * (l1[1] - sp[1])); + + const float c = dot_v2v2(sp, sp) + dot_v2v2(l1, l1) - (2.0f * dot_v2v2(sp, l1)) - (r * r); + + const float i = b * b - 4.0f * a * c; + + float mu; + + if (i < 0.0f) { + /* no intersections */ + return 0; + } + else if (i == 0.0f) { + /* one intersection */ + mu = -b / (2.0f * a); + madd_v2_v2v2fl(r_p1, l1, ldir, mu); + return 1; + } + else if (i > 0.0f) { + const float i_sqrt = sqrtf(i); /* avoid calc twice */ + + /* first intersection */ + mu = (-b + i_sqrt) / (2.0f * a); + madd_v2_v2v2fl(r_p1, l1, ldir, mu); + + /* second intersection */ + mu = (-b - i_sqrt) / (2.0f * a); + madd_v2_v2v2fl(r_p2, l1, ldir, mu); + return 2; + } + else { + /* math domain error - nan */ + return -1; + } } /* point in polygon (keep float and int versions in sync) */ -bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, +bool isect_point_poly_v2(const float pt[2], + const float verts[][2], + const unsigned int nr, const bool UNUSED(use_holes)) { - unsigned int i, j; - bool isect = false; - for (i = 0, j = nr - 1; i < nr; j = i++) { - if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && - (pt[0] < (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) + verts[i][0])) - { - isect = !isect; - } - } - return isect; -} -bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, + unsigned int i, j; + bool isect = false; + for (i = 0, j = nr - 1; i < nr; j = i++) { + if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && + (pt[0] < + (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) + + verts[i][0])) { + isect = !isect; + } + } + return isect; +} +bool isect_point_poly_v2_int(const int pt[2], + const int verts[][2], + const unsigned int nr, const bool UNUSED(use_holes)) { - unsigned int i, j; - bool isect = false; - for (i = 0, j = nr - 1; i < nr; j = i++) { - if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && - (pt[0] < (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) + verts[i][0])) - { - isect = !isect; - } - } - return isect; + unsigned int i, j; + bool isect = false; + for (i = 0, j = nr - 1; i < nr; j = i++) { + if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && + (pt[0] < + (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) + + verts[i][0])) { + isect = !isect; + } + } + return isect; } /* point in tri */ /* only single direction */ -bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]) +bool isect_point_tri_v2_cw(const float pt[2], + const float v1[2], + const float v2[2], + const float v3[2]) { - if (line_point_side_v2(v1, v2, pt) >= 0.0f) { - if (line_point_side_v2(v2, v3, pt) >= 0.0f) { - if (line_point_side_v2(v3, v1, pt) >= 0.0f) { - return true; - } - } - } + if (line_point_side_v2(v1, v2, pt) >= 0.0f) { + if (line_point_side_v2(v2, v3, pt) >= 0.0f) { + if (line_point_side_v2(v3, v1, pt) >= 0.0f) { + return true; + } + } + } - return false; + return false; } int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2]) { - if (line_point_side_v2(v1, v2, pt) >= 0.0f) { - if (line_point_side_v2(v2, v3, pt) >= 0.0f) { - if (line_point_side_v2(v3, v1, pt) >= 0.0f) { - return 1; - } - } - } - else { - if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { - if (!(line_point_side_v2(v3, v1, pt) >= 0.0f)) { - return -1; - } - } - } + if (line_point_side_v2(v1, v2, pt) >= 0.0f) { + if (line_point_side_v2(v2, v3, pt) >= 0.0f) { + if (line_point_side_v2(v3, v1, pt) >= 0.0f) { + return 1; + } + } + } + else { + if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { + if (!(line_point_side_v2(v3, v1, pt) >= 0.0f)) { + return -1; + } + } + } - return 0; + return 0; } /* point in quad - only convex quads */ -int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2]) -{ - if (line_point_side_v2(v1, v2, pt) >= 0.0f) { - if (line_point_side_v2(v2, v3, pt) >= 0.0f) { - if (line_point_side_v2(v3, v4, pt) >= 0.0f) { - if (line_point_side_v2(v4, v1, pt) >= 0.0f) { - return 1; - } - } - } - } - else { - if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { - if (!(line_point_side_v2(v3, v4, pt) >= 0.0f)) { - if (!(line_point_side_v2(v4, v1, pt) >= 0.0f)) { - return -1; - } - } - } - } - - return 0; +int isect_point_quad_v2( + const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2]) +{ + if (line_point_side_v2(v1, v2, pt) >= 0.0f) { + if (line_point_side_v2(v2, v3, pt) >= 0.0f) { + if (line_point_side_v2(v3, v4, pt) >= 0.0f) { + if (line_point_side_v2(v4, v1, pt) >= 0.0f) { + return 1; + } + } + } + } + else { + if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { + if (!(line_point_side_v2(v3, v4, pt) >= 0.0f)) { + if (!(line_point_side_v2(v4, v1, pt) >= 0.0f)) { + return -1; + } + } + } + } + + return 0; } /* moved from effect.c * test if the line starting at p1 ending at p2 intersects the triangle v0..v2 * return non zero if it does */ -bool isect_line_segment_tri_v3( - const float p1[3], const float p2[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) +bool isect_line_segment_tri_v3(const float p1[3], + const float p2[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2]) { - float p[3], s[3], d[3], e1[3], e2[3], q[3]; - float a, f, u, v; + float p[3], s[3], d[3], e1[3], e2[3], q[3]; + float a, f, u, v; - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); - sub_v3_v3v3(d, p2, p1); + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(d, p2, p1); - cross_v3_v3v3(p, d, e2); - a = dot_v3v3(e1, p); - if (a == 0.0f) { - return false; - } - f = 1.0f / a; + cross_v3_v3v3(p, d, e2); + a = dot_v3v3(e1, p); + if (a == 0.0f) { + return false; + } + f = 1.0f / a; - sub_v3_v3v3(s, p1, v0); + sub_v3_v3v3(s, p1, v0); - u = f * dot_v3v3(s, p); - if ((u < 0.0f) || (u > 1.0f)) { - return false; - } + u = f * dot_v3v3(s, p); + if ((u < 0.0f) || (u > 1.0f)) { + return false; + } - cross_v3_v3v3(q, s, e1); + cross_v3_v3v3(q, s, e1); - v = f * dot_v3v3(d, q); - if ((v < 0.0f) || ((u + v) > 1.0f)) { - return false; - } + v = f * dot_v3v3(d, q); + if ((v < 0.0f) || ((u + v) > 1.0f)) { + return false; + } - *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { - return false; - } + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { + return false; + } - if (r_uv) { - r_uv[0] = u; - r_uv[1] = v; - } + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } - return true; + return true; } /* like isect_line_segment_tri_v3, but allows epsilon tolerance around triangle */ -bool isect_line_segment_tri_epsilon_v3( - const float p1[3], const float p2[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2], const float epsilon) +bool isect_line_segment_tri_epsilon_v3(const float p1[3], + const float p2[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2], + const float epsilon) { - float p[3], s[3], d[3], e1[3], e2[3], q[3]; - float a, f, u, v; + float p[3], s[3], d[3], e1[3], e2[3], q[3]; + float a, f, u, v; - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); - sub_v3_v3v3(d, p2, p1); + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(d, p2, p1); - cross_v3_v3v3(p, d, e2); - a = dot_v3v3(e1, p); - if (a == 0.0f) { - return false; - } - f = 1.0f / a; + cross_v3_v3v3(p, d, e2); + a = dot_v3v3(e1, p); + if (a == 0.0f) { + return false; + } + f = 1.0f / a; - sub_v3_v3v3(s, p1, v0); + sub_v3_v3v3(s, p1, v0); - u = f * dot_v3v3(s, p); - if ((u < -epsilon) || (u > 1.0f + epsilon)) { - return false; - } + u = f * dot_v3v3(s, p); + if ((u < -epsilon) || (u > 1.0f + epsilon)) { + return false; + } - cross_v3_v3v3(q, s, e1); + cross_v3_v3v3(q, s, e1); - v = f * dot_v3v3(d, q); - if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) { - return false; - } + v = f * dot_v3v3(d, q); + if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) { + return false; + } - *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { - return false; - } + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { + return false; + } - if (r_uv) { - r_uv[0] = u; - r_uv[1] = v; - } + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } - return true; + return true; } /* moved from effect.c * test if the ray starting at p1 going in d direction intersects the triangle v0..v2 * return non zero if it does */ -bool isect_ray_tri_v3( - const float ray_origin[3], const float ray_direction[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) +bool isect_ray_tri_v3(const float ray_origin[3], + const float ray_direction[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2]) { - /* note: these values were 0.000001 in 2.4x but for projection snapping on - * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */ - const float epsilon = 0.00000001f; - float p[3], s[3], e1[3], e2[3], q[3]; - float a, f, u, v; + /* note: these values were 0.000001 in 2.4x but for projection snapping on + * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */ + const float epsilon = 0.00000001f; + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); - cross_v3_v3v3(p, ray_direction, e2); - a = dot_v3v3(e1, p); - if ((a > -epsilon) && (a < epsilon)) { - return false; - } - f = 1.0f / a; + cross_v3_v3v3(p, ray_direction, e2); + a = dot_v3v3(e1, p); + if ((a > -epsilon) && (a < epsilon)) { + return false; + } + f = 1.0f / a; - sub_v3_v3v3(s, ray_origin, v0); + sub_v3_v3v3(s, ray_origin, v0); - u = f * dot_v3v3(s, p); - if ((u < 0.0f) || (u > 1.0f)) { - return false; - } + u = f * dot_v3v3(s, p); + if ((u < 0.0f) || (u > 1.0f)) { + return false; + } - cross_v3_v3v3(q, s, e1); + cross_v3_v3v3(q, s, e1); - v = f * dot_v3v3(ray_direction, q); - if ((v < 0.0f) || ((u + v) > 1.0f)) { - return false; - } + v = f * dot_v3v3(ray_direction, q); + if ((v < 0.0f) || ((u + v) > 1.0f)) { + return false; + } - *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { - return false; - } + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f)) { + return false; + } - if (r_uv) { - r_uv[0] = u; - r_uv[1] = v; - } + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } - return true; + return true; } /** @@ -1721,187 +1751,196 @@ bool isect_ray_tri_v3( * * \note #line_plane_factor_v3() shares logic. */ -bool isect_ray_plane_v3( - const float ray_origin[3], const float ray_direction[3], - const float plane[4], - float *r_lambda, const bool clip) -{ - float h[3], plane_co[3]; - float dot; - - dot = dot_v3v3(plane, ray_direction); - if (dot == 0.0f) { - return false; - } - mul_v3_v3fl(plane_co, plane, (-plane[3] / len_squared_v3(plane))); - sub_v3_v3v3(h, ray_origin, plane_co); - *r_lambda = -dot_v3v3(plane, h) / dot; - if (clip && (*r_lambda < 0.0f)) { - return false; - } - return true; -} - -bool isect_ray_tri_epsilon_v3( - const float ray_origin[3], const float ray_direction[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2], const float epsilon) -{ - float p[3], s[3], e1[3], e2[3], q[3]; - float a, f, u, v; - - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); - - cross_v3_v3v3(p, ray_direction, e2); - a = dot_v3v3(e1, p); - if (a == 0.0f) { - return false; - } - f = 1.0f / a; - - sub_v3_v3v3(s, ray_origin, v0); - - u = f * dot_v3v3(s, p); - if ((u < -epsilon) || (u > 1.0f + epsilon)) { - return false; - } - - cross_v3_v3v3(q, s, e1); - - v = f * dot_v3v3(ray_direction, q); - if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) { - return false; - } - - *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { - return false; - } - - if (r_uv) { - r_uv[0] = u; - r_uv[1] = v; - } - - return true; -} - -void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float ray_direction[3]) -{ - float inv_dir_z; - - /* Calculate dimension where the ray direction is maximal. */ - int kz = axis_dominant_v3_single(ray_direction); - int kx = (kz != 2) ? (kz + 1) : 0; - int ky = (kx != 2) ? (kx + 1) : 0; - - /* Swap kx and ky dimensions to preserve winding direction of triangles. */ - if (ray_direction[kz] < 0.0f) { - SWAP(int, kx, ky); - } - - /* Calculate the shear constants. */ - inv_dir_z = 1.0f / ray_direction[kz]; - isect_precalc->sx = ray_direction[kx] * inv_dir_z; - isect_precalc->sy = ray_direction[ky] * inv_dir_z; - isect_precalc->sz = inv_dir_z; - - /* Store the dimensions. */ - isect_precalc->kx = kx; - isect_precalc->ky = ky; - isect_precalc->kz = kz; -} - -bool isect_ray_tri_watertight_v3( - const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) -{ - const int kx = isect_precalc->kx; - const int ky = isect_precalc->ky; - const int kz = isect_precalc->kz; - const float sx = isect_precalc->sx; - const float sy = isect_precalc->sy; - const float sz = isect_precalc->sz; - - /* Calculate vertices relative to ray origin. */ - const float a[3] = {v0[0] - ray_origin[0], v0[1] - ray_origin[1], v0[2] - ray_origin[2]}; - const float b[3] = {v1[0] - ray_origin[0], v1[1] - ray_origin[1], v1[2] - ray_origin[2]}; - const float c[3] = {v2[0] - ray_origin[0], v2[1] - ray_origin[1], v2[2] - ray_origin[2]}; - - const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz]; - const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz]; - const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz]; - - /* Perform shear and scale of vertices. */ - const float ax = a_kx - sx * a_kz; - const float ay = a_ky - sy * a_kz; - const float bx = b_kx - sx * b_kz; - const float by = b_ky - sy * b_kz; - const float cx = c_kx - sx * c_kz; - const float cy = c_ky - sy * c_kz; - - /* Calculate scaled barycentric coordinates. */ - const float u = cx * by - cy * bx; - const float v = ax * cy - ay * cx; - const float w = bx * ay - by * ax; - float det; - - if ((u < 0.0f || v < 0.0f || w < 0.0f) && - (u > 0.0f || v > 0.0f || w > 0.0f)) - { - return false; - } - - /* Calculate determinant. */ - det = u + v + w; - if (UNLIKELY(det == 0.0f || !isfinite(det))) { - return false; - } - else { - /* Calculate scaled z-coordinates of vertices and use them to calculate - * the hit distance. - */ - const int sign_det = (float_as_int(det) & (int)0x80000000); - const float t = (u * a_kz + v * b_kz + w * c_kz) * sz; - const float sign_t = xor_fl(t, sign_det); - if ((sign_t < 0.0f) - /* differ from Cycles, don't read r_lambda's original value - * otherwise we won't match any of the other intersect functions here... - * which would be confusing */ +bool isect_ray_plane_v3(const float ray_origin[3], + const float ray_direction[3], + const float plane[4], + float *r_lambda, + const bool clip) +{ + float h[3], plane_co[3]; + float dot; + + dot = dot_v3v3(plane, ray_direction); + if (dot == 0.0f) { + return false; + } + mul_v3_v3fl(plane_co, plane, (-plane[3] / len_squared_v3(plane))); + sub_v3_v3v3(h, ray_origin, plane_co); + *r_lambda = -dot_v3v3(plane, h) / dot; + if (clip && (*r_lambda < 0.0f)) { + return false; + } + return true; +} + +bool isect_ray_tri_epsilon_v3(const float ray_origin[3], + const float ray_direction[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2], + const float epsilon) +{ + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; + + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + + cross_v3_v3v3(p, ray_direction, e2); + a = dot_v3v3(e1, p); + if (a == 0.0f) { + return false; + } + f = 1.0f / a; + + sub_v3_v3v3(s, ray_origin, v0); + + u = f * dot_v3v3(s, p); + if ((u < -epsilon) || (u > 1.0f + epsilon)) { + return false; + } + + cross_v3_v3v3(q, s, e1); + + v = f * dot_v3v3(ray_direction, q); + if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) { + return false; + } + + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f)) { + return false; + } + + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } + + return true; +} + +void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, + const float ray_direction[3]) +{ + float inv_dir_z; + + /* Calculate dimension where the ray direction is maximal. */ + int kz = axis_dominant_v3_single(ray_direction); + int kx = (kz != 2) ? (kz + 1) : 0; + int ky = (kx != 2) ? (kx + 1) : 0; + + /* Swap kx and ky dimensions to preserve winding direction of triangles. */ + if (ray_direction[kz] < 0.0f) { + SWAP(int, kx, ky); + } + + /* Calculate the shear constants. */ + inv_dir_z = 1.0f / ray_direction[kz]; + isect_precalc->sx = ray_direction[kx] * inv_dir_z; + isect_precalc->sy = ray_direction[ky] * inv_dir_z; + isect_precalc->sz = inv_dir_z; + + /* Store the dimensions. */ + isect_precalc->kx = kx; + isect_precalc->ky = ky; + isect_precalc->kz = kz; +} + +bool isect_ray_tri_watertight_v3(const float ray_origin[3], + const struct IsectRayPrecalc *isect_precalc, + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2]) +{ + const int kx = isect_precalc->kx; + const int ky = isect_precalc->ky; + const int kz = isect_precalc->kz; + const float sx = isect_precalc->sx; + const float sy = isect_precalc->sy; + const float sz = isect_precalc->sz; + + /* Calculate vertices relative to ray origin. */ + const float a[3] = {v0[0] - ray_origin[0], v0[1] - ray_origin[1], v0[2] - ray_origin[2]}; + const float b[3] = {v1[0] - ray_origin[0], v1[1] - ray_origin[1], v1[2] - ray_origin[2]}; + const float c[3] = {v2[0] - ray_origin[0], v2[1] - ray_origin[1], v2[2] - ray_origin[2]}; + + const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz]; + const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz]; + const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz]; + + /* Perform shear and scale of vertices. */ + const float ax = a_kx - sx * a_kz; + const float ay = a_ky - sy * a_kz; + const float bx = b_kx - sx * b_kz; + const float by = b_ky - sy * b_kz; + const float cx = c_kx - sx * c_kz; + const float cy = c_ky - sy * c_kz; + + /* Calculate scaled barycentric coordinates. */ + const float u = cx * by - cy * bx; + const float v = ax * cy - ay * cx; + const float w = bx * ay - by * ax; + float det; + + if ((u < 0.0f || v < 0.0f || w < 0.0f) && (u > 0.0f || v > 0.0f || w > 0.0f)) { + return false; + } + + /* Calculate determinant. */ + det = u + v + w; + if (UNLIKELY(det == 0.0f || !isfinite(det))) { + return false; + } + else { + /* Calculate scaled z-coordinates of vertices and use them to calculate + * the hit distance. + */ + const int sign_det = (float_as_int(det) & (int)0x80000000); + const float t = (u * a_kz + v * b_kz + w * c_kz) * sz; + const float sign_t = xor_fl(t, sign_det); + if ((sign_t < 0.0f) + /* differ from Cycles, don't read r_lambda's original value + * otherwise we won't match any of the other intersect functions here... + * which would be confusing */ #if 0 - || - (sign_T > *r_lambda * xor_signmask(det, sign_mask)) + || + (sign_T > *r_lambda * xor_signmask(det, sign_mask)) #endif - ) - { - return false; - } - else { - /* Normalize u, v and t. */ - const float inv_det = 1.0f / det; - if (r_uv) { - r_uv[0] = u * inv_det; - r_uv[1] = v * inv_det; - } - *r_lambda = t * inv_det; - return true; - } - } -} - -bool isect_ray_tri_watertight_v3_simple( - const float ray_origin[3], const float ray_direction[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) -{ - struct IsectRayPrecalc isect_precalc; - isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction); - return isect_ray_tri_watertight_v3(ray_origin, &isect_precalc, v0, v1, v2, r_lambda, r_uv); -} - -#if 0 /* UNUSED */ + ) { + return false; + } + else { + /* Normalize u, v and t. */ + const float inv_det = 1.0f / det; + if (r_uv) { + r_uv[0] = u * inv_det; + r_uv[1] = v * inv_det; + } + *r_lambda = t * inv_det; + return true; + } + } +} + +bool isect_ray_tri_watertight_v3_simple(const float ray_origin[3], + const float ray_direction[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float r_uv[2]) +{ + struct IsectRayPrecalc isect_precalc; + isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction); + return isect_ray_tri_watertight_v3(ray_origin, &isect_precalc, v0, v1, v2, r_lambda, r_uv); +} + +#if 0 /* UNUSED */ /** * A version of #isect_ray_tri_v3 which takes a threshold argument * so rays slightly outside the triangle to be considered as intersecting. @@ -1911,164 +1950,162 @@ bool isect_ray_tri_threshold_v3( const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold) { - const float epsilon = 0.00000001f; - float p[3], s[3], e1[3], e2[3], q[3]; - float a, f, u, v; - float du, dv; + const float epsilon = 0.00000001f; + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; + float du, dv; - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); - cross_v3_v3v3(p, ray_direction, e2); - a = dot_v3v3(e1, p); - if ((a > -epsilon) && (a < epsilon)) return false; - f = 1.0f / a; + cross_v3_v3v3(p, ray_direction, e2); + a = dot_v3v3(e1, p); + if ((a > -epsilon) && (a < epsilon)) return false; + f = 1.0f / a; - sub_v3_v3v3(s, ray_origin, v0); + sub_v3_v3v3(s, ray_origin, v0); - cross_v3_v3v3(q, s, e1); - *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) return false; + cross_v3_v3v3(q, s, e1); + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f)) return false; - u = f * dot_v3v3(s, p); - v = f * dot_v3v3(ray_direction, q); + u = f * dot_v3v3(s, p); + v = f * dot_v3v3(ray_direction, q); - if (u > 0 && v > 0 && u + v > 1) { - float t = (u + v - 1) / 2; - du = u - t; - dv = v - t; - } - else { - if (u < 0) du = u; - else if (u > 1) du = u - 1; - else du = 0.0f; + if (u > 0 && v > 0 && u + v > 1) { + float t = (u + v - 1) / 2; + du = u - t; + dv = v - t; + } + else { + if (u < 0) du = u; + else if (u > 1) du = u - 1; + else du = 0.0f; - if (v < 0) dv = v; - else if (v > 1) dv = v - 1; - else dv = 0.0f; - } + if (v < 0) dv = v; + else if (v > 1) dv = v - 1; + else dv = 0.0f; + } - mul_v3_fl(e1, du); - mul_v3_fl(e2, dv); + mul_v3_fl(e1, du); + mul_v3_fl(e2, dv); - if (len_squared_v3(e1) + len_squared_v3(e2) > threshold * threshold) { - return false; - } + if (len_squared_v3(e1) + len_squared_v3(e2) > threshold * threshold) { + return false; + } - if (r_uv) { - r_uv[0] = u; - r_uv[1] = v; - } + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } - return true; + return true; } #endif - -bool isect_ray_seg_v2( - const float ray_origin[2], const float ray_direction[2], - const float v0[2], const float v1[2], - float *r_lambda, float *r_u) +bool isect_ray_seg_v2(const float ray_origin[2], + const float ray_direction[2], + const float v0[2], + const float v1[2], + float *r_lambda, + float *r_u) { - float v0_local[2], v1_local[2]; - sub_v2_v2v2(v0_local, v0, ray_origin); - sub_v2_v2v2(v1_local, v1, ray_origin); + float v0_local[2], v1_local[2]; + sub_v2_v2v2(v0_local, v0, ray_origin); + sub_v2_v2v2(v1_local, v1, ray_origin); - float s10[2]; - float det; + float s10[2]; + float det; - sub_v2_v2v2(s10, v1_local, v0_local); + sub_v2_v2v2(s10, v1_local, v0_local); - det = cross_v2v2(ray_direction, s10); - if (det != 0.0f) { - const float v = cross_v2v2(v0_local, v1_local); - float p[2] = {(ray_direction[0] * v) / det, (ray_direction[1] * v) / det}; + det = cross_v2v2(ray_direction, s10); + if (det != 0.0f) { + const float v = cross_v2v2(v0_local, v1_local); + float p[2] = {(ray_direction[0] * v) / det, (ray_direction[1] * v) / det}; - const float t = (dot_v2v2(p, ray_direction) / dot_v2v2(ray_direction, ray_direction)); - if ((t >= 0.0f) == 0) { - return false; - } + const float t = (dot_v2v2(p, ray_direction) / dot_v2v2(ray_direction, ray_direction)); + if ((t >= 0.0f) == 0) { + return false; + } - float h[2]; - sub_v2_v2v2(h, v1_local, p); - const float u = (dot_v2v2(s10, h) / dot_v2v2(s10, s10)); - if ((u >= 0.0f && u <= 1.0f) == 0) { - return false; - } + float h[2]; + sub_v2_v2v2(h, v1_local, p); + const float u = (dot_v2v2(s10, h) / dot_v2v2(s10, s10)); + if ((u >= 0.0f && u <= 1.0f) == 0) { + return false; + } - if (r_lambda) { - *r_lambda = t; - } - if (r_u) { - *r_u = u; - } + if (r_lambda) { + *r_lambda = t; + } + if (r_u) { + *r_u = u; + } - return true; - } + return true; + } - return false; + return false; } - -bool isect_ray_seg_v3( - const float ray_origin[3], const float ray_direction[3], - const float v0[3], const float v1[3], - float *r_lambda) +bool isect_ray_seg_v3(const float ray_origin[3], + const float ray_direction[3], + const float v0[3], + const float v1[3], + float *r_lambda) { - float a[3], t[3], n[3]; - sub_v3_v3v3(a, v1, v0); - sub_v3_v3v3(t, v0, ray_origin); - cross_v3_v3v3(n, a, ray_direction); - const float nlen = len_squared_v3(n); + float a[3], t[3], n[3]; + sub_v3_v3v3(a, v1, v0); + sub_v3_v3v3(t, v0, ray_origin); + cross_v3_v3v3(n, a, ray_direction); + const float nlen = len_squared_v3(n); - if (nlen == 0.0f) { - /* the lines are parallel.*/ - return false; - } + if (nlen == 0.0f) { + /* the lines are parallel.*/ + return false; + } - float c[3], cray[3]; - sub_v3_v3v3(c, n, t); - cross_v3_v3v3(cray, c, ray_direction); + float c[3], cray[3]; + sub_v3_v3v3(c, n, t); + cross_v3_v3v3(cray, c, ray_direction); - *r_lambda = dot_v3v3(cray, n) / nlen; + *r_lambda = dot_v3v3(cray, n) / nlen; - return true; + return true; } - /** * Check if a point is behind all planes. */ bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]) { - int i; + int i; - for (i = 0; i < totplane; i++) { - if (plane_point_side_v3(planes[i], p) > 0.0f) { - return false; - } - } + for (i = 0; i < totplane; i++) { + if (plane_point_side_v3(planes[i], p) > 0.0f) { + return false; + } + } - return true; + return true; } /** * Check if a point is in front all planes. * Same as isect_point_planes_v3 but with planes facing the opposite direction. */ -bool isect_point_planes_v3_negated( - const float(*planes)[4], const int totplane, const float p[3]) +bool isect_point_planes_v3_negated(const float (*planes)[4], const int totplane, const float p[3]) { - for (int i = 0; i < totplane; i++) { - if (plane_point_side_v3(planes[i], p) <= 0.0f) { - return false; - } - } + for (int i = 0; i < totplane; i++) { + if (plane_point_side_v3(planes[i], p) <= 0.0f) { + return false; + } + } - return true; + return true; } - /** * Intersect line/plane. * @@ -2080,27 +2117,28 @@ bool isect_point_planes_v3_negated( * * \note #line_plane_factor_v3() shares logic. */ -bool isect_line_plane_v3( - float r_isect_co[3], - const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3]) -{ - float u[3], h[3]; - float dot; - - sub_v3_v3v3(u, l2, l1); - sub_v3_v3v3(h, l1, plane_co); - dot = dot_v3v3(plane_no, u); - - if (fabsf(dot) > FLT_EPSILON) { - float lambda = -dot_v3v3(plane_no, h) / dot; - madd_v3_v3v3fl(r_isect_co, l1, u, lambda); - return true; - } - else { - /* The segment is parallel to plane */ - return false; - } +bool isect_line_plane_v3(float r_isect_co[3], + const float l1[3], + const float l2[3], + const float plane_co[3], + const float plane_no[3]) +{ + float u[3], h[3]; + float dot; + + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); + + if (fabsf(dot) > FLT_EPSILON) { + float lambda = -dot_v3v3(plane_no, h) / dot; + madd_v3_v3v3fl(r_isect_co, l1, u, lambda); + return true; + } + else { + /* The segment is parallel to plane */ + return false; + } } /** @@ -2110,37 +2148,38 @@ bool isect_line_plane_v3( * \param plane_a, plane_b, plane_c: Planes. * \param r_isect_co: The resulting intersection point. */ -bool isect_plane_plane_plane_v3( - const float plane_a[4], const float plane_b[4], const float plane_c[4], - float r_isect_co[3]) +bool isect_plane_plane_plane_v3(const float plane_a[4], + const float plane_b[4], + const float plane_c[4], + float r_isect_co[3]) { - float det; + float det; - det = determinant_m3(UNPACK3(plane_a), UNPACK3(plane_b), UNPACK3(plane_c)); + det = determinant_m3(UNPACK3(plane_a), UNPACK3(plane_b), UNPACK3(plane_c)); - if (det != 0.0f) { - float tmp[3]; + if (det != 0.0f) { + float tmp[3]; - /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] + - * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3] + - * plane_a.xyz.cross(plane_b.xyz) * -plane_c[3]) / det; */ + /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] + + * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3] + + * plane_a.xyz.cross(plane_b.xyz) * -plane_c[3]) / det; */ - cross_v3_v3v3(tmp, plane_c, plane_b); - mul_v3_v3fl(r_isect_co, tmp, plane_a[3]); + cross_v3_v3v3(tmp, plane_c, plane_b); + mul_v3_v3fl(r_isect_co, tmp, plane_a[3]); - cross_v3_v3v3(tmp, plane_a, plane_c); - madd_v3_v3fl(r_isect_co, tmp, plane_b[3]); + cross_v3_v3v3(tmp, plane_a, plane_c); + madd_v3_v3fl(r_isect_co, tmp, plane_b[3]); - cross_v3_v3v3(tmp, plane_b, plane_a); - madd_v3_v3fl(r_isect_co, tmp, plane_c[3]); + cross_v3_v3v3(tmp, plane_b, plane_a); + madd_v3_v3fl(r_isect_co, tmp, plane_c[3]); - mul_v3_fl(r_isect_co, 1.0f / det); + mul_v3_fl(r_isect_co, 1.0f / det); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } /** @@ -2154,38 +2193,39 @@ bool isect_plane_plane_plane_v3( * * \note \a r_isect_no isn't unit length. */ -bool isect_plane_plane_v3( - const float plane_a[4], const float plane_b[4], - float r_isect_co[3], float r_isect_no[3]) +bool isect_plane_plane_v3(const float plane_a[4], + const float plane_b[4], + float r_isect_co[3], + float r_isect_no[3]) { - float det, plane_c[3]; + float det, plane_c[3]; - /* direction is simply the cross product */ - cross_v3_v3v3(plane_c, plane_a, plane_b); + /* direction is simply the cross product */ + cross_v3_v3v3(plane_c, plane_a, plane_b); - /* in this case we don't need to use 'determinant_m3' */ - det = len_squared_v3(plane_c); + /* in this case we don't need to use 'determinant_m3' */ + det = len_squared_v3(plane_c); - if (det != 0.0f) { - float tmp[3]; + if (det != 0.0f) { + float tmp[3]; - /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] + - * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3]) / det; */ - cross_v3_v3v3(tmp, plane_c, plane_b); - mul_v3_v3fl(r_isect_co, tmp, plane_a[3]); + /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] + + * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3]) / det; */ + cross_v3_v3v3(tmp, plane_c, plane_b); + mul_v3_v3fl(r_isect_co, tmp, plane_a[3]); - cross_v3_v3v3(tmp, plane_a, plane_c); - madd_v3_v3fl(r_isect_co, tmp, plane_b[3]); + cross_v3_v3v3(tmp, plane_a, plane_c); + madd_v3_v3fl(r_isect_co, tmp, plane_b[3]); - mul_v3_fl(r_isect_co, 1.0f / det); + mul_v3_fl(r_isect_co, 1.0f / det); - copy_v3_v3(r_isect_no, plane_c); + copy_v3_v3(r_isect_no, plane_c); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } /** @@ -2196,138 +2236,140 @@ bool isect_plane_plane_v3( * * \note intersections between coplanar triangles are currently undetected. */ -bool isect_tri_tri_epsilon_v3( - const float t_a0[3], const float t_a1[3], const float t_a2[3], - const float t_b0[3], const float t_b1[3], const float t_b2[3], - float r_i1[3], float r_i2[3], - const float epsilon) -{ - const float *tri_pair[2][3] = {{t_a0, t_a1, t_a2}, {t_b0, t_b1, t_b2}}; - float plane_a[4], plane_b[4]; - float plane_co[3], plane_no[3]; - - BLI_assert((r_i1 != NULL) == (r_i2 != NULL)); - - /* normalizing is needed for small triangles T46007 */ - normal_tri_v3(plane_a, UNPACK3(tri_pair[0])); - normal_tri_v3(plane_b, UNPACK3(tri_pair[1])); - - plane_a[3] = -dot_v3v3(plane_a, t_a0); - plane_b[3] = -dot_v3v3(plane_b, t_b0); - - if (isect_plane_plane_v3(plane_a, plane_b, plane_co, plane_no) && - (normalize_v3(plane_no) > epsilon)) - { - /** - * Implementation note: its simpler to project the triangles onto the intersection plane - * before intersecting their edges with the ray, defined by 'isect_plane_plane_v3'. - * This way we can use 'line_point_factor_v3_ex' to see if an edge crosses 'co_proj', - * then use the factor to calculate the world-space point. - */ - struct { - float min, max; - } range[2] = {{FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}}; - int t; - float co_proj[3]; - - closest_to_plane3_normalized_v3(co_proj, plane_no, plane_co); - - /* For both triangles, find the overlap with the line defined by the ray [co_proj, plane_no]. - * When the ranges overlap we know the triangles do too. */ - for (t = 0; t < 2; t++) { - int j, j_prev; - float tri_proj[3][3]; - - closest_to_plane3_normalized_v3(tri_proj[0], plane_no, tri_pair[t][0]); - closest_to_plane3_normalized_v3(tri_proj[1], plane_no, tri_pair[t][1]); - closest_to_plane3_normalized_v3(tri_proj[2], plane_no, tri_pair[t][2]); - - for (j = 0, j_prev = 2; j < 3; j_prev = j++) { - /* note that its important to have a very small nonzero epsilon here - * otherwise this fails for very small faces. - * However if its too small, large adjacent faces will count as intersecting */ - const float edge_fac = line_point_factor_v3_ex(co_proj, tri_proj[j_prev], tri_proj[j], 1e-10f, -1.0f); - /* ignore collinear lines, they are either an edge shared between 2 tri's - * (which runs along [co_proj, plane_no], but can be safely ignored). - * - * or a collinear edge placed away from the ray - - * which we don't intersect with & can ignore. */ - if (UNLIKELY(edge_fac == -1.0f)) { - /* pass */ - } - else if (edge_fac > 0.0f && edge_fac < 1.0f) { - float ix_tri[3]; - float span_fac; - - interp_v3_v3v3(ix_tri, tri_pair[t][j_prev], tri_pair[t][j], edge_fac); - /* the actual distance, since 'plane_no' is normalized */ - span_fac = dot_v3v3(plane_no, ix_tri); - - range[t].min = min_ff(range[t].min, span_fac); - range[t].max = max_ff(range[t].max, span_fac); - } - } - - if (range[t].min == FLT_MAX) { - return false; - } - } - - if (((range[0].min > range[1].max) || - (range[0].max < range[1].min)) == 0) - { - if (r_i1 && r_i2) { - project_plane_normalized_v3_v3v3(plane_co, plane_co, plane_no); - madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min)); - madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max)); - } - - return true; - } - } - - return false; +bool isect_tri_tri_epsilon_v3(const float t_a0[3], + const float t_a1[3], + const float t_a2[3], + const float t_b0[3], + const float t_b1[3], + const float t_b2[3], + float r_i1[3], + float r_i2[3], + const float epsilon) +{ + const float *tri_pair[2][3] = {{t_a0, t_a1, t_a2}, {t_b0, t_b1, t_b2}}; + float plane_a[4], plane_b[4]; + float plane_co[3], plane_no[3]; + + BLI_assert((r_i1 != NULL) == (r_i2 != NULL)); + + /* normalizing is needed for small triangles T46007 */ + normal_tri_v3(plane_a, UNPACK3(tri_pair[0])); + normal_tri_v3(plane_b, UNPACK3(tri_pair[1])); + + plane_a[3] = -dot_v3v3(plane_a, t_a0); + plane_b[3] = -dot_v3v3(plane_b, t_b0); + + if (isect_plane_plane_v3(plane_a, plane_b, plane_co, plane_no) && + (normalize_v3(plane_no) > epsilon)) { + /** + * Implementation note: its simpler to project the triangles onto the intersection plane + * before intersecting their edges with the ray, defined by 'isect_plane_plane_v3'. + * This way we can use 'line_point_factor_v3_ex' to see if an edge crosses 'co_proj', + * then use the factor to calculate the world-space point. + */ + struct { + float min, max; + } range[2] = {{FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}}; + int t; + float co_proj[3]; + + closest_to_plane3_normalized_v3(co_proj, plane_no, plane_co); + + /* For both triangles, find the overlap with the line defined by the ray [co_proj, plane_no]. + * When the ranges overlap we know the triangles do too. */ + for (t = 0; t < 2; t++) { + int j, j_prev; + float tri_proj[3][3]; + + closest_to_plane3_normalized_v3(tri_proj[0], plane_no, tri_pair[t][0]); + closest_to_plane3_normalized_v3(tri_proj[1], plane_no, tri_pair[t][1]); + closest_to_plane3_normalized_v3(tri_proj[2], plane_no, tri_pair[t][2]); + + for (j = 0, j_prev = 2; j < 3; j_prev = j++) { + /* note that its important to have a very small nonzero epsilon here + * otherwise this fails for very small faces. + * However if its too small, large adjacent faces will count as intersecting */ + const float edge_fac = line_point_factor_v3_ex( + co_proj, tri_proj[j_prev], tri_proj[j], 1e-10f, -1.0f); + /* ignore collinear lines, they are either an edge shared between 2 tri's + * (which runs along [co_proj, plane_no], but can be safely ignored). + * + * or a collinear edge placed away from the ray - + * which we don't intersect with & can ignore. */ + if (UNLIKELY(edge_fac == -1.0f)) { + /* pass */ + } + else if (edge_fac > 0.0f && edge_fac < 1.0f) { + float ix_tri[3]; + float span_fac; + + interp_v3_v3v3(ix_tri, tri_pair[t][j_prev], tri_pair[t][j], edge_fac); + /* the actual distance, since 'plane_no' is normalized */ + span_fac = dot_v3v3(plane_no, ix_tri); + + range[t].min = min_ff(range[t].min, span_fac); + range[t].max = max_ff(range[t].max, span_fac); + } + } + + if (range[t].min == FLT_MAX) { + return false; + } + } + + if (((range[0].min > range[1].max) || (range[0].max < range[1].min)) == 0) { + if (r_i1 && r_i2) { + project_plane_normalized_v3_v3v3(plane_co, plane_co, plane_no); + madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min)); + madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max)); + } + + return true; + } + } + + return false; } /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ -static bool getLowestRoot(const float a, const float b, const float c, const float maxR, float *root) -{ - /* Check if a solution exists */ - const float determinant = b * b - 4.0f * a * c; - - /* If determinant is negative it means no solutions. */ - if (determinant >= 0.0f) { - /* calculate the two roots: (if determinant == 0 then - * x1==x2 but lets disregard that slight optimization) */ - const float sqrtD = sqrtf(determinant); - float r1 = (-b - sqrtD) / (2.0f * a); - float r2 = (-b + sqrtD) / (2.0f * a); - - /* Sort so x1 <= x2 */ - if (r1 > r2) { - SWAP(float, r1, r2); - } - - /* Get lowest root: */ - if (r1 > 0.0f && r1 < maxR) { - *root = r1; - return true; - } - - /* It is possible that we want x2 - this can happen */ - /* if x1 < 0 */ - if (r2 > 0.0f && r2 < maxR) { - *root = r2; - return true; - } - } - /* No (valid) solutions */ - return false; +static bool getLowestRoot( + const float a, const float b, const float c, const float maxR, float *root) +{ + /* Check if a solution exists */ + const float determinant = b * b - 4.0f * a * c; + + /* If determinant is negative it means no solutions. */ + if (determinant >= 0.0f) { + /* calculate the two roots: (if determinant == 0 then + * x1==x2 but lets disregard that slight optimization) */ + const float sqrtD = sqrtf(determinant); + float r1 = (-b - sqrtD) / (2.0f * a); + float r2 = (-b + sqrtD) / (2.0f * a); + + /* Sort so x1 <= x2 */ + if (r1 > r2) { + SWAP(float, r1, r2); + } + + /* Get lowest root: */ + if (r1 > 0.0f && r1 < maxR) { + *root = r1; + return true; + } + + /* It is possible that we want x2 - this can happen */ + /* if x1 < 0 */ + if (r2 > 0.0f && r2 < maxR) { + *root = r2; + return true; + } + } + /* No (valid) solutions */ + return false; } - /** * Checks status of an AABB in relation to a list of planes. * @@ -2336,268 +2378,272 @@ static bool getLowestRoot(const float a, const float b, const float c, const flo * - ISECT_AABB_PLANE_CROSS_ANY (1): AABB intersects at least 1 plane; * - ISECT_AABB_PLANE_IN_FRONT_ALL (2): AABB is completely in front of all planes; */ -int isect_aabb_planes_v3( - const float (*planes)[4], const int totplane, - const float bbmin[3], const float bbmax[3]) -{ - int ret = ISECT_AABB_PLANE_IN_FRONT_ALL; - - float bb_near[3], bb_far[3]; - for (int i = 0; i < totplane; i++) { - aabb_get_near_far_from_plane(planes[i], bbmin, bbmax, bb_near, bb_far); - - if (plane_point_side_v3(planes[i], bb_far) < 0.0f) { - return ISECT_AABB_PLANE_BEHIND_ANY; - } - else if ((ret != ISECT_AABB_PLANE_CROSS_ANY) && - (plane_point_side_v3(planes[i], bb_near) < 0.0f)) - { - ret = ISECT_AABB_PLANE_CROSS_ANY; - } - } - - return ret; -} - -bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float ipoint[3]) -{ - float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; - float a, b, c, d, e, x, y, z, radius2 = radius * radius; - float elen2, edotv, edotbv, nordotv; - float newLambda; - bool found_by_sweep = false; - - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); - sub_v3_v3v3(vel, p2, p1); - - /*---test plane of tri---*/ - cross_v3_v3v3(nor, e1, e2); - normalize_v3(nor); - - /* flip normal */ - if (dot_v3v3(nor, vel) > 0.0f) { - negate_v3(nor); - } - - a = dot_v3v3(p1, nor) - dot_v3v3(v0, nor); - nordotv = dot_v3v3(nor, vel); - - if (fabsf(nordotv) < 0.000001f) { - if (fabsf(a) >= radius) { - return false; - } - } - else { - float t0 = (-a + radius) / nordotv; - float t1 = (-a - radius) / nordotv; - - if (t0 > t1) { - SWAP(float, t0, t1); - } - - if (t0 > 1.0f || t1 < 0.0f) { - return false; - } - - /* clamp to [0, 1] */ - CLAMP(t0, 0.0f, 1.0f); - CLAMP(t1, 0.0f, 1.0f); - - /*---test inside of tri---*/ - /* plane intersection point */ - - point[0] = p1[0] + vel[0] * t0 - nor[0] * radius; - point[1] = p1[1] + vel[1] * t0 - nor[1] * radius; - point[2] = p1[2] + vel[2] * t0 - nor[2] * radius; - - - /* is the point in the tri? */ - a = dot_v3v3(e1, e1); - b = dot_v3v3(e1, e2); - c = dot_v3v3(e2, e2); - - sub_v3_v3v3(temp, point, v0); - d = dot_v3v3(temp, e1); - e = dot_v3v3(temp, e2); - - x = d * c - e * b; - y = e * a - d * b; - z = x + y - (a * c - b * b); - - - if (z <= 0.0f && (x >= 0.0f && y >= 0.0f)) { - //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) { - *r_lambda = t0; - copy_v3_v3(ipoint, point); - return true; - } - } - - - *r_lambda = 1.0f; - - /*---test points---*/ - a = dot_v3v3(vel, vel); - - /*v0*/ - sub_v3_v3v3(temp, p1, v0); - b = 2.0f * dot_v3v3(vel, temp); - c = dot_v3v3(temp, temp) - radius2; - - if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { - copy_v3_v3(ipoint, v0); - found_by_sweep = true; - } - - /*v1*/ - sub_v3_v3v3(temp, p1, v1); - b = 2.0f * dot_v3v3(vel, temp); - c = dot_v3v3(temp, temp) - radius2; - - if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { - copy_v3_v3(ipoint, v1); - found_by_sweep = true; - } - - /*v2*/ - sub_v3_v3v3(temp, p1, v2); - b = 2.0f * dot_v3v3(vel, temp); - c = dot_v3v3(temp, temp) - radius2; - - if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { - copy_v3_v3(ipoint, v2); - found_by_sweep = true; - } - - /*---test edges---*/ - sub_v3_v3v3(e3, v2, v1); /* wasnt yet calculated */ - - - /*e1*/ - sub_v3_v3v3(bv, v0, p1); - - elen2 = dot_v3v3(e1, e1); - edotv = dot_v3v3(e1, vel); - edotbv = dot_v3v3(e1, bv); - - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; - b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); - c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; - - if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { - e = (edotv * newLambda - edotbv) / elen2; - - if (e >= 0.0f && e <= 1.0f) { - *r_lambda = newLambda; - copy_v3_v3(ipoint, e1); - mul_v3_fl(ipoint, e); - add_v3_v3(ipoint, v0); - found_by_sweep = true; - } - } - - /*e2*/ - /*bv is same*/ - elen2 = dot_v3v3(e2, e2); - edotv = dot_v3v3(e2, vel); - edotbv = dot_v3v3(e2, bv); - - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; - b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); - c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; - - if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { - e = (edotv * newLambda - edotbv) / elen2; - - if (e >= 0.0f && e <= 1.0f) { - *r_lambda = newLambda; - copy_v3_v3(ipoint, e2); - mul_v3_fl(ipoint, e); - add_v3_v3(ipoint, v0); - found_by_sweep = true; - } - } - - /*e3*/ - /* sub_v3_v3v3(bv, v0, p1); */ /* UNUSED */ - /* elen2 = dot_v3v3(e1, e1); */ /* UNUSED */ - /* edotv = dot_v3v3(e1, vel); */ /* UNUSED */ - /* edotbv = dot_v3v3(e1, bv); */ /* UNUSED */ - - sub_v3_v3v3(bv, v1, p1); - elen2 = dot_v3v3(e3, e3); - edotv = dot_v3v3(e3, vel); - edotbv = dot_v3v3(e3, bv); - - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; - b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); - c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; - - if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { - e = (edotv * newLambda - edotbv) / elen2; - - if (e >= 0.0f && e <= 1.0f) { - *r_lambda = newLambda; - copy_v3_v3(ipoint, e3); - mul_v3_fl(ipoint, e); - add_v3_v3(ipoint, v1); - found_by_sweep = true; - } - } - - - return found_by_sweep; -} - -bool isect_axial_line_segment_tri_v3( - const int axis, const float p1[3], const float p2[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda) -{ - const float epsilon = 0.000001f; - float p[3], e1[3], e2[3]; - float u, v, f; - int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3; - - sub_v3_v3v3(e1, v1, v0); - sub_v3_v3v3(e2, v2, v0); - sub_v3_v3v3(p, v0, p1); - - f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]); - if ((f > -epsilon) && (f < epsilon)) { - return false; - } - - v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f; - if ((v < 0.0f) || (v > 1.0f)) { - return false; - } - - f = e1[a1]; - if ((f > -epsilon) && (f < epsilon)) { - f = e1[a2]; - if ((f > -epsilon) && (f < epsilon)) { - return false; - } - u = (-p[a2] - v * e2[a2]) / f; - } - else { - u = (-p[a1] - v * e2[a1]) / f; - } - - if ((u < 0.0f) || ((u + v) > 1.0f)) { - return false; - } - - *r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]); - - if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { - return false; - } - - return true; +int isect_aabb_planes_v3(const float (*planes)[4], + const int totplane, + const float bbmin[3], + const float bbmax[3]) +{ + int ret = ISECT_AABB_PLANE_IN_FRONT_ALL; + + float bb_near[3], bb_far[3]; + for (int i = 0; i < totplane; i++) { + aabb_get_near_far_from_plane(planes[i], bbmin, bbmax, bb_near, bb_far); + + if (plane_point_side_v3(planes[i], bb_far) < 0.0f) { + return ISECT_AABB_PLANE_BEHIND_ANY; + } + else if ((ret != ISECT_AABB_PLANE_CROSS_ANY) && + (plane_point_side_v3(planes[i], bb_near) < 0.0f)) { + ret = ISECT_AABB_PLANE_CROSS_ANY; + } + } + + return ret; +} + +bool isect_sweeping_sphere_tri_v3(const float p1[3], + const float p2[3], + const float radius, + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda, + float ipoint[3]) +{ + float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; + float a, b, c, d, e, x, y, z, radius2 = radius * radius; + float elen2, edotv, edotbv, nordotv; + float newLambda; + bool found_by_sweep = false; + + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(vel, p2, p1); + + /*---test plane of tri---*/ + cross_v3_v3v3(nor, e1, e2); + normalize_v3(nor); + + /* flip normal */ + if (dot_v3v3(nor, vel) > 0.0f) { + negate_v3(nor); + } + + a = dot_v3v3(p1, nor) - dot_v3v3(v0, nor); + nordotv = dot_v3v3(nor, vel); + + if (fabsf(nordotv) < 0.000001f) { + if (fabsf(a) >= radius) { + return false; + } + } + else { + float t0 = (-a + radius) / nordotv; + float t1 = (-a - radius) / nordotv; + + if (t0 > t1) { + SWAP(float, t0, t1); + } + + if (t0 > 1.0f || t1 < 0.0f) { + return false; + } + + /* clamp to [0, 1] */ + CLAMP(t0, 0.0f, 1.0f); + CLAMP(t1, 0.0f, 1.0f); + + /*---test inside of tri---*/ + /* plane intersection point */ + + point[0] = p1[0] + vel[0] * t0 - nor[0] * radius; + point[1] = p1[1] + vel[1] * t0 - nor[1] * radius; + point[2] = p1[2] + vel[2] * t0 - nor[2] * radius; + + /* is the point in the tri? */ + a = dot_v3v3(e1, e1); + b = dot_v3v3(e1, e2); + c = dot_v3v3(e2, e2); + + sub_v3_v3v3(temp, point, v0); + d = dot_v3v3(temp, e1); + e = dot_v3v3(temp, e2); + + x = d * c - e * b; + y = e * a - d * b; + z = x + y - (a * c - b * b); + + if (z <= 0.0f && (x >= 0.0f && y >= 0.0f)) { + //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) { + *r_lambda = t0; + copy_v3_v3(ipoint, point); + return true; + } + } + + *r_lambda = 1.0f; + + /*---test points---*/ + a = dot_v3v3(vel, vel); + + /*v0*/ + sub_v3_v3v3(temp, p1, v0); + b = 2.0f * dot_v3v3(vel, temp); + c = dot_v3v3(temp, temp) - radius2; + + if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { + copy_v3_v3(ipoint, v0); + found_by_sweep = true; + } + + /*v1*/ + sub_v3_v3v3(temp, p1, v1); + b = 2.0f * dot_v3v3(vel, temp); + c = dot_v3v3(temp, temp) - radius2; + + if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { + copy_v3_v3(ipoint, v1); + found_by_sweep = true; + } + + /*v2*/ + sub_v3_v3v3(temp, p1, v2); + b = 2.0f * dot_v3v3(vel, temp); + c = dot_v3v3(temp, temp) - radius2; + + if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) { + copy_v3_v3(ipoint, v2); + found_by_sweep = true; + } + + /*---test edges---*/ + sub_v3_v3v3(e3, v2, v1); /* wasnt yet calculated */ + + /*e1*/ + sub_v3_v3v3(bv, v0, p1); + + elen2 = dot_v3v3(e1, e1); + edotv = dot_v3v3(e1, vel); + edotbv = dot_v3v3(e1, bv); + + a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); + c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; + + if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { + e = (edotv * newLambda - edotbv) / elen2; + + if (e >= 0.0f && e <= 1.0f) { + *r_lambda = newLambda; + copy_v3_v3(ipoint, e1); + mul_v3_fl(ipoint, e); + add_v3_v3(ipoint, v0); + found_by_sweep = true; + } + } + + /*e2*/ + /*bv is same*/ + elen2 = dot_v3v3(e2, e2); + edotv = dot_v3v3(e2, vel); + edotbv = dot_v3v3(e2, bv); + + a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); + c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; + + if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { + e = (edotv * newLambda - edotbv) / elen2; + + if (e >= 0.0f && e <= 1.0f) { + *r_lambda = newLambda; + copy_v3_v3(ipoint, e2); + mul_v3_fl(ipoint, e); + add_v3_v3(ipoint, v0); + found_by_sweep = true; + } + } + + /*e3*/ + /* sub_v3_v3v3(bv, v0, p1); */ /* UNUSED */ + /* elen2 = dot_v3v3(e1, e1); */ /* UNUSED */ + /* edotv = dot_v3v3(e1, vel); */ /* UNUSED */ + /* edotbv = dot_v3v3(e1, bv); */ /* UNUSED */ + + sub_v3_v3v3(bv, v1, p1); + elen2 = dot_v3v3(e3, e3); + edotv = dot_v3v3(e3, vel); + edotbv = dot_v3v3(e3, bv); + + a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); + c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; + + if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) { + e = (edotv * newLambda - edotbv) / elen2; + + if (e >= 0.0f && e <= 1.0f) { + *r_lambda = newLambda; + copy_v3_v3(ipoint, e3); + mul_v3_fl(ipoint, e); + add_v3_v3(ipoint, v1); + found_by_sweep = true; + } + } + + return found_by_sweep; +} + +bool isect_axial_line_segment_tri_v3(const int axis, + const float p1[3], + const float p2[3], + const float v0[3], + const float v1[3], + const float v2[3], + float *r_lambda) +{ + const float epsilon = 0.000001f; + float p[3], e1[3], e2[3]; + float u, v, f; + int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3; + + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(p, v0, p1); + + f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]); + if ((f > -epsilon) && (f < epsilon)) { + return false; + } + + v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f; + if ((v < 0.0f) || (v > 1.0f)) { + return false; + } + + f = e1[a1]; + if ((f > -epsilon) && (f < epsilon)) { + f = e1[a2]; + if ((f > -epsilon) && (f < epsilon)) { + return false; + } + u = (-p[a2] - v * e2[a2]) / f; + } + else { + u = (-p[a1] - v * e2[a1]) / f; + } + + if ((u < 0.0f) || ((u + v) > 1.0f)) { + return false; + } + + *r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]); + + if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) { + return false; + } + + return true; } /** @@ -2606,201 +2652,210 @@ bool isect_axial_line_segment_tri_v3( * 1 - lines are coplanar, i1 is set to intersection * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively */ -int isect_line_line_epsilon_v3( - const float v1[3], const float v2[3], - const float v3[3], const float v4[3], - float r_i1[3], float r_i2[3], - const float epsilon) -{ - float a[3], b[3], c[3], ab[3], cb[3]; - float d, div; - - sub_v3_v3v3(c, v3, v1); - sub_v3_v3v3(a, v2, v1); - sub_v3_v3v3(b, v4, v3); - - cross_v3_v3v3(ab, a, b); - d = dot_v3v3(c, ab); - div = dot_v3v3(ab, ab); - - /* important not to use an epsilon here, see: T45919 */ - /* test zero length line */ - if (UNLIKELY(div == 0.0f)) { - return 0; - } - /* test if the two lines are coplanar */ - else if (UNLIKELY(fabsf(d) <= epsilon)) { - cross_v3_v3v3(cb, c, b); - - mul_v3_fl(a, dot_v3v3(cb, ab) / div); - add_v3_v3v3(r_i1, v1, a); - copy_v3_v3(r_i2, r_i1); - - return 1; /* one intersection only */ - } - /* if not */ - else { - float n[3], t[3]; - float v3t[3], v4t[3]; - sub_v3_v3v3(t, v1, v3); - - /* offset between both plane where the lines lies */ - cross_v3_v3v3(n, a, b); - project_v3_v3v3(t, t, n); - - /* for the first line, offset the second line until it is coplanar */ - add_v3_v3v3(v3t, v3, t); - add_v3_v3v3(v4t, v4, t); - - sub_v3_v3v3(c, v3t, v1); - sub_v3_v3v3(a, v2, v1); - sub_v3_v3v3(b, v4t, v3t); - - cross_v3_v3v3(ab, a, b); - cross_v3_v3v3(cb, c, b); - - mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab)); - add_v3_v3v3(r_i1, v1, a); - - /* for the second line, just substract the offset from the first intersection point */ - sub_v3_v3v3(r_i2, r_i1, t); - - return 2; /* two nearest points */ - } -} - -int isect_line_line_v3( - const float v1[3], const float v2[3], - const float v3[3], const float v4[3], - float r_i1[3], float r_i2[3]) -{ - const float epsilon = 0.000001f; - return isect_line_line_epsilon_v3(v1, v2, v3, v4, r_i1, r_i2, epsilon); +int isect_line_line_epsilon_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + float r_i1[3], + float r_i2[3], + const float epsilon) +{ + float a[3], b[3], c[3], ab[3], cb[3]; + float d, div; + + sub_v3_v3v3(c, v3, v1); + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v4, v3); + + cross_v3_v3v3(ab, a, b); + d = dot_v3v3(c, ab); + div = dot_v3v3(ab, ab); + + /* important not to use an epsilon here, see: T45919 */ + /* test zero length line */ + if (UNLIKELY(div == 0.0f)) { + return 0; + } + /* test if the two lines are coplanar */ + else if (UNLIKELY(fabsf(d) <= epsilon)) { + cross_v3_v3v3(cb, c, b); + + mul_v3_fl(a, dot_v3v3(cb, ab) / div); + add_v3_v3v3(r_i1, v1, a); + copy_v3_v3(r_i2, r_i1); + + return 1; /* one intersection only */ + } + /* if not */ + else { + float n[3], t[3]; + float v3t[3], v4t[3]; + sub_v3_v3v3(t, v1, v3); + + /* offset between both plane where the lines lies */ + cross_v3_v3v3(n, a, b); + project_v3_v3v3(t, t, n); + + /* for the first line, offset the second line until it is coplanar */ + add_v3_v3v3(v3t, v3, t); + add_v3_v3v3(v4t, v4, t); + + sub_v3_v3v3(c, v3t, v1); + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v4t, v3t); + + cross_v3_v3v3(ab, a, b); + cross_v3_v3v3(cb, c, b); + + mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab)); + add_v3_v3v3(r_i1, v1, a); + + /* for the second line, just substract the offset from the first intersection point */ + sub_v3_v3v3(r_i2, r_i1, t); + + return 2; /* two nearest points */ + } +} + +int isect_line_line_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + float r_i1[3], + float r_i2[3]) +{ + const float epsilon = 0.000001f; + return isect_line_line_epsilon_v3(v1, v2, v3, v4, r_i1, r_i2, epsilon); } /** Intersection point strictly between the two lines * \return false when no intersection is found */ -bool isect_line_line_strict_v3(const float v1[3], const float v2[3], - const float v3[3], const float v4[3], - float vi[3], float *r_lambda) -{ - const float epsilon = 0.000001f; - float a[3], b[3], c[3], ab[3], cb[3], ca[3]; - float d, div; - - sub_v3_v3v3(c, v3, v1); - sub_v3_v3v3(a, v2, v1); - sub_v3_v3v3(b, v4, v3); - - cross_v3_v3v3(ab, a, b); - d = dot_v3v3(c, ab); - div = dot_v3v3(ab, ab); - - /* important not to use an epsilon here, see: T45919 */ - /* test zero length line */ - if (UNLIKELY(div == 0.0f)) { - return false; - } - /* test if the two lines are coplanar */ - else if (UNLIKELY(fabsf(d) < epsilon)) { - return false; - } - else { - float f1, f2; - cross_v3_v3v3(cb, c, b); - cross_v3_v3v3(ca, c, a); - - f1 = dot_v3v3(cb, ab) / div; - f2 = dot_v3v3(ca, ab) / div; - - if (f1 >= 0 && f1 <= 1 && - f2 >= 0 && f2 <= 1) - { - mul_v3_fl(a, f1); - add_v3_v3v3(vi, v1, a); - - if (r_lambda) { - *r_lambda = f1; - } - - return true; /* intersection found */ - } - else { - return false; - } - } -} - -bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]) -{ - return (min1[0] < max2[0] && min1[1] < max2[1] && min1[2] < max2[2] && - min2[0] < max1[0] && min2[1] < max1[1] && min2[2] < max1[2]); -} - -void isect_ray_aabb_v3_precalc( - struct IsectRayAABB_Precalc *data, - const float ray_origin[3], const float ray_direction[3]) -{ - copy_v3_v3(data->ray_origin, ray_origin); - - data->ray_inv_dir[0] = 1.0f / ray_direction[0]; - data->ray_inv_dir[1] = 1.0f / ray_direction[1]; - data->ray_inv_dir[2] = 1.0f / ray_direction[2]; - - data->sign[0] = data->ray_inv_dir[0] < 0.0f; - data->sign[1] = data->ray_inv_dir[1] < 0.0f; - data->sign[2] = data->ray_inv_dir[2] < 0.0f; +bool isect_line_line_strict_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + float vi[3], + float *r_lambda) +{ + const float epsilon = 0.000001f; + float a[3], b[3], c[3], ab[3], cb[3], ca[3]; + float d, div; + + sub_v3_v3v3(c, v3, v1); + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v4, v3); + + cross_v3_v3v3(ab, a, b); + d = dot_v3v3(c, ab); + div = dot_v3v3(ab, ab); + + /* important not to use an epsilon here, see: T45919 */ + /* test zero length line */ + if (UNLIKELY(div == 0.0f)) { + return false; + } + /* test if the two lines are coplanar */ + else if (UNLIKELY(fabsf(d) < epsilon)) { + return false; + } + else { + float f1, f2; + cross_v3_v3v3(cb, c, b); + cross_v3_v3v3(ca, c, a); + + f1 = dot_v3v3(cb, ab) / div; + f2 = dot_v3v3(ca, ab) / div; + + if (f1 >= 0 && f1 <= 1 && f2 >= 0 && f2 <= 1) { + mul_v3_fl(a, f1); + add_v3_v3v3(vi, v1, a); + + if (r_lambda) { + *r_lambda = f1; + } + + return true; /* intersection found */ + } + else { + return false; + } + } +} + +bool isect_aabb_aabb_v3(const float min1[3], + const float max1[3], + const float min2[3], + const float max2[3]) +{ + return (min1[0] < max2[0] && min1[1] < max2[1] && min1[2] < max2[2] && min2[0] < max1[0] && + min2[1] < max1[1] && min2[2] < max1[2]); +} + +void isect_ray_aabb_v3_precalc(struct IsectRayAABB_Precalc *data, + const float ray_origin[3], + const float ray_direction[3]) +{ + copy_v3_v3(data->ray_origin, ray_origin); + + data->ray_inv_dir[0] = 1.0f / ray_direction[0]; + data->ray_inv_dir[1] = 1.0f / ray_direction[1]; + data->ray_inv_dir[2] = 1.0f / ray_direction[2]; + + data->sign[0] = data->ray_inv_dir[0] < 0.0f; + data->sign[1] = data->ray_inv_dir[1] < 0.0f; + data->sign[2] = data->ray_inv_dir[2] < 0.0f; } /* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */ -bool isect_ray_aabb_v3( - const struct IsectRayAABB_Precalc *data, const float bb_min[3], - const float bb_max[3], float *tmin_out) +bool isect_ray_aabb_v3(const struct IsectRayAABB_Precalc *data, + const float bb_min[3], + const float bb_max[3], + float *tmin_out) { - float bbox[2][3]; + float bbox[2][3]; - copy_v3_v3(bbox[0], bb_min); - copy_v3_v3(bbox[1], bb_max); + copy_v3_v3(bbox[0], bb_min); + copy_v3_v3(bbox[1], bb_max); - float tmin = (bbox[data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0]; - float tmax = (bbox[1 - data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0]; + float tmin = (bbox[data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0]; + float tmax = (bbox[1 - data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0]; - const float tymin = (bbox[data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1]; - const float tymax = (bbox[1 - data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1]; + const float tymin = (bbox[data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1]; + const float tymax = (bbox[1 - data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1]; - if ((tmin > tymax) || (tymin > tmax)) { - return false; - } + if ((tmin > tymax) || (tymin > tmax)) { + return false; + } - if (tymin > tmin) { - tmin = tymin; - } + if (tymin > tmin) { + tmin = tymin; + } - if (tymax < tmax) { - tmax = tymax; - } + if (tymax < tmax) { + tmax = tymax; + } - const float tzmin = (bbox[data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2]; - const float tzmax = (bbox[1 - data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2]; + const float tzmin = (bbox[data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2]; + const float tzmax = (bbox[1 - data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2]; - if ((tmin > tzmax) || (tzmin > tmax)) { - return false; - } + if ((tmin > tzmax) || (tzmin > tmax)) { + return false; + } - if (tzmin > tmin) { - tmin = tzmin; - } + if (tzmin > tmin) { + tmin = tzmin; + } - /* Note: tmax does not need to be updated since we don't use it - * keeping this here for future reference - jwilkins */ - //if (tzmax < tmax) tmax = tzmax; + /* Note: tmax does not need to be updated since we don't use it + * keeping this here for future reference - jwilkins */ + //if (tzmax < tmax) tmax = tzmax; - if (tmin_out) { - (*tmin_out) = tmin; - } + if (tmin_out) { + (*tmin_out) = tmin; + } - return true; + return true; } /** @@ -2809,36 +2864,38 @@ bool isect_ray_aabb_v3( * * \note: \a direction should be normalized if you intend to use the \a tmin or \a tmax distance results! */ -bool isect_ray_aabb_v3_simple( - const float orig[3], const float dir[3], - const float bb_min[3], const float bb_max[3], - float *tmin, float *tmax) -{ - double t[6]; - float hit_dist[2]; - const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX; - const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX; - const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX; - t[0] = (double)(bb_min[0] - orig[0]) * invdirx; - t[1] = (double)(bb_max[0] - orig[0]) * invdirx; - t[2] = (double)(bb_min[1] - orig[1]) * invdiry; - t[3] = (double)(bb_max[1] - orig[1]) * invdiry; - t[4] = (double)(bb_min[2] - orig[2]) * invdirz; - t[5] = (double)(bb_max[2] - orig[2]) * invdirz; - hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); - hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); - if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { - return false; - } - else { - if (tmin) { - *tmin = hit_dist[0]; - } - if (tmax) { - *tmax = hit_dist[1]; - } - return true; - } +bool isect_ray_aabb_v3_simple(const float orig[3], + const float dir[3], + const float bb_min[3], + const float bb_max[3], + float *tmin, + float *tmax) +{ + double t[6]; + float hit_dist[2]; + const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX; + const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX; + const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX; + t[0] = (double)(bb_min[0] - orig[0]) * invdirx; + t[1] = (double)(bb_max[0] - orig[0]) * invdirx; + t[2] = (double)(bb_min[1] - orig[1]) * invdiry; + t[3] = (double)(bb_max[1] - orig[1]) * invdiry; + t[4] = (double)(bb_min[2] - orig[2]) * invdirz; + t[5] = (double)(bb_max[2] - orig[2]) * invdirz; + hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); + hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); + if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { + return false; + } + else { + if (tmin) { + *tmin = hit_dist[0]; + } + if (tmax) { + *tmax = hit_dist[1]; + } + return true; + } } /* find closest point to p on line through (l1, l2) and return lambda, @@ -2846,41 +2903,44 @@ bool isect_ray_aabb_v3_simple( */ float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]) { - float h[3], u[3], lambda; - sub_v3_v3v3(u, l2, l1); - sub_v3_v3v3(h, p, l1); - lambda = dot_v3v3(u, h) / dot_v3v3(u, u); - r_close[0] = l1[0] + u[0] * lambda; - r_close[1] = l1[1] + u[1] * lambda; - r_close[2] = l1[2] + u[2] * lambda; - return lambda; + float h[3], u[3], lambda; + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, p, l1); + lambda = dot_v3v3(u, h) / dot_v3v3(u, u); + r_close[0] = l1[0] + u[0] * lambda; + r_close[1] = l1[1] + u[1] * lambda; + r_close[2] = l1[2] + u[2] * lambda; + return lambda; } float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2]) { - float h[2], u[2], lambda; - sub_v2_v2v2(u, l2, l1); - sub_v2_v2v2(h, p, l1); - lambda = dot_v2v2(u, h) / dot_v2v2(u, u); - r_close[0] = l1[0] + u[0] * lambda; - r_close[1] = l1[1] + u[1] * lambda; - return lambda; + float h[2], u[2], lambda; + sub_v2_v2v2(u, l2, l1); + sub_v2_v2v2(h, p, l1); + lambda = dot_v2v2(u, h) / dot_v2v2(u, u); + r_close[0] = l1[0] + u[0] * lambda; + r_close[1] = l1[1] + u[1] * lambda; + return lambda; } -float ray_point_factor_v3_ex( - const float p[3], const float ray_origin[3], const float ray_direction[3], - const float epsilon, const float fallback) +float ray_point_factor_v3_ex(const float p[3], + const float ray_origin[3], + const float ray_direction[3], + const float epsilon, + const float fallback) { - float p_relative[3]; - sub_v3_v3v3(p_relative, p, ray_origin); - const float dot = len_squared_v3(ray_direction); - return (dot > epsilon) ? (dot_v3v3(ray_direction, p_relative) / dot) : fallback; + float p_relative[3]; + sub_v3_v3v3(p_relative, p, ray_origin); + const float dot = len_squared_v3(ray_direction); + return (dot > epsilon) ? (dot_v3v3(ray_direction, p_relative) / dot) : fallback; } -float ray_point_factor_v3( - const float p[3], const float ray_origin[3], const float ray_direction[3]) +float ray_point_factor_v3(const float p[3], + const float ray_origin[3], + const float ray_direction[3]) { - return ray_point_factor_v3_ex(p, ray_origin, ray_direction, 0.0f, 0.0f); + return ray_point_factor_v3_ex(p, ray_origin, ray_direction, 0.0f, 0.0f); } /** @@ -2890,55 +2950,60 @@ float ray_point_factor_v3( * \param epsilon: avoid approaching divide-by-zero. * Passing a zero will just check for nonzero division. */ -float line_point_factor_v3_ex( - const float p[3], const float l1[3], const float l2[3], - const float epsilon, const float fallback) +float line_point_factor_v3_ex(const float p[3], + const float l1[3], + const float l2[3], + const float epsilon, + const float fallback) { - float h[3], u[3]; - float dot; - sub_v3_v3v3(u, l2, l1); - sub_v3_v3v3(h, p, l1); + float h[3], u[3]; + float dot; + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, p, l1); - /* better check for zero */ - dot = len_squared_v3(u); - return (dot > epsilon) ? (dot_v3v3(u, h) / dot) : fallback; + /* better check for zero */ + dot = len_squared_v3(u); + return (dot > epsilon) ? (dot_v3v3(u, h) / dot) : fallback; } -float line_point_factor_v3( - const float p[3], const float l1[3], const float l2[3]) +float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]) { - return line_point_factor_v3_ex(p, l1, l2, 0.0f, 0.0f); + return line_point_factor_v3_ex(p, l1, l2, 0.0f, 0.0f); } -float line_point_factor_v2_ex( - const float p[2], const float l1[2], const float l2[2], - const float epsilon, const float fallback) +float line_point_factor_v2_ex(const float p[2], + const float l1[2], + const float l2[2], + const float epsilon, + const float fallback) { - float h[2], u[2]; - float dot; - sub_v2_v2v2(u, l2, l1); - sub_v2_v2v2(h, p, l1); - /* better check for zero */ - dot = len_squared_v2(u); - return (dot > epsilon) ? (dot_v2v2(u, h) / dot) : fallback; + float h[2], u[2]; + float dot; + sub_v2_v2v2(u, l2, l1); + sub_v2_v2v2(h, p, l1); + /* better check for zero */ + dot = len_squared_v2(u); + return (dot > epsilon) ? (dot_v2v2(u, h) / dot) : fallback; } float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]) { - return line_point_factor_v2_ex(p, l1, l2, 0.0f, 0.0f); + return line_point_factor_v2_ex(p, l1, l2, 0.0f, 0.0f); } /** * \note #isect_line_plane_v3() shares logic */ -float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], - const float l1[3], const float l2[3]) +float line_plane_factor_v3(const float plane_co[3], + const float plane_no[3], + const float l1[3], + const float l2[3]) { - float u[3], h[3]; - float dot; - sub_v3_v3v3(u, l2, l1); - sub_v3_v3v3(h, l1, plane_co); - dot = dot_v3v3(plane_no, u); - return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f; + float u[3], h[3]; + float dot; + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); + return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f; } /** @@ -2947,19 +3012,19 @@ float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], */ void limit_dist_v3(float v1[3], float v2[3], const float dist) { - const float dist_old = len_v3v3(v1, v2); + const float dist_old = len_v3v3(v1, v2); - if (dist_old > dist) { - float v1_old[3]; - float v2_old[3]; - float fac = (dist / dist_old) * 0.5f; + if (dist_old > dist) { + float v1_old[3]; + float v2_old[3]; + float fac = (dist / dist_old) * 0.5f; - copy_v3_v3(v1_old, v1); - copy_v3_v3(v2_old, v2); + copy_v3_v3(v1_old, v1); + copy_v3_v3(v2_old, v2); - interp_v3_v3v3(v1, v1_old, v2_old, 0.5f - fac); - interp_v3_v3v3(v2, v1_old, v2_old, 0.5f + fac); - } + interp_v3_v3v3(v1, v1_old, v2_old, 0.5f - fac); + interp_v3_v3v3(v2, v1_old, v2_old, 0.5f + fac); + } } /* @@ -2969,79 +3034,92 @@ void limit_dist_v3(float v1[3], float v2[3], const float dist) * | \ * x1,y1-- x2,y1 */ -int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b) +int isect_point_tri_v2_int( + const int x1, const int y1, const int x2, const int y2, const int a, const int b) { - float v1[2], v2[2], v3[2], p[2]; + float v1[2], v2[2], v3[2], p[2]; - v1[0] = (float)x1; - v1[1] = (float)y1; + v1[0] = (float)x1; + v1[1] = (float)y1; - v2[0] = (float)x1; - v2[1] = (float)y2; + v2[0] = (float)x1; + v2[1] = (float)y2; - v3[0] = (float)x2; - v3[1] = (float)y1; + v3[0] = (float)x2; + v3[1] = (float)y1; - p[0] = (float)a; - p[1] = (float)b; + p[0] = (float)a; + p[1] = (float)b; - return isect_point_tri_v2(p, v1, v2, v3); + return isect_point_tri_v2(p, v1, v2, v3); } -static bool point_in_slice(const float p[3], const float v1[3], const float l1[3], const float l2[3]) +static bool point_in_slice(const float p[3], + const float v1[3], + const float l1[3], + const float l2[3]) { - /* - * what is a slice ? - * some maths: - * a line including (l1, l2) and a point not on the line - * define a subset of R3 delimited by planes parallel to the line and orthogonal - * to the (point --> line) distance vector, one plane on the line one on the point, - * the room inside usually is rather small compared to R3 though still infinite - * useful for restricting (speeding up) searches - * e.g. all points of triangular prism are within the intersection of 3 'slices' - * another trivial case : cube - * but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too - */ - float h, rp[3], cp[3], q[3]; + /* + * what is a slice ? + * some maths: + * a line including (l1, l2) and a point not on the line + * define a subset of R3 delimited by planes parallel to the line and orthogonal + * to the (point --> line) distance vector, one plane on the line one on the point, + * the room inside usually is rather small compared to R3 though still infinite + * useful for restricting (speeding up) searches + * e.g. all points of triangular prism are within the intersection of 3 'slices' + * another trivial case : cube + * but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too + */ + float h, rp[3], cp[3], q[3]; - closest_to_line_v3(cp, v1, l1, l2); - sub_v3_v3v3(q, cp, v1); + closest_to_line_v3(cp, v1, l1, l2); + sub_v3_v3v3(q, cp, v1); - sub_v3_v3v3(rp, p, v1); - h = dot_v3v3(q, rp) / dot_v3v3(q, q); - /* note: when 'h' is nan/-nan, this check returns false - * without explicit check - covering the degenerate case */ - return (h >= 0.0f && h <= 1.0f); + sub_v3_v3v3(rp, p, v1); + h = dot_v3v3(q, rp) / dot_v3v3(q, q); + /* note: when 'h' is nan/-nan, this check returns false + * without explicit check - covering the degenerate case */ + return (h >= 0.0f && h <= 1.0f); } /* adult sister defining the slice planes by the origin and the normal * NOTE |normal| may not be 1 but defining the thickness of the slice */ static bool point_in_slice_as(float p[3], float origin[3], float normal[3]) { - float h, rp[3]; - sub_v3_v3v3(rp, p, origin); - h = dot_v3v3(normal, rp) / dot_v3v3(normal, normal); - if (h < 0.0f || h > 1.0f) { - return false; - } - return true; + float h, rp[3]; + sub_v3_v3v3(rp, p, origin); + h = dot_v3v3(normal, rp) / dot_v3v3(normal, normal); + if (h < 0.0f || h > 1.0f) { + return false; + } + return true; } bool point_in_slice_seg(float p[3], float l1[3], float l2[3]) { - float normal[3]; + float normal[3]; - sub_v3_v3v3(normal, l2, l1); + sub_v3_v3v3(normal, l2, l1); - return point_in_slice_as(p, l1, normal); + return point_in_slice_as(p, l1, normal); } -bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]) +bool isect_point_tri_prism_v3(const float p[3], + const float v1[3], + const float v2[3], + const float v3[3]) { - if (!point_in_slice(p, v1, v2, v3)) { return false; } - if (!point_in_slice(p, v2, v3, v1)) { return false; } - if (!point_in_slice(p, v3, v1, v2)) { return false; } - return true; + if (!point_in_slice(p, v1, v2, v3)) { + return false; + } + if (!point_in_slice(p, v2, v3, v1)) { + return false; + } + if (!point_in_slice(p, v3, v1, v2)) { + return false; + } + return true; } /** @@ -3050,133 +3128,132 @@ bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v * \note Its up to the caller to check the distance between \a p and \a r_vi against an error margin. */ bool isect_point_tri_v3( - const float p[3], const float v1[3], const float v2[3], const float v3[3], - float r_isect_co[3]) + const float p[3], const float v1[3], const float v2[3], const float v3[3], float r_isect_co[3]) { - if (isect_point_tri_prism_v3(p, v1, v2, v3)) { - float plane[4]; - float no[3]; + if (isect_point_tri_prism_v3(p, v1, v2, v3)) { + float plane[4]; + float no[3]; - /* Could use normal_tri_v3, but doesn't have to be unit-length */ - cross_tri_v3(no, v1, v2, v3); - BLI_assert(len_squared_v3(no) != 0.0f); + /* Could use normal_tri_v3, but doesn't have to be unit-length */ + cross_tri_v3(no, v1, v2, v3); + BLI_assert(len_squared_v3(no) != 0.0f); - plane_from_point_normal_v3(plane, v1, no); - closest_to_plane_v3(r_isect_co, plane, p); + plane_from_point_normal_v3(plane, v1, no); + closest_to_plane_v3(r_isect_co, plane, p); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } bool clip_segment_v3_plane( - const float p1[3], const float p2[3], - const float plane[4], - float r_p1[3], float r_p2[3]) -{ - float dp[3], div; - - sub_v3_v3v3(dp, p2, p1); - div = dot_v3v3(dp, plane); - - if (div == 0.0f) { - /* parallel */ - return true; - } - - float t = -plane_point_side_v3(plane, p1); - - if (div > 0.0f) { - /* behind plane, completely clipped */ - if (t >= div) { - return false; - } - else if (t > 0.0f) { - const float p1_copy[3] = {UNPACK3(p1)}; - copy_v3_v3(r_p2, p2); - madd_v3_v3v3fl(r_p1, p1_copy, dp, t / div); - return true; - } - } - else { - /* behind plane, completely clipped */ - if (t >= 0.0f) { - return false; - } - else if (t > div) { - const float p1_copy[3] = {UNPACK3(p1)}; - copy_v3_v3(r_p1, p1); - madd_v3_v3v3fl(r_p2, p1_copy, dp, t / div); - return true; - } - } - - /* incase input/output values match (above also) */ - const float p1_copy[3] = {UNPACK3(p1)}; - copy_v3_v3(r_p2, p2); - copy_v3_v3(r_p1, p1_copy); - return true; -} - -bool clip_segment_v3_plane_n( - const float p1[3], const float p2[3], - const float plane_array[][4], const int plane_tot, - float r_p1[3], float r_p2[3]) -{ - /* intersect from both directions */ - float p1_fac = 0.0f, p2_fac = 1.0f; - - float dp[3]; - sub_v3_v3v3(dp, p2, p1); - - for (int i = 0; i < plane_tot; i++) { - const float *plane = plane_array[i]; - const float div = dot_v3v3(dp, plane); - - if (div != 0.0f) { - float t = -plane_point_side_v3(plane, p1); - if (div > 0.0f) { - /* clip p1 lower bounds */ - if (t >= div) { - return false; - } - else if (t > 0.0f) { - t /= div; - if (t > p1_fac) { - p1_fac = t; - if (p1_fac > p2_fac) { - return false; - } - } - } - } - else if (div < 0.0f) { - /* clip p2 upper bounds */ - if (t >= 0.0f) { - return false; - } - else if (t > div) { - t /= div; - if (t < p2_fac) { - p2_fac = t; - if (p1_fac > p2_fac) { - return false; - } - } - } - } - } - } - - /* incase input/output values match */ - const float p1_copy[3] = {UNPACK3(p1)}; - - madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac); - madd_v3_v3v3fl(r_p2, p1_copy, dp, p2_fac); - - return true; + const float p1[3], const float p2[3], const float plane[4], float r_p1[3], float r_p2[3]) +{ + float dp[3], div; + + sub_v3_v3v3(dp, p2, p1); + div = dot_v3v3(dp, plane); + + if (div == 0.0f) { + /* parallel */ + return true; + } + + float t = -plane_point_side_v3(plane, p1); + + if (div > 0.0f) { + /* behind plane, completely clipped */ + if (t >= div) { + return false; + } + else if (t > 0.0f) { + const float p1_copy[3] = {UNPACK3(p1)}; + copy_v3_v3(r_p2, p2); + madd_v3_v3v3fl(r_p1, p1_copy, dp, t / div); + return true; + } + } + else { + /* behind plane, completely clipped */ + if (t >= 0.0f) { + return false; + } + else if (t > div) { + const float p1_copy[3] = {UNPACK3(p1)}; + copy_v3_v3(r_p1, p1); + madd_v3_v3v3fl(r_p2, p1_copy, dp, t / div); + return true; + } + } + + /* incase input/output values match (above also) */ + const float p1_copy[3] = {UNPACK3(p1)}; + copy_v3_v3(r_p2, p2); + copy_v3_v3(r_p1, p1_copy); + return true; +} + +bool clip_segment_v3_plane_n(const float p1[3], + const float p2[3], + const float plane_array[][4], + const int plane_tot, + float r_p1[3], + float r_p2[3]) +{ + /* intersect from both directions */ + float p1_fac = 0.0f, p2_fac = 1.0f; + + float dp[3]; + sub_v3_v3v3(dp, p2, p1); + + for (int i = 0; i < plane_tot; i++) { + const float *plane = plane_array[i]; + const float div = dot_v3v3(dp, plane); + + if (div != 0.0f) { + float t = -plane_point_side_v3(plane, p1); + if (div > 0.0f) { + /* clip p1 lower bounds */ + if (t >= div) { + return false; + } + else if (t > 0.0f) { + t /= div; + if (t > p1_fac) { + p1_fac = t; + if (p1_fac > p2_fac) { + return false; + } + } + } + } + else if (div < 0.0f) { + /* clip p2 upper bounds */ + if (t >= 0.0f) { + return false; + } + else if (t > div) { + t /= div; + if (t < p2_fac) { + p2_fac = t; + if (p1_fac > p2_fac) { + return false; + } + } + } + } + } + } + + /* incase input/output values match */ + const float p1_copy[3] = {UNPACK3(p1)}; + + madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac); + madd_v3_v3v3fl(r_p2, p1_copy, dp, p2_fac); + + return true; } /****************************** Axis Utils ********************************/ @@ -3193,18 +3270,19 @@ bool clip_segment_v3_plane_n( */ void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]) { - BLI_ASSERT_UNIT_V3(normal); + BLI_ASSERT_UNIT_V3(normal); - copy_v3_v3(r_mat[2], normal); - ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]); + copy_v3_v3(r_mat[2], normal); + ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]); - BLI_ASSERT_UNIT_V3(r_mat[0]); - BLI_ASSERT_UNIT_V3(r_mat[1]); + BLI_ASSERT_UNIT_V3(r_mat[0]); + BLI_ASSERT_UNIT_V3(r_mat[1]); - transpose_m3(r_mat); + transpose_m3(r_mat); - BLI_assert(!is_negative_m3(r_mat)); - BLI_assert((fabsf(dot_m3_v3_row_z(r_mat, normal) - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || is_zero_v3(normal)); + BLI_assert(!is_negative_m3(r_mat)); + BLI_assert((fabsf(dot_m3_v3_row_z(r_mat, normal) - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || + is_zero_v3(normal)); } /** @@ -3212,143 +3290,151 @@ void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]) */ void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3]) { - BLI_ASSERT_UNIT_V3(normal); + BLI_ASSERT_UNIT_V3(normal); - negate_v3_v3(r_mat[2], normal); - ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]); + negate_v3_v3(r_mat[2], normal); + ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]); - BLI_ASSERT_UNIT_V3(r_mat[0]); - BLI_ASSERT_UNIT_V3(r_mat[1]); + BLI_ASSERT_UNIT_V3(r_mat[0]); + BLI_ASSERT_UNIT_V3(r_mat[1]); - transpose_m3(r_mat); + transpose_m3(r_mat); - BLI_assert(!is_negative_m3(r_mat)); - BLI_assert((dot_m3_v3_row_z(r_mat, normal) < BLI_ASSERT_UNIT_EPSILON) || is_zero_v3(normal)); + BLI_assert(!is_negative_m3(r_mat)); + BLI_assert((dot_m3_v3_row_z(r_mat, normal) < BLI_ASSERT_UNIT_EPSILON) || is_zero_v3(normal)); } /****************************** Interpolation ********************************/ -static float tri_signed_area(const float v1[3], const float v2[3], const float v3[3], const int i, const int j) +static float tri_signed_area( + const float v1[3], const float v2[3], const float v3[3], const int i, const int j) { - return 0.5f * ((v1[i] - v2[i]) * (v2[j] - v3[j]) + (v1[j] - v2[j]) * (v3[i] - v2[i])); + return 0.5f * ((v1[i] - v2[i]) * (v2[j] - v3[j]) + (v1[j] - v2[j]) * (v3[i] - v2[i])); } /* return 1 when degenerate */ -static bool barycentric_weights(const float v1[3], const float v2[3], const float v3[3], const float co[3], const float n[3], float w[3]) -{ - float wtot; - int i, j; - - axis_dominant_v3(&i, &j, n); - - w[0] = tri_signed_area(v2, v3, co, i, j); - w[1] = tri_signed_area(v3, v1, co, i, j); - w[2] = tri_signed_area(v1, v2, co, i, j); - - wtot = w[0] + w[1] + w[2]; - - if (fabsf(wtot) > FLT_EPSILON) { - mul_v3_fl(w, 1.0f / wtot); - return false; - } - else { - /* zero area triangle */ - copy_v3_fl(w, 1.0f / 3.0f); - return true; - } -} - -void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3]) -{ - float n[3]; - - normal_tri_v3(n, v1, v2, v3); - barycentric_weights(v1, v2, v3, co, n, w); -} - -void interp_weights_quad_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3]) -{ - float w2[3]; - - w[0] = w[1] = w[2] = w[3] = 0.0f; - - /* first check for exact match */ - if (equals_v3v3(co, v1)) { - w[0] = 1.0f; - } - else if (equals_v3v3(co, v2)) { - w[1] = 1.0f; - } - else if (equals_v3v3(co, v3)) { - w[2] = 1.0f; - } - else if (equals_v3v3(co, v4)) { - w[3] = 1.0f; - } - else { - /* otherwise compute barycentric interpolation weights */ - float n1[3], n2[3], n[3]; - bool degenerate; - - sub_v3_v3v3(n1, v1, v3); - sub_v3_v3v3(n2, v2, v4); - cross_v3_v3v3(n, n1, n2); - - degenerate = barycentric_weights(v1, v2, v4, co, n, w); - SWAP(float, w[2], w[3]); - - if (degenerate || (w[0] < 0.0f)) { - /* if w[1] is negative, co is on the other side of the v1-v3 edge, - * so we interpolate using the other triangle */ - degenerate = barycentric_weights(v2, v3, v4, co, n, w2); - - if (!degenerate) { - w[0] = 0.0f; - w[1] = w2[0]; - w[2] = w2[1]; - w[3] = w2[2]; - } - } - } +static bool barycentric_weights(const float v1[3], + const float v2[3], + const float v3[3], + const float co[3], + const float n[3], + float w[3]) +{ + float wtot; + int i, j; + + axis_dominant_v3(&i, &j, n); + + w[0] = tri_signed_area(v2, v3, co, i, j); + w[1] = tri_signed_area(v3, v1, co, i, j); + w[2] = tri_signed_area(v1, v2, co, i, j); + + wtot = w[0] + w[1] + w[2]; + + if (fabsf(wtot) > FLT_EPSILON) { + mul_v3_fl(w, 1.0f / wtot); + return false; + } + else { + /* zero area triangle */ + copy_v3_fl(w, 1.0f / 3.0f); + return true; + } +} + +void interp_weights_tri_v3( + float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3]) +{ + float n[3]; + + normal_tri_v3(n, v1, v2, v3); + barycentric_weights(v1, v2, v3, co, n, w); +} + +void interp_weights_quad_v3(float w[4], + const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + const float co[3]) +{ + float w2[3]; + + w[0] = w[1] = w[2] = w[3] = 0.0f; + + /* first check for exact match */ + if (equals_v3v3(co, v1)) { + w[0] = 1.0f; + } + else if (equals_v3v3(co, v2)) { + w[1] = 1.0f; + } + else if (equals_v3v3(co, v3)) { + w[2] = 1.0f; + } + else if (equals_v3v3(co, v4)) { + w[3] = 1.0f; + } + else { + /* otherwise compute barycentric interpolation weights */ + float n1[3], n2[3], n[3]; + bool degenerate; + + sub_v3_v3v3(n1, v1, v3); + sub_v3_v3v3(n2, v2, v4); + cross_v3_v3v3(n, n1, n2); + + degenerate = barycentric_weights(v1, v2, v4, co, n, w); + SWAP(float, w[2], w[3]); + + if (degenerate || (w[0] < 0.0f)) { + /* if w[1] is negative, co is on the other side of the v1-v3 edge, + * so we interpolate using the other triangle */ + degenerate = barycentric_weights(v2, v3, v4, co, n, w2); + + if (!degenerate) { + w[0] = 0.0f; + w[1] = w2[0]; + w[2] = w2[1]; + w[3] = w2[2]; + } + } + } } /* return 1 of point is inside triangle, 2 if it's on the edge, 0 if point is outside of triangle */ int barycentric_inside_triangle_v2(const float w[3]) { - if (IN_RANGE(w[0], 0.0f, 1.0f) && - IN_RANGE(w[1], 0.0f, 1.0f) && - IN_RANGE(w[2], 0.0f, 1.0f)) - { - return 1; - } - else if (IN_RANGE_INCL(w[0], 0.0f, 1.0f) && - IN_RANGE_INCL(w[1], 0.0f, 1.0f) && - IN_RANGE_INCL(w[2], 0.0f, 1.0f)) - { - return 2; - } + if (IN_RANGE(w[0], 0.0f, 1.0f) && IN_RANGE(w[1], 0.0f, 1.0f) && IN_RANGE(w[2], 0.0f, 1.0f)) { + return 1; + } + else if (IN_RANGE_INCL(w[0], 0.0f, 1.0f) && IN_RANGE_INCL(w[1], 0.0f, 1.0f) && + IN_RANGE_INCL(w[2], 0.0f, 1.0f)) { + return 2; + } - return 0; + return 0; } /* returns 0 for degenerated triangles */ -bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) +bool barycentric_coords_v2( + const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) { - const float x = co[0], y = co[1]; - const float x1 = v1[0], y1 = v1[1]; - const float x2 = v2[0], y2 = v2[1]; - const float x3 = v3[0], y3 = v3[1]; - const float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3); + const float x = co[0], y = co[1]; + const float x1 = v1[0], y1 = v1[1]; + const float x2 = v2[0], y2 = v2[1]; + const float x3 = v3[0], y3 = v3[1]; + const float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3); - if (fabsf(det) > FLT_EPSILON) { - w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det; - w[1] = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / det; - w[2] = 1.0f - w[0] - w[1]; + if (fabsf(det) > FLT_EPSILON) { + w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det; + w[1] = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / det; + w[2] = 1.0f - w[0] - w[1]; - return true; - } + return true; + } - return false; + return false; } /** @@ -3358,22 +3444,21 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[ * although it has double precision and is used for texture baking, so keep both. */ void barycentric_weights_v2( - const float v1[2], const float v2[2], const float v3[2], - const float co[2], float w[3]) + const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) { - float wtot; + float wtot; - w[0] = cross_tri_v2(v2, v3, co); - w[1] = cross_tri_v2(v3, v1, co); - w[2] = cross_tri_v2(v1, v2, co); - wtot = w[0] + w[1] + w[2]; + w[0] = cross_tri_v2(v2, v3, co); + w[1] = cross_tri_v2(v3, v1, co); + w[2] = cross_tri_v2(v1, v2, co); + wtot = w[0] + w[1] + w[2]; - if (wtot != 0.0f) { - mul_v3_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - copy_v3_fl(w, 1.0f / 3.0f); - } + if (wtot != 0.0f) { + mul_v3_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + copy_v3_fl(w, 1.0f / 3.0f); + } } /** @@ -3381,22 +3466,21 @@ void barycentric_weights_v2( * Useful when negative values cause problems and points are only ever slightly outside of the triangle. */ void barycentric_weights_v2_clamped( - const float v1[2], const float v2[2], const float v3[2], - const float co[2], float w[3]) + const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) { - float wtot; + float wtot; - w[0] = max_ff(cross_tri_v2(v2, v3, co), 0.0f); - w[1] = max_ff(cross_tri_v2(v3, v1, co), 0.0f); - w[2] = max_ff(cross_tri_v2(v1, v2, co), 0.0f); - wtot = w[0] + w[1] + w[2]; + w[0] = max_ff(cross_tri_v2(v2, v3, co), 0.0f); + w[1] = max_ff(cross_tri_v2(v3, v1, co), 0.0f); + w[2] = max_ff(cross_tri_v2(v1, v2, co), 0.0f); + wtot = w[0] + w[1] + w[2]; - if (wtot != 0.0f) { - mul_v3_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - copy_v3_fl(w, 1.0f / 3.0f); - } + if (wtot != 0.0f) { + mul_v3_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + copy_v3_fl(w, 1.0f / 3.0f); + } } /** @@ -3404,22 +3488,21 @@ void barycentric_weights_v2_clamped( * using their 4th component as a weight */ void barycentric_weights_v2_persp( - const float v1[4], const float v2[4], const float v3[4], - const float co[2], float w[3]) + const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3]) { - float wtot; + float wtot; - w[0] = cross_tri_v2(v2, v3, co) / v1[3]; - w[1] = cross_tri_v2(v3, v1, co) / v2[3]; - w[2] = cross_tri_v2(v1, v2, co) / v3[3]; - wtot = w[0] + w[1] + w[2]; + w[0] = cross_tri_v2(v2, v3, co) / v1[3]; + w[1] = cross_tri_v2(v3, v1, co) / v2[3]; + w[2] = cross_tri_v2(v1, v2, co) / v3[3]; + wtot = w[0] + w[1] + w[2]; - if (wtot != 0.0f) { - mul_v3_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - w[0] = w[1] = w[2] = 1.0f / 3.0f; - } + if (wtot != 0.0f) { + mul_v3_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + w[0] = w[1] = w[2] = 1.0f / 3.0f; + } } /** @@ -3427,54 +3510,70 @@ void barycentric_weights_v2_persp( * note: untested for values outside the quad's bounds * this is #interp_weights_poly_v2 expanded for quads only */ -void barycentric_weights_v2_quad( - const float v1[2], const float v2[2], const float v3[2], const float v4[2], - const float co[2], float w[4]) -{ - /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2). - * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results - * without adding absf(). If this becomes an issue for more general usage we could have - * this optional or use a different function - Campbell */ +void barycentric_weights_v2_quad(const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2], + const float co[2], + float w[4]) +{ + /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2). + * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results + * without adding absf(). If this becomes an issue for more general usage we could have + * this optional or use a different function - Campbell */ #define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2) \ - ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ - fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : 0.0f) - - const float dirs[4][2] = { - {v1[0] - co[0], v1[1] - co[1]}, - {v2[0] - co[0], v2[1] - co[1]}, - {v3[0] - co[0], v3[1] - co[1]}, - {v4[0] - co[0], v4[1] - co[1]}, - }; - - const float lens[4] = { - len_v2(dirs[0]), - len_v2(dirs[1]), - len_v2(dirs[2]), - len_v2(dirs[3]), - }; - - /* avoid divide by zero */ - if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; } - else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; } - else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; } - else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f; } - else { - float wtot, area; - - /* variable 'area' is just for storage, - * the order its initialized doesn't matter */ + ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ + fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : \ + 0.0f) + + const float dirs[4][2] = { + {v1[0] - co[0], v1[1] - co[1]}, + {v2[0] - co[0], v2[1] - co[1]}, + {v3[0] - co[0], v3[1] - co[1]}, + {v4[0] - co[0], v4[1] - co[1]}, + }; + + const float lens[4] = { + len_v2(dirs[0]), + len_v2(dirs[1]), + len_v2(dirs[2]), + len_v2(dirs[3]), + }; + + /* avoid divide by zero */ + if (UNLIKELY(lens[0] < FLT_EPSILON)) { + w[0] = 1.0f; + w[1] = w[2] = w[3] = 0.0f; + } + else if (UNLIKELY(lens[1] < FLT_EPSILON)) { + w[1] = 1.0f; + w[0] = w[2] = w[3] = 0.0f; + } + else if (UNLIKELY(lens[2] < FLT_EPSILON)) { + w[2] = 1.0f; + w[0] = w[1] = w[3] = 0.0f; + } + else if (UNLIKELY(lens[3] < FLT_EPSILON)) { + w[3] = 1.0f; + w[0] = w[1] = w[2] = 0.0f; + } + else { + float wtot, area; + + /* variable 'area' is just for storage, + * the order its initialized doesn't matter */ #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunsequenced" #endif - /* inline mean_value_half_tan four times here */ - const float t[4] = { - MEAN_VALUE_HALF_TAN_V2(area, 0, 1), - MEAN_VALUE_HALF_TAN_V2(area, 1, 2), - MEAN_VALUE_HALF_TAN_V2(area, 2, 3), - MEAN_VALUE_HALF_TAN_V2(area, 3, 0), - }; + /* inline mean_value_half_tan four times here */ + const float t[4] = { + MEAN_VALUE_HALF_TAN_V2(area, 0, 1), + MEAN_VALUE_HALF_TAN_V2(area, 1, 2), + MEAN_VALUE_HALF_TAN_V2(area, 2, 3), + MEAN_VALUE_HALF_TAN_V2(area, 3, 0), + }; #ifdef __clang__ # pragma clang diagnostic pop @@ -3482,365 +3581,376 @@ void barycentric_weights_v2_quad( #undef MEAN_VALUE_HALF_TAN_V2 - w[0] = (t[3] + t[0]) / lens[0]; - w[1] = (t[0] + t[1]) / lens[1]; - w[2] = (t[1] + t[2]) / lens[2]; - w[3] = (t[2] + t[3]) / lens[3]; + w[0] = (t[3] + t[0]) / lens[0]; + w[1] = (t[0] + t[1]) / lens[1]; + w[2] = (t[1] + t[2]) / lens[2]; + w[3] = (t[2] + t[3]) / lens[3]; - wtot = w[0] + w[1] + w[2] + w[3]; + wtot = w[0] + w[1] + w[2] + w[3]; - if (wtot != 0.0f) { - mul_v4_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - copy_v4_fl(w, 1.0f / 4.0f); - } - } + if (wtot != 0.0f) { + mul_v4_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + copy_v4_fl(w, 1.0f / 4.0f); + } + } } /* given 2 triangles in 3D space, and a point in relation to the first triangle. * calculate the location of a point in relation to the second triangle. * Useful for finding relative positions with geometry */ -void transform_point_by_tri_v3( - float pt_tar[3], float const pt_src[3], - const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3], - const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3]) -{ - /* this works by moving the source triangle so its normal is pointing on the Z - * axis where its barycentric weights can be calculated in 2D and its Z offset can - * be re-applied. The weights are applied directly to the targets 3D points and the - * z-depth is used to scale the targets normal as an offset. - * This saves transforming the target into its Z-Up orientation and back - * (which could also work) */ - float no_tar[3], no_src[3]; - float mat_src[3][3]; - float pt_src_xy[3]; - float tri_xy_src[3][3]; - float w_src[3]; - float area_tar, area_src; - float z_ofs_src; - - normal_tri_v3(no_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3); - normal_tri_v3(no_src, tri_src_p1, tri_src_p2, tri_src_p3); - - axis_dominant_v3_to_m3(mat_src, no_src); - - /* make the source tri xy space */ - mul_v3_m3v3(pt_src_xy, mat_src, pt_src); - mul_v3_m3v3(tri_xy_src[0], mat_src, tri_src_p1); - mul_v3_m3v3(tri_xy_src[1], mat_src, tri_src_p2); - mul_v3_m3v3(tri_xy_src[2], mat_src, tri_src_p3); - - - barycentric_weights_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2], pt_src_xy, w_src); - interp_v3_v3v3v3(pt_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3, w_src); - - area_tar = sqrtf(area_tri_v3(tri_tar_p1, tri_tar_p2, tri_tar_p3)); - area_src = sqrtf(area_tri_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2])); - - z_ofs_src = pt_src_xy[2] - tri_xy_src[0][2]; - madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar); +void transform_point_by_tri_v3(float pt_tar[3], + float const pt_src[3], + const float tri_tar_p1[3], + const float tri_tar_p2[3], + const float tri_tar_p3[3], + const float tri_src_p1[3], + const float tri_src_p2[3], + const float tri_src_p3[3]) +{ + /* this works by moving the source triangle so its normal is pointing on the Z + * axis where its barycentric weights can be calculated in 2D and its Z offset can + * be re-applied. The weights are applied directly to the targets 3D points and the + * z-depth is used to scale the targets normal as an offset. + * This saves transforming the target into its Z-Up orientation and back + * (which could also work) */ + float no_tar[3], no_src[3]; + float mat_src[3][3]; + float pt_src_xy[3]; + float tri_xy_src[3][3]; + float w_src[3]; + float area_tar, area_src; + float z_ofs_src; + + normal_tri_v3(no_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3); + normal_tri_v3(no_src, tri_src_p1, tri_src_p2, tri_src_p3); + + axis_dominant_v3_to_m3(mat_src, no_src); + + /* make the source tri xy space */ + mul_v3_m3v3(pt_src_xy, mat_src, pt_src); + mul_v3_m3v3(tri_xy_src[0], mat_src, tri_src_p1); + mul_v3_m3v3(tri_xy_src[1], mat_src, tri_src_p2); + mul_v3_m3v3(tri_xy_src[2], mat_src, tri_src_p3); + + barycentric_weights_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2], pt_src_xy, w_src); + interp_v3_v3v3v3(pt_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3, w_src); + + area_tar = sqrtf(area_tri_v3(tri_tar_p1, tri_tar_p2, tri_tar_p3)); + area_src = sqrtf(area_tri_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2])); + + z_ofs_src = pt_src_xy[2] - tri_xy_src[0][2]; + madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar); } /** * Simply re-interpolates, * assumes p_src is between \a l_src_p1-l_src_p2 */ -void transform_point_by_seg_v3( - float p_dst[3], const float p_src[3], - const float l_dst_p1[3], const float l_dst_p2[3], - const float l_src_p1[3], const float l_src_p2[3]) +void transform_point_by_seg_v3(float p_dst[3], + const float p_src[3], + const float l_dst_p1[3], + const float l_dst_p2[3], + const float l_src_p1[3], + const float l_src_p2[3]) { - float t = line_point_factor_v3(p_src, l_src_p1, l_src_p2); - interp_v3_v3v3(p_dst, l_dst_p1, l_dst_p2, t); + float t = line_point_factor_v3(p_src, l_src_p1, l_src_p2); + interp_v3_v3v3(p_dst, l_dst_p1, l_dst_p2, t); } /* given an array with some invalid values this function interpolates valid values * replacing the invalid ones */ int interp_sparse_array(float *array, const int list_size, const float skipval) { - int found_invalid = 0; - int found_valid = 0; - int i; - - for (i = 0; i < list_size; i++) { - if (array[i] == skipval) { - found_invalid = 1; - } - else { - found_valid = 1; - } - } - - if (found_valid == 0) { - return -1; - } - else if (found_invalid == 0) { - return 0; - } - else { - /* found invalid depths, interpolate */ - float valid_last = skipval; - int valid_ofs = 0; - - float *array_up = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); - float *array_down = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); - - int *ofs_tot_up = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tup"); - int *ofs_tot_down = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tdown"); - - for (i = 0; i < list_size; i++) { - if (array[i] == skipval) { - array_up[i] = valid_last; - ofs_tot_up[i] = ++valid_ofs; - } - else { - valid_last = array[i]; - valid_ofs = 0; - } - } - - valid_last = skipval; - valid_ofs = 0; - - for (i = list_size - 1; i >= 0; i--) { - if (array[i] == skipval) { - array_down[i] = valid_last; - ofs_tot_down[i] = ++valid_ofs; - } - else { - valid_last = array[i]; - valid_ofs = 0; - } - } - - /* now blend */ - for (i = 0; i < list_size; i++) { - if (array[i] == skipval) { - if (array_up[i] != skipval && array_down[i] != skipval) { - array[i] = ((array_up[i] * (float)ofs_tot_down[i]) + - (array_down[i] * (float)ofs_tot_up[i])) / (float)(ofs_tot_down[i] + ofs_tot_up[i]); - } - else if (array_up[i] != skipval) { - array[i] = array_up[i]; - } - else if (array_down[i] != skipval) { - array[i] = array_down[i]; - } - } - } - - MEM_freeN(array_up); - MEM_freeN(array_down); - - MEM_freeN(ofs_tot_up); - MEM_freeN(ofs_tot_down); - } - - return 1; + int found_invalid = 0; + int found_valid = 0; + int i; + + for (i = 0; i < list_size; i++) { + if (array[i] == skipval) { + found_invalid = 1; + } + else { + found_valid = 1; + } + } + + if (found_valid == 0) { + return -1; + } + else if (found_invalid == 0) { + return 0; + } + else { + /* found invalid depths, interpolate */ + float valid_last = skipval; + int valid_ofs = 0; + + float *array_up = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); + float *array_down = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); + + int *ofs_tot_up = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tup"); + int *ofs_tot_down = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tdown"); + + for (i = 0; i < list_size; i++) { + if (array[i] == skipval) { + array_up[i] = valid_last; + ofs_tot_up[i] = ++valid_ofs; + } + else { + valid_last = array[i]; + valid_ofs = 0; + } + } + + valid_last = skipval; + valid_ofs = 0; + + for (i = list_size - 1; i >= 0; i--) { + if (array[i] == skipval) { + array_down[i] = valid_last; + ofs_tot_down[i] = ++valid_ofs; + } + else { + valid_last = array[i]; + valid_ofs = 0; + } + } + + /* now blend */ + for (i = 0; i < list_size; i++) { + if (array[i] == skipval) { + if (array_up[i] != skipval && array_down[i] != skipval) { + array[i] = ((array_up[i] * (float)ofs_tot_down[i]) + + (array_down[i] * (float)ofs_tot_up[i])) / + (float)(ofs_tot_down[i] + ofs_tot_up[i]); + } + else if (array_up[i] != skipval) { + array[i] = array_up[i]; + } + else if (array_down[i] != skipval) { + array[i] = array_down[i]; + } + } + } + + MEM_freeN(array_up); + MEM_freeN(array_down); + + MEM_freeN(ofs_tot_up); + MEM_freeN(ofs_tot_down); + } + + return 1; } /** \name interp_weights_poly_v2, v3 * \{ */ -#define IS_POINT_IX (1 << 0) -#define IS_SEGMENT_IX (1 << 1) +#define IS_POINT_IX (1 << 0) +#define IS_SEGMENT_IX (1 << 1) -#define DIR_V3_SET(d_len, va, vb) { \ - sub_v3_v3v3((d_len)->dir, va, vb); \ - (d_len)->len = len_v3((d_len)->dir); \ -} (void)0 +#define DIR_V3_SET(d_len, va, vb) \ + { \ + sub_v3_v3v3((d_len)->dir, va, vb); \ + (d_len)->len = len_v3((d_len)->dir); \ + } \ + (void)0 -#define DIR_V2_SET(d_len, va, vb) { \ - sub_v2_v2v2((d_len)->dir, va, vb); \ - (d_len)->len = len_v2((d_len)->dir); \ -} (void)0 +#define DIR_V2_SET(d_len, va, vb) \ + { \ + sub_v2_v2v2((d_len)->dir, va, vb); \ + (d_len)->len = len_v2((d_len)->dir); \ + } \ + (void)0 struct Float3_Len { - float dir[3], len; + float dir[3], len; }; struct Float2_Len { - float dir[2], len; + float dir[2], len; }; /* Mean value weights - smooth interpolation weights for polygons with * more than 3 vertices */ -static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, const struct Float3_Len *d_next) -{ - float cross[3], area; - cross_v3_v3v3(cross, d_curr->dir, d_next->dir); - area = len_v3(cross); - if (LIKELY(fabsf(area) > FLT_EPSILON)) { - const float dot = dot_v3v3(d_curr->dir, d_next->dir); - const float len = d_curr->len * d_next->len; - return (len - dot) / area; - } - else { - return 0.0f; - } -} - -static float mean_value_half_tan_v2(const struct Float2_Len *d_curr, const struct Float2_Len *d_next) -{ - float area; - /* different from the 3d version but still correct */ - area = cross_v2v2(d_curr->dir, d_next->dir); - if (LIKELY(fabsf(area) > FLT_EPSILON)) { - const float dot = dot_v2v2(d_curr->dir, d_next->dir); - const float len = d_curr->len * d_next->len; - return (len - dot) / area; - } - else { - return 0.0f; - } +static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, + const struct Float3_Len *d_next) +{ + float cross[3], area; + cross_v3_v3v3(cross, d_curr->dir, d_next->dir); + area = len_v3(cross); + if (LIKELY(fabsf(area) > FLT_EPSILON)) { + const float dot = dot_v3v3(d_curr->dir, d_next->dir); + const float len = d_curr->len * d_next->len; + return (len - dot) / area; + } + else { + return 0.0f; + } +} + +static float mean_value_half_tan_v2(const struct Float2_Len *d_curr, + const struct Float2_Len *d_next) +{ + float area; + /* different from the 3d version but still correct */ + area = cross_v2v2(d_curr->dir, d_next->dir); + if (LIKELY(fabsf(area) > FLT_EPSILON)) { + const float dot = dot_v2v2(d_curr->dir, d_next->dir); + const float len = d_curr->len * d_next->len; + return (len - dot) / area; + } + else { + return 0.0f; + } } void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3]) { - const float eps = 1e-5f; /* take care, low values cause [#36105] */ - const float eps_sq = eps * eps; - const float *v_curr, *v_next; - float ht_prev, ht; /* half tangents */ - float totweight = 0.0f; - int i_curr, i_next; - char ix_flag = 0; - struct Float3_Len d_curr, d_next; - - /* loop over 'i_next' */ - i_curr = n - 1; - i_next = 0; - - v_curr = v[i_curr]; - v_next = v[i_next]; - - DIR_V3_SET(&d_curr, v_curr - 3 /* v[n - 2] */, co); - DIR_V3_SET(&d_next, v_curr /* v[n - 1] */, co); - ht_prev = mean_value_half_tan_v3(&d_curr, &d_next); - - while (i_next < n) { - /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close - * to borders of face. - * In that case, do simple linear interpolation between the two edge vertices */ - - /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */ - if (UNLIKELY(d_next.len < eps)) { - ix_flag = IS_POINT_IX; - break; - } - else if (UNLIKELY(dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq)) { - ix_flag = IS_SEGMENT_IX; - break; - } - - d_curr = d_next; - DIR_V3_SET(&d_next, v_next, co); - ht = mean_value_half_tan_v3(&d_curr, &d_next); - w[i_curr] = (ht_prev + ht) / d_curr.len; - totweight += w[i_curr]; - - /* step */ - i_curr = i_next++; - v_curr = v_next; - v_next = v[i_next]; - - ht_prev = ht; - } - - if (ix_flag) { - memset(w, 0, sizeof(*w) * (size_t)n); - - if (ix_flag & IS_POINT_IX) { - w[i_curr] = 1.0f; - } - else { - float fac = line_point_factor_v3(co, v_curr, v_next); - CLAMP(fac, 0.0f, 1.0f); - w[i_curr] = 1.0f - fac; - w[i_next] = fac; - } - } - else { - if (totweight != 0.0f) { - for (i_curr = 0; i_curr < n; i_curr++) { - w[i_curr] /= totweight; - } - } - } + const float eps = 1e-5f; /* take care, low values cause [#36105] */ + const float eps_sq = eps * eps; + const float *v_curr, *v_next; + float ht_prev, ht; /* half tangents */ + float totweight = 0.0f; + int i_curr, i_next; + char ix_flag = 0; + struct Float3_Len d_curr, d_next; + + /* loop over 'i_next' */ + i_curr = n - 1; + i_next = 0; + + v_curr = v[i_curr]; + v_next = v[i_next]; + + DIR_V3_SET(&d_curr, v_curr - 3 /* v[n - 2] */, co); + DIR_V3_SET(&d_next, v_curr /* v[n - 1] */, co); + ht_prev = mean_value_half_tan_v3(&d_curr, &d_next); + + while (i_next < n) { + /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close + * to borders of face. + * In that case, do simple linear interpolation between the two edge vertices */ + + /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */ + if (UNLIKELY(d_next.len < eps)) { + ix_flag = IS_POINT_IX; + break; + } + else if (UNLIKELY(dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq)) { + ix_flag = IS_SEGMENT_IX; + break; + } + + d_curr = d_next; + DIR_V3_SET(&d_next, v_next, co); + ht = mean_value_half_tan_v3(&d_curr, &d_next); + w[i_curr] = (ht_prev + ht) / d_curr.len; + totweight += w[i_curr]; + + /* step */ + i_curr = i_next++; + v_curr = v_next; + v_next = v[i_next]; + + ht_prev = ht; + } + + if (ix_flag) { + memset(w, 0, sizeof(*w) * (size_t)n); + + if (ix_flag & IS_POINT_IX) { + w[i_curr] = 1.0f; + } + else { + float fac = line_point_factor_v3(co, v_curr, v_next); + CLAMP(fac, 0.0f, 1.0f); + w[i_curr] = 1.0f - fac; + w[i_next] = fac; + } + } + else { + if (totweight != 0.0f) { + for (i_curr = 0; i_curr < n; i_curr++) { + w[i_curr] /= totweight; + } + } + } } - void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2]) { - const float eps = 1e-5f; /* take care, low values cause [#36105] */ - const float eps_sq = eps * eps; - const float *v_curr, *v_next; - float ht_prev, ht; /* half tangents */ - float totweight = 0.0f; - int i_curr, i_next; - char ix_flag = 0; - struct Float2_Len d_curr, d_next; - - /* loop over 'i_next' */ - i_curr = n - 1; - i_next = 0; - - v_curr = v[i_curr]; - v_next = v[i_next]; - - DIR_V2_SET(&d_curr, v_curr - 2 /* v[n - 2] */, co); - DIR_V2_SET(&d_next, v_curr /* v[n - 1] */, co); - ht_prev = mean_value_half_tan_v2(&d_curr, &d_next); - - while (i_next < n) { - /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close - * to borders of face. In that case, - * do simple linear interpolation between the two edge vertices */ - - /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */ - if (UNLIKELY(d_next.len < eps)) { - ix_flag = IS_POINT_IX; - break; - } - else if (UNLIKELY(dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq)) { - ix_flag = IS_SEGMENT_IX; - break; - } - - d_curr = d_next; - DIR_V2_SET(&d_next, v_next, co); - ht = mean_value_half_tan_v2(&d_curr, &d_next); - w[i_curr] = (ht_prev + ht) / d_curr.len; - totweight += w[i_curr]; - - /* step */ - i_curr = i_next++; - v_curr = v_next; - v_next = v[i_next]; - - ht_prev = ht; - } - - if (ix_flag) { - memset(w, 0, sizeof(*w) * (size_t)n); - - if (ix_flag & IS_POINT_IX) { - w[i_curr] = 1.0f; - } - else { - float fac = line_point_factor_v2(co, v_curr, v_next); - CLAMP(fac, 0.0f, 1.0f); - w[i_curr] = 1.0f - fac; - w[i_next] = fac; - } - } - else { - if (totweight != 0.0f) { - for (i_curr = 0; i_curr < n; i_curr++) { - w[i_curr] /= totweight; - } - } - } + const float eps = 1e-5f; /* take care, low values cause [#36105] */ + const float eps_sq = eps * eps; + const float *v_curr, *v_next; + float ht_prev, ht; /* half tangents */ + float totweight = 0.0f; + int i_curr, i_next; + char ix_flag = 0; + struct Float2_Len d_curr, d_next; + + /* loop over 'i_next' */ + i_curr = n - 1; + i_next = 0; + + v_curr = v[i_curr]; + v_next = v[i_next]; + + DIR_V2_SET(&d_curr, v_curr - 2 /* v[n - 2] */, co); + DIR_V2_SET(&d_next, v_curr /* v[n - 1] */, co); + ht_prev = mean_value_half_tan_v2(&d_curr, &d_next); + + while (i_next < n) { + /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close + * to borders of face. In that case, + * do simple linear interpolation between the two edge vertices */ + + /* 'd_next.len' is infact 'd_curr.len', just avoid copy to begin with */ + if (UNLIKELY(d_next.len < eps)) { + ix_flag = IS_POINT_IX; + break; + } + else if (UNLIKELY(dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq)) { + ix_flag = IS_SEGMENT_IX; + break; + } + + d_curr = d_next; + DIR_V2_SET(&d_next, v_next, co); + ht = mean_value_half_tan_v2(&d_curr, &d_next); + w[i_curr] = (ht_prev + ht) / d_curr.len; + totweight += w[i_curr]; + + /* step */ + i_curr = i_next++; + v_curr = v_next; + v_next = v[i_next]; + + ht_prev = ht; + } + + if (ix_flag) { + memset(w, 0, sizeof(*w) * (size_t)n); + + if (ix_flag & IS_POINT_IX) { + w[i_curr] = 1.0f; + } + else { + float fac = line_point_factor_v2(co, v_curr, v_next); + CLAMP(fac, 0.0f, 1.0f); + w[i_curr] = 1.0f - fac; + w[i_next] = fac; + } + } + else { + if (totweight != 0.0f) { + for (i_curr = 0; i_curr < n; i_curr++) { + w[i_curr] /= totweight; + } + } + } } #undef IS_POINT_IX @@ -3851,30 +3961,35 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[ /** \} */ - /* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0<t<1 --> (x, v)(t) */ -void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t) +void interp_cubic_v3(float x[3], + float v[3], + const float x1[3], + const float v1[3], + const float x2[3], + const float v2[3], + const float t) { - float a[3], b[3]; - const float t2 = t * t; - const float t3 = t2 * t; + float a[3], b[3]; + const float t2 = t * t; + const float t3 = t2 * t; - /* cubic interpolation */ - a[0] = v1[0] + v2[0] + 2 * (x1[0] - x2[0]); - a[1] = v1[1] + v2[1] + 2 * (x1[1] - x2[1]); - a[2] = v1[2] + v2[2] + 2 * (x1[2] - x2[2]); + /* cubic interpolation */ + a[0] = v1[0] + v2[0] + 2 * (x1[0] - x2[0]); + a[1] = v1[1] + v2[1] + 2 * (x1[1] - x2[1]); + a[2] = v1[2] + v2[2] + 2 * (x1[2] - x2[2]); - b[0] = -2 * v1[0] - v2[0] - 3 * (x1[0] - x2[0]); - b[1] = -2 * v1[1] - v2[1] - 3 * (x1[1] - x2[1]); - b[2] = -2 * v1[2] - v2[2] - 3 * (x1[2] - x2[2]); + b[0] = -2 * v1[0] - v2[0] - 3 * (x1[0] - x2[0]); + b[1] = -2 * v1[1] - v2[1] - 3 * (x1[1] - x2[1]); + b[2] = -2 * v1[2] - v2[2] - 3 * (x1[2] - x2[2]); - x[0] = a[0] * t3 + b[0] * t2 + v1[0] * t + x1[0]; - x[1] = a[1] * t3 + b[1] * t2 + v1[1] * t + x1[1]; - x[2] = a[2] * t3 + b[2] * t2 + v1[2] * t + x1[2]; + x[0] = a[0] * t3 + b[0] * t2 + v1[0] * t + x1[0]; + x[1] = a[1] * t3 + b[1] * t2 + v1[1] * t + x1[1]; + x[2] = a[2] * t3 + b[2] * t2 + v1[2] * t + x1[2]; - v[0] = 3 * a[0] * t2 + 2 * b[0] * t + v1[0]; - v[1] = 3 * a[1] * t2 + 2 * b[1] * t + v1[1]; - v[2] = 3 * a[2] * t2 + 2 * b[2] * t + v1[2]; + v[0] = 3 * a[0] * t2 + 2 * b[0] * t + v1[0]; + v[1] = 3 * a[1] * t2 + 2 * b[1] * t + v1[1]; + v[2] = 3 * a[2] * t2 + 2 * b[2] * t + v1[2]; } /* unfortunately internal calculations have to be done at double precision @@ -3889,26 +4004,26 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3 * * \note same basic result as #barycentric_weights_v2, see it's comment for details. */ -void resolve_tri_uv_v2(float r_uv[2], const float st[2], - const float st0[2], const float st1[2], const float st2[2]) +void resolve_tri_uv_v2( + float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]) { - /* find UV such that - * t = u * t0 + v * t1 + (1 - u - v) * t2 - * u * (t0 - t2) + v * (t1 - t2) = t - t2 */ - const double a = st0[0] - st2[0], b = st1[0] - st2[0]; - const double c = st0[1] - st2[1], d = st1[1] - st2[1]; - const double det = a * d - c * b; + /* find UV such that + * t = u * t0 + v * t1 + (1 - u - v) * t2 + * u * (t0 - t2) + v * (t1 - t2) = t - t2 */ + const double a = st0[0] - st2[0], b = st1[0] - st2[0]; + const double c = st0[1] - st2[1], d = st1[1] - st2[1]; + const double det = a * d - c * b; - /* det should never be zero since the determinant is the signed ST area of the triangle. */ - if (IS_ZERO(det) == 0) { - const double x[2] = {st[0] - st2[0], st[1] - st2[1]}; + /* det should never be zero since the determinant is the signed ST area of the triangle. */ + if (IS_ZERO(det) == 0) { + const double x[2] = {st[0] - st2[0], st[1] - st2[1]}; - r_uv[0] = (float)((d * x[0] - b * x[1]) / det); - r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det); - } - else { - zero_v2(r_uv); - } + r_uv[0] = (float)((d * x[0] - b * x[1]) / det); + r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det); + } + else { + zero_v2(r_uv); + } } /** @@ -3916,189 +4031,215 @@ void resolve_tri_uv_v2(float r_uv[2], const float st[2], * * Compute coordinates (u, v) for point \a st with respect to triangle (\a st0, \a st1, \a st2) */ -void resolve_tri_uv_v3(float r_uv[2], const float st[3], const float st0[3], const float st1[3], const float st2[3]) +void resolve_tri_uv_v3( + float r_uv[2], const float st[3], const float st0[3], const float st1[3], const float st2[3]) { - float v0[3], v1[3], v2[3]; - double d00, d01, d11, d20, d21, det; + float v0[3], v1[3], v2[3]; + double d00, d01, d11, d20, d21, det; - sub_v3_v3v3(v0, st1, st0); - sub_v3_v3v3(v1, st2, st0); - sub_v3_v3v3(v2, st, st0); + sub_v3_v3v3(v0, st1, st0); + sub_v3_v3v3(v1, st2, st0); + sub_v3_v3v3(v2, st, st0); - d00 = dot_v3v3(v0, v0); - d01 = dot_v3v3(v0, v1); - d11 = dot_v3v3(v1, v1); - d20 = dot_v3v3(v2, v0); - d21 = dot_v3v3(v2, v1); + d00 = dot_v3v3(v0, v0); + d01 = dot_v3v3(v0, v1); + d11 = dot_v3v3(v1, v1); + d20 = dot_v3v3(v2, v0); + d21 = dot_v3v3(v2, v1); - det = d00 * d11 - d01 * d01; + det = d00 * d11 - d01 * d01; - /* det should never be zero since the determinant is the signed ST area of the triangle. */ - if (IS_ZERO(det) == 0) { - float w; + /* det should never be zero since the determinant is the signed ST area of the triangle. */ + if (IS_ZERO(det) == 0) { + float w; - w = (float)((d00 * d21 - d01 * d20) / det); - r_uv[1] = (float)((d11 * d20 - d01 * d21) / det); - r_uv[0] = 1.0f - r_uv[1] - w; - } - else { - zero_v2(r_uv); - } + w = (float)((d00 * d21 - d01 * d20) / det); + r_uv[1] = (float)((d11 * d20 - d01 * d21) / det); + r_uv[0] = 1.0f - r_uv[1] - w; + } + else { + zero_v2(r_uv); + } } /* bilinear reverse */ -void resolve_quad_uv_v2(float r_uv[2], const float st[2], - const float st0[2], const float st1[2], const float st2[2], const float st3[2]) +void resolve_quad_uv_v2(float r_uv[2], + const float st[2], + const float st0[2], + const float st1[2], + const float st2[2], + const float st3[2]) { - resolve_quad_uv_v2_deriv(r_uv, NULL, st, st0, st1, st2, st3); + resolve_quad_uv_v2_deriv(r_uv, NULL, st, st0, st1, st2, st3); } /* bilinear reverse with derivatives */ -void resolve_quad_uv_v2_deriv(float r_uv[2], float r_deriv[2][2], - const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]) -{ - const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + (st1[0] * st2[1] - st1[1] * st2[0]) + - (st2[0] * st3[1] - st2[1] * st3[0]) + (st3[0] * st0[1] - st3[1] * st0[0]); - - /* X is 2D cross product (determinant) - * A = (p0 - p) X (p0 - p3)*/ - const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); - - /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ - const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + - ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); - - /* C = (p1-p) X (p1-p2) */ - const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); - double denom = a - 2 * b + fC; - - /* clear outputs */ - zero_v2(r_uv); - - if (IS_ZERO(denom) != 0) { - const double fDen = a - fC; - if (IS_ZERO(fDen) == 0) { - r_uv[0] = (float)(a / fDen); - } - } - else { - const double desc_sq = b * b - a * fC; - const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); - const double s = signed_area > 0 ? (-1.0) : 1.0; - - r_uv[0] = (float)(((a - b) + s * desc) / denom); - } - - /* find UV such that - * fST = (1-u)(1-v) * ST0 + u * (1-v) * ST1 + u * v * ST2 + (1-u) * v * ST3 */ - { - const double denom_s = (1 - r_uv[0]) * (st0[0] - st3[0]) + r_uv[0] * (st1[0] - st2[0]); - const double denom_t = (1 - r_uv[0]) * (st0[1] - st3[1]) + r_uv[0] * (st1[1] - st2[1]); - int i = 0; - denom = denom_s; - - if (fabs(denom_s) < fabs(denom_t)) { - i = 1; - denom = denom_t; - } - - if (IS_ZERO(denom) == 0) { - r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) + r_uv[0] * (st1[i] - st[i])) / denom); - } - } - - if (r_deriv) { - float tmp1[2], tmp2[2], s[2], t[2]; - - /* clear outputs */ - zero_v2(r_deriv[0]); - zero_v2(r_deriv[1]); - - sub_v2_v2v2(tmp1, st1, st0); - sub_v2_v2v2(tmp2, st2, st3); - interp_v2_v2v2(s, tmp1, tmp2, r_uv[1]); - sub_v2_v2v2(tmp1, st3, st0); - sub_v2_v2v2(tmp2, st2, st1); - interp_v2_v2v2(t, tmp1, tmp2, r_uv[0]); - - denom = t[0] * s[1] - t[1] * s[0]; - - if (!IS_ZERO(denom)) { - double inv_denom = 1.0 / denom; - r_deriv[0][0] = (float)((double)-t[1] * inv_denom); - r_deriv[0][1] = (float)((double) t[0] * inv_denom); - r_deriv[1][0] = (float)((double) s[1] * inv_denom); - r_deriv[1][1] = (float)((double)-s[0] * inv_denom); - } - } +void resolve_quad_uv_v2_deriv(float r_uv[2], + float r_deriv[2][2], + const float st[2], + const float st0[2], + const float st1[2], + const float st2[2], + const float st3[2]) +{ + const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + + (st1[0] * st2[1] - st1[1] * st2[0]) + + (st2[0] * st3[1] - st2[1] * st3[0]) + + (st3[0] * st0[1] - st3[1] * st0[0]); + + /* X is 2D cross product (determinant) + * A = (p0 - p) X (p0 - p3)*/ + const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); + + /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ + const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - + (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - + (st1[1] - st[1]) * (st0[0] - st3[0]))); + + /* C = (p1-p) X (p1-p2) */ + const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); + double denom = a - 2 * b + fC; + + /* clear outputs */ + zero_v2(r_uv); + + if (IS_ZERO(denom) != 0) { + const double fDen = a - fC; + if (IS_ZERO(fDen) == 0) { + r_uv[0] = (float)(a / fDen); + } + } + else { + const double desc_sq = b * b - a * fC; + const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); + const double s = signed_area > 0 ? (-1.0) : 1.0; + + r_uv[0] = (float)(((a - b) + s * desc) / denom); + } + + /* find UV such that + * fST = (1-u)(1-v) * ST0 + u * (1-v) * ST1 + u * v * ST2 + (1-u) * v * ST3 */ + { + const double denom_s = (1 - r_uv[0]) * (st0[0] - st3[0]) + r_uv[0] * (st1[0] - st2[0]); + const double denom_t = (1 - r_uv[0]) * (st0[1] - st3[1]) + r_uv[0] * (st1[1] - st2[1]); + int i = 0; + denom = denom_s; + + if (fabs(denom_s) < fabs(denom_t)) { + i = 1; + denom = denom_t; + } + + if (IS_ZERO(denom) == 0) { + r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) + + r_uv[0] * (st1[i] - st[i])) / + denom); + } + } + + if (r_deriv) { + float tmp1[2], tmp2[2], s[2], t[2]; + + /* clear outputs */ + zero_v2(r_deriv[0]); + zero_v2(r_deriv[1]); + + sub_v2_v2v2(tmp1, st1, st0); + sub_v2_v2v2(tmp2, st2, st3); + interp_v2_v2v2(s, tmp1, tmp2, r_uv[1]); + sub_v2_v2v2(tmp1, st3, st0); + sub_v2_v2v2(tmp2, st2, st1); + interp_v2_v2v2(t, tmp1, tmp2, r_uv[0]); + + denom = t[0] * s[1] - t[1] * s[0]; + + if (!IS_ZERO(denom)) { + double inv_denom = 1.0 / denom; + r_deriv[0][0] = (float)((double)-t[1] * inv_denom); + r_deriv[0][1] = (float)((double)t[0] * inv_denom); + r_deriv[1][0] = (float)((double)s[1] * inv_denom); + r_deriv[1][1] = (float)((double)-s[0] * inv_denom); + } + } } /* a version of resolve_quad_uv_v2 that only calculates the 'u' */ -float resolve_quad_u_v2( - const float st[2], - const float st0[2], const float st1[2], const float st2[2], const float st3[2]) -{ - const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + (st1[0] * st2[1] - st1[1] * st2[0]) + - (st2[0] * st3[1] - st2[1] * st3[0]) + (st3[0] * st0[1] - st3[1] * st0[0]); - - /* X is 2D cross product (determinant) - * A = (p0 - p) X (p0 - p3)*/ - const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); - - /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ - const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + - ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); - - /* C = (p1-p) X (p1-p2) */ - const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); - double denom = a - 2 * b + fC; - - if (IS_ZERO(denom) != 0) { - const double fDen = a - fC; - if (IS_ZERO(fDen) == 0) { - return (float)(a / fDen); - } - else { - return 0.0f; - } - } - else { - const double desc_sq = b * b - a * fC; - const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); - const double s = signed_area > 0 ? (-1.0) : 1.0; - - return (float)(((a - b) + s * desc) / denom); - } +float resolve_quad_u_v2(const float st[2], + const float st0[2], + const float st1[2], + const float st2[2], + const float st3[2]) +{ + const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + + (st1[0] * st2[1] - st1[1] * st2[0]) + + (st2[0] * st3[1] - st2[1] * st3[0]) + + (st3[0] * st0[1] - st3[1] * st0[0]); + + /* X is 2D cross product (determinant) + * A = (p0 - p) X (p0 - p3)*/ + const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); + + /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ + const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - + (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - + (st1[1] - st[1]) * (st0[0] - st3[0]))); + + /* C = (p1-p) X (p1-p2) */ + const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); + double denom = a - 2 * b + fC; + + if (IS_ZERO(denom) != 0) { + const double fDen = a - fC; + if (IS_ZERO(fDen) == 0) { + return (float)(a / fDen); + } + else { + return 0.0f; + } + } + else { + const double desc_sq = b * b - a * fC; + const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); + const double s = signed_area > 0 ? (-1.0) : 1.0; + + return (float)(((a - b) + s * desc) / denom); + } } - #undef IS_ZERO /* reverse of the functions above */ void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]) { - float vec[3]; + float vec[3]; - copy_v3_v3(res, data[0]); - mul_v3_fl(res, (1 - u) * (1 - v)); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, u * v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[3]); - mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); + copy_v3_v3(res, data[0]); + mul_v3_fl(res, (1 - u) * (1 - v)); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, u * (1 - v)); + add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, u * v); + add_v3_v3(res, vec); + copy_v3_v3(vec, data[3]); + mul_v3_fl(vec, (1 - u) * v); + add_v3_v3(res, vec); } void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]) { - float vec[3]; + float vec[3]; - copy_v3_v3(res, data[0]); - mul_v3_fl(res, u); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); + copy_v3_v3(res, data[0]); + mul_v3_fl(res, u); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, v); + add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, 1.0f - u - v); + add_v3_v3(res, vec); } /***************************** View & Projection *****************************/ @@ -4106,80 +4247,88 @@ void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]) /** * Matches `glOrtho` result. */ -void orthographic_m4(float matrix[4][4], const float left, const float right, const float bottom, const float top, - const float nearClip, const float farClip) -{ - float Xdelta, Ydelta, Zdelta; - - Xdelta = right - left; - Ydelta = top - bottom; - Zdelta = farClip - nearClip; - if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) { - return; - } - unit_m4(matrix); - matrix[0][0] = 2.0f / Xdelta; - matrix[3][0] = -(right + left) / Xdelta; - matrix[1][1] = 2.0f / Ydelta; - matrix[3][1] = -(top + bottom) / Ydelta; - matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */ - matrix[3][2] = -(farClip + nearClip) / Zdelta; +void orthographic_m4(float matrix[4][4], + const float left, + const float right, + const float bottom, + const float top, + const float nearClip, + const float farClip) +{ + float Xdelta, Ydelta, Zdelta; + + Xdelta = right - left; + Ydelta = top - bottom; + Zdelta = farClip - nearClip; + if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) { + return; + } + unit_m4(matrix); + matrix[0][0] = 2.0f / Xdelta; + matrix[3][0] = -(right + left) / Xdelta; + matrix[1][1] = 2.0f / Ydelta; + matrix[3][1] = -(top + bottom) / Ydelta; + matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */ + matrix[3][2] = -(farClip + nearClip) / Zdelta; } /** * Matches `glFrustum` result. */ -void perspective_m4(float mat[4][4], const float left, const float right, const float bottom, const float top, - const float nearClip, const float farClip) -{ - const float Xdelta = right - left; - const float Ydelta = top - bottom; - const float Zdelta = farClip - nearClip; - - if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) { - return; - } - mat[0][0] = nearClip * 2.0f / Xdelta; - mat[1][1] = nearClip * 2.0f / Ydelta; - mat[2][0] = (right + left) / Xdelta; /* note: negate Z */ - mat[2][1] = (top + bottom) / Ydelta; - mat[2][2] = -(farClip + nearClip) / Zdelta; - mat[2][3] = -1.0f; - mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta; - mat[0][1] = mat[0][2] = mat[0][3] = - mat[1][0] = mat[1][2] = mat[1][3] = - mat[3][0] = mat[3][1] = mat[3][3] = 0.0f; - +void perspective_m4(float mat[4][4], + const float left, + const float right, + const float bottom, + const float top, + const float nearClip, + const float farClip) +{ + const float Xdelta = right - left; + const float Ydelta = top - bottom; + const float Zdelta = farClip - nearClip; + + if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) { + return; + } + mat[0][0] = nearClip * 2.0f / Xdelta; + mat[1][1] = nearClip * 2.0f / Ydelta; + mat[2][0] = (right + left) / Xdelta; /* note: negate Z */ + mat[2][1] = (top + bottom) / Ydelta; + mat[2][2] = -(farClip + nearClip) / Zdelta; + mat[2][3] = -1.0f; + mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta; + mat[0][1] = mat[0][2] = mat[0][3] = mat[1][0] = mat[1][2] = mat[1][3] = mat[3][0] = mat[3][1] = + mat[3][3] = 0.0f; } /* translate a matrix created by orthographic_m4 or perspective_m4 in XY coords * (used to jitter the view) */ void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x, const float y) { - if (winmat[2][3] == -1.0f) { - /* in the case of a win-matrix, this means perspective always */ - float v1[3]; - float v2[3]; - float len1, len2; + if (winmat[2][3] == -1.0f) { + /* in the case of a win-matrix, this means perspective always */ + float v1[3]; + float v2[3]; + float len1, len2; - v1[0] = perspmat[0][0]; - v1[1] = perspmat[1][0]; - v1[2] = perspmat[2][0]; + v1[0] = perspmat[0][0]; + v1[1] = perspmat[1][0]; + v1[2] = perspmat[2][0]; - v2[0] = perspmat[0][1]; - v2[1] = perspmat[1][1]; - v2[2] = perspmat[2][1]; + v2[0] = perspmat[0][1]; + v2[1] = perspmat[1][1]; + v2[2] = perspmat[2][1]; - len1 = (1.0f / len_v3(v1)); - len2 = (1.0f / len_v3(v2)); + len1 = (1.0f / len_v3(v1)); + len2 = (1.0f / len_v3(v2)); - winmat[2][0] += len1 * winmat[0][0] * x; - winmat[2][1] += len2 * winmat[1][1] * y; - } - else { - winmat[3][0] += x; - winmat[3][1] += y; - } + winmat[2][0] += len1 * winmat[0][0] * x; + winmat[2][1] += len2 * winmat[1][1] * y; + } + else { + winmat[3][0] += x; + winmat[3][1] += y; + } } /** @@ -4187,423 +4336,466 @@ void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x * * plane parameters can be NULL if you do not need them. */ -void planes_from_projmat(float mat[4][4], float left[4], float right[4], float top[4], float bottom[4], - float near[4], float far[4]) -{ - /* References: - * - * https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/ - * http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf - */ - - int i; - - if (left) { - for (i = 4; i--; ) { - left[i] = mat[i][3] + mat[i][0]; - } - } - - if (right) { - for (i = 4; i--; ) { - right[i] = mat[i][3] - mat[i][0]; - } - } - - if (bottom) { - for (i = 4; i--; ) { - bottom[i] = mat[i][3] + mat[i][1]; - } - } - - if (top) { - for (i = 4; i--; ) { - top[i] = mat[i][3] - mat[i][1]; - } - } - - if (near) { - for (i = 4; i--; ) { - near[i] = mat[i][3] + mat[i][2]; - } - } - - if (far) { - for (i = 4; i--; ) { - far[i] = mat[i][3] - mat[i][2]; - } - } +void planes_from_projmat(float mat[4][4], + float left[4], + float right[4], + float top[4], + float bottom[4], + float near[4], + float far[4]) +{ + /* References: + * + * https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/ + * http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf + */ + + int i; + + if (left) { + for (i = 4; i--;) { + left[i] = mat[i][3] + mat[i][0]; + } + } + + if (right) { + for (i = 4; i--;) { + right[i] = mat[i][3] - mat[i][0]; + } + } + + if (bottom) { + for (i = 4; i--;) { + bottom[i] = mat[i][3] + mat[i][1]; + } + } + + if (top) { + for (i = 4; i--;) { + top[i] = mat[i][3] - mat[i][1]; + } + } + + if (near) { + for (i = 4; i--;) { + near[i] = mat[i][3] + mat[i][2]; + } + } + + if (far) { + for (i = 4; i--;) { + far[i] = mat[i][3] - mat[i][2]; + } + } } void projmat_dimensions(const float projmat[4][4], - float *r_left, float *r_right, - float *r_bottom, float *r_top, - float *r_near, float *r_far) -{ - bool is_persp = projmat[3][3] == 0.0f; - - if (is_persp) { - *r_left = (projmat[2][0] - 1.0f) / projmat[0][0]; - *r_right = (projmat[2][0] + 1.0f) / projmat[0][0]; - *r_bottom = (projmat[2][1] - 1.0f) / projmat[1][1]; - *r_top = (projmat[2][1] + 1.0f) / projmat[1][1]; - *r_near = projmat[3][2] / (projmat[2][2] - 1.0f); - *r_far = projmat[3][2] / (projmat[2][2] + 1.0f); - } - else { - *r_left = (-projmat[3][0] - 1.0f) / projmat[0][0]; - *r_right = (-projmat[3][0] + 1.0f) / projmat[0][0]; - *r_bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; - *r_top = (-projmat[3][1] + 1.0f) / projmat[1][1]; - *r_near = ( projmat[3][2] + 1.0f) / projmat[2][2]; - *r_far = ( projmat[3][2] - 1.0f) / projmat[2][2]; - } - + float *r_left, + float *r_right, + float *r_bottom, + float *r_top, + float *r_near, + float *r_far) +{ + bool is_persp = projmat[3][3] == 0.0f; + + if (is_persp) { + *r_left = (projmat[2][0] - 1.0f) / projmat[0][0]; + *r_right = (projmat[2][0] + 1.0f) / projmat[0][0]; + *r_bottom = (projmat[2][1] - 1.0f) / projmat[1][1]; + *r_top = (projmat[2][1] + 1.0f) / projmat[1][1]; + *r_near = projmat[3][2] / (projmat[2][2] - 1.0f); + *r_far = projmat[3][2] / (projmat[2][2] + 1.0f); + } + else { + *r_left = (-projmat[3][0] - 1.0f) / projmat[0][0]; + *r_right = (-projmat[3][0] + 1.0f) / projmat[0][0]; + *r_bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; + *r_top = (-projmat[3][1] + 1.0f) / projmat[1][1]; + *r_near = (projmat[3][2] + 1.0f) / projmat[2][2]; + *r_far = (projmat[3][2] - 1.0f) / projmat[2][2]; + } } static void i_multmatrix(float icand[4][4], float Vm[4][4]) { - int row, col; - float temp[4][4]; + int row, col; + float temp[4][4]; - for (row = 0; row < 4; row++) { - for (col = 0; col < 4; col++) { - temp[row][col] = (icand[row][0] * Vm[0][col] + - icand[row][1] * Vm[1][col] + - icand[row][2] * Vm[2][col] + - icand[row][3] * Vm[3][col]); - } - } - copy_m4_m4(Vm, temp); + for (row = 0; row < 4; row++) { + for (col = 0; col < 4; col++) { + temp[row][col] = (icand[row][0] * Vm[0][col] + icand[row][1] * Vm[1][col] + + icand[row][2] * Vm[2][col] + icand[row][3] * Vm[3][col]); + } + } + copy_m4_m4(Vm, temp); } void polarview_m4(float Vm[4][4], float dist, float azimuth, float incidence, float twist) { - unit_m4(Vm); + unit_m4(Vm); - translate_m4(Vm, 0.0, 0.0, -dist); - rotate_m4(Vm, 'Z', -twist); - rotate_m4(Vm, 'X', -incidence); - rotate_m4(Vm, 'Z', -azimuth); + translate_m4(Vm, 0.0, 0.0, -dist); + rotate_m4(Vm, 'Z', -twist); + rotate_m4(Vm, 'X', -incidence); + rotate_m4(Vm, 'Z', -azimuth); } -void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py, float pz, float twist) +void lookat_m4( + float mat[4][4], float vx, float vy, float vz, float px, float py, float pz, float twist) { - float sine, cosine, hyp, hyp1, dx, dy, dz; - float mat1[4][4]; + float sine, cosine, hyp, hyp1, dx, dy, dz; + float mat1[4][4]; - unit_m4(mat1); + unit_m4(mat1); - axis_angle_to_mat4_single(mat, 'Z', -twist); + axis_angle_to_mat4_single(mat, 'Z', -twist); - dx = px - vx; - dy = py - vy; - dz = pz - vz; - hyp = dx * dx + dz * dz; /* hyp squared */ - hyp1 = sqrtf(dy * dy + hyp); - hyp = sqrtf(hyp); /* the real hyp */ + dx = px - vx; + dy = py - vy; + dz = pz - vz; + hyp = dx * dx + dz * dz; /* hyp squared */ + hyp1 = sqrtf(dy * dy + hyp); + hyp = sqrtf(hyp); /* the real hyp */ - if (hyp1 != 0.0f) { /* rotate X */ - sine = -dy / hyp1; - cosine = hyp / hyp1; - } - else { - sine = 0.0f; - cosine = 1.0f; - } - mat1[1][1] = cosine; - mat1[1][2] = sine; - mat1[2][1] = -sine; - mat1[2][2] = cosine; + if (hyp1 != 0.0f) { /* rotate X */ + sine = -dy / hyp1; + cosine = hyp / hyp1; + } + else { + sine = 0.0f; + cosine = 1.0f; + } + mat1[1][1] = cosine; + mat1[1][2] = sine; + mat1[2][1] = -sine; + mat1[2][2] = cosine; - i_multmatrix(mat1, mat); + i_multmatrix(mat1, mat); - mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */ - mat1[1][2] = mat1[2][1] = 0.0f; /* those modified by the last */ + mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */ + mat1[1][2] = mat1[2][1] = 0.0f; /* those modified by the last */ - /* paragraph */ - if (hyp != 0.0f) { /* rotate Y */ - sine = dx / hyp; - cosine = -dz / hyp; - } - else { - sine = 0.0f; - cosine = 1.0f; - } - mat1[0][0] = cosine; - mat1[0][2] = -sine; - mat1[2][0] = sine; - mat1[2][2] = cosine; + /* paragraph */ + if (hyp != 0.0f) { /* rotate Y */ + sine = dx / hyp; + cosine = -dz / hyp; + } + else { + sine = 0.0f; + cosine = 1.0f; + } + mat1[0][0] = cosine; + mat1[0][2] = -sine; + mat1[2][0] = sine; + mat1[2][2] = cosine; - i_multmatrix(mat1, mat); - translate_m4(mat, -vx, -vy, -vz); /* translate viewpoint to origin */ + i_multmatrix(mat1, mat); + translate_m4(mat, -vx, -vy, -vz); /* translate viewpoint to origin */ } int box_clip_bounds_m4(float boundbox[2][3], const float bounds[4], float winmat[4][4]) { - float mat[4][4], vec[4]; - int a, fl, flag = -1; - - copy_m4_m4(mat, winmat); - - for (a = 0; a < 8; a++) { - vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0]; - vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1]; - vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2]; - vec[3] = 1.0; - mul_m4_v4(mat, vec); - - fl = 0; - if (bounds) { - if (vec[0] > bounds[1] * vec[3]) { fl |= 1; } - if (vec[0] < bounds[0] * vec[3]) { fl |= 2; } - if (vec[1] > bounds[3] * vec[3]) { fl |= 4; } - if (vec[1] < bounds[2] * vec[3]) { fl |= 8; } - } - else { - if (vec[0] < -vec[3]) { fl |= 1; } - if (vec[0] > vec[3]) { fl |= 2; } - if (vec[1] < -vec[3]) { fl |= 4; } - if (vec[1] > vec[3]) { fl |= 8; } - } - if (vec[2] < -vec[3]) { fl |= 16; } - if (vec[2] > vec[3]) { fl |= 32; } - - flag &= fl; - if (flag == 0) { - return 0; - } - } - - return flag; + float mat[4][4], vec[4]; + int a, fl, flag = -1; + + copy_m4_m4(mat, winmat); + + for (a = 0; a < 8; a++) { + vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0]; + vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1]; + vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2]; + vec[3] = 1.0; + mul_m4_v4(mat, vec); + + fl = 0; + if (bounds) { + if (vec[0] > bounds[1] * vec[3]) { + fl |= 1; + } + if (vec[0] < bounds[0] * vec[3]) { + fl |= 2; + } + if (vec[1] > bounds[3] * vec[3]) { + fl |= 4; + } + if (vec[1] < bounds[2] * vec[3]) { + fl |= 8; + } + } + else { + if (vec[0] < -vec[3]) { + fl |= 1; + } + if (vec[0] > vec[3]) { + fl |= 2; + } + if (vec[1] < -vec[3]) { + fl |= 4; + } + if (vec[1] > vec[3]) { + fl |= 8; + } + } + if (vec[2] < -vec[3]) { + fl |= 16; + } + if (vec[2] > vec[3]) { + fl |= 32; + } + + flag &= fl; + if (flag == 0) { + return 0; + } + } + + return flag; } void box_minmax_bounds_m4(float min[3], float max[3], float boundbox[2][3], float mat[4][4]) { - float mn[3], mx[3], vec[3]; - int a; + float mn[3], mx[3], vec[3]; + int a; - copy_v3_v3(mn, min); - copy_v3_v3(mx, max); + copy_v3_v3(mn, min); + copy_v3_v3(mx, max); - for (a = 0; a < 8; a++) { - vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0]; - vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1]; - vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2]; + for (a = 0; a < 8; a++) { + vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0]; + vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1]; + vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2]; - mul_m4_v3(mat, vec); - minmax_v3v3_v3(mn, mx, vec); - } + mul_m4_v3(mat, vec); + minmax_v3v3_v3(mn, mx, vec); + } - copy_v3_v3(min, mn); - copy_v3_v3(max, mx); + copy_v3_v3(min, mn); + copy_v3_v3(max, mx); } /********************************** Mapping **********************************/ void map_to_tube(float *r_u, float *r_v, const float x, const float y, const float z) { - float len; + float len; - *r_v = (z + 1.0f) / 2.0f; + *r_v = (z + 1.0f) / 2.0f; - len = sqrtf(x * x + y * y); - if (len > 0.0f) { - *r_u = (1.0f - (atan2f(x / len, y / len) / (float)M_PI)) / 2.0f; - } - else { - *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */ - } + len = sqrtf(x * x + y * y); + if (len > 0.0f) { + *r_u = (1.0f - (atan2f(x / len, y / len) / (float)M_PI)) / 2.0f; + } + else { + *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */ + } } void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z) { - float len; + float len; - len = sqrtf(x * x + y * y + z * z); - if (len > 0.0f) { - if (UNLIKELY(x == 0.0f && y == 0.0f)) { - *r_u = 0.0f; /* othwise domain error */ - } - else { - *r_u = (1.0f - atan2f(x, y) / (float)M_PI) / 2.0f; - } + len = sqrtf(x * x + y * y + z * z); + if (len > 0.0f) { + if (UNLIKELY(x == 0.0f && y == 0.0f)) { + *r_u = 0.0f; /* othwise domain error */ + } + else { + *r_u = (1.0f - atan2f(x, y) / (float)M_PI) / 2.0f; + } - *r_v = 1.0f - saacos(z / len) / (float)M_PI; - } - else { - *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */ - } + *r_v = 1.0f - saacos(z / len) / (float)M_PI; + } + else { + *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */ + } } void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3]) { - float target[3] = {0.0f, 0.0f, 1.0f}; - float axis[3]; + float target[3] = {0.0f, 0.0f, 1.0f}; + float axis[3]; - cross_v3_v3v3(axis, no, target); - normalize_v3(axis); + cross_v3_v3v3(axis, no, target); + normalize_v3(axis); - map_to_plane_axis_angle_v2_v3v3fl(r_co, co, axis, angle_normalized_v3v3(no, target)); + map_to_plane_axis_angle_v2_v3v3fl(r_co, co, axis, angle_normalized_v3v3(no, target)); } -void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle) +void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], + const float co[3], + const float axis[3], + const float angle) { - float tmp[3]; + float tmp[3]; - rotate_normalized_v3_v3v3fl(tmp, co, axis, angle); + rotate_normalized_v3_v3v3fl(tmp, co, axis, angle); - copy_v2_v2(r_co, tmp); + copy_v2_v2(r_co, tmp); } /********************************* Normals **********************************/ -void accumulate_vertex_normals_tri_v3( - float n1[3], float n2[3], float n3[3], - const float f_no[3], - const float co1[3], const float co2[3], const float co3[3]) -{ - float vdiffs[3][3]; - const int nverts = 3; - - /* compute normalized edge vectors */ - sub_v3_v3v3(vdiffs[0], co2, co1); - sub_v3_v3v3(vdiffs[1], co3, co2); - sub_v3_v3v3(vdiffs[2], co1, co3); - - normalize_v3(vdiffs[0]); - normalize_v3(vdiffs[1]); - normalize_v3(vdiffs[2]); - - /* accumulate angle weighted face normal */ - { - float *vn[] = {n1, n2, n3}; - const float *prev_edge = vdiffs[nverts - 1]; - int i; - - for (i = 0; i < nverts; i++) { - const float *cur_edge = vdiffs[i]; - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - - /* accumulate */ - madd_v3_v3fl(vn[i], f_no, fac); - prev_edge = cur_edge; - } - } -} - -void accumulate_vertex_normals_v3( - float n1[3], float n2[3], float n3[3], float n4[3], - const float f_no[3], - const float co1[3], const float co2[3], const float co3[3], const float co4[3]) -{ - float vdiffs[4][3]; - const int nverts = (n4 != NULL && co4 != NULL) ? 4 : 3; - - /* compute normalized edge vectors */ - sub_v3_v3v3(vdiffs[0], co2, co1); - sub_v3_v3v3(vdiffs[1], co3, co2); - - if (nverts == 3) { - sub_v3_v3v3(vdiffs[2], co1, co3); - } - else { - sub_v3_v3v3(vdiffs[2], co4, co3); - sub_v3_v3v3(vdiffs[3], co1, co4); - normalize_v3(vdiffs[3]); - } - - normalize_v3(vdiffs[0]); - normalize_v3(vdiffs[1]); - normalize_v3(vdiffs[2]); - - /* accumulate angle weighted face normal */ - { - float *vn[] = {n1, n2, n3, n4}; - const float *prev_edge = vdiffs[nverts - 1]; - int i; - - for (i = 0; i < nverts; i++) { - const float *cur_edge = vdiffs[i]; - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - - /* accumulate */ - madd_v3_v3fl(vn[i], f_no, fac); - prev_edge = cur_edge; - } - } +void accumulate_vertex_normals_tri_v3(float n1[3], + float n2[3], + float n3[3], + const float f_no[3], + const float co1[3], + const float co2[3], + const float co3[3]) +{ + float vdiffs[3][3]; + const int nverts = 3; + + /* compute normalized edge vectors */ + sub_v3_v3v3(vdiffs[0], co2, co1); + sub_v3_v3v3(vdiffs[1], co3, co2); + sub_v3_v3v3(vdiffs[2], co1, co3); + + normalize_v3(vdiffs[0]); + normalize_v3(vdiffs[1]); + normalize_v3(vdiffs[2]); + + /* accumulate angle weighted face normal */ + { + float *vn[] = {n1, n2, n3}; + const float *prev_edge = vdiffs[nverts - 1]; + int i; + + for (i = 0; i < nverts; i++) { + const float *cur_edge = vdiffs[i]; + const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + + /* accumulate */ + madd_v3_v3fl(vn[i], f_no, fac); + prev_edge = cur_edge; + } + } +} + +void accumulate_vertex_normals_v3(float n1[3], + float n2[3], + float n3[3], + float n4[3], + const float f_no[3], + const float co1[3], + const float co2[3], + const float co3[3], + const float co4[3]) +{ + float vdiffs[4][3]; + const int nverts = (n4 != NULL && co4 != NULL) ? 4 : 3; + + /* compute normalized edge vectors */ + sub_v3_v3v3(vdiffs[0], co2, co1); + sub_v3_v3v3(vdiffs[1], co3, co2); + + if (nverts == 3) { + sub_v3_v3v3(vdiffs[2], co1, co3); + } + else { + sub_v3_v3v3(vdiffs[2], co4, co3); + sub_v3_v3v3(vdiffs[3], co1, co4); + normalize_v3(vdiffs[3]); + } + + normalize_v3(vdiffs[0]); + normalize_v3(vdiffs[1]); + normalize_v3(vdiffs[2]); + + /* accumulate angle weighted face normal */ + { + float *vn[] = {n1, n2, n3, n4}; + const float *prev_edge = vdiffs[nverts - 1]; + int i; + + for (i = 0; i < nverts; i++) { + const float *cur_edge = vdiffs[i]; + const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + + /* accumulate */ + madd_v3_v3fl(vn[i], f_no, fac); + prev_edge = cur_edge; + } + } } /* Add weighted face normal component into normals of the face vertices. * Caller must pass pre-allocated vdiffs of nverts length. */ -void accumulate_vertex_normals_poly_v3(float **vertnos, const float polyno[3], - const float **vertcos, float vdiffs[][3], const int nverts) +void accumulate_vertex_normals_poly_v3(float **vertnos, + const float polyno[3], + const float **vertcos, + float vdiffs[][3], + const int nverts) { - int i; + int i; - /* calculate normalized edge directions for each edge in the poly */ - for (i = 0; i < nverts; i++) { - sub_v3_v3v3(vdiffs[i], vertcos[(i + 1) % nverts], vertcos[i]); - normalize_v3(vdiffs[i]); - } + /* calculate normalized edge directions for each edge in the poly */ + for (i = 0; i < nverts; i++) { + sub_v3_v3v3(vdiffs[i], vertcos[(i + 1) % nverts], vertcos[i]); + normalize_v3(vdiffs[i]); + } - /* accumulate angle weighted face normal */ - { - const float *prev_edge = vdiffs[nverts - 1]; + /* accumulate angle weighted face normal */ + { + const float *prev_edge = vdiffs[nverts - 1]; - for (i = 0; i < nverts; i++) { - const float *cur_edge = vdiffs[i]; + for (i = 0; i < nverts; i++) { + const float *cur_edge = vdiffs[i]; - /* calculate angle between the two poly edges incident on - * this vertex */ - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + /* calculate angle between the two poly edges incident on + * this vertex */ + const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - /* accumulate */ - madd_v3_v3fl(vertnos[i], polyno, fac); - prev_edge = cur_edge; - } - } + /* accumulate */ + madd_v3_v3fl(vertnos[i], polyno, fac); + prev_edge = cur_edge; + } + } } /********************************* Tangents **********************************/ -void tangent_from_uv_v3( - const float uv1[2], const float uv2[2], const float uv3[3], - const float co1[3], const float co2[3], const float co3[3], - const float n[3], - float r_tang[3]) -{ - const float s1 = uv2[0] - uv1[0]; - const float s2 = uv3[0] - uv1[0]; - const float t1 = uv2[1] - uv1[1]; - const float t2 = uv3[1] - uv1[1]; - float det = (s1 * t2 - s2 * t1); - - /* otherwise 'r_tang' becomes nan */ - if (det != 0.0f) { - float tangv[3], ct[3], e1[3], e2[3]; - - det = 1.0f / det; - - /* normals in render are inversed... */ - sub_v3_v3v3(e1, co1, co2); - sub_v3_v3v3(e2, co1, co3); - r_tang[0] = (t2 * e1[0] - t1 * e2[0]) * det; - r_tang[1] = (t2 * e1[1] - t1 * e2[1]) * det; - r_tang[2] = (t2 * e1[2] - t1 * e2[2]) * det; - tangv[0] = (s1 * e2[0] - s2 * e1[0]) * det; - tangv[1] = (s1 * e2[1] - s2 * e1[1]) * det; - tangv[2] = (s1 * e2[2] - s2 * e1[2]) * det; - cross_v3_v3v3(ct, r_tang, tangv); - - /* check flip */ - if (dot_v3v3(ct, n) < 0.0f) { - negate_v3(r_tang); - } - } - else { - zero_v3(r_tang); - } +void tangent_from_uv_v3(const float uv1[2], + const float uv2[2], + const float uv3[3], + const float co1[3], + const float co2[3], + const float co3[3], + const float n[3], + float r_tang[3]) +{ + const float s1 = uv2[0] - uv1[0]; + const float s2 = uv3[0] - uv1[0]; + const float t1 = uv2[1] - uv1[1]; + const float t2 = uv3[1] - uv1[1]; + float det = (s1 * t2 - s2 * t1); + + /* otherwise 'r_tang' becomes nan */ + if (det != 0.0f) { + float tangv[3], ct[3], e1[3], e2[3]; + + det = 1.0f / det; + + /* normals in render are inversed... */ + sub_v3_v3v3(e1, co1, co2); + sub_v3_v3v3(e2, co1, co3); + r_tang[0] = (t2 * e1[0] - t1 * e2[0]) * det; + r_tang[1] = (t2 * e1[1] - t1 * e2[1]) * det; + r_tang[2] = (t2 * e1[2] - t1 * e2[2]) * det; + tangv[0] = (s1 * e2[0] - s2 * e1[0]) * det; + tangv[1] = (s1 * e2[1] - s2 * e1[1]) * det; + tangv[2] = (s1 * e2[2] - s2 * e1[2]) * det; + cross_v3_v3v3(ct, r_tang, tangv); + + /* check flip */ + if (dot_v3v3(ct, n) < 0.0f) { + negate_v3(r_tang); + } + } + else { + zero_v3(r_tang); + } } /****************************** Vector Clouds ********************************/ @@ -4628,424 +4820,449 @@ void tangent_from_uv_v3( * pointers may be NULL if not needed */ -void vcloud_estimate_transform_v3( - const int list_size, const float (*pos)[3], const float *weight, const float (*rpos)[3], const float *rweight, - float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3]) -{ - float accu_com[3] = {0.0f, 0.0f, 0.0f}, accu_rcom[3] = {0.0f, 0.0f, 0.0f}; - float accu_weight = 0.0f, accu_rweight = 0.0f; - const float eps = 1e-6f; - - int a; - /* first set up a nice default response */ - if (lloc) { zero_v3(lloc); } - if (rloc) { zero_v3(rloc); } - if (lrot) { unit_m3(lrot); } - if (lscale) { unit_m3(lscale); } - /* do com for both clouds */ - if (pos && rpos && (list_size > 0)) { /* paranoya check */ - /* do com for both clouds */ - for (a = 0; a < list_size; a++) { - if (weight) { - float v[3]; - copy_v3_v3(v, pos[a]); - mul_v3_fl(v, weight[a]); - add_v3_v3(accu_com, v); - accu_weight += weight[a]; - } - else { - add_v3_v3(accu_com, pos[a]); - } - - if (rweight) { - float v[3]; - copy_v3_v3(v, rpos[a]); - mul_v3_fl(v, rweight[a]); - add_v3_v3(accu_rcom, v); - accu_rweight += rweight[a]; - } - else { - add_v3_v3(accu_rcom, rpos[a]); - } - } - if (!weight || !rweight) { - accu_weight = accu_rweight = (float)list_size; - } - - mul_v3_fl(accu_com, 1.0f / accu_weight); - mul_v3_fl(accu_rcom, 1.0f / accu_rweight); - if (lloc) { - copy_v3_v3(lloc, accu_com); - } - if (rloc) { - copy_v3_v3(rloc, accu_rcom); - } - if (lrot || lscale) { /* caller does not want rot nor scale, strange but legal */ - /* so now do some reverse engineering and see if we can - * split rotation from scale -> Polardecompose */ - /* build 'projection' matrix */ - float m[3][3], mr[3][3], q[3][3], qi[3][3]; - float va[3], vb[3], stunt[3]; - float odet, ndet; - int i = 0, imax = 15; - zero_m3(m); - zero_m3(mr); - - /* build 'projection' matrix */ - for (a = 0; a < list_size; a++) { - sub_v3_v3v3(va, rpos[a], accu_rcom); - /* mul_v3_fl(va, bp->mass); mass needs renormalzation here ?? */ - sub_v3_v3v3(vb, pos[a], accu_com); - /* mul_v3_fl(va, rp->mass); */ - m[0][0] += va[0] * vb[0]; - m[0][1] += va[0] * vb[1]; - m[0][2] += va[0] * vb[2]; - - m[1][0] += va[1] * vb[0]; - m[1][1] += va[1] * vb[1]; - m[1][2] += va[1] * vb[2]; - - m[2][0] += va[2] * vb[0]; - m[2][1] += va[2] * vb[1]; - m[2][2] += va[2] * vb[2]; - - /* building the reference matrix on the fly - * needed to scale properly later */ - - mr[0][0] += va[0] * va[0]; - mr[0][1] += va[0] * va[1]; - mr[0][2] += va[0] * va[2]; - - mr[1][0] += va[1] * va[0]; - mr[1][1] += va[1] * va[1]; - mr[1][2] += va[1] * va[2]; - - mr[2][0] += va[2] * va[0]; - mr[2][1] += va[2] * va[1]; - mr[2][2] += va[2] * va[2]; - } - copy_m3_m3(q, m); - stunt[0] = q[0][0]; - stunt[1] = q[1][1]; - stunt[2] = q[2][2]; - /* renormalizing for numeric stability */ - mul_m3_fl(q, 1.f / len_v3(stunt)); - - /* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */ - /* without the far case ... but seems to work here pretty neat */ - odet = 0.0f; - ndet = determinant_m3_array(q); - while ((odet - ndet) * (odet - ndet) > eps && i < imax) { - invert_m3_m3(qi, q); - transpose_m3(qi); - add_m3_m3m3(q, q, qi); - mul_m3_fl(q, 0.5f); - odet = ndet; - ndet = determinant_m3_array(q); - i++; - } - - if (i) { - float scale[3][3]; - float irot[3][3]; - if (lrot) { - copy_m3_m3(lrot, q); - } - invert_m3_m3(irot, q); - invert_m3_m3(qi, mr); - mul_m3_m3m3(q, m, qi); - mul_m3_m3m3(scale, irot, q); - if (lscale) { - copy_m3_m3(lscale, scale); - } - - } - } - } +void vcloud_estimate_transform_v3(const int list_size, + const float (*pos)[3], + const float *weight, + const float (*rpos)[3], + const float *rweight, + float lloc[3], + float rloc[3], + float lrot[3][3], + float lscale[3][3]) +{ + float accu_com[3] = {0.0f, 0.0f, 0.0f}, accu_rcom[3] = {0.0f, 0.0f, 0.0f}; + float accu_weight = 0.0f, accu_rweight = 0.0f; + const float eps = 1e-6f; + + int a; + /* first set up a nice default response */ + if (lloc) { + zero_v3(lloc); + } + if (rloc) { + zero_v3(rloc); + } + if (lrot) { + unit_m3(lrot); + } + if (lscale) { + unit_m3(lscale); + } + /* do com for both clouds */ + if (pos && rpos && (list_size > 0)) { /* paranoya check */ + /* do com for both clouds */ + for (a = 0; a < list_size; a++) { + if (weight) { + float v[3]; + copy_v3_v3(v, pos[a]); + mul_v3_fl(v, weight[a]); + add_v3_v3(accu_com, v); + accu_weight += weight[a]; + } + else { + add_v3_v3(accu_com, pos[a]); + } + + if (rweight) { + float v[3]; + copy_v3_v3(v, rpos[a]); + mul_v3_fl(v, rweight[a]); + add_v3_v3(accu_rcom, v); + accu_rweight += rweight[a]; + } + else { + add_v3_v3(accu_rcom, rpos[a]); + } + } + if (!weight || !rweight) { + accu_weight = accu_rweight = (float)list_size; + } + + mul_v3_fl(accu_com, 1.0f / accu_weight); + mul_v3_fl(accu_rcom, 1.0f / accu_rweight); + if (lloc) { + copy_v3_v3(lloc, accu_com); + } + if (rloc) { + copy_v3_v3(rloc, accu_rcom); + } + if (lrot || lscale) { /* caller does not want rot nor scale, strange but legal */ + /* so now do some reverse engineering and see if we can + * split rotation from scale -> Polardecompose */ + /* build 'projection' matrix */ + float m[3][3], mr[3][3], q[3][3], qi[3][3]; + float va[3], vb[3], stunt[3]; + float odet, ndet; + int i = 0, imax = 15; + zero_m3(m); + zero_m3(mr); + + /* build 'projection' matrix */ + for (a = 0; a < list_size; a++) { + sub_v3_v3v3(va, rpos[a], accu_rcom); + /* mul_v3_fl(va, bp->mass); mass needs renormalzation here ?? */ + sub_v3_v3v3(vb, pos[a], accu_com); + /* mul_v3_fl(va, rp->mass); */ + m[0][0] += va[0] * vb[0]; + m[0][1] += va[0] * vb[1]; + m[0][2] += va[0] * vb[2]; + + m[1][0] += va[1] * vb[0]; + m[1][1] += va[1] * vb[1]; + m[1][2] += va[1] * vb[2]; + + m[2][0] += va[2] * vb[0]; + m[2][1] += va[2] * vb[1]; + m[2][2] += va[2] * vb[2]; + + /* building the reference matrix on the fly + * needed to scale properly later */ + + mr[0][0] += va[0] * va[0]; + mr[0][1] += va[0] * va[1]; + mr[0][2] += va[0] * va[2]; + + mr[1][0] += va[1] * va[0]; + mr[1][1] += va[1] * va[1]; + mr[1][2] += va[1] * va[2]; + + mr[2][0] += va[2] * va[0]; + mr[2][1] += va[2] * va[1]; + mr[2][2] += va[2] * va[2]; + } + copy_m3_m3(q, m); + stunt[0] = q[0][0]; + stunt[1] = q[1][1]; + stunt[2] = q[2][2]; + /* renormalizing for numeric stability */ + mul_m3_fl(q, 1.f / len_v3(stunt)); + + /* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */ + /* without the far case ... but seems to work here pretty neat */ + odet = 0.0f; + ndet = determinant_m3_array(q); + while ((odet - ndet) * (odet - ndet) > eps && i < imax) { + invert_m3_m3(qi, q); + transpose_m3(qi); + add_m3_m3m3(q, q, qi); + mul_m3_fl(q, 0.5f); + odet = ndet; + ndet = determinant_m3_array(q); + i++; + } + + if (i) { + float scale[3][3]; + float irot[3][3]; + if (lrot) { + copy_m3_m3(lrot, q); + } + invert_m3_m3(irot, q); + invert_m3_m3(qi, mr); + mul_m3_m3m3(q, m, qi); + mul_m3_m3m3(scale, irot, q); + if (lscale) { + copy_m3_m3(lscale, scale); + } + } + } + } } /******************************* Form Factor *********************************/ static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const float fac) { - r[0] = v1[0] + fac * (v2[0] - v1[0]); - r[1] = v1[1] + fac * (v2[1] - v1[1]); - r[2] = v1[2] + fac * (v2[2] - v1[2]); -} - -bool form_factor_visible_quad(const float p[3], const float n[3], - const float v0[3], const float v1[3], const float v2[3], - float q0[3], float q1[3], float q2[3], float q3[3]) -{ - static const float epsilon = 1e-6f; - float sd[3]; - const float c = dot_v3v3(n, p); - - /* signed distances from the vertices to the plane. */ - sd[0] = dot_v3v3(n, v0) - c; - sd[1] = dot_v3v3(n, v1) - c; - sd[2] = dot_v3v3(n, v2) - c; - - if (fabsf(sd[0]) < epsilon) { sd[0] = 0.0f; } - if (fabsf(sd[1]) < epsilon) { sd[1] = 0.0f; } - if (fabsf(sd[2]) < epsilon) { sd[2] = 0.0f; } - - if (sd[0] > 0.0f) { - if (sd[1] > 0.0f) { - if (sd[2] > 0.0f) { - /* +++ */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* ++- */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); - vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2]))); - } - else { - /* ++0 */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - } - else if (sd[1] < 0.0f) { - if (sd[2] > 0.0f) { - /* +-+ */ - copy_v3_v3(q0, v0); - vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); - vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); - copy_v3_v3(q3, v2); - } - else if (sd[2] < 0.0f) { - /* +-- */ - copy_v3_v3(q0, v0); - vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); - vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2]))); - copy_v3_v3(q3, q2); - } - else { - /* +-0 */ - copy_v3_v3(q0, v0); - vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - } - else { - if (sd[2] > 0.0f) { - /* +0+ */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* +0- */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2]))); - copy_v3_v3(q3, q2); - } - else { - /* +00 */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - } - } - else if (sd[0] < 0.0f) { - if (sd[1] > 0.0f) { - if (sd[2] > 0.0f) { - /* -++ */ - vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2]))); - } - else if (sd[2] < 0.0f) { - /* -+- */ - vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); - copy_v3_v3(q1, v1); - vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); - copy_v3_v3(q3, q2); - } - else { - /* -+0 */ - vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - } - else if (sd[1] < 0.0f) { - if (sd[2] > 0.0f) { - /* --+ */ - vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2]))); - vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2]))); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* --- */ - return false; - } - else { - /* --0 */ - return false; - } - } - else { - if (sd[2] > 0.0f) { - /* -0+ */ - vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2]))); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* -0- */ - return false; - } - else { - /* -00 */ - return false; - } - } - } - else { - if (sd[1] > 0.0f) { - if (sd[2] > 0.0f) { - /* 0++ */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* 0+- */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); - copy_v3_v3(q3, q2); - } - else { - /* 0+0 */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - } - else if (sd[1] < 0.0f) { - if (sd[2] > 0.0f) { - /* 0-+ */ - copy_v3_v3(q0, v0); - vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2]))); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* 0-- */ - return false; - } - else { - /* 0-0 */ - return false; - } - } - else { - if (sd[2] > 0.0f) { - /* 00+ */ - copy_v3_v3(q0, v0); - copy_v3_v3(q1, v1); - copy_v3_v3(q2, v2); - copy_v3_v3(q3, q2); - } - else if (sd[2] < 0.0f) { - /* 00- */ - return false; - } - else { - /* 000 */ - return false; - } - } - } - - return true; + r[0] = v1[0] + fac * (v2[0] - v1[0]); + r[1] = v1[1] + fac * (v2[1] - v1[1]); + r[2] = v1[2] + fac * (v2[2] - v1[2]); +} + +bool form_factor_visible_quad(const float p[3], + const float n[3], + const float v0[3], + const float v1[3], + const float v2[3], + float q0[3], + float q1[3], + float q2[3], + float q3[3]) +{ + static const float epsilon = 1e-6f; + float sd[3]; + const float c = dot_v3v3(n, p); + + /* signed distances from the vertices to the plane. */ + sd[0] = dot_v3v3(n, v0) - c; + sd[1] = dot_v3v3(n, v1) - c; + sd[2] = dot_v3v3(n, v2) - c; + + if (fabsf(sd[0]) < epsilon) { + sd[0] = 0.0f; + } + if (fabsf(sd[1]) < epsilon) { + sd[1] = 0.0f; + } + if (fabsf(sd[2]) < epsilon) { + sd[2] = 0.0f; + } + + if (sd[0] > 0.0f) { + if (sd[1] > 0.0f) { + if (sd[2] > 0.0f) { + /* +++ */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* ++- */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); + vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2]))); + } + else { + /* ++0 */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + } + else if (sd[1] < 0.0f) { + if (sd[2] > 0.0f) { + /* +-+ */ + copy_v3_v3(q0, v0); + vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); + vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); + copy_v3_v3(q3, v2); + } + else if (sd[2] < 0.0f) { + /* +-- */ + copy_v3_v3(q0, v0); + vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); + vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2]))); + copy_v3_v3(q3, q2); + } + else { + /* +-0 */ + copy_v3_v3(q0, v0); + vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1]))); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + } + else { + if (sd[2] > 0.0f) { + /* +0+ */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* +0- */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2]))); + copy_v3_v3(q3, q2); + } + else { + /* +00 */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + } + } + else if (sd[0] < 0.0f) { + if (sd[1] > 0.0f) { + if (sd[2] > 0.0f) { + /* -++ */ + vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2]))); + } + else if (sd[2] < 0.0f) { + /* -+- */ + vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); + copy_v3_v3(q1, v1); + vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); + copy_v3_v3(q3, q2); + } + else { + /* -+0 */ + vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1]))); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + } + else if (sd[1] < 0.0f) { + if (sd[2] > 0.0f) { + /* --+ */ + vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2]))); + vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2]))); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* --- */ + return false; + } + else { + /* --0 */ + return false; + } + } + else { + if (sd[2] > 0.0f) { + /* -0+ */ + vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2]))); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* -0- */ + return false; + } + else { + /* -00 */ + return false; + } + } + } + else { + if (sd[1] > 0.0f) { + if (sd[2] > 0.0f) { + /* 0++ */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* 0+- */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2]))); + copy_v3_v3(q3, q2); + } + else { + /* 0+0 */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + } + else if (sd[1] < 0.0f) { + if (sd[2] > 0.0f) { + /* 0-+ */ + copy_v3_v3(q0, v0); + vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2]))); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* 0-- */ + return false; + } + else { + /* 0-0 */ + return false; + } + } + else { + if (sd[2] > 0.0f) { + /* 00+ */ + copy_v3_v3(q0, v0); + copy_v3_v3(q1, v1); + copy_v3_v3(q2, v2); + copy_v3_v3(q3, q2); + } + else if (sd[2] < 0.0f) { + /* 00- */ + return false; + } + else { + /* 000 */ + return false; + } + } + } + + return true; } /* altivec optimization, this works, but is unused */ #if 0 -#include <Accelerate/Accelerate.h> +# include <Accelerate/Accelerate.h> typedef union { - vFloat v; - float f[4]; + vFloat v; + float f[4]; } vFloatResult; static vFloat vec_splat_float(float val) { - return (vFloat) {val, val, val, val}; + return (vFloat) {val, val, val, val}; } static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3) { - vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle; - vUInt8 rotate = (vUInt8) {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3}; - vFloatResult vresult; - float result; + vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle; + vUInt8 rotate = (vUInt8) {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3}; + vFloatResult vresult; + float result; - /* compute r* */ - vrx = (vFloat) {q0[0], q1[0], q2[0], q3[0]} -vec_splat_float(p[0]); - vry = (vFloat) {q0[1], q1[1], q2[1], q3[1]} -vec_splat_float(p[1]); - vrz = (vFloat) {q0[2], q1[2], q2[2], q3[2]} -vec_splat_float(p[2]); + /* compute r* */ + vrx = (vFloat) {q0[0], q1[0], q2[0], q3[0]} -vec_splat_float(p[0]); + vry = (vFloat) {q0[1], q1[1], q2[1], q3[1]} -vec_splat_float(p[1]); + vrz = (vFloat) {q0[2], q1[2], q2[2], q3[2]} -vec_splat_float(p[2]); - /* normalize r* */ - rlen = vec_rsqrte(vrx * vrx + vry * vry + vrz * vrz + vec_splat_float(1e-16f)); - vrx = vrx * rlen; - vry = vry * rlen; - vrz = vrz * rlen; + /* normalize r* */ + rlen = vec_rsqrte(vrx * vrx + vry * vry + vrz * vrz + vec_splat_float(1e-16f)); + vrx = vrx * rlen; + vry = vry * rlen; + vrz = vrz * rlen; - /* rotate r* for cross and dot */ - vsrx = vec_perm(vrx, vrx, rotate); - vsry = vec_perm(vry, vry, rotate); - vsrz = vec_perm(vrz, vrz, rotate); + /* rotate r* for cross and dot */ + vsrx = vec_perm(vrx, vrx, rotate); + vsry = vec_perm(vry, vry, rotate); + vsrz = vec_perm(vrz, vrz, rotate); - /* cross product */ - gx = vsry * vrz - vsrz * vry; - gy = vsrz * vrx - vsrx * vrz; - gz = vsrx * vry - vsry * vrx; + /* cross product */ + gx = vsry * vrz - vsrz * vry; + gy = vsrz * vrx - vsrx * vrz; + gz = vsrx * vry - vsry * vrx; - /* normalize */ - rlen = vec_rsqrte(gx * gx + gy * gy + gz * gz + vec_splat_float(1e-16f)); - gx = gx * rlen; - gy = gy * rlen; - gz = gz * rlen; + /* normalize */ + rlen = vec_rsqrte(gx * gx + gy * gy + gz * gz + vec_splat_float(1e-16f)); + gx = gx * rlen; + gy = gy * rlen; + gz = gz * rlen; - /* angle */ - vcos = vrx * vsrx + vry * vsry + vrz * vsrz; - vcos = vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f)); - vangle = vacosf(vcos); + /* angle */ + vcos = vrx * vsrx + vry * vsry + vrz * vsrz; + vcos = vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f)); + vangle = vacosf(vcos); - /* dot */ - vresult.v = (vec_splat_float(n[0]) * gx + - vec_splat_float(n[1]) * gy + - vec_splat_float(n[2]) * gz) * vangle; + /* dot */ + vresult.v = (vec_splat_float(n[0]) * gx + + vec_splat_float(n[1]) * gy + + vec_splat_float(n[2]) * gz) * vangle; - result = (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3]) * (0.5f / (float)M_PI); - result = MAX2(result, 0.0f); + result = (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3]) * (0.5f / (float)M_PI); + result = MAX2(result, 0.0f); - return result; + return result; } #endif @@ -5054,141 +5271,146 @@ static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float #if 0 -#include <xmmintrin.h> +# include <xmmintrin.h> static __m128 sse_approx_acos(__m128 x) { - /* needs a better approximation than taylor expansion of acos, since that - * gives big errors for near 1.0 values, sqrt(2 * x) * acos(1 - x) should work - * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */ + /* needs a better approximation than taylor expansion of acos, since that + * gives big errors for near 1.0 values, sqrt(2 * x) * acos(1 - x) should work + * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */ - return _mm_set_ps1(1.0f); + return _mm_set_ps1(1.0f); } static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3) { - float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; - float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; - float fresult[4] __attribute__((aligned(16))); - __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult; + float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; + float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; + float fresult[4] __attribute__((aligned(16))); + __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult; - /* compute r */ - qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]); - qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]); - qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]); + /* compute r */ + qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]); + qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]); + qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]); - rx = qx - _mm_set_ps1(p[0]); - ry = qy - _mm_set_ps1(p[1]); - rz = qz - _mm_set_ps1(p[2]); + rx = qx - _mm_set_ps1(p[0]); + ry = qy - _mm_set_ps1(p[1]); + rz = qz - _mm_set_ps1(p[2]); - /* normalize r */ - rlen = _mm_rsqrt_ps(rx * rx + ry * ry + rz * rz + _mm_set_ps1(1e-16f)); - rx = rx * rlen; - ry = ry * rlen; - rz = rz * rlen; + /* normalize r */ + rlen = _mm_rsqrt_ps(rx * rx + ry * ry + rz * rz + _mm_set_ps1(1e-16f)); + rx = rx * rlen; + ry = ry * rlen; + rz = rz * rlen; - /* cross product */ - srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0, 3, 2, 1)); - sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0, 3, 2, 1)); - srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0, 3, 2, 1)); + /* cross product */ + srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0, 3, 2, 1)); + sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0, 3, 2, 1)); + srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0, 3, 2, 1)); - gx = sry * rz - srz * ry; - gy = srz * rx - srx * rz; - gz = srx * ry - sry * rx; + gx = sry * rz - srz * ry; + gy = srz * rx - srx * rz; + gz = srx * ry - sry * rx; - /* normalize g */ - glen = _mm_rsqrt_ps(gx * gx + gy * gy + gz * gz + _mm_set_ps1(1e-16f)); - gx = gx * glen; - gy = gy * glen; - gz = gz * glen; + /* normalize g */ + glen = _mm_rsqrt_ps(gx * gx + gy * gy + gz * gz + _mm_set_ps1(1e-16f)); + gx = gx * glen; + gy = gy * glen; + gz = gz * glen; - /* compute angle */ - rcos = rx * srx + ry * sry + rz * srz; - rcos = _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f)); + /* compute angle */ + rcos = rx * srx + ry * sry + rz * srz; + rcos = _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f)); - angle = sse_approx_cos(rcos); - aresult = (_mm_set_ps1(n[0]) * gx + _mm_set_ps1(n[1]) * gy + _mm_set_ps1(n[2]) * gz) * angle; + angle = sse_approx_cos(rcos); + aresult = (_mm_set_ps1(n[0]) * gx + _mm_set_ps1(n[1]) * gy + _mm_set_ps1(n[2]) * gz) * angle; - /* sum together */ - result = (fresult[0] + fresult[1] + fresult[2] + fresult[3]) * (0.5f / (float)M_PI); - result = MAX2(result, 0.0f); + /* sum together */ + result = (fresult[0] + fresult[1] + fresult[2] + fresult[3]) * (0.5f / (float)M_PI); + result = MAX2(result, 0.0f); - return result; + return result; } #endif static void ff_normalize(float n[3]) { - float d; + float d; - d = dot_v3v3(n, n); + d = dot_v3v3(n, n); - if (d > 1.0e-35f) { - d = 1.0f / sqrtf(d); + if (d > 1.0e-35f) { + d = 1.0f / sqrtf(d); - n[0] *= d; - n[1] *= d; - n[2] *= d; - } + n[0] *= d; + n[1] *= d; + n[2] *= d; + } } -float form_factor_quad(const float p[3], const float n[3], - const float q0[3], const float q1[3], const float q2[3], const float q3[3]) +float form_factor_quad(const float p[3], + const float n[3], + const float q0[3], + const float q1[3], + const float q2[3], + const float q3[3]) { - float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; - float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; + float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; + float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; - sub_v3_v3v3(r0, q0, p); - sub_v3_v3v3(r1, q1, p); - sub_v3_v3v3(r2, q2, p); - sub_v3_v3v3(r3, q3, p); + sub_v3_v3v3(r0, q0, p); + sub_v3_v3v3(r1, q1, p); + sub_v3_v3v3(r2, q2, p); + sub_v3_v3v3(r3, q3, p); - ff_normalize(r0); - ff_normalize(r1); - ff_normalize(r2); - ff_normalize(r3); + ff_normalize(r0); + ff_normalize(r1); + ff_normalize(r2); + ff_normalize(r3); - cross_v3_v3v3(g0, r1, r0); - ff_normalize(g0); - cross_v3_v3v3(g1, r2, r1); - ff_normalize(g1); - cross_v3_v3v3(g2, r3, r2); - ff_normalize(g2); - cross_v3_v3v3(g3, r0, r3); - ff_normalize(g3); + cross_v3_v3v3(g0, r1, r0); + ff_normalize(g0); + cross_v3_v3v3(g1, r2, r1); + ff_normalize(g1); + cross_v3_v3v3(g2, r3, r2); + ff_normalize(g2); + cross_v3_v3v3(g3, r0, r3); + ff_normalize(g3); - a1 = saacosf(dot_v3v3(r0, r1)); - a2 = saacosf(dot_v3v3(r1, r2)); - a3 = saacosf(dot_v3v3(r2, r3)); - a4 = saacosf(dot_v3v3(r3, r0)); + a1 = saacosf(dot_v3v3(r0, r1)); + a2 = saacosf(dot_v3v3(r1, r2)); + a3 = saacosf(dot_v3v3(r2, r3)); + a4 = saacosf(dot_v3v3(r3, r0)); - dot1 = dot_v3v3(n, g0); - dot2 = dot_v3v3(n, g1); - dot3 = dot_v3v3(n, g2); - dot4 = dot_v3v3(n, g3); + dot1 = dot_v3v3(n, g0); + dot2 = dot_v3v3(n, g1); + dot3 = dot_v3v3(n, g2); + dot4 = dot_v3v3(n, g3); - result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / (float)M_PI; - result = MAX2(result, 0.0f); + result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / (float)M_PI; + result = MAX2(result, 0.0f); - return result; + return result; } -float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], float v3[3], float v4[3]) +float form_factor_hemi_poly( + float p[3], float n[3], float v1[3], float v2[3], float v3[3], float v4[3]) { - /* computes how much hemisphere defined by point and normal is - * covered by a quad or triangle, cosine weighted */ - float q0[3], q1[3], q2[3], q3[3], contrib = 0.0f; + /* computes how much hemisphere defined by point and normal is + * covered by a quad or triangle, cosine weighted */ + float q0[3], q1[3], q2[3], q3[3], contrib = 0.0f; - if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) { - contrib += form_factor_quad(p, n, q0, q1, q2, q3); - } + if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) { + contrib += form_factor_quad(p, n, q0, q1, q2, q3); + } - if (v4 && form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) { - contrib += form_factor_quad(p, n, q0, q1, q2, q3); - } + if (v4 && form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) { + contrib += form_factor_quad(p, n, q0, q1, q2, q3); + } - return contrib; + return contrib; } /** @@ -5196,99 +5418,97 @@ float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], fl */ bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - /** - * Method projects points onto a plane and checks its convex using following method: - * - * - Create a plane from the cross-product of both diagonal vectors. - * - Project all points onto the plane. - * - Subtract for direction vectors. - * - Return true if all corners cross-products point the direction of the plane. - */ + /** + * Method projects points onto a plane and checks its convex using following method: + * + * - Create a plane from the cross-product of both diagonal vectors. + * - Project all points onto the plane. + * - Subtract for direction vectors. + * - Return true if all corners cross-products point the direction of the plane. + */ - /* non-unit length normal, used as a projection plane */ - float plane[3]; + /* non-unit length normal, used as a projection plane */ + float plane[3]; - { - float v13[3], v24[3]; + { + float v13[3], v24[3]; - sub_v3_v3v3(v13, v1, v3); - sub_v3_v3v3(v24, v2, v4); + sub_v3_v3v3(v13, v1, v3); + sub_v3_v3v3(v24, v2, v4); - cross_v3_v3v3(plane, v13, v24); + cross_v3_v3v3(plane, v13, v24); - if (len_squared_v3(plane) < FLT_EPSILON) { - return false; - } - } + if (len_squared_v3(plane) < FLT_EPSILON) { + return false; + } + } - const float *quad_coords[4] = {v1, v2, v3, v4}; - float quad_proj[4][3]; + const float *quad_coords[4] = {v1, v2, v3, v4}; + float quad_proj[4][3]; - for (int i = 0; i < 4; i++) { - project_plane_v3_v3v3(quad_proj[i], quad_coords[i], plane); - } + for (int i = 0; i < 4; i++) { + project_plane_v3_v3v3(quad_proj[i], quad_coords[i], plane); + } - float quad_dirs[4][3]; - for (int i = 0, j = 3; i < 4; j = i++) { - sub_v3_v3v3(quad_dirs[i], quad_proj[i], quad_proj[j]); - } + float quad_dirs[4][3]; + for (int i = 0, j = 3; i < 4; j = i++) { + sub_v3_v3v3(quad_dirs[i], quad_proj[i], quad_proj[j]); + } - float test_dir[3]; + float test_dir[3]; #define CROSS_SIGN(dir_a, dir_b) \ - ((void)cross_v3_v3v3(test_dir, dir_a, dir_b), (dot_v3v3(plane, test_dir) > 0.0f)) + ((void)cross_v3_v3v3(test_dir, dir_a, dir_b), (dot_v3v3(plane, test_dir) > 0.0f)) - return (CROSS_SIGN(quad_dirs[0], quad_dirs[1]) && - CROSS_SIGN(quad_dirs[1], quad_dirs[2]) && - CROSS_SIGN(quad_dirs[2], quad_dirs[3]) && - CROSS_SIGN(quad_dirs[3], quad_dirs[0])); + return (CROSS_SIGN(quad_dirs[0], quad_dirs[1]) && CROSS_SIGN(quad_dirs[1], quad_dirs[2]) && + CROSS_SIGN(quad_dirs[2], quad_dirs[3]) && CROSS_SIGN(quad_dirs[3], quad_dirs[0])); #undef CROSS_SIGN } bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) { - /* linetests, the 2 diagonals have to instersect to be convex */ - return (isect_seg_seg_v2(v1, v3, v2, v4) > 0); + /* linetests, the 2 diagonals have to instersect to be convex */ + return (isect_seg_seg_v2(v1, v3, v2, v4) > 0); } bool is_poly_convex_v2(const float verts[][2], unsigned int nr) { - unsigned int sign_flag = 0; - unsigned int a; - const float *co_curr, *co_prev; - float dir_curr[2], dir_prev[2]; + unsigned int sign_flag = 0; + unsigned int a; + const float *co_curr, *co_prev; + float dir_curr[2], dir_prev[2]; - co_prev = verts[nr - 1]; - co_curr = verts[0]; + co_prev = verts[nr - 1]; + co_curr = verts[0]; - sub_v2_v2v2(dir_prev, verts[nr - 2], co_prev); + sub_v2_v2v2(dir_prev, verts[nr - 2], co_prev); - for (a = 0; a < nr; a++) { - float cross; + for (a = 0; a < nr; a++) { + float cross; - sub_v2_v2v2(dir_curr, co_prev, co_curr); + sub_v2_v2v2(dir_curr, co_prev, co_curr); - cross = cross_v2v2(dir_prev, dir_curr); + cross = cross_v2v2(dir_prev, dir_curr); - if (cross < 0.0f) { - sign_flag |= 1; - } - else if (cross > 0.0f) { - sign_flag |= 2; - } + if (cross < 0.0f) { + sign_flag |= 1; + } + else if (cross > 0.0f) { + sign_flag |= 2; + } - if (sign_flag == (1 | 2)) { - return false; - } + if (sign_flag == (1 | 2)) { + return false; + } - copy_v2_v2(dir_prev, dir_curr); + copy_v2_v2(dir_prev, dir_curr); - co_prev = co_curr; - co_curr += 2; - } + co_prev = co_curr; + co_curr += 2; + } - return true; + return true; } /** @@ -5299,36 +5519,39 @@ bool is_poly_convex_v2(const float verts[][2], unsigned int nr) */ int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - float d_12[3], d_23[3], d_34[3], d_41[3]; - float cross_a[3], cross_b[3]; - int ret = 0; + float d_12[3], d_23[3], d_34[3], d_41[3]; + float cross_a[3], cross_b[3]; + int ret = 0; - sub_v3_v3v3(d_12, v1, v2); - sub_v3_v3v3(d_23, v2, v3); - sub_v3_v3v3(d_34, v3, v4); - sub_v3_v3v3(d_41, v4, v1); + sub_v3_v3v3(d_12, v1, v2); + sub_v3_v3v3(d_23, v2, v3); + sub_v3_v3v3(d_34, v3, v4); + sub_v3_v3v3(d_41, v4, v1); - cross_v3_v3v3(cross_a, d_12, d_23); - cross_v3_v3v3(cross_b, d_34, d_41); - ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 0); + cross_v3_v3v3(cross_a, d_12, d_23); + cross_v3_v3v3(cross_b, d_34, d_41); + ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 0); - cross_v3_v3v3(cross_a, d_23, d_34); - cross_v3_v3v3(cross_b, d_41, d_12); - ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 1); + cross_v3_v3v3(cross_a, d_23, d_34); + cross_v3_v3v3(cross_b, d_41, d_12); + ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 1); - return ret; + return ret; } -bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +bool is_quad_flip_v3_first_third_fast(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3]) { - float d_12[3], d_13[3], d_14[3]; - float cross_a[3], cross_b[3]; - sub_v3_v3v3(d_12, v2, v1); - sub_v3_v3v3(d_13, v3, v1); - sub_v3_v3v3(d_14, v4, v1); - cross_v3_v3v3(cross_a, d_12, d_13); - cross_v3_v3v3(cross_b, d_14, d_13); - return dot_v3v3(cross_a, cross_b) > 0.0f; + float d_12[3], d_13[3], d_14[3]; + float cross_a[3], cross_b[3]; + sub_v3_v3v3(d_12, v2, v1); + sub_v3_v3v3(d_13, v3, v1); + sub_v3_v3v3(d_14, v4, v1); + cross_v3_v3v3(cross_a, d_12, d_13); + cross_v3_v3v3(cross_b, d_14, d_13); + return dot_v3v3(cross_a, cross_b) > 0.0f; } /** @@ -5341,28 +5564,28 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], cons */ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]) { - BLI_ASSERT_UNIT_V3(tan_l); - BLI_ASSERT_UNIT_V3(tan_r); - - /* -7f causes instability/glitches with Bendy Bones + Custom Refs */ - const float eps = 1e-5f; - - const float tan_dot = dot_v3v3(tan_l, tan_r); - if (tan_dot > 1.0f - eps) { - /* no angle difference (use fallback, length wont make any difference) */ - return (1.0f / 3.0f) * 0.75f; - } - else if (tan_dot < -1.0f + eps) { - /* parallele tangents (half-circle) */ - return (1.0f / 2.0f); - } - else { - /* non-aligned tangents, calculate handle length */ - const float angle = acosf(tan_dot) / 2.0f; - - /* could also use 'angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0' */ - const float angle_sin = sinf(angle); - const float angle_cos = cosf(angle); - return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin; - } + BLI_ASSERT_UNIT_V3(tan_l); + BLI_ASSERT_UNIT_V3(tan_r); + + /* -7f causes instability/glitches with Bendy Bones + Custom Refs */ + const float eps = 1e-5f; + + const float tan_dot = dot_v3v3(tan_l, tan_r); + if (tan_dot > 1.0f - eps) { + /* no angle difference (use fallback, length wont make any difference) */ + return (1.0f / 3.0f) * 0.75f; + } + else if (tan_dot < -1.0f + eps) { + /* parallele tangents (half-circle) */ + return (1.0f / 2.0f); + } + else { + /* non-aligned tangents, calculate handle length */ + const float angle = acosf(tan_dot) / 2.0f; + + /* could also use 'angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0' */ + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin; + } } diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 0922c47f553..d275ea0862e 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -32,202 +32,215 @@ #include <string.h> /* A few small defines. Keep'em local! */ -#define SMALL_NUMBER 1.e-8f +#define SMALL_NUMBER 1.e-8f /********************************** Polygons *********************************/ MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]) { - return (v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]); + return (v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]); } MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]) { - return 0.5f * ((v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0])); + return 0.5f * ((v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0])); } MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2]) { - return fabsf(area_tri_signed_v2(v1, v2, v3)); + return fabsf(area_tri_signed_v2(v1, v2, v3)); } MINLINE float area_squared_tri_v2(const float v1[2], const float v2[2], const float v3[2]) { - float area = area_tri_signed_v2(v1, v2, v3); - return area * area; + float area = area_tri_signed_v2(v1, v2, v3); + return area * area; } /****************************** Spherical Harmonics **************************/ MINLINE void zero_sh(float r[9]) { - memset(r, 0, sizeof(float) * 9); + memset(r, 0, sizeof(float) * 9); } MINLINE void copy_sh_sh(float r[9], const float a[9]) { - memcpy(r, a, sizeof(float) * 9); + memcpy(r, a, sizeof(float) * 9); } MINLINE void mul_sh_fl(float r[9], const float f) { - int i; + int i; - for (i = 0; i < 9; i++) { - r[i] *= f; - } + for (i = 0; i < 9; i++) { + r[i] *= f; + } } MINLINE void add_sh_shsh(float r[9], const float a[9], const float b[9]) { - int i; + int i; - for (i = 0; i < 9; i++) { - r[i] = a[i] + b[i]; - } + for (i = 0; i < 9; i++) { + r[i] = a[i] + b[i]; + } } MINLINE float dot_shsh(const float a[9], const float b[9]) { - float r = 0.0f; - int i; + float r = 0.0f; + int i; - for (i = 0; i < 9; i++) { - r += a[i] * b[i]; - } + for (i = 0; i < 9; i++) { + r += a[i] * b[i]; + } - return r; + return r; } MINLINE float diffuse_shv3(float sh[9], const float v[3]) { - /* See formula (13) in: - * "An Efficient Representation for Irradiance Environment Maps" */ - static const float c1 = 0.429043f, c2 = 0.511664f, c3 = 0.743125f; - static const float c4 = 0.886227f, c5 = 0.247708f; - float x, y, z, sum; - - x = v[0]; - y = v[1]; - z = v[2]; - - sum = c1 * sh[8] * (x * x - y * y); - sum += c3 * sh[6] * z * z; - sum += c4 * sh[0]; - sum += -c5 * sh[6]; - sum += 2.0f * c1 * (sh[4] * x * y + sh[7] * x * z + sh[5] * y * z); - sum += 2.0f * c2 * (sh[3] * x + sh[1] * y + sh[2] * z); - - return sum; + /* See formula (13) in: + * "An Efficient Representation for Irradiance Environment Maps" */ + static const float c1 = 0.429043f, c2 = 0.511664f, c3 = 0.743125f; + static const float c4 = 0.886227f, c5 = 0.247708f; + float x, y, z, sum; + + x = v[0]; + y = v[1]; + z = v[2]; + + sum = c1 * sh[8] * (x * x - y * y); + sum += c3 * sh[6] * z * z; + sum += c4 * sh[0]; + sum += -c5 * sh[6]; + sum += 2.0f * c1 * (sh[4] * x * y + sh[7] * x * z + sh[5] * y * z); + sum += 2.0f * c2 * (sh[3] * x + sh[1] * y + sh[2] * z); + + return sum; } MINLINE void vec_fac_to_sh(float r[9], const float v[3], const float f) { - /* See formula (3) in: - * "An Efficient Representation for Irradiance Environment Maps" */ - float sh[9], x, y, z; + /* See formula (3) in: + * "An Efficient Representation for Irradiance Environment Maps" */ + float sh[9], x, y, z; - x = v[0]; - y = v[1]; - z = v[2]; + x = v[0]; + y = v[1]; + z = v[2]; - sh[0] = 0.282095f; + sh[0] = 0.282095f; - sh[1] = 0.488603f * y; - sh[2] = 0.488603f * z; - sh[3] = 0.488603f * x; + sh[1] = 0.488603f * y; + sh[2] = 0.488603f * z; + sh[3] = 0.488603f * x; - sh[4] = 1.092548f * x * y; - sh[5] = 1.092548f * y * z; - sh[6] = 0.315392f * (3.0f * z * z - 1.0f); - sh[7] = 1.092548f * x * z; - sh[8] = 0.546274f * (x * x - y * y); + sh[4] = 1.092548f * x * y; + sh[5] = 1.092548f * y * z; + sh[6] = 0.315392f * (3.0f * z * z - 1.0f); + sh[7] = 1.092548f * x * z; + sh[8] = 0.546274f * (x * x - y * y); - mul_sh_fl(sh, f); - copy_sh_sh(r, sh); + mul_sh_fl(sh, f); + copy_sh_sh(r, sh); } MINLINE float eval_shv3(float sh[9], const float v[3]) { - float tmp[9]; + float tmp[9]; - vec_fac_to_sh(tmp, v, 1.0f); - return dot_shsh(tmp, sh); + vec_fac_to_sh(tmp, v, 1.0f); + return dot_shsh(tmp, sh); } MINLINE void madd_sh_shfl(float r[9], const float sh[9], const float f) { - float tmp[9]; + float tmp[9]; - copy_sh_sh(tmp, sh); - mul_sh_fl(tmp, f); - add_sh_shsh(r, r, tmp); + copy_sh_sh(tmp, sh); + mul_sh_fl(tmp, f); + add_sh_shsh(r, r, tmp); } /* get the 2 dominant axis values, 0==X, 1==Y, 2==Z */ MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]) { - const float xn = fabsf(axis[0]); - const float yn = fabsf(axis[1]); - const float zn = fabsf(axis[2]); - - if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; } - else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; } - else { *r_axis_a = 1; *r_axis_b = 2; } + const float xn = fabsf(axis[0]); + const float yn = fabsf(axis[1]); + const float zn = fabsf(axis[2]); + + if (zn >= xn && zn >= yn) { + *r_axis_a = 0; + *r_axis_b = 1; + } + else if (yn >= xn && yn >= zn) { + *r_axis_a = 0; + *r_axis_b = 2; + } + else { + *r_axis_a = 1; + *r_axis_b = 2; + } } /* same as axis_dominant_v3 but return the max value */ MINLINE float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) { - const float xn = fabsf(axis[0]); - const float yn = fabsf(axis[1]); - const float zn = fabsf(axis[2]); - - if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; return zn; } - else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; return yn; } - else { *r_axis_a = 1; *r_axis_b = 2; return xn; } + const float xn = fabsf(axis[0]); + const float yn = fabsf(axis[1]); + const float zn = fabsf(axis[2]); + + if (zn >= xn && zn >= yn) { + *r_axis_a = 0; + *r_axis_b = 1; + return zn; + } + else if (yn >= xn && yn >= zn) { + *r_axis_a = 0; + *r_axis_b = 2; + return yn; + } + else { + *r_axis_a = 1; + *r_axis_b = 2; + return xn; + } } /* get the single dominant axis value, 0==X, 1==Y, 2==Z */ MINLINE int axis_dominant_v3_single(const float vec[3]) { - const float x = fabsf(vec[0]); - const float y = fabsf(vec[1]); - const float z = fabsf(vec[2]); - return ((x > y) ? - ((x > z) ? 0 : 2) : - ((y > z) ? 1 : 2)); + const float x = fabsf(vec[0]); + const float y = fabsf(vec[1]); + const float z = fabsf(vec[2]); + return ((x > y) ? ((x > z) ? 0 : 2) : ((y > z) ? 1 : 2)); } /* the dominant axis of an orthogonal vector */ MINLINE int axis_dominant_v3_ortho_single(const float vec[3]) { - const float x = fabsf(vec[0]); - const float y = fabsf(vec[1]); - const float z = fabsf(vec[2]); - return ((x < y) ? - ((x < z) ? 0 : 2) : - ((y < z) ? 1 : 2)); + const float x = fabsf(vec[0]); + const float y = fabsf(vec[1]); + const float z = fabsf(vec[2]); + return ((x < y) ? ((x < z) ? 0 : 2) : ((y < z) ? 1 : 2)); } MINLINE int max_axis_v3(const float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; - const float z = vec[2]; - return ((x > y) ? - ((x > z) ? 0 : 2) : - ((y > z) ? 1 : 2)); + const float x = vec[0]; + const float y = vec[1]; + const float z = vec[2]; + return ((x > y) ? ((x > z) ? 0 : 2) : ((y > z) ? 1 : 2)); } MINLINE int min_axis_v3(const float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; - const float z = vec[2]; - return ((x < y) ? - ((x < z) ? 0 : 2) : - ((y < z) ? 1 : 2)); + const float x = vec[0]; + const float y = vec[1]; + const float z = vec[2]; + return ((x < y) ? ((x < z) ? 0 : 2) : ((y < z) ? 1 : 2)); } /** @@ -238,13 +251,13 @@ MINLINE int min_axis_v3(const float vec[3]) */ MINLINE int poly_to_tri_count(const int poly_count, const int corner_count) { - BLI_assert(!poly_count || corner_count > poly_count * 2); - return corner_count - (poly_count * 2); + BLI_assert(!poly_count || corner_count > poly_count * 2); + return corner_count - (poly_count * 2); } MINLINE float plane_point_side_v3(const float plane[4], const float co[3]) { - return dot_v3v3(co, plane) + plane[3]; + return dot_v3v3(co, plane) + plane[3]; } /* useful to calculate an even width shell, by taking the angle between 2 planes. @@ -253,27 +266,27 @@ MINLINE float plane_point_side_v3(const float plane[4], const float co[3]) * the distance gets very high, 180d would be inf, but this case isn't valid */ MINLINE float shell_angle_to_dist(const float angle) { - return (UNLIKELY(angle < SMALL_NUMBER)) ? 1.0f : fabsf(1.0f / cosf(angle)); + return (UNLIKELY(angle < SMALL_NUMBER)) ? 1.0f : fabsf(1.0f / cosf(angle)); } /** * equivalent to ``shell_angle_to_dist(angle_normalized_v3v3(a, b))`` */ MINLINE float shell_v3v3_normalized_to_dist(const float a[3], const float b[3]) { - const float angle_cos = fabsf(dot_v3v3(a, b)); - BLI_ASSERT_UNIT_V3(a); - BLI_ASSERT_UNIT_V3(b); - return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); + const float angle_cos = fabsf(dot_v3v3(a, b)); + BLI_ASSERT_UNIT_V3(a); + BLI_ASSERT_UNIT_V3(b); + return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); } /** * equivalent to ``shell_angle_to_dist(angle_normalized_v2v2(a, b))`` */ MINLINE float shell_v2v2_normalized_to_dist(const float a[2], const float b[2]) { - const float angle_cos = fabsf(dot_v2v2(a, b)); - BLI_ASSERT_UNIT_V2(a); - BLI_ASSERT_UNIT_V2(b); - return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); + const float angle_cos = fabsf(dot_v2v2(a, b)); + BLI_ASSERT_UNIT_V2(a); + BLI_ASSERT_UNIT_V2(b); + return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); } /** @@ -281,13 +294,13 @@ MINLINE float shell_v2v2_normalized_to_dist(const float a[2], const float b[2]) */ MINLINE float shell_v3v3_mid_normalized_to_dist(const float a[3], const float b[3]) { - float angle_cos; - float ab[3]; - BLI_ASSERT_UNIT_V3(a); - BLI_ASSERT_UNIT_V3(b); - add_v3_v3v3(ab, a, b); - angle_cos = (normalize_v3(ab) != 0.0f) ? fabsf(dot_v3v3(a, ab)) : 0.0f; - return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); + float angle_cos; + float ab[3]; + BLI_ASSERT_UNIT_V3(a); + BLI_ASSERT_UNIT_V3(b); + add_v3_v3v3(ab, a, b); + angle_cos = (normalize_v3(ab) != 0.0f) ? fabsf(dot_v3v3(a, ab)) : 0.0f; + return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); } /** @@ -295,13 +308,13 @@ MINLINE float shell_v3v3_mid_normalized_to_dist(const float a[3], const float b[ */ MINLINE float shell_v2v2_mid_normalized_to_dist(const float a[2], const float b[2]) { - float angle_cos; - float ab[2]; - BLI_ASSERT_UNIT_V2(a); - BLI_ASSERT_UNIT_V2(b); - add_v2_v2v2(ab, a, b); - angle_cos = (normalize_v2(ab) != 0.0f) ? fabsf(dot_v2v2(a, ab)) : 0.0f; - return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); + float angle_cos; + float ab[2]; + BLI_ASSERT_UNIT_V2(a); + BLI_ASSERT_UNIT_V2(b); + add_v2_v2v2(ab, a, b); + angle_cos = (normalize_v2(ab) != 0.0f) ? fabsf(dot_v2v2(a, ab)) : 0.0f; + return (UNLIKELY(angle_cos < SMALL_NUMBER)) ? 1.0f : (1.0f / angle_cos); } #undef SMALL_NUMBER diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index ed2b48f6e62..6acfb538036 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -40,418 +40,473 @@ static float P(float k) { - float p1, p2, p3, p4; - p1 = max_ff(k + 2.0f, 0.0f); - p2 = max_ff(k + 1.0f, 0.0f); - p3 = max_ff(k, 0.0f); - p4 = max_ff(k - 1.0f, 0.0f); - return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); + float p1, p2, p3, p4; + p1 = max_ff(k + 2.0f, 0.0f); + p2 = max_ff(k + 1.0f, 0.0f); + p3 = max_ff(k, 0.0f); + p4 = max_ff(k - 1.0f, 0.0f); + return (float)(1.0f / 6.0f) * + (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); } - #if 0 /* older, slower function, works the same as above */ static float P(float k) { - return (float)(1.0f / 6.0f) * - (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * - pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * - pow(MAX2(k, 0), 3.0f) - 4.0f * - pow(MAX2(k - 1.0f, 0), 3.0f)); + return (float)(1.0f / 6.0f) * + (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * + pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * + pow(MAX2(k, 0), 3.0f) - 4.0f * + pow(MAX2(k - 1.0f, 0), 3.0f)); } #endif static void vector_from_float(const float *data, float vector[4], int components) { - if (components == 1) { - vector[0] = data[0]; - } - else if (components == 3) { - copy_v3_v3(vector, data); - } - else { - copy_v4_v4(vector, data); - } + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + copy_v3_v3(vector, data); + } + else { + copy_v4_v4(vector, data); + } } static void vector_from_byte(const unsigned char *data, float vector[4], int components) { - if (components == 1) { - vector[0] = data[0]; - } - else if (components == 3) { - vector[0] = data[0]; - vector[1] = data[1]; - vector[2] = data[2]; - } - else { - vector[0] = data[0]; - vector[1] = data[1]; - vector[2] = data[2]; - vector[3] = data[3]; - } + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + } + else { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + vector[3] = data[3]; + } } /* BICUBIC INTERPOLATION */ -BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, - unsigned char *byte_output, float *float_output, int width, int height, - int components, float u, float v) +BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, + const float *float_buffer, + unsigned char *byte_output, + float *float_output, + int width, + int height, + int components, + float u, + float v) { - int i, j, n, m, x1, y1; - float a, b, w, wx, wy[4], out[4]; - - /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { - if (float_output) { - copy_vn_fl(float_output, components, 0.0f); - } - if (byte_output) { - copy_vn_uchar(byte_output, components, 0); - } - return; - } - - i = (int)floor(u); - j = (int)floor(v); - a = u - (float)i; - b = v - (float)j; - - zero_v4(out); - -/* Optimized and not so easy to read */ - - /* avoid calling multiple times */ - wy[0] = P(b - (-1)); - wy[1] = P(b - 0); - wy[2] = P(b - 1); - wy[3] = P(b - 2); - - for (n = -1; n <= 2; n++) { - x1 = i + n; - CLAMP(x1, 0, width - 1); - wx = P((float)n - a); - for (m = -1; m <= 2; m++) { - float data[4]; - - y1 = j + m; - CLAMP(y1, 0, height - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, - * better precalc these */ - w = wx * wy[m + 1]; - - if (float_output) { - const float *float_data = float_buffer + width * y1 * components + components * x1; - - vector_from_float(float_data, data, components); - } - else { - const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; - - vector_from_byte(byte_data, data, components); - } - - if (components == 1) { - out[0] += data[0] * w; - } - else if (components == 3) { - out[0] += data[0] * w; - out[1] += data[1] * w; - out[2] += data[2] * w; - } - else { - out[0] += data[0] * w; - out[1] += data[1] * w; - out[2] += data[2] * w; - out[3] += data[3] * w; - } - } - } - -/* Done with optimized part */ + int i, j, n, m, x1, y1; + float a, b, w, wx, wy[4], out[4]; + + /* sample area entirely outside image? */ + if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { + if (float_output) { + copy_vn_fl(float_output, components, 0.0f); + } + if (byte_output) { + copy_vn_uchar(byte_output, components, 0); + } + return; + } + + i = (int)floor(u); + j = (int)floor(v); + a = u - (float)i; + b = v - (float)j; + + zero_v4(out); + + /* Optimized and not so easy to read */ + + /* avoid calling multiple times */ + wy[0] = P(b - (-1)); + wy[1] = P(b - 0); + wy[2] = P(b - 1); + wy[3] = P(b - 2); + + for (n = -1; n <= 2; n++) { + x1 = i + n; + CLAMP(x1, 0, width - 1); + wx = P((float)n - a); + for (m = -1; m <= 2; m++) { + float data[4]; + + y1 = j + m; + CLAMP(y1, 0, height - 1); + /* normally we could do this */ + /* w = P(n-a) * P(b-m); */ + /* except that would call P() 16 times per pixel therefor pow() 64 times, + * better precalc these */ + w = wx * wy[m + 1]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * w; + } + else if (components == 3) { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + } + else { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + out[3] += data[3] * w; + } + } + } + + /* Done with optimized part */ #if 0 - /* older, slower function, works the same as above */ - for (n = -1; n <= 2; n++) { - for (m = -1; m <= 2; m++) { - x1 = i + n; - y1 = j + m; - if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { - float data[4]; - - if (float_output) { - const float *float_data = float_buffer + width * y1 * components + components * x1; - - vector_from_float(float_data, data, components); - } - else { - const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; - - vector_from_byte(byte_data, data, components); - } - - if (components == 1) { - out[0] += data[0] * P(n - a) * P(b - m); - } - else if (components == 3) { - out[0] += data[0] * P(n - a) * P(b - m); - out[1] += data[1] * P(n - a) * P(b - m); - out[2] += data[2] * P(n - a) * P(b - m); - } - else { - out[0] += data[0] * P(n - a) * P(b - m); - out[1] += data[1] * P(n - a) * P(b - m); - out[2] += data[2] * P(n - a) * P(b - m); - out[3] += data[3] * P(n - a) * P(b - m); - } - } - } - } + /* older, slower function, works the same as above */ + for (n = -1; n <= 2; n++) { + for (m = -1; m <= 2; m++) { + x1 = i + n; + y1 = j + m; + if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { + float data[4]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * P(n - a) * P(b - m); + } + else if (components == 3) { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + } + else { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + out[3] += data[3] * P(n - a) * P(b - m); + } + } + } + } #endif - if (float_output) { - if (components == 1) { - float_output[0] = out[0]; - } - else if (components == 3) { - copy_v3_v3(float_output, out); - } - else { - copy_v4_v4(float_output, out); - } - } - else { - if (components == 1) { - byte_output[0] = (unsigned char)(out[0] + 0.5f); - } - else if (components == 3) { - byte_output[0] = (unsigned char)(out[0] + 0.5f); - byte_output[1] = (unsigned char)(out[1] + 0.5f); - byte_output[2] = (unsigned char)(out[2] + 0.5f); - } - else { - byte_output[0] = (unsigned char)(out[0] + 0.5f); - byte_output[1] = (unsigned char)(out[1] + 0.5f); - byte_output[2] = (unsigned char)(out[2] + 0.5f); - byte_output[3] = (unsigned char)(out[3] + 0.5f); - } - } + if (float_output) { + if (components == 1) { + float_output[0] = out[0]; + } + else if (components == 3) { + copy_v3_v3(float_output, out); + } + else { + copy_v4_v4(float_output, out); + } + } + else { + if (components == 1) { + byte_output[0] = (unsigned char)(out[0] + 0.5f); + } + else if (components == 3) { + byte_output[0] = (unsigned char)(out[0] + 0.5f); + byte_output[1] = (unsigned char)(out[1] + 0.5f); + byte_output[2] = (unsigned char)(out[2] + 0.5f); + } + else { + byte_output[0] = (unsigned char)(out[0] + 0.5f); + byte_output[1] = (unsigned char)(out[1] + 0.5f); + byte_output[2] = (unsigned char)(out[2] + 0.5f); + byte_output[3] = (unsigned char)(out[3] + 0.5f); + } + } } -void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, - int components, float u, float v) +void BLI_bicubic_interpolation_fl( + const float *buffer, float *output, int width, int height, int components, float u, float v) { - bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); + bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); } -void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, - int components, float u, float v) +void BLI_bicubic_interpolation_char(const unsigned char *buffer, + unsigned char *output, + int width, + int height, + int components, + float u, + float v) { - bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); + bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); } /* BILINEAR INTERPOLATION */ -BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, - unsigned char *byte_output, float *float_output, int width, int height, - int components, float u, float v, bool wrap_x, bool wrap_y) +BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, + const float *float_buffer, + unsigned char *byte_output, + float *float_output, + int width, + int height, + int components, + float u, + float v, + bool wrap_x, + bool wrap_y) { - float a, b; - float a_b, ma_b, a_mb, ma_mb; - int y1, y2, x1, x2; - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - if (float_output) { - const float *row1, *row2, *row3, *row4; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - /* pixel value must be already wrapped, however values at boundaries may flip */ - if (wrap_x) { - if (x1 < 0) { - x1 = width - 1; - } - if (x2 >= width) { - x2 = 0; - } - } - else if (x2 < 0 || x1 >= width) { - copy_vn_fl(float_output, components, 0.0f); - return; - } - - if (wrap_y) { - if (y1 < 0) { - y1 = height - 1; - } - if (y2 >= height) { - y2 = 0; - } - } - else if (y2 < 0 || y1 >= height) { - copy_vn_fl(float_output, components, 0.0f); - return; - } - - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) { - row1 = empty; - } - else { - row1 = float_buffer + width * y1 * components + components * x1; - } - - if (x1 < 0 || y2 > height - 1) { - row2 = empty; - } - else { - row2 = float_buffer + width * y2 * components + components * x1; - } - - if (x2 > width - 1 || y1 < 0) { - row3 = empty; - } - else { - row3 = float_buffer + width * y1 * components + components * x2; - } - - if (x2 > width - 1 || y2 > height - 1) { - row4 = empty; - } - else { - row4 = float_buffer + width * y2 * components + components * x2; - } - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - if (components == 1) { - float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - } - else if (components == 3) { - float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - } - else { - float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; - } - } - else { - const unsigned char *row1, *row2, *row3, *row4; - unsigned char empty[4] = {0, 0, 0, 0}; - - /* pixel value must be already wrapped, however values at boundaries may flip */ - if (wrap_x) { - if (x1 < 0) { - x1 = width - 1; - } - if (x2 >= width) { - x2 = 0; - } - } - else if (x2 < 0 || x1 >= width) { - copy_vn_uchar(byte_output, components, 0); - return; - } - - if (wrap_y) { - if (y1 < 0) { - y1 = height - 1; - } - if (y2 >= height) { - y2 = 0; - } - } - else if (y2 < 0 || y1 >= height) { - copy_vn_uchar(byte_output, components, 0); - return; - } - - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) { - row1 = empty; - } - else { - row1 = byte_buffer + width * y1 * components + components * x1; - } - - if (x1 < 0 || y2 > height - 1) { - row2 = empty; - } - else { - row2 = byte_buffer + width * y2 * components + components * x1; - } - - if (x2 > width - 1 || y1 < 0) { - row3 = empty; - } - else { - row3 = byte_buffer + width * y1 * components + components * x2; - } - - if (x2 > width - 1 || y2 > height - 1) { - row4 = empty; - } - else { - row4 = byte_buffer + width * y2 * components + components * x2; - } - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - if (components == 1) { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f); - } - else if (components == 3) { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f); - byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f); - byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f); - } - else { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f); - byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f); - byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f); - byte_output[3] = (unsigned char)(ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3] + 0.5f); - } - } + float a, b; + float a_b, ma_b, a_mb, ma_mb; + int y1, y2, x1, x2; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)floor(u); + x2 = (int)ceil(u); + y1 = (int)floor(v); + y2 = (int)ceil(v); + + if (float_output) { + const float *row1, *row2, *row3, *row4; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* pixel value must be already wrapped, however values at boundaries may flip */ + if (wrap_x) { + if (x1 < 0) { + x1 = width - 1; + } + if (x2 >= width) { + x2 = 0; + } + } + else if (x2 < 0 || x1 >= width) { + copy_vn_fl(float_output, components, 0.0f); + return; + } + + if (wrap_y) { + if (y1 < 0) { + y1 = height - 1; + } + if (y2 >= height) { + y2 = 0; + } + } + else if (y2 < 0 || y1 >= height) { + copy_vn_fl(float_output, components, 0.0f); + return; + } + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) { + row1 = empty; + } + else { + row1 = float_buffer + width * y1 * components + components * x1; + } + + if (x1 < 0 || y2 > height - 1) { + row2 = empty; + } + else { + row2 = float_buffer + width * y2 * components + components * x1; + } + + if (x2 > width - 1 || y1 < 0) { + row3 = empty; + } + else { + row3 = float_buffer + width * y1 * components + components * x2; + } + + if (x2 > width - 1 || y2 > height - 1) { + row4 = empty; + } + else { + row4 = float_buffer + width * y2 * components + components * x2; + } + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; + ma_b = (1.0f - a) * b; + a_mb = a * (1.0f - b); + ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } + } + else { + const unsigned char *row1, *row2, *row3, *row4; + unsigned char empty[4] = {0, 0, 0, 0}; + + /* pixel value must be already wrapped, however values at boundaries may flip */ + if (wrap_x) { + if (x1 < 0) { + x1 = width - 1; + } + if (x2 >= width) { + x2 = 0; + } + } + else if (x2 < 0 || x1 >= width) { + copy_vn_uchar(byte_output, components, 0); + return; + } + + if (wrap_y) { + if (y1 < 0) { + y1 = height - 1; + } + if (y2 >= height) { + y2 = 0; + } + } + else if (y2 < 0 || y1 >= height) { + copy_vn_uchar(byte_output, components, 0); + return; + } + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) { + row1 = empty; + } + else { + row1 = byte_buffer + width * y1 * components + components * x1; + } + + if (x1 < 0 || y2 > height - 1) { + row2 = empty; + } + else { + row2 = byte_buffer + width * y2 * components + components * x1; + } + + if (x2 > width - 1 || y1 < 0) { + row3 = empty; + } + else { + row3 = byte_buffer + width * y1 * components + components * x2; + } + + if (x2 > width - 1 || y2 > height - 1) { + row4 = empty; + } + else { + row4 = byte_buffer + width * y2 * components + components * x2; + } + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; + ma_b = (1.0f - a) * b; + a_mb = a * (1.0f - b); + ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + + a_b * row4[0] + 0.5f); + } + else if (components == 3) { + byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + + a_b * row4[0] + 0.5f); + byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + + a_b * row4[1] + 0.5f); + byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + + a_b * row4[2] + 0.5f); + } + else { + byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + + a_b * row4[0] + 0.5f); + byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + + a_b * row4[1] + 0.5f); + byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + + a_b * row4[2] + 0.5f); + byte_output[3] = (unsigned char)(ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + + a_b * row4[3] + 0.5f); + } + } } -void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, - int components, float u, float v) +void BLI_bilinear_interpolation_fl( + const float *buffer, float *output, int width, int height, int components, float u, float v) { - bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v, false, false); + bilinear_interpolation( + NULL, buffer, NULL, output, width, height, components, u, v, false, false); } -void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, - int components, float u, float v) +void BLI_bilinear_interpolation_char(const unsigned char *buffer, + unsigned char *output, + int width, + int height, + int components, + float u, + float v) { - bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v, false, false); + bilinear_interpolation( + buffer, NULL, output, NULL, width, height, components, u, v, false, false); } -void BLI_bilinear_interpolation_wrap_fl(const float *buffer, float *output, int width, int height, - int components, float u, float v, bool wrap_x, bool wrap_y) +void BLI_bilinear_interpolation_wrap_fl(const float *buffer, + float *output, + int width, + int height, + int components, + float u, + float v, + bool wrap_x, + bool wrap_y) { - bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v, wrap_x, wrap_y); + bilinear_interpolation( + NULL, buffer, NULL, output, width, height, components, u, v, wrap_x, wrap_y); } -void BLI_bilinear_interpolation_wrap_char(const unsigned char *buffer, unsigned char *output, int width, int height, - int components, float u, float v, bool wrap_x, bool wrap_y) +void BLI_bilinear_interpolation_wrap_char(const unsigned char *buffer, + unsigned char *output, + int width, + int height, + int components, + float u, + float v, + bool wrap_x, + bool wrap_y) { - bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v, wrap_x, wrap_y); + bilinear_interpolation( + buffer, NULL, output, NULL, width, height, components, u, v, wrap_x, wrap_y); } - /************************************************************************** * Filtering method based on * "Creating raster omnimax images from multiple perspective views @@ -463,80 +518,87 @@ void BLI_bilinear_interpolation_wrap_char(const unsigned char *buffer, unsigned * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */ #define EWA_MAXIDX 255 const float EWA_WTS[EWA_MAXIDX + 1] = { - 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, - 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, - 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, - 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, - 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, - 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, - 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, - 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, - 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, - 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, - 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, - 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, - 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, - 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, - 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, - 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, - 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, - 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, - 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, - 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, - 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, - 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, - 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, - 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, - 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, - 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, - 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, - 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, - 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, - 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, - 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, - 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f, + 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, + 0.938216f, 0.929664f, 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, + 0.879734f, 0.871638f, 0.863605f, 0.855636f, 0.847728f, 0.839883f, 0.832098f, + 0.824375f, 0.816712f, 0.809108f, 0.801564f, 0.794079f, 0.786653f, 0.779284f, + 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, 0.736267f, 0.729292f, + 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, 0.68197f, + 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, + 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, + 0.588906f, 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, + 0.549084f, 0.543572f, 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, + 0.511389f, 0.506171f, 0.500994f, 0.495857f, 0.490761f, 0.485704f, 0.480687f, + 0.475709f, 0.470769f, 0.465869f, 0.461006f, 0.456182f, 0.451395f, 0.446646f, + 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, 0.418919f, 0.414424f, + 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, 0.383923f, + 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, + 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, + 0.323939f, 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, + 0.298272f, 0.294719f, 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, + 0.273976f, 0.270613f, 0.267276f, 0.263965f, 0.26068f, 0.257421f, 0.254187f, + 0.250979f, 0.247795f, 0.244636f, 0.241502f, 0.238393f, 0.235308f, 0.232246f, + 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, 0.214375f, 0.211478f, + 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, 0.191819f, + 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, + 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, + 0.153157f, 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, + 0.136613f, 0.134323f, 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, + 0.120954f, 0.118786f, 0.116635f, 0.114501f, 0.112384f, 0.110283f, 0.108199f, + 0.106131f, 0.104079f, 0.102043f, 0.100023f, 0.0980186f, 0.09603f, 0.094057f, + 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, 0.0825384f, 0.0806708f, + 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, 0.0679997f, + 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, + 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, + 0.0430805f, 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, + 0.0324175f, 0.0309415f, 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, + 0.0223242f, 0.020927f, 0.0195408f, 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, + 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, 0.00754159f, 0.00625989f, 0.00498819f, + 0.00372644f, 0.00247454f, 0.00123242f, 0.f, }; static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F) { - float ct2 = cosf(th); - const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */ - ct2 *= ct2; - *A = a2 * st2 + b2 * ct2; - *B = (b2 - a2) * sinf(2.0f * th); - *C = a2 * ct2 + b2 * st2; - *F = a2 * b2; + float ct2 = cosf(th); + const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */ + ct2 *= ct2; + *A = a2 * st2 + b2 * ct2; + *B = (b2 - a2) * sinf(2.0f * th); + *C = a2 * ct2 + b2 * st2; + *F = a2 * b2; } /* all tests here are done to make sure possible overflows are hopefully minimized */ -void BLI_ewa_imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc) +void BLI_ewa_imp2radangle( + float A, float B, float C, float F, float *a, float *b, float *th, float *ecc) { - if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */ - *a = sqrtf(A > C ? A : C); - *b = 0.0f; - *ecc = 1e10f; - *th = 0.5f * (atan2f(B, A - C) + (float)M_PI); - } - else { - const float AmC = A - C, ApC = A + C, F2 = F * 2.0f; - const float r = sqrtf(AmC * AmC + B * B); - float d = ApC - r; - *a = (d <= 0.0f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d); - d = ApC + r; - if (d <= 0.0f) { - *b = 0.0f; - *ecc = 1e10f; - } - else { - *b = sqrtf(F2 / d); - *ecc = *a / *b; - } - /* incr theta by 0.5*pi (angle of major axis) */ - *th = 0.5f * (atan2f(B, AmC) + (float)M_PI); - } + if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */ + *a = sqrtf(A > C ? A : C); + *b = 0.0f; + *ecc = 1e10f; + *th = 0.5f * (atan2f(B, A - C) + (float)M_PI); + } + else { + const float AmC = A - C, ApC = A + C, F2 = F * 2.0f; + const float r = sqrtf(AmC * AmC + B * B); + float d = ApC - r; + *a = (d <= 0.0f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d); + d = ApC + r; + if (d <= 0.0f) { + *b = 0.0f; + *ecc = 1e10f; + } + else { + *b = sqrtf(F2 / d); + *ecc = *a / *b; + } + /* incr theta by 0.5*pi (angle of major axis) */ + *th = 0.5f * (atan2f(B, AmC) + (float)M_PI); + } } -void BLI_ewa_filter(const int width, const int height, +void BLI_ewa_filter(const int width, + const int height, const bool intpol, const bool use_alpha, const float uv[2], @@ -546,98 +608,106 @@ void BLI_ewa_filter(const int width, const int height, void *userdata, float result[4]) { - /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values, - * scaling by aspect ratio alone does the opposite, so try something in between instead... */ - const float ff2 = (float)width, ff = sqrtf(ff2), q = (float)height / ff; - const float Ux = du[0] * ff, Vx = du[1] * q, Uy = dv[0] * ff, Vy = dv[1] * q; - float A = Vx * Vx + Vy * Vy; - float B = -2.0f * (Ux * Vx + Uy * Vy); - float C = Ux * Ux + Uy * Uy; - float F = A * C - B * B * 0.25f; - float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; - int u, v, u1, u2, v1, v2; - - /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C, - * so the ellipse always covers at least some texels. But since the filter is now always larger, - * it also means that everywhere else it's also more blurry then ideally should be the case. - * So instead here the ellipse radii are modified instead whenever either is too low. - * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off, - * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on - * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */ - const float rmin = (intpol ? 1.5625f : 0.765625f) / ff2; - BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc); - if ((b2 = b * b) < rmin) { - if ((a2 = a * a) < rmin) { - B = 0.0f; - A = C = rmin; - F = A * C; - } - else { - b2 = rmin; - radangle2imp(a2, b2, th, &A, &B, &C, &F); - } - } - - ue = ff * sqrtf(C); - ve = ff * sqrtf(A); - d = (float)(EWA_MAXIDX + 1) / (F * ff2); - A *= d; - B *= d; - C *= d; - - U0 = uv[0] * (float)width; - V0 = uv[1] * (float)height; - u1 = (int)(floorf(U0 - ue)); - u2 = (int)(ceilf(U0 + ue)); - v1 = (int)(floorf(V0 - ve)); - v2 = (int)(ceilf(V0 + ve)); - - /* sane clamping to avoid unnecessarily huge loops */ - /* note: if eccentricity gets clamped (see above), - * the ue/ve limits can also be lowered accordingly - */ - if (U0 - (float)u1 > EWA_MAXIDX) { u1 = (int)U0 - EWA_MAXIDX; } - if ((float)u2 - U0 > EWA_MAXIDX) { u2 = (int)U0 + EWA_MAXIDX; } - if (V0 - (float)v1 > EWA_MAXIDX) { v1 = (int)V0 - EWA_MAXIDX; } - if ((float)v2 - V0 > EWA_MAXIDX) { v2 = (int)V0 + EWA_MAXIDX; } - - /* Early output check for cases the whole region is outside of the buffer. */ - if ((u2 < 0 || u1 >= width) || (v2 < 0 || v1 >= height)) { - zero_v4(result); - return; - } - - U0 -= 0.5f; - V0 -= 0.5f; - DDQ = 2.0f * A; - U = (float)u1 - U0; - ac1 = A * (2.0f * U + 1.0f); - ac2 = A * U * U; - BU = B * U; - - d = 0.0f; - zero_v4(result); - for (v = v1; v <= v2; ++v) { - const float V = (float)v - V0; - float DQ = ac1 + B * V; - float Q = (C * V + BU) * V + ac2; - for (u = u1; u <= u2; ++u) { - if (Q < (float)(EWA_MAXIDX + 1)) { - float tc[4]; - const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (unsigned int)Q]; - read_pixel_cb(userdata, u, v, tc); - madd_v3_v3fl(result, tc, wt); - result[3] += use_alpha ? tc[3] * wt : 0.0f; - d += wt; - } - Q += DQ; - DQ += DDQ; - } - } - - /* d should hopefully never be zero anymore */ - d = 1.0f / d; - mul_v3_fl(result, d); - /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */ - result[3] = use_alpha ? result[3] * d : 1.0f; + /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values, + * scaling by aspect ratio alone does the opposite, so try something in between instead... */ + const float ff2 = (float)width, ff = sqrtf(ff2), q = (float)height / ff; + const float Ux = du[0] * ff, Vx = du[1] * q, Uy = dv[0] * ff, Vy = dv[1] * q; + float A = Vx * Vx + Vy * Vy; + float B = -2.0f * (Ux * Vx + Uy * Vy); + float C = Ux * Ux + Uy * Uy; + float F = A * C - B * B * 0.25f; + float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; + int u, v, u1, u2, v1, v2; + + /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C, + * so the ellipse always covers at least some texels. But since the filter is now always larger, + * it also means that everywhere else it's also more blurry then ideally should be the case. + * So instead here the ellipse radii are modified instead whenever either is too low. + * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off, + * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on + * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */ + const float rmin = (intpol ? 1.5625f : 0.765625f) / ff2; + BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc); + if ((b2 = b * b) < rmin) { + if ((a2 = a * a) < rmin) { + B = 0.0f; + A = C = rmin; + F = A * C; + } + else { + b2 = rmin; + radangle2imp(a2, b2, th, &A, &B, &C, &F); + } + } + + ue = ff * sqrtf(C); + ve = ff * sqrtf(A); + d = (float)(EWA_MAXIDX + 1) / (F * ff2); + A *= d; + B *= d; + C *= d; + + U0 = uv[0] * (float)width; + V0 = uv[1] * (float)height; + u1 = (int)(floorf(U0 - ue)); + u2 = (int)(ceilf(U0 + ue)); + v1 = (int)(floorf(V0 - ve)); + v2 = (int)(ceilf(V0 + ve)); + + /* sane clamping to avoid unnecessarily huge loops */ + /* note: if eccentricity gets clamped (see above), + * the ue/ve limits can also be lowered accordingly + */ + if (U0 - (float)u1 > EWA_MAXIDX) { + u1 = (int)U0 - EWA_MAXIDX; + } + if ((float)u2 - U0 > EWA_MAXIDX) { + u2 = (int)U0 + EWA_MAXIDX; + } + if (V0 - (float)v1 > EWA_MAXIDX) { + v1 = (int)V0 - EWA_MAXIDX; + } + if ((float)v2 - V0 > EWA_MAXIDX) { + v2 = (int)V0 + EWA_MAXIDX; + } + + /* Early output check for cases the whole region is outside of the buffer. */ + if ((u2 < 0 || u1 >= width) || (v2 < 0 || v1 >= height)) { + zero_v4(result); + return; + } + + U0 -= 0.5f; + V0 -= 0.5f; + DDQ = 2.0f * A; + U = (float)u1 - U0; + ac1 = A * (2.0f * U + 1.0f); + ac2 = A * U * U; + BU = B * U; + + d = 0.0f; + zero_v4(result); + for (v = v1; v <= v2; ++v) { + const float V = (float)v - V0; + float DQ = ac1 + B * V; + float Q = (C * V + BU) * V + ac2; + for (u = u1; u <= u2; ++u) { + if (Q < (float)(EWA_MAXIDX + 1)) { + float tc[4]; + const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (unsigned int)Q]; + read_pixel_cb(userdata, u, v, tc); + madd_v3_v3fl(result, tc, wt); + result[3] += use_alpha ? tc[3] * wt : 0.0f; + d += wt; + } + Q += DQ; + DQ += DDQ; + } + } + + /* d should hopefully never be zero anymore */ + d = 1.0f / d; + mul_v3_fl(result, d); + /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */ + result[3] = use_alpha ? result[3] * d : 1.0f; } diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 3da69e92227..71ea1ce1bc9 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -23,7 +23,6 @@ * \ingroup bli */ - #include <assert.h> #include "BLI_math.h" @@ -35,1067 +34,1099 @@ void zero_m2(float m[2][2]) { - memset(m, 0, sizeof(float[2][2])); + memset(m, 0, sizeof(float[2][2])); } void zero_m3(float m[3][3]) { - memset(m, 0, sizeof(float[3][3])); + memset(m, 0, sizeof(float[3][3])); } void zero_m4(float m[4][4]) { - memset(m, 0, sizeof(float[4][4])); + memset(m, 0, sizeof(float[4][4])); } void unit_m2(float m[2][2]) { - m[0][0] = m[1][1] = 1.0f; - m[0][1] = 0.0f; - m[1][0] = 0.0f; + m[0][0] = m[1][1] = 1.0f; + m[0][1] = 0.0f; + m[1][0] = 0.0f; } void unit_m3(float m[3][3]) { - m[0][0] = m[1][1] = m[2][2] = 1.0f; - m[0][1] = m[0][2] = 0.0f; - m[1][0] = m[1][2] = 0.0f; - m[2][0] = m[2][1] = 0.0f; + m[0][0] = m[1][1] = m[2][2] = 1.0f; + m[0][1] = m[0][2] = 0.0f; + m[1][0] = m[1][2] = 0.0f; + m[2][0] = m[2][1] = 0.0f; } void unit_m4(float m[4][4]) { - m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; - m[0][1] = m[0][2] = m[0][3] = 0.0f; - m[1][0] = m[1][2] = m[1][3] = 0.0f; - m[2][0] = m[2][1] = m[2][3] = 0.0f; - m[3][0] = m[3][1] = m[3][2] = 0.0f; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; + m[0][1] = m[0][2] = m[0][3] = 0.0f; + m[1][0] = m[1][2] = m[1][3] = 0.0f; + m[2][0] = m[2][1] = m[2][3] = 0.0f; + m[3][0] = m[3][1] = m[3][2] = 0.0f; } void copy_m2_m2(float m1[2][2], const float m2[2][2]) { - memcpy(m1, m2, sizeof(float[2][2])); + memcpy(m1, m2, sizeof(float[2][2])); } void copy_m3_m3(float m1[3][3], const float m2[3][3]) { - /* destination comes first: */ - memcpy(m1, m2, sizeof(float[3][3])); + /* destination comes first: */ + memcpy(m1, m2, sizeof(float[3][3])); } void copy_m4_m4(float m1[4][4], const float m2[4][4]) { - memcpy(m1, m2, sizeof(float[4][4])); + memcpy(m1, m2, sizeof(float[4][4])); } void copy_m3_m4(float m1[3][3], const float m2[4][4]) { - m1[0][0] = m2[0][0]; - m1[0][1] = m2[0][1]; - m1[0][2] = m2[0][2]; + m1[0][0] = m2[0][0]; + m1[0][1] = m2[0][1]; + m1[0][2] = m2[0][2]; - m1[1][0] = m2[1][0]; - m1[1][1] = m2[1][1]; - m1[1][2] = m2[1][2]; + m1[1][0] = m2[1][0]; + m1[1][1] = m2[1][1]; + m1[1][2] = m2[1][2]; - m1[2][0] = m2[2][0]; - m1[2][1] = m2[2][1]; - m1[2][2] = m2[2][2]; + m1[2][0] = m2[2][0]; + m1[2][1] = m2[2][1]; + m1[2][2] = m2[2][2]; } void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */ { - m1[0][0] = m2[0][0]; - m1[0][1] = m2[0][1]; - m1[0][2] = m2[0][2]; - - m1[1][0] = m2[1][0]; - m1[1][1] = m2[1][1]; - m1[1][2] = m2[1][2]; + m1[0][0] = m2[0][0]; + m1[0][1] = m2[0][1]; + m1[0][2] = m2[0][2]; - m1[2][0] = m2[2][0]; - m1[2][1] = m2[2][1]; - m1[2][2] = m2[2][2]; + m1[1][0] = m2[1][0]; + m1[1][1] = m2[1][1]; + m1[1][2] = m2[1][2]; - /* Reevan's Bugfix */ - m1[0][3] = 0.0f; - m1[1][3] = 0.0f; - m1[2][3] = 0.0f; + m1[2][0] = m2[2][0]; + m1[2][1] = m2[2][1]; + m1[2][2] = m2[2][2]; - m1[3][0] = 0.0f; - m1[3][1] = 0.0f; - m1[3][2] = 0.0f; - m1[3][3] = 1.0f; + /* Reevan's Bugfix */ + m1[0][3] = 0.0f; + m1[1][3] = 0.0f; + m1[2][3] = 0.0f; + m1[3][0] = 0.0f; + m1[3][1] = 0.0f; + m1[3][2] = 0.0f; + m1[3][3] = 1.0f; } void copy_m3_m3d(float R[3][3], const double A[3][3]) { - /* Keep it stupid simple for better data flow in CPU. */ - R[0][0] = (float)A[0][0]; - R[0][1] = (float)A[0][1]; - R[0][2] = (float)A[0][2]; + /* Keep it stupid simple for better data flow in CPU. */ + R[0][0] = (float)A[0][0]; + R[0][1] = (float)A[0][1]; + R[0][2] = (float)A[0][2]; - R[1][0] = (float)A[1][0]; - R[1][1] = (float)A[1][1]; - R[1][2] = (float)A[1][2]; + R[1][0] = (float)A[1][0]; + R[1][1] = (float)A[1][1]; + R[1][2] = (float)A[1][2]; - R[2][0] = (float)A[2][0]; - R[2][1] = (float)A[2][1]; - R[2][2] = (float)A[2][2]; + R[2][0] = (float)A[2][0]; + R[2][1] = (float)A[2][1]; + R[2][2] = (float)A[2][2]; } void swap_m3m3(float m1[3][3], float m2[3][3]) { - float t; - int i, j; + float t; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - t = m1[i][j]; - m1[i][j] = m2[i][j]; - m2[i][j] = t; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + t = m1[i][j]; + m1[i][j] = m2[i][j]; + m2[i][j] = t; + } + } } void swap_m4m4(float m1[4][4], float m2[4][4]) { - float t; - int i, j; + float t; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - t = m1[i][j]; - m1[i][j] = m2[i][j]; - m2[i][j] = t; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + t = m1[i][j]; + m1[i][j] = m2[i][j]; + m2[i][j] = t; + } + } } /******************************** Arithmetic *********************************/ void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]) { - if (A == R) { - mul_m4_m4_post(R, B); - } - else if (B == R) { - mul_m4_m4_pre(R, A); - } - else { - mul_m4_m4m4_uniq(R, A, B); - } + if (A == R) { + mul_m4_m4_post(R, B); + } + else if (B == R) { + mul_m4_m4_pre(R, A); + } + else { + mul_m4_m4m4_uniq(R, A, B); + } } void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]) { - BLI_assert(R != A && R != B); + BLI_assert(R != A && R != B); - /* matrix product: R[j][k] = A[j][i] . B[i][k] */ + /* matrix product: R[j][k] = A[j][i] . B[i][k] */ #ifdef __SSE2__ - __m128 A0 = _mm_loadu_ps(A[0]); - __m128 A1 = _mm_loadu_ps(A[1]); - __m128 A2 = _mm_loadu_ps(A[2]); - __m128 A3 = _mm_loadu_ps(A[3]); - - for (int i = 0; i < 4; i++) { - __m128 B0 = _mm_set1_ps(B[i][0]); - __m128 B1 = _mm_set1_ps(B[i][1]); - __m128 B2 = _mm_set1_ps(B[i][2]); - __m128 B3 = _mm_set1_ps(B[i][3]); - - __m128 sum = _mm_add_ps( - _mm_add_ps(_mm_mul_ps(B0, A0), _mm_mul_ps(B1, A1)), - _mm_add_ps(_mm_mul_ps(B2, A2), _mm_mul_ps(B3, A3))); - - _mm_storeu_ps(R[i], sum); - } + __m128 A0 = _mm_loadu_ps(A[0]); + __m128 A1 = _mm_loadu_ps(A[1]); + __m128 A2 = _mm_loadu_ps(A[2]); + __m128 A3 = _mm_loadu_ps(A[3]); + + for (int i = 0; i < 4; i++) { + __m128 B0 = _mm_set1_ps(B[i][0]); + __m128 B1 = _mm_set1_ps(B[i][1]); + __m128 B2 = _mm_set1_ps(B[i][2]); + __m128 B3 = _mm_set1_ps(B[i][3]); + + __m128 sum = _mm_add_ps(_mm_add_ps(_mm_mul_ps(B0, A0), _mm_mul_ps(B1, A1)), + _mm_add_ps(_mm_mul_ps(B2, A2), _mm_mul_ps(B3, A3))); + + _mm_storeu_ps(R[i], sum); + } #else - R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0]; - R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1]; - R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2]; - R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3]; - - R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0]; - R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1]; - R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2]; - R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3]; - - R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0]; - R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1]; - R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2]; - R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3]; - - R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0]; - R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1]; - R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2]; - R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3]; + R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0]; + R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1]; + R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2]; + R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3]; + + R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0]; + R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1]; + R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2]; + R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3]; + + R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0]; + R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1]; + R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2]; + R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3]; + + R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0]; + R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1]; + R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2]; + R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3]; #endif } void mul_m4_m4_pre(float R[4][4], const float A[4][4]) { - BLI_assert(A != R); - float B[4][4]; - copy_m4_m4(B, R); - mul_m4_m4m4_uniq(R, A, B); + BLI_assert(A != R); + float B[4][4]; + copy_m4_m4(B, R); + mul_m4_m4m4_uniq(R, A, B); } void mul_m4_m4_post(float R[4][4], const float B[4][4]) { - BLI_assert(B != R); - float A[4][4]; - copy_m4_m4(A, R); - mul_m4_m4m4_uniq(R, A, B); + BLI_assert(B != R); + float A[4][4]; + copy_m4_m4(A, R); + mul_m4_m4m4_uniq(R, A, B); } void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]) { - if (A == R) { - mul_m3_m3_post(R, B); - } - else if (B == R) { - mul_m3_m3_pre(R, A); - } - else { - mul_m3_m3m3_uniq(R, A, B); - } + if (A == R) { + mul_m3_m3_post(R, B); + } + else if (B == R) { + mul_m3_m3_pre(R, A); + } + else { + mul_m3_m3m3_uniq(R, A, B); + } } void mul_m3_m3_pre(float R[3][3], const float A[3][3]) { - BLI_assert(A != R); - float B[3][3]; - copy_m3_m3(B, R); - mul_m3_m3m3_uniq(R, A, B); + BLI_assert(A != R); + float B[3][3]; + copy_m3_m3(B, R); + mul_m3_m3m3_uniq(R, A, B); } void mul_m3_m3_post(float R[3][3], const float B[3][3]) { - BLI_assert(B != R); - float A[3][3]; - copy_m3_m3(A, R); - mul_m3_m3m3_uniq(R, A, B); + BLI_assert(B != R); + float A[3][3]; + copy_m3_m3(A, R); + mul_m3_m3m3_uniq(R, A, B); } void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]) { - BLI_assert(R != A && R != B); + BLI_assert(R != A && R != B); - R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0]; - R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1]; - R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2]; + R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0]; + R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1]; + R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2]; - R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0]; - R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1]; - R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2]; + R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0]; + R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1]; + R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2]; - R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0]; - R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1]; - R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2]; + R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0]; + R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1]; + R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2]; } void mul_m4_m4m3(float m1[4][4], const float m3_[4][4], const float m2_[3][3]) { - float m2[3][3], m3[4][4]; + float m2[3][3], m3[4][4]; - /* copy so it works when m1 is the same pointer as m2 or m3 */ - /* TODO: avoid copying when matrices are different */ - copy_m3_m3(m2, m2_); - copy_m4_m4(m3, m3_); + /* copy so it works when m1 is the same pointer as m2 or m3 */ + /* TODO: avoid copying when matrices are different */ + copy_m3_m3(m2, m2_); + copy_m4_m4(m3, m3_); - m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; - m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; - m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; - m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; - m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; - m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; - m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; - m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; - m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } /* m1 = m2 * m3, ignore the elements on the 4th row/column of m2 */ void mul_m3_m3m4(float m1[3][3], const float m3_[3][3], const float m2_[4][4]) { - float m2[4][4], m3[3][3]; + float m2[4][4], m3[3][3]; - /* copy so it works when m1 is the same pointer as m2 or m3 */ - /* TODO: avoid copying when matrices are different */ - copy_m4_m4(m2, m2_); - copy_m3_m3(m3, m3_); + /* copy so it works when m1 is the same pointer as m2 or m3 */ + /* TODO: avoid copying when matrices are different */ + copy_m4_m4(m2, m2_); + copy_m3_m3(m3, m3_); - /* m1[i][j] = m2[i][k] * m3[k][j] */ - m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; - m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; - m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; + /* m1[i][j] = m2[i][k] * m3[k][j] */ + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; - m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; - m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; - m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; - m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; - m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; - m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } /* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */ void mul_m3_m4m3(float m1[3][3], const float m3_[4][4], const float m2_[3][3]) { - float m2[3][3], m3[4][4]; + float m2[3][3], m3[4][4]; - /* copy so it works when m1 is the same pointer as m2 or m3 */ - /* TODO: avoid copying when matrices are different */ - copy_m3_m3(m2, m2_); - copy_m4_m4(m3, m3_); + /* copy so it works when m1 is the same pointer as m2 or m3 */ + /* TODO: avoid copying when matrices are different */ + copy_m3_m3(m2, m2_); + copy_m4_m4(m3, m3_); - /* m1[i][j] = m2[i][k] * m3[k][j] */ - m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; - m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; - m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; + /* m1[i][j] = m2[i][k] * m3[k][j] */ + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; - m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; - m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; - m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; - m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; - m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; - m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } void mul_m4_m3m4(float m1[4][4], const float m3_[3][3], const float m2_[4][4]) { - float m2[4][4], m3[3][3]; + float m2[4][4], m3[3][3]; - /* copy so it works when m1 is the same pointer as m2 or m3 */ - /* TODO: avoid copying when matrices are different */ - copy_m4_m4(m2, m2_); - copy_m3_m3(m3, m3_); + /* copy so it works when m1 is the same pointer as m2 or m3 */ + /* TODO: avoid copying when matrices are different */ + copy_m4_m4(m2, m2_); + copy_m3_m3(m3, m3_); - m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; - m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; - m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; - m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; - m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; - m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; - m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; - m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; - m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } void mul_m3_m4m4(float m1[3][3], const float m3[4][4], const float m2[4][4]) { - m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; - m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; - m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; - m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; - m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; - m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; - m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; - m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; - m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2]; + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } /** \name Macro helpers for: mul_m3_series * \{ */ -void _va_mul_m3_series_3( - float r[3][3], - const float m1[3][3], const float m2[3][3]) -{ - mul_m3_m3m3(r, m1, m2); -} -void _va_mul_m3_series_4( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); -} -void _va_mul_m3_series_5( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); - mul_m3_m3m3(r, r, m4); -} -void _va_mul_m3_series_6( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3], - const float m5[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); - mul_m3_m3m3(r, r, m4); - mul_m3_m3m3(r, r, m5); -} -void _va_mul_m3_series_7( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3], - const float m5[3][3], const float m6[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); - mul_m3_m3m3(r, r, m4); - mul_m3_m3m3(r, r, m5); - mul_m3_m3m3(r, r, m6); -} -void _va_mul_m3_series_8( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3], - const float m5[3][3], const float m6[3][3], const float m7[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); - mul_m3_m3m3(r, r, m4); - mul_m3_m3m3(r, r, m5); - mul_m3_m3m3(r, r, m6); - mul_m3_m3m3(r, r, m7); -} -void _va_mul_m3_series_9( - float r[3][3], - const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3], - const float m5[3][3], const float m6[3][3], const float m7[3][3], const float m8[3][3]) -{ - mul_m3_m3m3(r, m1, m2); - mul_m3_m3m3(r, r, m3); - mul_m3_m3m3(r, r, m4); - mul_m3_m3m3(r, r, m5); - mul_m3_m3m3(r, r, m6); - mul_m3_m3m3(r, r, m7); - mul_m3_m3m3(r, r, m8); +void _va_mul_m3_series_3(float r[3][3], const float m1[3][3], const float m2[3][3]) +{ + mul_m3_m3m3(r, m1, m2); +} +void _va_mul_m3_series_4(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); +} +void _va_mul_m3_series_5(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); + mul_m3_m3m3(r, r, m4); +} +void _va_mul_m3_series_6(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); + mul_m3_m3m3(r, r, m4); + mul_m3_m3m3(r, r, m5); +} +void _va_mul_m3_series_7(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); + mul_m3_m3m3(r, r, m4); + mul_m3_m3m3(r, r, m5); + mul_m3_m3m3(r, r, m6); +} +void _va_mul_m3_series_8(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3], + const float m7[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); + mul_m3_m3m3(r, r, m4); + mul_m3_m3m3(r, r, m5); + mul_m3_m3m3(r, r, m6); + mul_m3_m3m3(r, r, m7); +} +void _va_mul_m3_series_9(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3], + const float m7[3][3], + const float m8[3][3]) +{ + mul_m3_m3m3(r, m1, m2); + mul_m3_m3m3(r, r, m3); + mul_m3_m3m3(r, r, m4); + mul_m3_m3m3(r, r, m5); + mul_m3_m3m3(r, r, m6); + mul_m3_m3m3(r, r, m7); + mul_m3_m3m3(r, r, m8); } /** \} */ /** \name Macro helpers for: mul_m4_series * \{ */ -void _va_mul_m4_series_3( - float r[4][4], - const float m1[4][4], const float m2[4][4]) -{ - mul_m4_m4m4(r, m1, m2); -} -void _va_mul_m4_series_4( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); -} -void _va_mul_m4_series_5( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); - mul_m4_m4m4(r, r, m4); -} -void _va_mul_m4_series_6( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4], - const float m5[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); - mul_m4_m4m4(r, r, m4); - mul_m4_m4m4(r, r, m5); -} -void _va_mul_m4_series_7( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4], - const float m5[4][4], const float m6[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); - mul_m4_m4m4(r, r, m4); - mul_m4_m4m4(r, r, m5); - mul_m4_m4m4(r, r, m6); -} -void _va_mul_m4_series_8( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4], - const float m5[4][4], const float m6[4][4], const float m7[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); - mul_m4_m4m4(r, r, m4); - mul_m4_m4m4(r, r, m5); - mul_m4_m4m4(r, r, m6); - mul_m4_m4m4(r, r, m7); -} -void _va_mul_m4_series_9( - float r[4][4], - const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4], - const float m5[4][4], const float m6[4][4], const float m7[4][4], const float m8[4][4]) -{ - mul_m4_m4m4(r, m1, m2); - mul_m4_m4m4(r, r, m3); - mul_m4_m4m4(r, r, m4); - mul_m4_m4m4(r, r, m5); - mul_m4_m4m4(r, r, m6); - mul_m4_m4m4(r, r, m7); - mul_m4_m4m4(r, r, m8); +void _va_mul_m4_series_3(float r[4][4], const float m1[4][4], const float m2[4][4]) +{ + mul_m4_m4m4(r, m1, m2); +} +void _va_mul_m4_series_4(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); +} +void _va_mul_m4_series_5(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); + mul_m4_m4m4(r, r, m4); +} +void _va_mul_m4_series_6(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); + mul_m4_m4m4(r, r, m4); + mul_m4_m4m4(r, r, m5); +} +void _va_mul_m4_series_7(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); + mul_m4_m4m4(r, r, m4); + mul_m4_m4m4(r, r, m5); + mul_m4_m4m4(r, r, m6); +} +void _va_mul_m4_series_8(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4], + const float m7[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); + mul_m4_m4m4(r, r, m4); + mul_m4_m4m4(r, r, m5); + mul_m4_m4m4(r, r, m6); + mul_m4_m4m4(r, r, m7); +} +void _va_mul_m4_series_9(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4], + const float m7[4][4], + const float m8[4][4]) +{ + mul_m4_m4m4(r, m1, m2); + mul_m4_m4m4(r, r, m3); + mul_m4_m4m4(r, r, m4); + mul_m4_m4m4(r, r, m5); + mul_m4_m4m4(r, r, m6); + mul_m4_m4m4(r, r, m7); + mul_m4_m4m4(r, r, m8); } /** \} */ void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]) { - float temp[3], warped[3]; + float temp[3], warped[3]; - copy_v2_v2(temp, v); - temp[2] = 1.0f; + copy_v2_v2(temp, v); + temp[2] = 1.0f; - mul_v3_m3v3(warped, m, temp); + mul_v3_m3v3(warped, m, temp); - r[0] = warped[0] / warped[2]; - r[1] = warped[1] / warped[2]; + r[0] = warped[0] / warped[2]; + r[1] = warped[1] / warped[2]; } void mul_m3_v2(const float m[3][3], float r[2]) { - mul_v2_m3v2(r, m, r); + mul_v2_m3v2(r, m, r); } void mul_m4_v3(const float mat[4][4], float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; - vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; - vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; + vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; - r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; - r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3]) { - const float x = vec[0]; + const float x = vec[0]; - r[0] = x * mat[0][0] + vec[1] * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; - r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + r[0] = x * mat[0][0] + vec[1] * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; } void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2]) { - const float x = vec[0]; + const float x = vec[0]; - r[0] = mat[0][0] * x + mat[1][0] * vec[1]; - r[1] = mat[0][1] * x + mat[1][1] * vec[1]; + r[0] = mat[0][0] * x + mat[1][0] * vec[1]; + r[1] = mat[0][1] * x + mat[1][1] * vec[1]; } void mul_m2v2(const float mat[2][2], float vec[2]) { - mul_v2_m2v2(vec, mat, vec); + mul_v2_m2v2(vec, mat, vec); } /* same as mul_m4_v3() but doesnt apply translation component */ void mul_mat3_m4_v3(const float mat[4][4], float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; - vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; - vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; + vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; + vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; + vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; } void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; - r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; - r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; } void mul_project_m4_v3(const float mat[4][4], float vec[3]) { - /* absolute value to not flip the frustum upside down behind the camera */ - const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); - mul_m4_v3(mat, vec); + /* absolute value to not flip the frustum upside down behind the camera */ + const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); + mul_m4_v3(mat, vec); - vec[0] /= w; - vec[1] /= w; - vec[2] /= w; + vec[0] /= w; + vec[1] /= w; + vec[2] /= w; } void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]) { - const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); - mul_v3_m4v3(r, mat, vec); + const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); + mul_v3_m4v3(r, mat, vec); - r[0] /= w; - r[1] /= w; - r[2] /= w; + r[0] /= w; + r[1] /= w; + r[2] /= w; } void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3]) { - const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); - mul_v2_m4v3(r, mat, vec); + const float w = fabsf(mul_project_m4_v3_zfac(mat, vec)); + mul_v2_m4v3(r, mat, vec); - r[0] /= w; - r[1] /= w; + r[0] /= w; + r[1] /= w; } void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4]) { - const float x = v[0]; - const float y = v[1]; - const float z = v[2]; + const float x = v[0]; + const float y = v[1]; + const float z = v[2]; - r[0] = x * mat[0][0] + y * mat[1][0] + z * mat[2][0] + mat[3][0] * v[3]; - r[1] = x * mat[0][1] + y * mat[1][1] + z * mat[2][1] + mat[3][1] * v[3]; - r[2] = x * mat[0][2] + y * mat[1][2] + z * mat[2][2] + mat[3][2] * v[3]; - r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3]; + r[0] = x * mat[0][0] + y * mat[1][0] + z * mat[2][0] + mat[3][0] * v[3]; + r[1] = x * mat[0][1] + y * mat[1][1] + z * mat[2][1] + mat[3][1] * v[3]; + r[2] = x * mat[0][2] + y * mat[1][2] + z * mat[2][2] + mat[3][2] * v[3]; + r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3]; } void mul_m4_v4(const float mat[4][4], float r[4]) { - mul_v4_m4v4(r, mat, r); + mul_v4_m4v4(r, mat, r); } void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4]) { - const double x = v[0]; - const double y = v[1]; - const double z = v[2]; + const double x = v[0]; + const double y = v[1]; + const double z = v[2]; - r[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + z * (double)mat[2][0] + (double)mat[3][0] * v[3]; - r[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + z * (double)mat[2][1] + (double)mat[3][1] * v[3]; - r[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + z * (double)mat[2][2] + (double)mat[3][2] * v[3]; - r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + (double)mat[3][3] * v[3]; + r[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + z * (double)mat[2][0] + + (double)mat[3][0] * v[3]; + r[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + z * (double)mat[2][1] + + (double)mat[3][1] * v[3]; + r[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + z * (double)mat[2][2] + + (double)mat[3][2] * v[3]; + r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + + (double)mat[3][3] * v[3]; } void mul_m4_v4d(const float mat[4][4], double r[4]) { - mul_v4d_m4v4d(r, mat, r); + mul_v4d_m4v4d(r, mat, r); } void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]) { - /* v has implicit w = 1.0f */ - r[0] = v[0] * M[0][0] + v[1] * M[1][0] + M[2][0] * v[2] + M[3][0]; - r[1] = v[0] * M[0][1] + v[1] * M[1][1] + M[2][1] * v[2] + M[3][1]; - r[2] = v[0] * M[0][2] + v[1] * M[1][2] + M[2][2] * v[2] + M[3][2]; - r[3] = v[0] * M[0][3] + v[1] * M[1][3] + M[2][3] * v[2] + M[3][3]; + /* v has implicit w = 1.0f */ + r[0] = v[0] * M[0][0] + v[1] * M[1][0] + M[2][0] * v[2] + M[3][0]; + r[1] = v[0] * M[0][1] + v[1] * M[1][1] + M[2][1] * v[2] + M[3][1]; + r[2] = v[0] * M[0][2] + v[1] * M[1][2] + M[2][2] * v[2] + M[3][2]; + r[3] = v[0] * M[0][3] + v[1] * M[1][3] + M[2][3] * v[2] + M[3][3]; } void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3]) { - float t[3]; - copy_v3_v3(t, a); + float t[3]; + copy_v3_v3(t, a); - r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; - r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; - r[2] = M[0][2] * t[0] + M[1][2] * t[1] + M[2][2] * t[2]; + r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; + r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; + r[2] = M[0][2] * t[0] + M[1][2] * t[1] + M[2][2] * t[2]; } void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3]) { - double t[3]; - copy_v3_v3_db(t, a); + double t[3]; + copy_v3_v3_db(t, a); - r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; - r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; - r[2] = M[0][2] * t[0] + M[1][2] * t[1] + M[2][2] * t[2]; + r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; + r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; + r[2] = M[0][2] * t[0] + M[1][2] * t[1] + M[2][2] * t[2]; } void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3]) { - float t[3]; - copy_v3_v3(t, a); + float t[3]; + copy_v3_v3(t, a); - r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; - r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; + r[0] = M[0][0] * t[0] + M[1][0] * t[1] + M[2][0] * t[2]; + r[1] = M[0][1] * t[0] + M[1][1] * t[1] + M[2][1] * t[2]; } void mul_m3_v3(const float M[3][3], float r[3]) { - mul_v3_m3v3(r, M, (const float[3]){UNPACK3(r)}); + mul_v3_m3v3(r, M, (const float[3]){UNPACK3(r)}); } void mul_m3_v3_db(const double M[3][3], double r[3]) { - mul_v3_m3v3_db(r, M, (const double[3]){UNPACK3(r)}); + mul_v3_m3v3_db(r, M, (const double[3]){UNPACK3(r)}); } void mul_transposed_m3_v3(const float mat[3][3], float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2]; - vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2]; - vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2]; + vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2]; + vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2]; + vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2]; } void mul_transposed_mat3_m4_v3(const float mat[4][4], float vec[3]) { - const float x = vec[0]; - const float y = vec[1]; + const float x = vec[0]; + const float y = vec[1]; - vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2]; - vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2]; - vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2]; + vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2]; + vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2]; + vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2]; } void mul_m3_fl(float m[3][3], float f) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m[i][j] *= f; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m[i][j] *= f; + } + } } void mul_m4_fl(float m[4][4], float f) { - int i, j; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - m[i][j] *= f; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + m[i][j] *= f; + } + } } void mul_mat3_m4_fl(float m[4][4], float f) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m[i][j] *= f; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m[i][j] *= f; + } + } } void negate_m3(float m[3][3]) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m[i][j] *= -1.0f; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m[i][j] *= -1.0f; + } + } } void negate_mat3_m4(float m[4][4]) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m[i][j] *= -1.0f; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m[i][j] *= -1.0f; + } + } } void negate_m4(float m[4][4]) { - int i, j; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - m[i][j] *= -1.0f; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + m[i][j] *= -1.0f; + } + } } void mul_m3_v3_double(const float mat[3][3], double vec[3]) { - const double x = vec[0]; - const double y = vec[1]; + const double x = vec[0]; + const double y = vec[1]; - vec[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + (double)mat[2][0] * vec[2]; - vec[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + (double)mat[2][1] * vec[2]; - vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2]; + vec[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + (double)mat[2][0] * vec[2]; + vec[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + (double)mat[2][1] * vec[2]; + vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2]; } void add_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3]) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m1[i][j] = m2[i][j] + m3[i][j]; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m1[i][j] = m2[i][j] + m3[i][j]; + } + } } void add_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4]) { - int i, j; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - m1[i][j] = m2[i][j] + m3[i][j]; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + m1[i][j] = m2[i][j] + m3[i][j]; + } + } } void madd_m3_m3m3fl(float m1[3][3], const float m2[3][3], const float m3[3][3], const float f) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m1[i][j] = m2[i][j] + m3[i][j] * f; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m1[i][j] = m2[i][j] + m3[i][j] * f; + } + } } void madd_m4_m4m4fl(float m1[4][4], const float m2[4][4], const float m3[4][4], const float f) { - int i, j; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - m1[i][j] = m2[i][j] + m3[i][j] * f; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + m1[i][j] = m2[i][j] + m3[i][j] * f; + } + } } void sub_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3]) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 3; j++) { - m1[i][j] = m2[i][j] - m3[i][j]; - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m1[i][j] = m2[i][j] - m3[i][j]; + } + } } void sub_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4]) { - int i, j; + int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - m1[i][j] = m2[i][j] - m3[i][j]; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + m1[i][j] = m2[i][j] - m3[i][j]; + } + } } float determinant_m3_array(const float m[3][3]) { - return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - - m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + - m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); + return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - + m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + + m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); } bool invert_m3_ex(float m[3][3], const float epsilon) { - float tmp[3][3]; - const bool success = invert_m3_m3_ex(tmp, m, epsilon); + float tmp[3][3]; + const bool success = invert_m3_m3_ex(tmp, m, epsilon); - copy_m3_m3(m, tmp); - return success; + copy_m3_m3(m, tmp); + return success; } bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon) { - float det; - int a, b; - bool success; + float det; + int a, b; + bool success; - BLI_assert(epsilon >= 0.0f); + BLI_assert(epsilon >= 0.0f); - /* calc adjoint */ - adjoint_m3_m3(m1, m2); + /* calc adjoint */ + adjoint_m3_m3(m1, m2); - /* then determinant old matrix! */ - det = determinant_m3_array(m2); + /* then determinant old matrix! */ + det = determinant_m3_array(m2); - success = (fabsf(det) > epsilon); + success = (fabsf(det) > epsilon); - if (LIKELY(det != 0.0f)) { - det = 1.0f / det; - for (a = 0; a < 3; a++) { - for (b = 0; b < 3; b++) { - m1[a][b] *= det; - } - } - } - return success; + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } + } + } + return success; } bool invert_m3(float m[3][3]) { - float tmp[3][3]; - const bool success = invert_m3_m3(tmp, m); + float tmp[3][3]; + const bool success = invert_m3_m3(tmp, m); - copy_m3_m3(m, tmp); - return success; + copy_m3_m3(m, tmp); + return success; } bool invert_m3_m3(float m1[3][3], const float m2[3][3]) { - float det; - int a, b; - bool success; + float det; + int a, b; + bool success; - /* calc adjoint */ - adjoint_m3_m3(m1, m2); + /* calc adjoint */ + adjoint_m3_m3(m1, m2); - /* then determinant old matrix! */ - det = determinant_m3_array(m2); + /* then determinant old matrix! */ + det = determinant_m3_array(m2); - success = (det != 0.0f); + success = (det != 0.0f); - if (LIKELY(det != 0.0f)) { - det = 1.0f / det; - for (a = 0; a < 3; a++) { - for (b = 0; b < 3; b++) { - m1[a][b] *= det; - } - } - } + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } + } + } - return success; + return success; } bool invert_m4(float m[4][4]) { - float tmp[4][4]; - const bool success = invert_m4_m4(tmp, m); + float tmp[4][4]; + const bool success = invert_m4_m4(tmp, m); - copy_m4_m4(m, tmp); - return success; + copy_m4_m4(m, tmp); + return success; } bool invert_m4_m4(float inverse[4][4], const float mat[4][4]) { - /* Use optimized matrix inverse from Eigen, since performance - * impact of this function is significant in complex rigs. */ - return EIG_invert_m4_m4(inverse, mat); + /* Use optimized matrix inverse from Eigen, since performance + * impact of this function is significant in complex rigs. */ + return EIG_invert_m4_m4(inverse, mat); } /****************************** Linear Algebra *******************************/ void transpose_m3(float mat[3][3]) { - float t; + float t; - t = mat[0][1]; - mat[0][1] = mat[1][0]; - mat[1][0] = t; - t = mat[0][2]; - mat[0][2] = mat[2][0]; - mat[2][0] = t; - t = mat[1][2]; - mat[1][2] = mat[2][1]; - mat[2][1] = t; + t = mat[0][1]; + mat[0][1] = mat[1][0]; + mat[1][0] = t; + t = mat[0][2]; + mat[0][2] = mat[2][0]; + mat[2][0] = t; + t = mat[1][2]; + mat[1][2] = mat[2][1]; + mat[2][1] = t; } void transpose_m3_m3(float rmat[3][3], const float mat[3][3]) { - BLI_assert(rmat != mat); + BLI_assert(rmat != mat); - rmat[0][0] = mat[0][0]; - rmat[0][1] = mat[1][0]; - rmat[0][2] = mat[2][0]; - rmat[1][0] = mat[0][1]; - rmat[1][1] = mat[1][1]; - rmat[1][2] = mat[2][1]; - rmat[2][0] = mat[0][2]; - rmat[2][1] = mat[1][2]; - rmat[2][2] = mat[2][2]; + rmat[0][0] = mat[0][0]; + rmat[0][1] = mat[1][0]; + rmat[0][2] = mat[2][0]; + rmat[1][0] = mat[0][1]; + rmat[1][1] = mat[1][1]; + rmat[1][2] = mat[2][1]; + rmat[2][0] = mat[0][2]; + rmat[2][1] = mat[1][2]; + rmat[2][2] = mat[2][2]; } /* seems obscure but in-fact a common operation */ void transpose_m3_m4(float rmat[3][3], const float mat[4][4]) { - BLI_assert(&rmat[0][0] != &mat[0][0]); + BLI_assert(&rmat[0][0] != &mat[0][0]); - rmat[0][0] = mat[0][0]; - rmat[0][1] = mat[1][0]; - rmat[0][2] = mat[2][0]; - rmat[1][0] = mat[0][1]; - rmat[1][1] = mat[1][1]; - rmat[1][2] = mat[2][1]; - rmat[2][0] = mat[0][2]; - rmat[2][1] = mat[1][2]; - rmat[2][2] = mat[2][2]; + rmat[0][0] = mat[0][0]; + rmat[0][1] = mat[1][0]; + rmat[0][2] = mat[2][0]; + rmat[1][0] = mat[0][1]; + rmat[1][1] = mat[1][1]; + rmat[1][2] = mat[2][1]; + rmat[2][0] = mat[0][2]; + rmat[2][1] = mat[1][2]; + rmat[2][2] = mat[2][2]; } void transpose_m4(float mat[4][4]) { - float t; + float t; - t = mat[0][1]; - mat[0][1] = mat[1][0]; - mat[1][0] = t; - t = mat[0][2]; - mat[0][2] = mat[2][0]; - mat[2][0] = t; - t = mat[0][3]; - mat[0][3] = mat[3][0]; - mat[3][0] = t; + t = mat[0][1]; + mat[0][1] = mat[1][0]; + mat[1][0] = t; + t = mat[0][2]; + mat[0][2] = mat[2][0]; + mat[2][0] = t; + t = mat[0][3]; + mat[0][3] = mat[3][0]; + mat[3][0] = t; - t = mat[1][2]; - mat[1][2] = mat[2][1]; - mat[2][1] = t; - t = mat[1][3]; - mat[1][3] = mat[3][1]; - mat[3][1] = t; + t = mat[1][2]; + mat[1][2] = mat[2][1]; + mat[2][1] = t; + t = mat[1][3]; + mat[1][3] = mat[3][1]; + mat[3][1] = t; - t = mat[2][3]; - mat[2][3] = mat[3][2]; - mat[3][2] = t; + t = mat[2][3]; + mat[2][3] = mat[3][2]; + mat[3][2] = t; } void transpose_m4_m4(float rmat[4][4], const float mat[4][4]) { - BLI_assert(rmat != mat); - - rmat[0][0] = mat[0][0]; - rmat[0][1] = mat[1][0]; - rmat[0][2] = mat[2][0]; - rmat[0][3] = mat[3][0]; - rmat[1][0] = mat[0][1]; - rmat[1][1] = mat[1][1]; - rmat[1][2] = mat[2][1]; - rmat[1][3] = mat[3][1]; - rmat[2][0] = mat[0][2]; - rmat[2][1] = mat[1][2]; - rmat[2][2] = mat[2][2]; - rmat[2][3] = mat[3][2]; - rmat[3][0] = mat[0][3]; - rmat[3][1] = mat[1][3]; - rmat[3][2] = mat[2][3]; - rmat[3][3] = mat[3][3]; + BLI_assert(rmat != mat); + + rmat[0][0] = mat[0][0]; + rmat[0][1] = mat[1][0]; + rmat[0][2] = mat[2][0]; + rmat[0][3] = mat[3][0]; + rmat[1][0] = mat[0][1]; + rmat[1][1] = mat[1][1]; + rmat[1][2] = mat[2][1]; + rmat[1][3] = mat[3][1]; + rmat[2][0] = mat[0][2]; + rmat[2][1] = mat[1][2]; + rmat[2][2] = mat[2][2]; + rmat[2][3] = mat[3][2]; + rmat[3][0] = mat[0][3]; + rmat[3][1] = mat[1][3]; + rmat[3][2] = mat[2][3]; + rmat[3][3] = mat[3][3]; } /* TODO: return bool */ int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit) { - if (compare_v4v4(mat1[0], mat2[0], limit)) { - if (compare_v4v4(mat1[1], mat2[1], limit)) { - if (compare_v4v4(mat1[2], mat2[2], limit)) { - if (compare_v4v4(mat1[3], mat2[3], limit)) { - return 1; - } - } - } - } - return 0; + if (compare_v4v4(mat1[0], mat2[0], limit)) { + if (compare_v4v4(mat1[1], mat2[1], limit)) { + if (compare_v4v4(mat1[2], mat2[2], limit)) { + if (compare_v4v4(mat1[3], mat2[3], limit)) { + return 1; + } + } + } + } + return 0; } /** @@ -1105,86 +1136,86 @@ int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit) */ void orthogonalize_m3(float mat[3][3], int axis) { - float size[3]; - mat3_to_size(size, mat); - normalize_v3(mat[axis]); - switch (axis) { - case 0: - if (dot_v3v3(mat[0], mat[1]) < 1) { - cross_v3_v3v3(mat[2], mat[0], mat[1]); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - else if (dot_v3v3(mat[0], mat[2]) < 1) { - cross_v3_v3v3(mat[1], mat[2], mat[0]); - normalize_v3(mat[1]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - else { - float vec[3]; - - vec[0] = mat[0][1]; - vec[1] = mat[0][2]; - vec[2] = mat[0][0]; - - cross_v3_v3v3(mat[2], mat[0], vec); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - break; - case 1: - if (dot_v3v3(mat[1], mat[0]) < 1) { - cross_v3_v3v3(mat[2], mat[0], mat[1]); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[0], mat[1], mat[2]); - } - else if (dot_v3v3(mat[0], mat[2]) < 1) { - cross_v3_v3v3(mat[0], mat[1], mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - else { - float vec[3]; - - vec[0] = mat[1][1]; - vec[1] = mat[1][2]; - vec[2] = mat[1][0]; - - cross_v3_v3v3(mat[0], mat[1], vec); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - break; - case 2: - if (dot_v3v3(mat[2], mat[0]) < 1) { - cross_v3_v3v3(mat[1], mat[2], mat[0]); - normalize_v3(mat[1]); - cross_v3_v3v3(mat[0], mat[1], mat[2]); - } - else if (dot_v3v3(mat[2], mat[1]) < 1) { - cross_v3_v3v3(mat[0], mat[1], mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - else { - float vec[3]; - - vec[0] = mat[2][1]; - vec[1] = mat[2][2]; - vec[2] = mat[2][0]; - - cross_v3_v3v3(mat[0], vec, mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - break; - default: - BLI_assert(0); - break; - } - mul_v3_fl(mat[0], size[0]); - mul_v3_fl(mat[1], size[1]); - mul_v3_fl(mat[2], size[2]); + float size[3]; + mat3_to_size(size, mat); + normalize_v3(mat[axis]); + switch (axis) { + case 0: + if (dot_v3v3(mat[0], mat[1]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + else { + float vec[3]; + + vec[0] = mat[0][1]; + vec[1] = mat[0][2]; + vec[2] = mat[0][0]; + + cross_v3_v3v3(mat[2], mat[0], vec); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + break; + case 1: + if (dot_v3v3(mat[1], mat[0]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } + else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + else { + float vec[3]; + + vec[0] = mat[1][1]; + vec[1] = mat[1][2]; + vec[2] = mat[1][0]; + + cross_v3_v3v3(mat[0], mat[1], vec); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + break; + case 2: + if (dot_v3v3(mat[2], mat[0]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } + else if (dot_v3v3(mat[2], mat[1]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + else { + float vec[3]; + + vec[0] = mat[2][1]; + vec[1] = mat[2][2]; + vec[2] = mat[2][0]; + + cross_v3_v3v3(mat[0], vec, mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + break; + default: + BLI_assert(0); + break; + } + mul_v3_fl(mat[0], size[0]); + mul_v3_fl(mat[1], size[1]); + mul_v3_fl(mat[2], size[2]); } /** @@ -1194,428 +1225,420 @@ void orthogonalize_m3(float mat[3][3], int axis) */ void orthogonalize_m4(float mat[4][4], int axis) { - float size[3]; - mat4_to_size(size, mat); - normalize_v3(mat[axis]); - switch (axis) { - case 0: - if (dot_v3v3(mat[0], mat[1]) < 1) { - cross_v3_v3v3(mat[2], mat[0], mat[1]); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - else if (dot_v3v3(mat[0], mat[2]) < 1) { - cross_v3_v3v3(mat[1], mat[2], mat[0]); - normalize_v3(mat[1]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - else { - float vec[3]; - - vec[0] = mat[0][1]; - vec[1] = mat[0][2]; - vec[2] = mat[0][0]; - - cross_v3_v3v3(mat[2], mat[0], vec); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - break; - case 1: - if (dot_v3v3(mat[1], mat[0]) < 1) { - cross_v3_v3v3(mat[2], mat[0], mat[1]); - normalize_v3(mat[2]); - cross_v3_v3v3(mat[0], mat[1], mat[2]); - } - else if (dot_v3v3(mat[0], mat[2]) < 1) { - cross_v3_v3v3(mat[0], mat[1], mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - else { - float vec[3]; - - vec[0] = mat[1][1]; - vec[1] = mat[1][2]; - vec[2] = mat[1][0]; - - cross_v3_v3v3(mat[0], mat[1], vec); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[2], mat[0], mat[1]); - } - break; - case 2: - if (dot_v3v3(mat[2], mat[0]) < 1) { - cross_v3_v3v3(mat[1], mat[2], mat[0]); - normalize_v3(mat[1]); - cross_v3_v3v3(mat[0], mat[1], mat[2]); - } - else if (dot_v3v3(mat[2], mat[1]) < 1) { - cross_v3_v3v3(mat[0], mat[1], mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - else { - float vec[3]; - - vec[0] = mat[2][1]; - vec[1] = mat[2][2]; - vec[2] = mat[2][0]; - - cross_v3_v3v3(mat[0], vec, mat[2]); - normalize_v3(mat[0]); - cross_v3_v3v3(mat[1], mat[2], mat[0]); - } - break; - default: - BLI_assert(0); - break; - } - mul_v3_fl(mat[0], size[0]); - mul_v3_fl(mat[1], size[1]); - mul_v3_fl(mat[2], size[2]); + float size[3]; + mat4_to_size(size, mat); + normalize_v3(mat[axis]); + switch (axis) { + case 0: + if (dot_v3v3(mat[0], mat[1]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + else { + float vec[3]; + + vec[0] = mat[0][1]; + vec[1] = mat[0][2]; + vec[2] = mat[0][0]; + + cross_v3_v3v3(mat[2], mat[0], vec); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + break; + case 1: + if (dot_v3v3(mat[1], mat[0]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } + else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + else { + float vec[3]; + + vec[0] = mat[1][1]; + vec[1] = mat[1][2]; + vec[2] = mat[1][0]; + + cross_v3_v3v3(mat[0], mat[1], vec); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + break; + case 2: + if (dot_v3v3(mat[2], mat[0]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } + else if (dot_v3v3(mat[2], mat[1]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + else { + float vec[3]; + + vec[0] = mat[2][1]; + vec[1] = mat[2][2]; + vec[2] = mat[2][0]; + + cross_v3_v3v3(mat[0], vec, mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + break; + default: + BLI_assert(0); + break; + } + mul_v3_fl(mat[0], size[0]); + mul_v3_fl(mat[1], size[1]); + mul_v3_fl(mat[2], size[2]); } bool is_orthogonal_m3(const float m[3][3]) { - int i, j; + int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < i; j++) { - if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f) { - return false; - } - } - } + for (i = 0; i < 3; i++) { + for (j = 0; j < i; j++) { + if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f) { + return false; + } + } + } - return true; + return true; } bool is_orthogonal_m4(const float m[4][4]) { - int i, j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < i; j++) { - if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f) { - return false; - } - } + int i, j; - } + for (i = 0; i < 4; i++) { + for (j = 0; j < i; j++) { + if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f) { + return false; + } + } + } - return true; + return true; } bool is_orthonormal_m3(const float m[3][3]) { - if (is_orthogonal_m3(m)) { - int i; + if (is_orthogonal_m3(m)) { + int i; - for (i = 0; i < 3; i++) { - if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f) { - return false; - } - } + for (i = 0; i < 3; i++) { + if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f) { + return false; + } + } - return true; - } + return true; + } - return false; + return false; } bool is_orthonormal_m4(const float m[4][4]) { - if (is_orthogonal_m4(m)) { - int i; + if (is_orthogonal_m4(m)) { + int i; - for (i = 0; i < 4; i++) - if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f) { - return false; - } + for (i = 0; i < 4; i++) + if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f) { + return false; + } - return true; - } + return true; + } - return false; + return false; } bool is_uniform_scaled_m3(const float m[3][3]) { - const float eps = 1e-7f; - float t[3][3]; - float l1, l2, l3, l4, l5, l6; + const float eps = 1e-7f; + float t[3][3]; + float l1, l2, l3, l4, l5, l6; - transpose_m3_m3(t, m); + transpose_m3_m3(t, m); - l1 = len_squared_v3(m[0]); - l2 = len_squared_v3(m[1]); - l3 = len_squared_v3(m[2]); + l1 = len_squared_v3(m[0]); + l2 = len_squared_v3(m[1]); + l3 = len_squared_v3(m[2]); - l4 = len_squared_v3(t[0]); - l5 = len_squared_v3(t[1]); - l6 = len_squared_v3(t[2]); + l4 = len_squared_v3(t[0]); + l5 = len_squared_v3(t[1]); + l6 = len_squared_v3(t[2]); - if (fabsf(l2 - l1) <= eps && - fabsf(l3 - l1) <= eps && - fabsf(l4 - l1) <= eps && - fabsf(l5 - l1) <= eps && - fabsf(l6 - l1) <= eps) - { - return true; - } + if (fabsf(l2 - l1) <= eps && fabsf(l3 - l1) <= eps && fabsf(l4 - l1) <= eps && + fabsf(l5 - l1) <= eps && fabsf(l6 - l1) <= eps) { + return true; + } - return false; + return false; } bool is_uniform_scaled_m4(const float m[4][4]) { - float t[3][3]; - copy_m3_m4(t, m); - return is_uniform_scaled_m3(t); + float t[3][3]; + copy_m3_m4(t, m); + return is_uniform_scaled_m3(t); } void normalize_m3_ex(float mat[3][3], float r_scale[3]) { - int i; - for (i = 0; i < 3; i++) { - r_scale[i] = normalize_v3(mat[i]); - } + int i; + for (i = 0; i < 3; i++) { + r_scale[i] = normalize_v3(mat[i]); + } } void normalize_m3(float mat[3][3]) { - int i; - for (i = 0; i < 3; i++) { - normalize_v3(mat[i]); - } + int i; + for (i = 0; i < 3; i++) { + normalize_v3(mat[i]); + } } void normalize_m3_m3_ex(float rmat[3][3], const float mat[3][3], float r_scale[3]) { - int i; - for (i = 0; i < 3; i++) { - r_scale[i] = normalize_v3_v3(rmat[i], mat[i]); - } + int i; + for (i = 0; i < 3; i++) { + r_scale[i] = normalize_v3_v3(rmat[i], mat[i]); + } } void normalize_m3_m3(float rmat[3][3], const float mat[3][3]) { - int i; - for (i = 0; i < 3; i++) { - normalize_v3_v3(rmat[i], mat[i]); - } + int i; + for (i = 0; i < 3; i++) { + normalize_v3_v3(rmat[i], mat[i]); + } } void normalize_m4_ex(float mat[4][4], float r_scale[3]) { - int i; - for (i = 0; i < 3; i++) { - r_scale[i] = normalize_v3(mat[i]); - if (r_scale[i] != 0.0f) { - mat[i][3] /= r_scale[i]; - } - } + int i; + for (i = 0; i < 3; i++) { + r_scale[i] = normalize_v3(mat[i]); + if (r_scale[i] != 0.0f) { + mat[i][3] /= r_scale[i]; + } + } } void normalize_m4(float mat[4][4]) { - int i; - for (i = 0; i < 3; i++) { - float len = normalize_v3(mat[i]); - if (len != 0.0f) { - mat[i][3] /= len; - } - } + int i; + for (i = 0; i < 3; i++) { + float len = normalize_v3(mat[i]); + if (len != 0.0f) { + mat[i][3] /= len; + } + } } void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3]) { - int i; - for (i = 0; i < 3; i++) { - r_scale[i] = normalize_v3_v3(rmat[i], mat[i]); - rmat[i][3] = (r_scale[i] != 0.0f) ? (mat[i][3] / r_scale[i]) : mat[i][3]; - } - copy_v4_v4(rmat[3], mat[3]); + int i; + for (i = 0; i < 3; i++) { + r_scale[i] = normalize_v3_v3(rmat[i], mat[i]); + rmat[i][3] = (r_scale[i] != 0.0f) ? (mat[i][3] / r_scale[i]) : mat[i][3]; + } + copy_v4_v4(rmat[3], mat[3]); } void normalize_m4_m4(float rmat[4][4], const float mat[4][4]) { - int i; - for (i = 0; i < 3; i++) { - float len = normalize_v3_v3(rmat[i], mat[i]); - rmat[i][3] = (len != 0.0f) ? (mat[i][3] / len) : mat[i][3]; - } - copy_v4_v4(rmat[3], mat[3]); + int i; + for (i = 0; i < 3; i++) { + float len = normalize_v3_v3(rmat[i], mat[i]); + rmat[i][3] = (len != 0.0f) ? (mat[i][3] / len) : mat[i][3]; + } + copy_v4_v4(rmat[3], mat[3]); } void adjoint_m2_m2(float m1[2][2], const float m[2][2]) { - BLI_assert(m1 != m); - m1[0][0] = m[1][1]; - m1[0][1] = -m[0][1]; - m1[1][0] = -m[1][0]; - m1[1][1] = m[0][0]; + BLI_assert(m1 != m); + m1[0][0] = m[1][1]; + m1[0][1] = -m[0][1]; + m1[1][0] = -m[1][0]; + m1[1][1] = m[0][0]; } void adjoint_m3_m3(float m1[3][3], const float m[3][3]) { - BLI_assert(m1 != m); - m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; - m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1]; - m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; + BLI_assert(m1 != m); + m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; + m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1]; + m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; - m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0]; - m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; - m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0]; + m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0]; + m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; + m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0]; - m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; - m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0]; - m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0]; + m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; + m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0]; + m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0]; } void adjoint_m4_m4(float out[4][4], const float in[4][4]) /* out = ADJ(in) */ { - float a1, a2, a3, a4, b1, b2, b3, b4; - float c1, c2, c3, c4, d1, d2, d3, d4; + float a1, a2, a3, a4, b1, b2, b3, b4; + float c1, c2, c3, c4, d1, d2, d3, d4; - a1 = in[0][0]; - b1 = in[0][1]; - c1 = in[0][2]; - d1 = in[0][3]; + a1 = in[0][0]; + b1 = in[0][1]; + c1 = in[0][2]; + d1 = in[0][3]; - a2 = in[1][0]; - b2 = in[1][1]; - c2 = in[1][2]; - d2 = in[1][3]; + a2 = in[1][0]; + b2 = in[1][1]; + c2 = in[1][2]; + d2 = in[1][3]; - a3 = in[2][0]; - b3 = in[2][1]; - c3 = in[2][2]; - d3 = in[2][3]; + a3 = in[2][0]; + b3 = in[2][1]; + c3 = in[2][2]; + d3 = in[2][3]; - a4 = in[3][0]; - b4 = in[3][1]; - c4 = in[3][2]; - d4 = in[3][3]; + a4 = in[3][0]; + b4 = in[3][1]; + c4 = in[3][2]; + d4 = in[3][3]; + out[0][0] = determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4); + out[1][0] = -determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4); + out[2][0] = determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4); + out[3][0] = -determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4); - out[0][0] = determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4); - out[1][0] = -determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4); - out[2][0] = determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4); - out[3][0] = -determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4); + out[0][1] = -determinant_m3(b1, b3, b4, c1, c3, c4, d1, d3, d4); + out[1][1] = determinant_m3(a1, a3, a4, c1, c3, c4, d1, d3, d4); + out[2][1] = -determinant_m3(a1, a3, a4, b1, b3, b4, d1, d3, d4); + out[3][1] = determinant_m3(a1, a3, a4, b1, b3, b4, c1, c3, c4); - out[0][1] = -determinant_m3(b1, b3, b4, c1, c3, c4, d1, d3, d4); - out[1][1] = determinant_m3(a1, a3, a4, c1, c3, c4, d1, d3, d4); - out[2][1] = -determinant_m3(a1, a3, a4, b1, b3, b4, d1, d3, d4); - out[3][1] = determinant_m3(a1, a3, a4, b1, b3, b4, c1, c3, c4); + out[0][2] = determinant_m3(b1, b2, b4, c1, c2, c4, d1, d2, d4); + out[1][2] = -determinant_m3(a1, a2, a4, c1, c2, c4, d1, d2, d4); + out[2][2] = determinant_m3(a1, a2, a4, b1, b2, b4, d1, d2, d4); + out[3][2] = -determinant_m3(a1, a2, a4, b1, b2, b4, c1, c2, c4); - out[0][2] = determinant_m3(b1, b2, b4, c1, c2, c4, d1, d2, d4); - out[1][2] = -determinant_m3(a1, a2, a4, c1, c2, c4, d1, d2, d4); - out[2][2] = determinant_m3(a1, a2, a4, b1, b2, b4, d1, d2, d4); - out[3][2] = -determinant_m3(a1, a2, a4, b1, b2, b4, c1, c2, c4); - - out[0][3] = -determinant_m3(b1, b2, b3, c1, c2, c3, d1, d2, d3); - out[1][3] = determinant_m3(a1, a2, a3, c1, c2, c3, d1, d2, d3); - out[2][3] = -determinant_m3(a1, a2, a3, b1, b2, b3, d1, d2, d3); - out[3][3] = determinant_m3(a1, a2, a3, b1, b2, b3, c1, c2, c3); + out[0][3] = -determinant_m3(b1, b2, b3, c1, c2, c3, d1, d2, d3); + out[1][3] = determinant_m3(a1, a2, a3, c1, c2, c3, d1, d2, d3); + out[2][3] = -determinant_m3(a1, a2, a3, b1, b2, b3, d1, d2, d3); + out[3][3] = determinant_m3(a1, a2, a3, b1, b2, b3, c1, c2, c3); } float determinant_m2(float a, float b, float c, float d) { - return a * d - b * c; + return a * d - b * c; } -float determinant_m3(float a1, float a2, float a3, - float b1, float b2, float b3, - float c1, float c2, float c3) +float determinant_m3( + float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) { - float ans; + float ans; - ans = (a1 * determinant_m2(b2, b3, c2, c3) - - b1 * determinant_m2(a2, a3, c2, c3) + - c1 * determinant_m2(a2, a3, b2, b3)); + ans = (a1 * determinant_m2(b2, b3, c2, c3) - b1 * determinant_m2(a2, a3, c2, c3) + + c1 * determinant_m2(a2, a3, b2, b3)); - return ans; + return ans; } float determinant_m4(const float m[4][4]) { - float ans; - float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4; + float ans; + float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4; - a1 = m[0][0]; - b1 = m[0][1]; - c1 = m[0][2]; - d1 = m[0][3]; + a1 = m[0][0]; + b1 = m[0][1]; + c1 = m[0][2]; + d1 = m[0][3]; - a2 = m[1][0]; - b2 = m[1][1]; - c2 = m[1][2]; - d2 = m[1][3]; + a2 = m[1][0]; + b2 = m[1][1]; + c2 = m[1][2]; + d2 = m[1][3]; - a3 = m[2][0]; - b3 = m[2][1]; - c3 = m[2][2]; - d3 = m[2][3]; + a3 = m[2][0]; + b3 = m[2][1]; + c3 = m[2][2]; + d3 = m[2][3]; - a4 = m[3][0]; - b4 = m[3][1]; - c4 = m[3][2]; - d4 = m[3][3]; + a4 = m[3][0]; + b4 = m[3][1]; + c4 = m[3][2]; + d4 = m[3][3]; - ans = (a1 * determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4) - - b1 * determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4) + - c1 * determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4) - - d1 * determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4)); + ans = (a1 * determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4) - + b1 * determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4) + + c1 * determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4) - + d1 * determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4)); - return ans; + return ans; } /****************************** Transformations ******************************/ void size_to_mat3(float mat[3][3], const float size[3]) { - mat[0][0] = size[0]; - mat[0][1] = 0.0f; - mat[0][2] = 0.0f; - mat[1][1] = size[1]; - mat[1][0] = 0.0f; - mat[1][2] = 0.0f; - mat[2][2] = size[2]; - mat[2][1] = 0.0f; - mat[2][0] = 0.0f; + mat[0][0] = size[0]; + mat[0][1] = 0.0f; + mat[0][2] = 0.0f; + mat[1][1] = size[1]; + mat[1][0] = 0.0f; + mat[1][2] = 0.0f; + mat[2][2] = size[2]; + mat[2][1] = 0.0f; + mat[2][0] = 0.0f; } void size_to_mat4(float mat[4][4], const float size[3]) { - mat[0][0] = size[0]; - mat[0][1] = 0.0f; - mat[0][2] = 0.0f; - mat[0][3] = 0.0f; - mat[1][0] = 0.0f; - mat[1][1] = size[1]; - mat[1][2] = 0.0f; - mat[1][3] = 0.0f; - mat[2][0] = 0.0f; - mat[2][1] = 0.0f; - mat[2][2] = size[2]; - mat[2][3] = 0.0f; - mat[3][0] = 0.0f; - mat[3][1] = 0.0f; - mat[3][2] = 0.0f; - mat[3][3] = 1.0f; + mat[0][0] = size[0]; + mat[0][1] = 0.0f; + mat[0][2] = 0.0f; + mat[0][3] = 0.0f; + mat[1][0] = 0.0f; + mat[1][1] = size[1]; + mat[1][2] = 0.0f; + mat[1][3] = 0.0f; + mat[2][0] = 0.0f; + mat[2][1] = 0.0f; + mat[2][2] = size[2]; + mat[2][3] = 0.0f; + mat[3][0] = 0.0f; + mat[3][1] = 0.0f; + mat[3][2] = 0.0f; + mat[3][3] = 1.0f; } void mat3_to_size(float size[3], const float mat[3][3]) { - size[0] = len_v3(mat[0]); - size[1] = len_v3(mat[1]); - size[2] = len_v3(mat[2]); + size[0] = len_v3(mat[0]); + size[1] = len_v3(mat[1]); + size[2] = len_v3(mat[2]); } void mat4_to_size(float size[3], const float mat[4][4]) { - size[0] = len_v3(mat[0]); - size[1] = len_v3(mat[1]); - size[2] = len_v3(mat[2]); + size[0] = len_v3(mat[0]); + size[1] = len_v3(mat[1]); + size[2] = len_v3(mat[2]); } /* this gets the average scale of a matrix, only use when your scaling @@ -1623,77 +1646,77 @@ void mat4_to_size(float size[3], const float mat[4][4]) * and curve radius */ float mat3_to_scale(const float mat[3][3]) { - /* unit length vector */ - float unit_vec[3]; - copy_v3_fl(unit_vec, (float)M_SQRT1_3); - mul_m3_v3(mat, unit_vec); - return len_v3(unit_vec); + /* unit length vector */ + float unit_vec[3]; + copy_v3_fl(unit_vec, (float)M_SQRT1_3); + mul_m3_v3(mat, unit_vec); + return len_v3(unit_vec); } float mat4_to_scale(const float mat[4][4]) { - /* unit length vector */ - float unit_vec[3]; - copy_v3_fl(unit_vec, (float)M_SQRT1_3); - mul_mat3_m4_v3(mat, unit_vec); - return len_v3(unit_vec); + /* unit length vector */ + float unit_vec[3]; + copy_v3_fl(unit_vec, (float)M_SQRT1_3); + mul_mat3_m4_v3(mat, unit_vec); + return len_v3(unit_vec); } /** Return 2D scale (in XY plane) of given mat4. */ float mat4_to_xy_scale(const float M[4][4]) { - /* unit length vector in xy plane */ - float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f}; - mul_mat3_m4_v3(M, unit_vec); - return len_v3(unit_vec); + /* unit length vector in xy plane */ + float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f}; + mul_mat3_m4_v3(M, unit_vec); + return len_v3(unit_vec); } void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]) { - /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ - size[0] = normalize_v3_v3(rot[0], mat3[0]); - size[1] = normalize_v3_v3(rot[1], mat3[1]); - size[2] = normalize_v3_v3(rot[2], mat3[2]); - if (UNLIKELY(is_negative_m3(rot))) { - negate_m3(rot); - negate_v3(size); - } + /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ + size[0] = normalize_v3_v3(rot[0], mat3[0]); + size[1] = normalize_v3_v3(rot[1], mat3[1]); + size[2] = normalize_v3_v3(rot[2], mat3[2]); + if (UNLIKELY(is_negative_m3(rot))) { + negate_m3(rot); + negate_v3(size); + } } void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]) { - float mat3[3][3]; /* wmat -> 3x3 */ + float mat3[3][3]; /* wmat -> 3x3 */ - copy_m3_m4(mat3, wmat); - mat3_to_rot_size(rot, size, mat3); + copy_m3_m4(mat3, wmat); + mat3_to_rot_size(rot, size, mat3); - /* location */ - copy_v3_v3(loc, wmat[3]); + /* location */ + copy_v3_v3(loc, wmat[3]); } void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]) { - float mat3[3][3]; - float mat3_n[3][3]; /* normalized mat3 */ + float mat3[3][3]; + float mat3_n[3][3]; /* normalized mat3 */ - copy_m3_m4(mat3, wmat); - normalize_m3_m3(mat3_n, mat3); + copy_m3_m4(mat3, wmat); + normalize_m3_m3(mat3_n, mat3); - /* so scale doesn't interfere with rotation [#24291] */ - /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ - if (is_negative_m3(mat3)) { - negate_m3(mat3_n); - } + /* so scale doesn't interfere with rotation [#24291] */ + /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ + if (is_negative_m3(mat3)) { + negate_m3(mat3_n); + } - mat3_normalized_to_quat(quat, mat3_n); - copy_v3_v3(loc, wmat[3]); + mat3_normalized_to_quat(quat, mat3_n); + copy_v3_v3(loc, wmat[3]); } void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]) { - float rot[3][3]; - mat4_to_loc_rot_size(loc, rot, size, wmat); - mat3_normalized_to_quat(quat, rot); + float rot[3][3]; + mat4_to_loc_rot_size(loc, rot, size, wmat); + mat3_normalized_to_quat(quat, rot); } /** @@ -1708,46 +1731,46 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat #ifndef MATH_STANDALONE void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]) { - /* From svd decomposition (M = WSV*), we have: - * U = WV* - * P = VSV* - */ - float W[3][3], S[3][3], V[3][3], Vt[3][3]; - float sval[3]; + /* From svd decomposition (M = WSV*), we have: + * U = WV* + * P = VSV* + */ + float W[3][3], S[3][3], V[3][3], Vt[3][3]; + float sval[3]; - BLI_svd_m3(mat3, W, sval, V); + BLI_svd_m3(mat3, W, sval, V); - size_to_mat3(S, sval); + size_to_mat3(S, sval); - transpose_m3_m3(Vt, V); - mul_m3_m3m3(r_U, W, Vt); - mul_m3_series(r_P, V, S, Vt); + transpose_m3_m3(Vt, V); + mul_m3_m3m3(r_U, W, Vt); + mul_m3_series(r_P, V, S, Vt); } #endif void scale_m3_fl(float m[3][3], float scale) { - m[0][0] = m[1][1] = m[2][2] = scale; - m[0][1] = m[0][2] = 0.0; - m[1][0] = m[1][2] = 0.0; - m[2][0] = m[2][1] = 0.0; + m[0][0] = m[1][1] = m[2][2] = scale; + m[0][1] = m[0][2] = 0.0; + m[1][0] = m[1][2] = 0.0; + m[2][0] = m[2][1] = 0.0; } void scale_m4_fl(float m[4][4], float scale) { - m[0][0] = m[1][1] = m[2][2] = scale; - m[3][3] = 1.0; - m[0][1] = m[0][2] = m[0][3] = 0.0; - m[1][0] = m[1][2] = m[1][3] = 0.0; - m[2][0] = m[2][1] = m[2][3] = 0.0; - m[3][0] = m[3][1] = m[3][2] = 0.0; + m[0][0] = m[1][1] = m[2][2] = scale; + m[3][3] = 1.0; + m[0][1] = m[0][2] = m[0][3] = 0.0; + m[1][0] = m[1][2] = m[1][3] = 0.0; + m[2][0] = m[2][1] = m[2][3] = 0.0; + m[3][0] = m[3][1] = m[3][2] = 0.0; } void translate_m4(float mat[4][4], float Tx, float Ty, float Tz) { - mat[3][0] += (Tx * mat[0][0] + Ty * mat[1][0] + Tz * mat[2][0]); - mat[3][1] += (Tx * mat[0][1] + Ty * mat[1][1] + Tz * mat[2][1]); - mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]); + mat[3][0] += (Tx * mat[0][0] + Ty * mat[1][0] + Tz * mat[2][0]); + mat[3][1] += (Tx * mat[0][1] + Ty * mat[1][1] + Tz * mat[2][1]); + mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]); } /* TODO: enum for axis? */ @@ -1760,39 +1783,39 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz) */ void rotate_m4(float mat[4][4], const char axis, const float angle) { - const float angle_cos = cosf(angle); - const float angle_sin = sinf(angle); - - assert(axis >= 'X' && axis <= 'Z'); - - switch (axis) { - case 'X': - for (int col = 0; col < 4; col++) { - float temp = angle_cos * mat[1][col] + angle_sin * mat[2][col]; - mat[2][col] = -angle_sin * mat[1][col] + angle_cos * mat[2][col]; - mat[1][col] = temp; - } - break; - - case 'Y': - for (int col = 0; col < 4; col++) { - float temp = angle_cos * mat[0][col] - angle_sin * mat[2][col]; - mat[2][col] = angle_sin * mat[0][col] + angle_cos * mat[2][col]; - mat[0][col] = temp; - } - break; - - case 'Z': - for (int col = 0; col < 4; col++) { - float temp = angle_cos * mat[0][col] + angle_sin * mat[1][col]; - mat[1][col] = -angle_sin * mat[0][col] + angle_cos * mat[1][col]; - mat[0][col] = temp; - } - break; - default: - BLI_assert(0); - break; - } + const float angle_cos = cosf(angle); + const float angle_sin = sinf(angle); + + assert(axis >= 'X' && axis <= 'Z'); + + switch (axis) { + case 'X': + for (int col = 0; col < 4; col++) { + float temp = angle_cos * mat[1][col] + angle_sin * mat[2][col]; + mat[2][col] = -angle_sin * mat[1][col] + angle_cos * mat[2][col]; + mat[1][col] = temp; + } + break; + + case 'Y': + for (int col = 0; col < 4; col++) { + float temp = angle_cos * mat[0][col] - angle_sin * mat[2][col]; + mat[2][col] = angle_sin * mat[0][col] + angle_cos * mat[2][col]; + mat[0][col] = temp; + } + break; + + case 'Z': + for (int col = 0; col < 4; col++) { + float temp = angle_cos * mat[0][col] + angle_sin * mat[1][col]; + mat[1][col] = -angle_sin * mat[0][col] + angle_cos * mat[1][col]; + mat[0][col] = temp; + } + break; + default: + BLI_assert(0); + break; + } } /** @@ -1805,61 +1828,67 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) */ void transform_pivot_set_m4(float mat[4][4], const float pivot[3]) { - float tmat[4][4]; + float tmat[4][4]; - unit_m4(tmat); + unit_m4(tmat); - copy_v3_v3(tmat[3], pivot); - mul_m4_m4m4(mat, tmat, mat); + copy_v3_v3(tmat[3], pivot); + mul_m4_m4m4(mat, tmat, mat); - /* invert the matrix */ - negate_v3(tmat[3]); - mul_m4_m4m4(mat, mat, tmat); + /* invert the matrix */ + negate_v3(tmat[3]); + mul_m4_m4m4(mat, mat, tmat); } -void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], const float srcweight) +void blend_m3_m3m3(float out[3][3], + const float dst[3][3], + const float src[3][3], + const float srcweight) { - float srot[3][3], drot[3][3]; - float squat[4], dquat[4], fquat[4]; - float sscale[3], dscale[3], fsize[3]; - float rmat[3][3], smat[3][3]; + float srot[3][3], drot[3][3]; + float squat[4], dquat[4], fquat[4]; + float sscale[3], dscale[3], fsize[3]; + float rmat[3][3], smat[3][3]; - mat3_to_rot_size(drot, dscale, dst); - mat3_to_rot_size(srot, sscale, src); + mat3_to_rot_size(drot, dscale, dst); + mat3_to_rot_size(srot, sscale, src); - mat3_normalized_to_quat(dquat, drot); - mat3_normalized_to_quat(squat, srot); + mat3_normalized_to_quat(dquat, drot); + mat3_normalized_to_quat(squat, srot); - /* do blending */ - interp_qt_qtqt(fquat, dquat, squat, srcweight); - interp_v3_v3v3(fsize, dscale, sscale, srcweight); + /* do blending */ + interp_qt_qtqt(fquat, dquat, squat, srcweight); + interp_v3_v3v3(fsize, dscale, sscale, srcweight); - /* compose new matrix */ - quat_to_mat3(rmat, fquat); - size_to_mat3(smat, fsize); - mul_m3_m3m3(out, rmat, smat); + /* compose new matrix */ + quat_to_mat3(rmat, fquat); + size_to_mat3(smat, fsize); + mul_m3_m3m3(out, rmat, smat); } -void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], const float srcweight) +void blend_m4_m4m4(float out[4][4], + const float dst[4][4], + const float src[4][4], + const float srcweight) { - float sloc[3], dloc[3], floc[3]; - float srot[3][3], drot[3][3]; - float squat[4], dquat[4], fquat[4]; - float sscale[3], dscale[3], fsize[3]; + float sloc[3], dloc[3], floc[3]; + float srot[3][3], drot[3][3]; + float squat[4], dquat[4], fquat[4]; + float sscale[3], dscale[3], fsize[3]; - mat4_to_loc_rot_size(dloc, drot, dscale, dst); - mat4_to_loc_rot_size(sloc, srot, sscale, src); + mat4_to_loc_rot_size(dloc, drot, dscale, dst); + mat4_to_loc_rot_size(sloc, srot, sscale, src); - mat3_normalized_to_quat(dquat, drot); - mat3_normalized_to_quat(squat, srot); + mat3_normalized_to_quat(dquat, drot); + mat3_normalized_to_quat(squat, srot); - /* do blending */ - interp_v3_v3v3(floc, dloc, sloc, srcweight); - interp_qt_qtqt(fquat, dquat, squat, srcweight); - interp_v3_v3v3(fsize, dscale, sscale, srcweight); + /* do blending */ + interp_v3_v3v3(floc, dloc, sloc, srcweight); + interp_qt_qtqt(fquat, dquat, squat, srcweight); + interp_v3_v3v3(fsize, dscale, sscale, srcweight); - /* compose new matrix */ - loc_quat_size_to_mat4(out, floc, fquat, fsize); + /* compose new matrix */ + loc_quat_size_to_mat4(out, floc, fquat, fsize); } /* for builds without Eigen */ @@ -1880,31 +1909,31 @@ void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4] */ void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t) { - /* 'Rotation' component ('U' part of polar decomposition, - * the closest orthogonal matrix to M3 rot/scale - * transformation matrix), spherically interpolated. */ - float U_A[3][3], U_B[3][3], U[3][3]; - float quat_A[4], quat_B[4], quat[4]; - /* 'Scaling' component ('P' part of polar decomposition, i.e. scaling in U-defined space), - * linearly interpolated. */ - float P_A[3][3], P_B[3][3], P[3][3]; + /* 'Rotation' component ('U' part of polar decomposition, + * the closest orthogonal matrix to M3 rot/scale + * transformation matrix), spherically interpolated. */ + float U_A[3][3], U_B[3][3], U[3][3]; + float quat_A[4], quat_B[4], quat[4]; + /* 'Scaling' component ('P' part of polar decomposition, i.e. scaling in U-defined space), + * linearly interpolated. */ + float P_A[3][3], P_B[3][3], P[3][3]; - int i; + int i; - mat3_polar_decompose(A, U_A, P_A); - mat3_polar_decompose(B, U_B, P_B); + mat3_polar_decompose(A, U_A, P_A); + mat3_polar_decompose(B, U_B, P_B); - mat3_to_quat(quat_A, U_A); - mat3_to_quat(quat_B, U_B); - interp_qt_qtqt(quat, quat_A, quat_B, t); - quat_to_mat3(U, quat); + mat3_to_quat(quat_A, U_A); + mat3_to_quat(quat_B, U_B); + interp_qt_qtqt(quat, quat_A, quat_B, t); + quat_to_mat3(U, quat); - for (i = 0; i < 3; i++) { - interp_v3_v3v3(P[i], P_A[i], P_B[i], t); - } + for (i = 0; i < 3; i++) { + interp_v3_v3v3(P[i], P_A[i], P_B[i], t); + } - /* And we reconstruct rot/scale matrix from interpolated polar components */ - mul_m3_m3m3(R, U, P); + /* And we reconstruct rot/scale matrix from interpolated polar components */ + mul_m3_m3m3(R, U, P); } /** @@ -1917,168 +1946,173 @@ void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], con */ void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t) { - float A3[3][3], B3[3][3], R3[3][3]; + float A3[3][3], B3[3][3], R3[3][3]; - /* Location component, linearly interpolated. */ - float loc_A[3], loc_B[3], loc[3]; + /* Location component, linearly interpolated. */ + float loc_A[3], loc_B[3], loc[3]; - copy_v3_v3(loc_A, A[3]); - copy_v3_v3(loc_B, B[3]); - interp_v3_v3v3(loc, loc_A, loc_B, t); + copy_v3_v3(loc_A, A[3]); + copy_v3_v3(loc_B, B[3]); + interp_v3_v3v3(loc, loc_A, loc_B, t); - copy_m3_m4(A3, A); - copy_m3_m4(B3, B); + copy_m3_m4(A3, A); + copy_m3_m4(B3, B); - interp_m3_m3m3(R3, A3, B3, t); + interp_m3_m3m3(R3, A3, B3, t); - copy_m4_m3(R, R3); - copy_v3_v3(R[3], loc); + copy_m4_m3(R, R3); + copy_v3_v3(R[3], loc); } -#endif /* MATH_STANDALONE */ +#endif /* MATH_STANDALONE */ bool is_negative_m3(const float mat[3][3]) { - float vec[3]; - cross_v3_v3v3(vec, mat[0], mat[1]); - return (dot_v3v3(vec, mat[2]) < 0.0f); + float vec[3]; + cross_v3_v3v3(vec, mat[0], mat[1]); + return (dot_v3v3(vec, mat[2]) < 0.0f); } bool is_negative_m4(const float mat[4][4]) { - float vec[3]; - cross_v3_v3v3(vec, mat[0], mat[1]); - return (dot_v3v3(vec, mat[2]) < 0.0f); + float vec[3]; + cross_v3_v3v3(vec, mat[0], mat[1]); + return (dot_v3v3(vec, mat[2]) < 0.0f); } bool is_zero_m3(const float mat[3][3]) { - return (is_zero_v3(mat[0]) && - is_zero_v3(mat[1]) && - is_zero_v3(mat[2])); + return (is_zero_v3(mat[0]) && is_zero_v3(mat[1]) && is_zero_v3(mat[2])); } bool is_zero_m4(const float mat[4][4]) { - return (is_zero_v4(mat[0]) && - is_zero_v4(mat[1]) && - is_zero_v4(mat[2]) && - is_zero_v4(mat[3])); + return (is_zero_v4(mat[0]) && is_zero_v4(mat[1]) && is_zero_v4(mat[2]) && is_zero_v4(mat[3])); } bool equals_m3m3(const float mat1[3][3], const float mat2[3][3]) { - return (equals_v3v3(mat1[0], mat2[0]) && - equals_v3v3(mat1[1], mat2[1]) && - equals_v3v3(mat1[2], mat2[2])); + return (equals_v3v3(mat1[0], mat2[0]) && equals_v3v3(mat1[1], mat2[1]) && + equals_v3v3(mat1[2], mat2[2])); } bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]) { - return (equals_v4v4(mat1[0], mat2[0]) && - equals_v4v4(mat1[1], mat2[1]) && - equals_v4v4(mat1[2], mat2[2]) && - equals_v4v4(mat1[3], mat2[3])); + return (equals_v4v4(mat1[0], mat2[0]) && equals_v4v4(mat1[1], mat2[1]) && + equals_v4v4(mat1[2], mat2[2]) && equals_v4v4(mat1[3], mat2[3])); } /* make a 4x4 matrix out of 3 transform components */ /* matrices are made in the order: scale * rot * loc */ /* TODO: need to have a version that allows for rotation order... */ -void loc_eul_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], const float size[3]) +void loc_eul_size_to_mat4(float mat[4][4], + const float loc[3], + const float eul[3], + const float size[3]) { - float rmat[3][3], smat[3][3], tmat[3][3]; + float rmat[3][3], smat[3][3], tmat[3][3]; - /* initialize new matrix */ - unit_m4(mat); + /* initialize new matrix */ + unit_m4(mat); - /* make rotation + scaling part */ - eul_to_mat3(rmat, eul); - size_to_mat3(smat, size); - mul_m3_m3m3(tmat, rmat, smat); + /* make rotation + scaling part */ + eul_to_mat3(rmat, eul); + size_to_mat3(smat, size); + mul_m3_m3m3(tmat, rmat, smat); - /* copy rot/scale part to output matrix*/ - copy_m4_m3(mat, tmat); + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); - /* copy location to matrix */ - mat[3][0] = loc[0]; - mat[3][1] = loc[1]; - mat[3][2] = loc[2]; + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; } /* make a 4x4 matrix out of 3 transform components */ /* matrices are made in the order: scale * rot * loc */ -void loc_eulO_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], const float size[3], const short rotOrder) +void loc_eulO_size_to_mat4(float mat[4][4], + const float loc[3], + const float eul[3], + const float size[3], + const short rotOrder) { - float rmat[3][3], smat[3][3], tmat[3][3]; + float rmat[3][3], smat[3][3], tmat[3][3]; - /* initialize new matrix */ - unit_m4(mat); + /* initialize new matrix */ + unit_m4(mat); - /* make rotation + scaling part */ - eulO_to_mat3(rmat, eul, rotOrder); - size_to_mat3(smat, size); - mul_m3_m3m3(tmat, rmat, smat); + /* make rotation + scaling part */ + eulO_to_mat3(rmat, eul, rotOrder); + size_to_mat3(smat, size); + mul_m3_m3m3(tmat, rmat, smat); - /* copy rot/scale part to output matrix*/ - copy_m4_m3(mat, tmat); + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); - /* copy location to matrix */ - mat[3][0] = loc[0]; - mat[3][1] = loc[1]; - mat[3][2] = loc[2]; + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; } - /* make a 4x4 matrix out of 3 transform components */ /* matrices are made in the order: scale * rot * loc */ -void loc_quat_size_to_mat4(float mat[4][4], const float loc[3], const float quat[4], const float size[3]) +void loc_quat_size_to_mat4(float mat[4][4], + const float loc[3], + const float quat[4], + const float size[3]) { - float rmat[3][3], smat[3][3], tmat[3][3]; + float rmat[3][3], smat[3][3], tmat[3][3]; - /* initialize new matrix */ - unit_m4(mat); + /* initialize new matrix */ + unit_m4(mat); - /* make rotation + scaling part */ - quat_to_mat3(rmat, quat); - size_to_mat3(smat, size); - mul_m3_m3m3(tmat, rmat, smat); + /* make rotation + scaling part */ + quat_to_mat3(rmat, quat); + size_to_mat3(smat, size); + mul_m3_m3m3(tmat, rmat, smat); - /* copy rot/scale part to output matrix*/ - copy_m4_m3(mat, tmat); + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); - /* copy location to matrix */ - mat[3][0] = loc[0]; - mat[3][1] = loc[1]; - mat[3][2] = loc[2]; + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; } -void loc_axisangle_size_to_mat4(float mat[4][4], const float loc[3], const float axis[3], const float angle, const float size[3]) +void loc_axisangle_size_to_mat4(float mat[4][4], + const float loc[3], + const float axis[3], + const float angle, + const float size[3]) { - float q[4]; - axis_angle_to_quat(q, axis, angle); - loc_quat_size_to_mat4(mat, loc, q, size); + float q[4]; + axis_angle_to_quat(q, axis, angle); + loc_quat_size_to_mat4(mat, loc, q, size); } /*********************************** Other ***********************************/ void print_m3(const char *str, const float m[3][3]) { - printf("%s\n", str); - printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]); - printf("%f %f %f\n", m[0][1], m[1][1], m[2][1]); - printf("%f %f %f\n", m[0][2], m[1][2], m[2][2]); - printf("\n"); + printf("%s\n", str); + printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]); + printf("%f %f %f\n", m[0][1], m[1][1], m[2][1]); + printf("%f %f %f\n", m[0][2], m[1][2], m[2][2]); + printf("\n"); } void print_m4(const char *str, const float m[4][4]) { - printf("%s\n", str); - printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]); - printf("%f %f %f %f\n", m[0][1], m[1][1], m[2][1], m[3][1]); - printf("%f %f %f %f\n", m[0][2], m[1][2], m[2][2], m[3][2]); - printf("%f %f %f %f\n", m[0][3], m[1][3], m[2][3], m[3][3]); - printf("\n"); + printf("%s\n", str); + printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]); + printf("%f %f %f %f\n", m[0][1], m[1][1], m[2][1], m[3][1]); + printf("%f %f %f %f\n", m[0][2], m[1][2], m[2][2], m[3][2]); + printf("%f %f %f %f\n", m[0][3], m[1][3], m[2][3], m[3][3]); + printf("\n"); } /*********************************** SVD ************************************ @@ -2093,501 +2127,495 @@ void print_m4(const char *str, const float m[4][4]) void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) { - float A[4][4]; - float work1[4], work2[4]; - int m = 4; - int n = 4; - int maxiter = 200; - int nu = min_ii(m, n); - - float *work = work1; - float *e = work2; - float eps; - - int i = 0, j = 0, k = 0, p, pp, iter; - - /* Reduce A to bidiagonal form, storing the diagonal elements - * in s and the super-diagonal elements in e. */ - - int nct = min_ii(m - 1, n); - int nrt = max_ii(0, min_ii(n - 2, m)); - - copy_m4_m4(A, A_); - zero_m4(U); - zero_v4(s); - - for (k = 0; k < max_ii(nct, nrt); k++) { - if (k < nct) { - - /* Compute the transformation for the k-th column and - * place the k-th diagonal in s[k]. - * Compute 2-norm of k-th column without under/overflow. */ - s[k] = 0; - for (i = k; i < m; i++) { - s[k] = hypotf(s[k], A[i][k]); - } - if (s[k] != 0.0f) { - float invsk; - if (A[k][k] < 0.0f) { - s[k] = -s[k]; - } - invsk = 1.0f / s[k]; - for (i = k; i < m; i++) { - A[i][k] *= invsk; - } - A[k][k] += 1.0f; - } - s[k] = -s[k]; - } - for (j = k + 1; j < n; j++) { - if ((k < nct) && (s[k] != 0.0f)) { - - /* Apply the transformation. */ - - float t = 0; - for (i = k; i < m; i++) { - t += A[i][k] * A[i][j]; - } - t = -t / A[k][k]; - for (i = k; i < m; i++) { - A[i][j] += t * A[i][k]; - } - } - - /* Place the k-th row of A into e for the */ - /* subsequent calculation of the row transformation. */ - - e[j] = A[k][j]; - } - if (k < nct) { - - /* Place the transformation in U for subsequent back - * multiplication. */ - - for (i = k; i < m; i++) { - U[i][k] = A[i][k]; - } - } - if (k < nrt) { - - /* Compute the k-th row transformation and place the - * k-th super-diagonal in e[k]. - * Compute 2-norm without under/overflow. */ - e[k] = 0; - for (i = k + 1; i < n; i++) { - e[k] = hypotf(e[k], e[i]); - } - if (e[k] != 0.0f) { - float invek; - if (e[k + 1] < 0.0f) { - e[k] = -e[k]; - } - invek = 1.0f / e[k]; - for (i = k + 1; i < n; i++) { - e[i] *= invek; - } - e[k + 1] += 1.0f; - } - e[k] = -e[k]; - if ((k + 1 < m) & (e[k] != 0.0f)) { - float invek1; - - /* Apply the transformation. */ - - for (i = k + 1; i < m; i++) { - work[i] = 0.0f; - } - for (j = k + 1; j < n; j++) { - for (i = k + 1; i < m; i++) { - work[i] += e[j] * A[i][j]; - } - } - invek1 = 1.0f / e[k + 1]; - for (j = k + 1; j < n; j++) { - float t = -e[j] * invek1; - for (i = k + 1; i < m; i++) { - A[i][j] += t * work[i]; - } - } - } - - /* Place the transformation in V for subsequent - * back multiplication. */ - - for (i = k + 1; i < n; i++) { - V[i][k] = e[i]; - } - } - } - - /* Set up the final bidiagonal matrix or order p. */ - - p = min_ii(n, m + 1); - if (nct < n) { - s[nct] = A[nct][nct]; - } - if (m < p) { - s[p - 1] = 0.0f; - } - if (nrt + 1 < p) { - e[nrt] = A[nrt][p - 1]; - } - e[p - 1] = 0.0f; - - /* If required, generate U. */ - - for (j = nct; j < nu; j++) { - for (i = 0; i < m; i++) { - U[i][j] = 0.0f; - } - U[j][j] = 1.0f; - } - for (k = nct - 1; k >= 0; k--) { - if (s[k] != 0.0f) { - for (j = k + 1; j < nu; j++) { - float t = 0; - for (i = k; i < m; i++) { - t += U[i][k] * U[i][j]; - } - t = -t / U[k][k]; - for (i = k; i < m; i++) { - U[i][j] += t * U[i][k]; - } - } - for (i = k; i < m; i++) { - U[i][k] = -U[i][k]; - } - U[k][k] = 1.0f + U[k][k]; - for (i = 0; i < k - 1; i++) { - U[i][k] = 0.0f; - } - } - else { - for (i = 0; i < m; i++) { - U[i][k] = 0.0f; - } - U[k][k] = 1.0f; - } - } - - /* If required, generate V. */ - - for (k = n - 1; k >= 0; k--) { - if ((k < nrt) & (e[k] != 0.0f)) { - for (j = k + 1; j < nu; j++) { - float t = 0; - for (i = k + 1; i < n; i++) { - t += V[i][k] * V[i][j]; - } - t = -t / V[k + 1][k]; - for (i = k + 1; i < n; i++) { - V[i][j] += t * V[i][k]; - } - } - } - for (i = 0; i < n; i++) { - V[i][k] = 0.0f; - } - V[k][k] = 1.0f; - } - - /* Main iteration loop for the singular values. */ - - pp = p - 1; - iter = 0; - eps = powf(2.0f, -52.0f); - while (p > 0) { - int kase = 0; - - /* Test for maximum iterations to avoid infinite loop */ - if (maxiter == 0) { - break; - } - maxiter--; - - /* This section of the program inspects for - * negligible elements in the s and e arrays. On - * completion the variables kase and k are set as follows. - * - * kase = 1: if s(p) and e[k - 1] are negligible and k<p - * kase = 2: if s(k) is negligible and k<p - * kase = 3: if e[k - 1] is negligible, k<p, and - * s(k), ..., s(p) are not negligible (qr step). - * kase = 4: if e(p - 1) is negligible (convergence). */ - - for (k = p - 2; k >= -1; k--) { - if (k == -1) { - break; - } - if (fabsf(e[k]) <= eps * (fabsf(s[k]) + fabsf(s[k + 1]))) { - e[k] = 0.0f; - break; - } - } - if (k == p - 2) { - kase = 4; - } - else { - int ks; - for (ks = p - 1; ks >= k; ks--) { - float t; - if (ks == k) { - break; - } - t = (ks != p ? fabsf(e[ks]) : 0.f) + - (ks != k + 1 ? fabsf(e[ks - 1]) : 0.0f); - if (fabsf(s[ks]) <= eps * t) { - s[ks] = 0.0f; - break; - } - } - if (ks == k) { - kase = 3; - } - else if (ks == p - 1) { - kase = 1; - } - else { - kase = 2; - k = ks; - } - } - k++; - - /* Perform the task indicated by kase. */ - - switch (kase) { - - /* Deflate negligible s(p). */ - - case 1: - { - float f = e[p - 2]; - e[p - 2] = 0.0f; - for (j = p - 2; j >= k; j--) { - float t = hypotf(s[j], f); - float invt = 1.0f / t; - float cs = s[j] * invt; - float sn = f * invt; - s[j] = t; - if (j != k) { - f = -sn * e[j - 1]; - e[j - 1] = cs * e[j - 1]; - } - - for (i = 0; i < n; i++) { - t = cs * V[i][j] + sn * V[i][p - 1]; - V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1]; - V[i][j] = t; - } - } - break; - } - - /* Split at negligible s(k). */ - - case 2: - { - float f = e[k - 1]; - e[k - 1] = 0.0f; - for (j = k; j < p; j++) { - float t = hypotf(s[j], f); - float invt = 1.0f / t; - float cs = s[j] * invt; - float sn = f * invt; - s[j] = t; - f = -sn * e[j]; - e[j] = cs * e[j]; - - for (i = 0; i < m; i++) { - t = cs * U[i][j] + sn * U[i][k - 1]; - U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1]; - U[i][j] = t; - } - } - break; - } - - /* Perform one qr step. */ - - case 3: - { - - /* Calculate the shift. */ - - float scale = max_ff(max_ff(max_ff(max_ff( - fabsf(s[p - 1]), fabsf(s[p - 2])), fabsf(e[p - 2])), - fabsf(s[k])), fabsf(e[k])); - float invscale = 1.0f / scale; - float sp = s[p - 1] * invscale; - float spm1 = s[p - 2] * invscale; - float epm1 = e[p - 2] * invscale; - float sk = s[k] * invscale; - float ek = e[k] * invscale; - float b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) * 0.5f; - float c = (sp * epm1) * (sp * epm1); - float shift = 0.0f; - float f, g; - if ((b != 0.0f) || (c != 0.0f)) { - shift = sqrtf(b * b + c); - if (b < 0.0f) { - shift = -shift; - } - shift = c / (b + shift); - } - f = (sk + sp) * (sk - sp) + shift; - g = sk * ek; - - /* Chase zeros. */ - - for (j = k; j < p - 1; j++) { - float t = hypotf(f, g); - /* division by zero checks added to avoid NaN (brecht) */ - float cs = (t == 0.0f) ? 0.0f : f / t; - float sn = (t == 0.0f) ? 0.0f : g / t; - if (j != k) { - e[j - 1] = t; - } - f = cs * s[j] + sn * e[j]; - e[j] = cs * e[j] - sn * s[j]; - g = sn * s[j + 1]; - s[j + 1] = cs * s[j + 1]; - - for (i = 0; i < n; i++) { - t = cs * V[i][j] + sn * V[i][j + 1]; - V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1]; - V[i][j] = t; - } - - t = hypotf(f, g); - /* division by zero checks added to avoid NaN (brecht) */ - cs = (t == 0.0f) ? 0.0f : f / t; - sn = (t == 0.0f) ? 0.0f : g / t; - s[j] = t; - f = cs * e[j] + sn * s[j + 1]; - s[j + 1] = -sn * e[j] + cs * s[j + 1]; - g = sn * e[j + 1]; - e[j + 1] = cs * e[j + 1]; - if (j < m - 1) { - for (i = 0; i < m; i++) { - t = cs * U[i][j] + sn * U[i][j + 1]; - U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1]; - U[i][j] = t; - } - } - } - e[p - 2] = f; - iter = iter + 1; - break; - } - /* Convergence. */ - - case 4: - { - - /* Make the singular values positive. */ - - if (s[k] <= 0.0f) { - s[k] = (s[k] < 0.0f ? -s[k] : 0.0f); - - for (i = 0; i <= pp; i++) { - V[i][k] = -V[i][k]; - } - } - - /* Order the singular values. */ - - while (k < pp) { - float t; - if (s[k] >= s[k + 1]) { - break; - } - t = s[k]; - s[k] = s[k + 1]; - s[k + 1] = t; - if (k < n - 1) { - for (i = 0; i < n; i++) { - t = V[i][k + 1]; - V[i][k + 1] = V[i][k]; - V[i][k] = t; - } - } - if (k < m - 1) { - for (i = 0; i < m; i++) { - t = U[i][k + 1]; - U[i][k + 1] = U[i][k]; - U[i][k] = t; - } - } - k++; - } - iter = 0; - p--; - break; - } - } - } + float A[4][4]; + float work1[4], work2[4]; + int m = 4; + int n = 4; + int maxiter = 200; + int nu = min_ii(m, n); + + float *work = work1; + float *e = work2; + float eps; + + int i = 0, j = 0, k = 0, p, pp, iter; + + /* Reduce A to bidiagonal form, storing the diagonal elements + * in s and the super-diagonal elements in e. */ + + int nct = min_ii(m - 1, n); + int nrt = max_ii(0, min_ii(n - 2, m)); + + copy_m4_m4(A, A_); + zero_m4(U); + zero_v4(s); + + for (k = 0; k < max_ii(nct, nrt); k++) { + if (k < nct) { + + /* Compute the transformation for the k-th column and + * place the k-th diagonal in s[k]. + * Compute 2-norm of k-th column without under/overflow. */ + s[k] = 0; + for (i = k; i < m; i++) { + s[k] = hypotf(s[k], A[i][k]); + } + if (s[k] != 0.0f) { + float invsk; + if (A[k][k] < 0.0f) { + s[k] = -s[k]; + } + invsk = 1.0f / s[k]; + for (i = k; i < m; i++) { + A[i][k] *= invsk; + } + A[k][k] += 1.0f; + } + s[k] = -s[k]; + } + for (j = k + 1; j < n; j++) { + if ((k < nct) && (s[k] != 0.0f)) { + + /* Apply the transformation. */ + + float t = 0; + for (i = k; i < m; i++) { + t += A[i][k] * A[i][j]; + } + t = -t / A[k][k]; + for (i = k; i < m; i++) { + A[i][j] += t * A[i][k]; + } + } + + /* Place the k-th row of A into e for the */ + /* subsequent calculation of the row transformation. */ + + e[j] = A[k][j]; + } + if (k < nct) { + + /* Place the transformation in U for subsequent back + * multiplication. */ + + for (i = k; i < m; i++) { + U[i][k] = A[i][k]; + } + } + if (k < nrt) { + + /* Compute the k-th row transformation and place the + * k-th super-diagonal in e[k]. + * Compute 2-norm without under/overflow. */ + e[k] = 0; + for (i = k + 1; i < n; i++) { + e[k] = hypotf(e[k], e[i]); + } + if (e[k] != 0.0f) { + float invek; + if (e[k + 1] < 0.0f) { + e[k] = -e[k]; + } + invek = 1.0f / e[k]; + for (i = k + 1; i < n; i++) { + e[i] *= invek; + } + e[k + 1] += 1.0f; + } + e[k] = -e[k]; + if ((k + 1 < m) & (e[k] != 0.0f)) { + float invek1; + + /* Apply the transformation. */ + + for (i = k + 1; i < m; i++) { + work[i] = 0.0f; + } + for (j = k + 1; j < n; j++) { + for (i = k + 1; i < m; i++) { + work[i] += e[j] * A[i][j]; + } + } + invek1 = 1.0f / e[k + 1]; + for (j = k + 1; j < n; j++) { + float t = -e[j] * invek1; + for (i = k + 1; i < m; i++) { + A[i][j] += t * work[i]; + } + } + } + + /* Place the transformation in V for subsequent + * back multiplication. */ + + for (i = k + 1; i < n; i++) { + V[i][k] = e[i]; + } + } + } + + /* Set up the final bidiagonal matrix or order p. */ + + p = min_ii(n, m + 1); + if (nct < n) { + s[nct] = A[nct][nct]; + } + if (m < p) { + s[p - 1] = 0.0f; + } + if (nrt + 1 < p) { + e[nrt] = A[nrt][p - 1]; + } + e[p - 1] = 0.0f; + + /* If required, generate U. */ + + for (j = nct; j < nu; j++) { + for (i = 0; i < m; i++) { + U[i][j] = 0.0f; + } + U[j][j] = 1.0f; + } + for (k = nct - 1; k >= 0; k--) { + if (s[k] != 0.0f) { + for (j = k + 1; j < nu; j++) { + float t = 0; + for (i = k; i < m; i++) { + t += U[i][k] * U[i][j]; + } + t = -t / U[k][k]; + for (i = k; i < m; i++) { + U[i][j] += t * U[i][k]; + } + } + for (i = k; i < m; i++) { + U[i][k] = -U[i][k]; + } + U[k][k] = 1.0f + U[k][k]; + for (i = 0; i < k - 1; i++) { + U[i][k] = 0.0f; + } + } + else { + for (i = 0; i < m; i++) { + U[i][k] = 0.0f; + } + U[k][k] = 1.0f; + } + } + + /* If required, generate V. */ + + for (k = n - 1; k >= 0; k--) { + if ((k < nrt) & (e[k] != 0.0f)) { + for (j = k + 1; j < nu; j++) { + float t = 0; + for (i = k + 1; i < n; i++) { + t += V[i][k] * V[i][j]; + } + t = -t / V[k + 1][k]; + for (i = k + 1; i < n; i++) { + V[i][j] += t * V[i][k]; + } + } + } + for (i = 0; i < n; i++) { + V[i][k] = 0.0f; + } + V[k][k] = 1.0f; + } + + /* Main iteration loop for the singular values. */ + + pp = p - 1; + iter = 0; + eps = powf(2.0f, -52.0f); + while (p > 0) { + int kase = 0; + + /* Test for maximum iterations to avoid infinite loop */ + if (maxiter == 0) { + break; + } + maxiter--; + + /* This section of the program inspects for + * negligible elements in the s and e arrays. On + * completion the variables kase and k are set as follows. + * + * kase = 1: if s(p) and e[k - 1] are negligible and k<p + * kase = 2: if s(k) is negligible and k<p + * kase = 3: if e[k - 1] is negligible, k<p, and + * s(k), ..., s(p) are not negligible (qr step). + * kase = 4: if e(p - 1) is negligible (convergence). */ + + for (k = p - 2; k >= -1; k--) { + if (k == -1) { + break; + } + if (fabsf(e[k]) <= eps * (fabsf(s[k]) + fabsf(s[k + 1]))) { + e[k] = 0.0f; + break; + } + } + if (k == p - 2) { + kase = 4; + } + else { + int ks; + for (ks = p - 1; ks >= k; ks--) { + float t; + if (ks == k) { + break; + } + t = (ks != p ? fabsf(e[ks]) : 0.f) + (ks != k + 1 ? fabsf(e[ks - 1]) : 0.0f); + if (fabsf(s[ks]) <= eps * t) { + s[ks] = 0.0f; + break; + } + } + if (ks == k) { + kase = 3; + } + else if (ks == p - 1) { + kase = 1; + } + else { + kase = 2; + k = ks; + } + } + k++; + + /* Perform the task indicated by kase. */ + + switch (kase) { + + /* Deflate negligible s(p). */ + + case 1: { + float f = e[p - 2]; + e[p - 2] = 0.0f; + for (j = p - 2; j >= k; j--) { + float t = hypotf(s[j], f); + float invt = 1.0f / t; + float cs = s[j] * invt; + float sn = f * invt; + s[j] = t; + if (j != k) { + f = -sn * e[j - 1]; + e[j - 1] = cs * e[j - 1]; + } + + for (i = 0; i < n; i++) { + t = cs * V[i][j] + sn * V[i][p - 1]; + V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1]; + V[i][j] = t; + } + } + break; + } + + /* Split at negligible s(k). */ + + case 2: { + float f = e[k - 1]; + e[k - 1] = 0.0f; + for (j = k; j < p; j++) { + float t = hypotf(s[j], f); + float invt = 1.0f / t; + float cs = s[j] * invt; + float sn = f * invt; + s[j] = t; + f = -sn * e[j]; + e[j] = cs * e[j]; + + for (i = 0; i < m; i++) { + t = cs * U[i][j] + sn * U[i][k - 1]; + U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1]; + U[i][j] = t; + } + } + break; + } + + /* Perform one qr step. */ + + case 3: { + + /* Calculate the shift. */ + + float scale = max_ff( + max_ff(max_ff(max_ff(fabsf(s[p - 1]), fabsf(s[p - 2])), fabsf(e[p - 2])), fabsf(s[k])), + fabsf(e[k])); + float invscale = 1.0f / scale; + float sp = s[p - 1] * invscale; + float spm1 = s[p - 2] * invscale; + float epm1 = e[p - 2] * invscale; + float sk = s[k] * invscale; + float ek = e[k] * invscale; + float b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) * 0.5f; + float c = (sp * epm1) * (sp * epm1); + float shift = 0.0f; + float f, g; + if ((b != 0.0f) || (c != 0.0f)) { + shift = sqrtf(b * b + c); + if (b < 0.0f) { + shift = -shift; + } + shift = c / (b + shift); + } + f = (sk + sp) * (sk - sp) + shift; + g = sk * ek; + + /* Chase zeros. */ + + for (j = k; j < p - 1; j++) { + float t = hypotf(f, g); + /* division by zero checks added to avoid NaN (brecht) */ + float cs = (t == 0.0f) ? 0.0f : f / t; + float sn = (t == 0.0f) ? 0.0f : g / t; + if (j != k) { + e[j - 1] = t; + } + f = cs * s[j] + sn * e[j]; + e[j] = cs * e[j] - sn * s[j]; + g = sn * s[j + 1]; + s[j + 1] = cs * s[j + 1]; + + for (i = 0; i < n; i++) { + t = cs * V[i][j] + sn * V[i][j + 1]; + V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1]; + V[i][j] = t; + } + + t = hypotf(f, g); + /* division by zero checks added to avoid NaN (brecht) */ + cs = (t == 0.0f) ? 0.0f : f / t; + sn = (t == 0.0f) ? 0.0f : g / t; + s[j] = t; + f = cs * e[j] + sn * s[j + 1]; + s[j + 1] = -sn * e[j] + cs * s[j + 1]; + g = sn * e[j + 1]; + e[j + 1] = cs * e[j + 1]; + if (j < m - 1) { + for (i = 0; i < m; i++) { + t = cs * U[i][j] + sn * U[i][j + 1]; + U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1]; + U[i][j] = t; + } + } + } + e[p - 2] = f; + iter = iter + 1; + break; + } + /* Convergence. */ + + case 4: { + + /* Make the singular values positive. */ + + if (s[k] <= 0.0f) { + s[k] = (s[k] < 0.0f ? -s[k] : 0.0f); + + for (i = 0; i <= pp; i++) { + V[i][k] = -V[i][k]; + } + } + + /* Order the singular values. */ + + while (k < pp) { + float t; + if (s[k] >= s[k + 1]) { + break; + } + t = s[k]; + s[k] = s[k + 1]; + s[k + 1] = t; + if (k < n - 1) { + for (i = 0; i < n; i++) { + t = V[i][k + 1]; + V[i][k + 1] = V[i][k]; + V[i][k] = t; + } + } + if (k < m - 1) { + for (i = 0; i < m; i++) { + t = U[i][k + 1]; + U[i][k + 1] = U[i][k]; + U[i][k] = t; + } + } + k++; + } + iter = 0; + p--; + break; + } + } + } } void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon) { - /* compute Moore-Penrose pseudo inverse of matrix, singular values - * below epsilon are ignored for stability (truncated SVD) */ - float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4]; - int i; + /* compute Moore-Penrose pseudo inverse of matrix, singular values + * below epsilon are ignored for stability (truncated SVD) */ + float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4]; + int i; - transpose_m4_m4(A, A_); - svd_m4(V, W, U, A); - transpose_m4(U); - transpose_m4(V); + transpose_m4_m4(A, A_); + svd_m4(V, W, U, A); + transpose_m4(U); + transpose_m4(V); - zero_m4(Wm); - for (i = 0; i < 4; i++) { - Wm[i][i] = (W[i] < epsilon) ? 0.0f : 1.0f / W[i]; - } + zero_m4(Wm); + for (i = 0; i < 4; i++) { + Wm[i][i] = (W[i] < epsilon) ? 0.0f : 1.0f / W[i]; + } - transpose_m4(V); + transpose_m4(V); - mul_m4_series(Ainv, U, Wm, V); + mul_m4_series(Ainv, U, Wm, V); } void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon) { - /* try regular inverse when possible, otherwise fall back to slow svd */ - if (!invert_m3_m3(Ainv, A)) { - float tmp[4][4], tmpinv[4][4]; + /* try regular inverse when possible, otherwise fall back to slow svd */ + if (!invert_m3_m3(Ainv, A)) { + float tmp[4][4], tmpinv[4][4]; - copy_m4_m3(tmp, A); - pseudoinverse_m4_m4(tmpinv, tmp, epsilon); - copy_m3_m4(Ainv, tmpinv); - } + copy_m4_m3(tmp, A); + pseudoinverse_m4_m4(tmpinv, tmp, epsilon); + copy_m3_m4(Ainv, tmpinv); + } } bool has_zero_axis_m4(const float matrix[4][4]) { - return len_squared_v3(matrix[0]) < FLT_EPSILON || - len_squared_v3(matrix[1]) < FLT_EPSILON || - len_squared_v3(matrix[2]) < FLT_EPSILON; + return len_squared_v3(matrix[0]) < FLT_EPSILON || len_squared_v3(matrix[1]) < FLT_EPSILON || + len_squared_v3(matrix[2]) < FLT_EPSILON; } void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]) { - if (!invert_m4_m4(Ainv, A)) { - float Atemp[4][4]; + if (!invert_m4_m4(Ainv, A)) { + float Atemp[4][4]; - copy_m4_m4(Atemp, A); + copy_m4_m4(Atemp, A); - /* Matrix is degenerate (e.g. 0 scale on some axis), ideally we should - * never be in this situation, but try to invert it anyway with tweak. - */ - Atemp[0][0] += 1e-8f; - Atemp[1][1] += 1e-8f; - Atemp[2][2] += 1e-8f; + /* Matrix is degenerate (e.g. 0 scale on some axis), ideally we should + * never be in this situation, but try to invert it anyway with tweak. + */ + Atemp[0][0] += 1e-8f; + Atemp[1][1] += 1e-8f; + Atemp[2][2] += 1e-8f; - if (!invert_m4_m4(Ainv, Atemp)) { - unit_m4(Ainv); - } - } + if (!invert_m4_m4(Ainv, Atemp)) { + unit_m4(Ainv); + } + } } /** @@ -2617,12 +2645,14 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]) * this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z) * where (x', y', z') are the coordinates of P' in target space such that it keeps (X, Y, Z) coordinates in global space. */ -void BLI_space_transform_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4]) +void BLI_space_transform_from_matrices(SpaceTransform *data, + const float local[4][4], + const float target[4][4]) { - float itarget[4][4]; - invert_m4_m4(itarget, target); - mul_m4_m4m4(data->local2target, itarget, local); - invert_m4_m4(data->target2local, data->local2target); + float itarget[4][4]; + invert_m4_m4(itarget, target); + mul_m4_m4m4(data->local2target, itarget, local); + invert_m4_m4(data->target2local, data->local2target); } /** @@ -2635,32 +2665,34 @@ void BLI_space_transform_from_matrices(SpaceTransform *data, const float local[4 * this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z) * where (X', Y', Z') are the coordinates of p' in global space such that it keeps (x, y, z) coordinates in target space. */ -void BLI_space_transform_global_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4]) +void BLI_space_transform_global_from_matrices(SpaceTransform *data, + const float local[4][4], + const float target[4][4]) { - float ilocal[4][4]; - invert_m4_m4(ilocal, local); - mul_m4_m4m4(data->local2target, target, ilocal); - invert_m4_m4(data->target2local, data->local2target); + float ilocal[4][4]; + invert_m4_m4(ilocal, local); + mul_m4_m4m4(data->local2target, target, ilocal); + invert_m4_m4(data->target2local, data->local2target); } void BLI_space_transform_apply(const SpaceTransform *data, float co[3]) { - mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co); + mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co); } void BLI_space_transform_invert(const SpaceTransform *data, float co[3]) { - mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co); + mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co); } void BLI_space_transform_apply_normal(const SpaceTransform *data, float no[3]) { - mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no); - normalize_v3(no); + mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no); + normalize_v3(no); } void BLI_space_transform_invert_normal(const SpaceTransform *data, float no[3]) { - mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no); - normalize_v3(no); + mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no); + normalize_v3(no); } diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index b1bed27d2bd..47814b1080c 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -38,42 +38,42 @@ /* convenience, avoids setting Y axis everywhere */ void unit_axis_angle(float axis[3], float *angle) { - axis[0] = 0.0f; - axis[1] = 1.0f; - axis[2] = 0.0f; - *angle = 0.0f; + axis[0] = 0.0f; + axis[1] = 1.0f; + axis[2] = 0.0f; + *angle = 0.0f; } void unit_qt(float q[4]) { - q[0] = 1.0f; - q[1] = q[2] = q[3] = 0.0f; + q[0] = 1.0f; + q[1] = q[2] = q[3] = 0.0f; } void copy_qt_qt(float q1[4], const float q2[4]) { - q1[0] = q2[0]; - q1[1] = q2[1]; - q1[2] = q2[2]; - q1[3] = q2[3]; + q1[0] = q2[0]; + q1[1] = q2[1]; + q1[2] = q2[2]; + q1[3] = q2[3]; } bool is_zero_qt(const float q[4]) { - return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0); + return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0); } void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) { - float t0, t1, t2; + float t0, t1, t2; - t0 = q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]; - t1 = q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]; - t2 = q1[0] * q2[2] + q1[2] * q2[0] + q1[3] * q2[1] - q1[1] * q2[3]; - q[3] = q1[0] * q2[3] + q1[3] * q2[0] + q1[1] * q2[2] - q1[2] * q2[1]; - q[0] = t0; - q[1] = t1; - q[2] = t2; + t0 = q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]; + t1 = q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]; + t2 = q1[0] * q2[2] + q1[2] * q2[0] + q1[3] * q2[1] - q1[1] * q2[3]; + q[3] = q1[0] * q2[3] + q1[3] * q2[0] + q1[1] * q2[2] - q1[2] * q2[1]; + q[0] = t0; + q[1] = t1; + q[2] = t2; } /** @@ -97,58 +97,58 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) */ void mul_qt_v3(const float q[4], float v[3]) { - float t0, t1, t2; + float t0, t1, t2; - t0 = -q[1] * v[0] - q[2] * v[1] - q[3] * v[2]; - t1 = q[0] * v[0] + q[2] * v[2] - q[3] * v[1]; - t2 = q[0] * v[1] + q[3] * v[0] - q[1] * v[2]; - v[2] = q[0] * v[2] + q[1] * v[1] - q[2] * v[0]; - v[0] = t1; - v[1] = t2; + t0 = -q[1] * v[0] - q[2] * v[1] - q[3] * v[2]; + t1 = q[0] * v[0] + q[2] * v[2] - q[3] * v[1]; + t2 = q[0] * v[1] + q[3] * v[0] - q[1] * v[2]; + v[2] = q[0] * v[2] + q[1] * v[1] - q[2] * v[0]; + v[0] = t1; + v[1] = t2; - t1 = t0 * -q[1] + v[0] * q[0] - v[1] * q[3] + v[2] * q[2]; - t2 = t0 * -q[2] + v[1] * q[0] - v[2] * q[1] + v[0] * q[3]; - v[2] = t0 * -q[3] + v[2] * q[0] - v[0] * q[2] + v[1] * q[1]; - v[0] = t1; - v[1] = t2; + t1 = t0 * -q[1] + v[0] * q[0] - v[1] * q[3] + v[2] * q[2]; + t2 = t0 * -q[2] + v[1] * q[0] - v[2] * q[1] + v[0] * q[3]; + v[2] = t0 * -q[3] + v[2] * q[0] - v[0] * q[2] + v[1] * q[1]; + v[0] = t1; + v[1] = t2; } void conjugate_qt_qt(float q1[4], const float q2[4]) { - q1[0] = q2[0]; - q1[1] = -q2[1]; - q1[2] = -q2[2]; - q1[3] = -q2[3]; + q1[0] = q2[0]; + q1[1] = -q2[1]; + q1[2] = -q2[2]; + q1[3] = -q2[3]; } void conjugate_qt(float q[4]) { - q[1] = -q[1]; - q[2] = -q[2]; - q[3] = -q[3]; + q[1] = -q[1]; + q[2] = -q[2]; + q[3] = -q[3]; } float dot_qtqt(const float q1[4], const float q2[4]) { - return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3]; + return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3]; } void invert_qt(float q[4]) { - const float f = dot_qtqt(q, q); + const float f = dot_qtqt(q, q); - if (f == 0.0f) { - return; - } + if (f == 0.0f) { + return; + } - conjugate_qt(q); - mul_qt_fl(q, 1.0f / f); + conjugate_qt(q); + mul_qt_fl(q, 1.0f / f); } void invert_qt_qt(float q1[4], const float q2[4]) { - copy_qt_qt(q1, q2); - invert_qt(q1); + copy_qt_qt(q1, q2); + invert_qt(q1); } /** @@ -158,48 +158,47 @@ void invert_qt_qt(float q1[4], const float q2[4]) */ void invert_qt_normalized(float q[4]) { - BLI_ASSERT_UNIT_QUAT(q); - conjugate_qt(q); - + BLI_ASSERT_UNIT_QUAT(q); + conjugate_qt(q); } void invert_qt_qt_normalized(float q1[4], const float q2[4]) { - copy_qt_qt(q1, q2); - invert_qt_normalized(q1); + copy_qt_qt(q1, q2); + invert_qt_normalized(q1); } /* simple mult */ void mul_qt_fl(float q[4], const float f) { - q[0] *= f; - q[1] *= f; - q[2] *= f; - q[3] *= f; + q[0] *= f; + q[1] *= f; + q[2] *= f; + q[3] *= f; } void sub_qt_qtqt(float q[4], const float q1[4], const float q2[4]) { - float nq2[4]; + float nq2[4]; - nq2[0] = -q2[0]; - nq2[1] = q2[1]; - nq2[2] = q2[2]; - nq2[3] = q2[3]; + nq2[0] = -q2[0]; + nq2[1] = q2[1]; + nq2[2] = q2[2]; + nq2[3] = q2[3]; - mul_qt_qtqt(q, q1, nq2); + mul_qt_qtqt(q, q1, nq2); } /* raise a unit quaternion to the specified power */ void pow_qt_fl_normalized(float q[4], const float fac) { - BLI_ASSERT_UNIT_QUAT(q); - const float angle = fac * saacos(q[0]); /* quat[0] = cos(0.5 * angle), - * but now the 0.5 and 2.0 rule out */ - const float co = cosf(angle); - const float si = sinf(angle); - q[0] = co; - normalize_v3_length(q + 1, si); + BLI_ASSERT_UNIT_QUAT(q); + const float angle = fac * saacos(q[0]); /* quat[0] = cos(0.5 * angle), + * but now the 0.5 and 2.0 rule out */ + const float co = cosf(angle); + const float si = sinf(angle); + q[0] = co; + normalize_v3_length(q + 1, si); } /** @@ -208,248 +207,252 @@ void pow_qt_fl_normalized(float q[4], const float fac) */ void quat_to_compatible_quat(float q[4], const float a[4], const float old[4]) { - const float eps = 1e-4f; - BLI_ASSERT_UNIT_QUAT(a); - float old_unit[4]; - /* Skips `!finite_v4(old)` case too. */ - if (normalize_qt_qt(old_unit, old) > eps) { - float delta[4]; - rotation_between_quats_to_quat(delta, old_unit, a); - mul_qt_qtqt(q, old, delta); - if ((q[0] < 0.0f) != (old[0] < 0.0f)) { - negate_v4(q); - } - } - else { - copy_qt_qt(q, a); - } + const float eps = 1e-4f; + BLI_ASSERT_UNIT_QUAT(a); + float old_unit[4]; + /* Skips `!finite_v4(old)` case too. */ + if (normalize_qt_qt(old_unit, old) > eps) { + float delta[4]; + rotation_between_quats_to_quat(delta, old_unit, a); + mul_qt_qtqt(q, old, delta); + if ((q[0] < 0.0f) != (old[0] < 0.0f)) { + negate_v4(q); + } + } + else { + copy_qt_qt(q, a); + } } /* skip error check, currently only needed by mat3_to_quat_is_ok */ static void quat_to_mat3_no_error(float m[3][3], const float q[4]) { - double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; + double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; - q0 = M_SQRT2 * (double)q[0]; - q1 = M_SQRT2 * (double)q[1]; - q2 = M_SQRT2 * (double)q[2]; - q3 = M_SQRT2 * (double)q[3]; + q0 = M_SQRT2 * (double)q[0]; + q1 = M_SQRT2 * (double)q[1]; + q2 = M_SQRT2 * (double)q[2]; + q3 = M_SQRT2 * (double)q[3]; - qda = q0 * q1; - qdb = q0 * q2; - qdc = q0 * q3; - qaa = q1 * q1; - qab = q1 * q2; - qac = q1 * q3; - qbb = q2 * q2; - qbc = q2 * q3; - qcc = q3 * q3; + qda = q0 * q1; + qdb = q0 * q2; + qdc = q0 * q3; + qaa = q1 * q1; + qab = q1 * q2; + qac = q1 * q3; + qbb = q2 * q2; + qbc = q2 * q3; + qcc = q3 * q3; - m[0][0] = (float)(1.0 - qbb - qcc); - m[0][1] = (float)(qdc + qab); - m[0][2] = (float)(-qdb + qac); + m[0][0] = (float)(1.0 - qbb - qcc); + m[0][1] = (float)(qdc + qab); + m[0][2] = (float)(-qdb + qac); - m[1][0] = (float)(-qdc + qab); - m[1][1] = (float)(1.0 - qaa - qcc); - m[1][2] = (float)(qda + qbc); + m[1][0] = (float)(-qdc + qab); + m[1][1] = (float)(1.0 - qaa - qcc); + m[1][2] = (float)(qda + qbc); - m[2][0] = (float)(qdb + qac); - m[2][1] = (float)(-qda + qbc); - m[2][2] = (float)(1.0 - qaa - qbb); + m[2][0] = (float)(qdb + qac); + m[2][1] = (float)(-qda + qbc); + m[2][2] = (float)(1.0 - qaa - qbb); } void quat_to_mat3(float m[3][3], const float q[4]) { #ifdef DEBUG - float f; - if (!((f = dot_qtqt(q, q)) == 0.0f || (fabsf(f - 1.0f) < (float)QUAT_EPSILON))) { - fprintf(stderr, "Warning! quat_to_mat3() called with non-normalized: size %.8f *** report a bug ***\n", f); - } + float f; + if (!((f = dot_qtqt(q, q)) == 0.0f || (fabsf(f - 1.0f) < (float)QUAT_EPSILON))) { + fprintf(stderr, + "Warning! quat_to_mat3() called with non-normalized: size %.8f *** report a bug ***\n", + f); + } #endif - quat_to_mat3_no_error(m, q); + quat_to_mat3_no_error(m, q); } void quat_to_mat4(float m[4][4], const float q[4]) { - double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; + double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; #ifdef DEBUG - if (!((q0 = dot_qtqt(q, q)) == 0.0 || (fabs(q0 - 1.0) < QUAT_EPSILON))) { - fprintf(stderr, "Warning! quat_to_mat4() called with non-normalized: size %.8f *** report a bug ***\n", (float)q0); - } + if (!((q0 = dot_qtqt(q, q)) == 0.0 || (fabs(q0 - 1.0) < QUAT_EPSILON))) { + fprintf(stderr, + "Warning! quat_to_mat4() called with non-normalized: size %.8f *** report a bug ***\n", + (float)q0); + } #endif - q0 = M_SQRT2 * (double)q[0]; - q1 = M_SQRT2 * (double)q[1]; - q2 = M_SQRT2 * (double)q[2]; - q3 = M_SQRT2 * (double)q[3]; + q0 = M_SQRT2 * (double)q[0]; + q1 = M_SQRT2 * (double)q[1]; + q2 = M_SQRT2 * (double)q[2]; + q3 = M_SQRT2 * (double)q[3]; - qda = q0 * q1; - qdb = q0 * q2; - qdc = q0 * q3; - qaa = q1 * q1; - qab = q1 * q2; - qac = q1 * q3; - qbb = q2 * q2; - qbc = q2 * q3; - qcc = q3 * q3; + qda = q0 * q1; + qdb = q0 * q2; + qdc = q0 * q3; + qaa = q1 * q1; + qab = q1 * q2; + qac = q1 * q3; + qbb = q2 * q2; + qbc = q2 * q3; + qcc = q3 * q3; - m[0][0] = (float)(1.0 - qbb - qcc); - m[0][1] = (float)(qdc + qab); - m[0][2] = (float)(-qdb + qac); - m[0][3] = 0.0f; + m[0][0] = (float)(1.0 - qbb - qcc); + m[0][1] = (float)(qdc + qab); + m[0][2] = (float)(-qdb + qac); + m[0][3] = 0.0f; - m[1][0] = (float)(-qdc + qab); - m[1][1] = (float)(1.0 - qaa - qcc); - m[1][2] = (float)(qda + qbc); - m[1][3] = 0.0f; + m[1][0] = (float)(-qdc + qab); + m[1][1] = (float)(1.0 - qaa - qcc); + m[1][2] = (float)(qda + qbc); + m[1][3] = 0.0f; - m[2][0] = (float)(qdb + qac); - m[2][1] = (float)(-qda + qbc); - m[2][2] = (float)(1.0 - qaa - qbb); - m[2][3] = 0.0f; + m[2][0] = (float)(qdb + qac); + m[2][1] = (float)(-qda + qbc); + m[2][2] = (float)(1.0 - qaa - qbb); + m[2][3] = 0.0f; - m[3][0] = m[3][1] = m[3][2] = 0.0f; - m[3][3] = 1.0f; + m[3][0] = m[3][1] = m[3][2] = 0.0f; + m[3][3] = 1.0f; } void mat3_normalized_to_quat(float q[4], const float mat[3][3]) { - double tr, s; - - BLI_ASSERT_UNIT_M3(mat); - - tr = 0.25 * (double)(1.0f + mat[0][0] + mat[1][1] + mat[2][2]); - - if (tr > (double)1e-4f) { - s = sqrt(tr); - q[0] = (float)s; - s = 1.0 / (4.0 * s); - q[1] = (float)((double)(mat[1][2] - mat[2][1]) * s); - q[2] = (float)((double)(mat[2][0] - mat[0][2]) * s); - q[3] = (float)((double)(mat[0][1] - mat[1][0]) * s); - } - else { - if (mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) { - s = 2.0f * sqrtf(1.0f + mat[0][0] - mat[1][1] - mat[2][2]); - q[1] = (float)(0.25 * s); - - s = 1.0 / s; - q[0] = (float)((double)(mat[1][2] - mat[2][1]) * s); - q[2] = (float)((double)(mat[1][0] + mat[0][1]) * s); - q[3] = (float)((double)(mat[2][0] + mat[0][2]) * s); - } - else if (mat[1][1] > mat[2][2]) { - s = 2.0f * sqrtf(1.0f + mat[1][1] - mat[0][0] - mat[2][2]); - q[2] = (float)(0.25 * s); - - s = 1.0 / s; - q[0] = (float)((double)(mat[2][0] - mat[0][2]) * s); - q[1] = (float)((double)(mat[1][0] + mat[0][1]) * s); - q[3] = (float)((double)(mat[2][1] + mat[1][2]) * s); - } - else { - s = 2.0f * sqrtf(1.0f + mat[2][2] - mat[0][0] - mat[1][1]); - q[3] = (float)(0.25 * s); - - s = 1.0 / s; - q[0] = (float)((double)(mat[0][1] - mat[1][0]) * s); - q[1] = (float)((double)(mat[2][0] + mat[0][2]) * s); - q[2] = (float)((double)(mat[2][1] + mat[1][2]) * s); - } - } - - normalize_qt(q); + double tr, s; + + BLI_ASSERT_UNIT_M3(mat); + + tr = 0.25 * (double)(1.0f + mat[0][0] + mat[1][1] + mat[2][2]); + + if (tr > (double)1e-4f) { + s = sqrt(tr); + q[0] = (float)s; + s = 1.0 / (4.0 * s); + q[1] = (float)((double)(mat[1][2] - mat[2][1]) * s); + q[2] = (float)((double)(mat[2][0] - mat[0][2]) * s); + q[3] = (float)((double)(mat[0][1] - mat[1][0]) * s); + } + else { + if (mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) { + s = 2.0f * sqrtf(1.0f + mat[0][0] - mat[1][1] - mat[2][2]); + q[1] = (float)(0.25 * s); + + s = 1.0 / s; + q[0] = (float)((double)(mat[1][2] - mat[2][1]) * s); + q[2] = (float)((double)(mat[1][0] + mat[0][1]) * s); + q[3] = (float)((double)(mat[2][0] + mat[0][2]) * s); + } + else if (mat[1][1] > mat[2][2]) { + s = 2.0f * sqrtf(1.0f + mat[1][1] - mat[0][0] - mat[2][2]); + q[2] = (float)(0.25 * s); + + s = 1.0 / s; + q[0] = (float)((double)(mat[2][0] - mat[0][2]) * s); + q[1] = (float)((double)(mat[1][0] + mat[0][1]) * s); + q[3] = (float)((double)(mat[2][1] + mat[1][2]) * s); + } + else { + s = 2.0f * sqrtf(1.0f + mat[2][2] - mat[0][0] - mat[1][1]); + q[3] = (float)(0.25 * s); + + s = 1.0 / s; + q[0] = (float)((double)(mat[0][1] - mat[1][0]) * s); + q[1] = (float)((double)(mat[2][0] + mat[0][2]) * s); + q[2] = (float)((double)(mat[2][1] + mat[1][2]) * s); + } + } + + normalize_qt(q); } void mat3_to_quat(float q[4], const float m[3][3]) { - float unit_mat[3][3]; + float unit_mat[3][3]; - /* work on a copy */ - /* this is needed AND a 'normalize_qt' in the end */ - normalize_m3_m3(unit_mat, m); - mat3_normalized_to_quat(q, unit_mat); + /* work on a copy */ + /* this is needed AND a 'normalize_qt' in the end */ + normalize_m3_m3(unit_mat, m); + mat3_normalized_to_quat(q, unit_mat); } void mat4_normalized_to_quat(float q[4], const float m[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - copy_m3_m4(mat3, m); - mat3_normalized_to_quat(q, mat3); + copy_m3_m4(mat3, m); + mat3_normalized_to_quat(q, mat3); } void mat4_to_quat(float q[4], const float m[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - copy_m3_m4(mat3, m); - mat3_to_quat(q, mat3); + copy_m3_m4(mat3, m); + mat3_to_quat(q, mat3); } void mat3_to_quat_is_ok(float q[4], const float wmat[3][3]) { - float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3]; + float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3]; - /* work on a copy */ - copy_m3_m3(mat, wmat); - normalize_m3(mat); + /* work on a copy */ + copy_m3_m3(mat, wmat); + normalize_m3(mat); - /* rotate z-axis of matrix to z-axis */ + /* rotate z-axis of matrix to z-axis */ - nor[0] = mat[2][1]; /* cross product with (0,0,1) */ - nor[1] = -mat[2][0]; - nor[2] = 0.0; - normalize_v3(nor); + nor[0] = mat[2][1]; /* cross product with (0,0,1) */ + nor[1] = -mat[2][0]; + nor[2] = 0.0; + normalize_v3(nor); - co = mat[2][2]; - angle = 0.5f * saacos(co); + co = mat[2][2]; + angle = 0.5f * saacos(co); - co = cosf(angle); - si = sinf(angle); - q1[0] = co; - q1[1] = -nor[0] * si; /* negative here, but why? */ - q1[2] = -nor[1] * si; - q1[3] = -nor[2] * si; + co = cosf(angle); + si = sinf(angle); + q1[0] = co; + q1[1] = -nor[0] * si; /* negative here, but why? */ + q1[2] = -nor[1] * si; + q1[3] = -nor[2] * si; - /* rotate back x-axis from mat, using inverse q1 */ - quat_to_mat3_no_error(matr, q1); - invert_m3_m3(matn, matr); - mul_m3_v3(matn, mat[0]); + /* rotate back x-axis from mat, using inverse q1 */ + quat_to_mat3_no_error(matr, q1); + invert_m3_m3(matn, matr); + mul_m3_v3(matn, mat[0]); - /* and align x-axes */ - angle = 0.5f * atan2f(mat[0][1], mat[0][0]); + /* and align x-axes */ + angle = 0.5f * atan2f(mat[0][1], mat[0][0]); - co = cosf(angle); - si = sinf(angle); - q2[0] = co; - q2[1] = 0.0f; - q2[2] = 0.0f; - q2[3] = si; + co = cosf(angle); + si = sinf(angle); + q2[0] = co; + q2[1] = 0.0f; + q2[2] = 0.0f; + q2[3] = si; - mul_qt_qtqt(q, q1, q2); + mul_qt_qtqt(q, q1, q2); } float normalize_qt(float q[4]) { - const float len = sqrtf(dot_qtqt(q, q)); + const float len = sqrtf(dot_qtqt(q, q)); - if (len != 0.0f) { - mul_qt_fl(q, 1.0f / len); - } - else { - q[1] = 1.0f; - q[0] = q[2] = q[3] = 0.0f; - } + if (len != 0.0f) { + mul_qt_fl(q, 1.0f / len); + } + else { + q[1] = 1.0f; + q[0] = q[2] = q[3] = 0.0f; + } - return len; + return len; } float normalize_qt_qt(float r[4], const float q[4]) { - copy_qt_qt(r, q); - return normalize_qt(r); + copy_qt_qt(r, q); + return normalize_qt(r); } /** @@ -457,82 +460,81 @@ float normalize_qt_qt(float r[4], const float q[4]) */ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3]) { - float axis[3]; - /* avoid calculating the angle */ - float angle_sin; - float angle_cos; - - BLI_ASSERT_UNIT_V3(v1); - BLI_ASSERT_UNIT_V3(v2); - - cross_v3_v3v3(axis, v1, v2); - - angle_sin = normalize_v3(axis); - angle_cos = dot_v3v3(v1, v2); - - if (angle_sin > FLT_EPSILON) { -axis_calc: - BLI_ASSERT_UNIT_V3(axis); - axis_angle_normalized_to_mat3_ex(m, axis, angle_sin, angle_cos); - BLI_ASSERT_UNIT_M3(m); - } - else { - if (angle_cos > 0.0f) { - /* Same vectors, zero rotation... */ - unit_m3(m); - } - else { - /* Colinear but opposed vectors, 180 rotation... */ - ortho_v3_v3(axis, v1); - normalize_v3(axis); - angle_sin = 0.0f; /* sin(M_PI) */ - angle_cos = -1.0f; /* cos(M_PI) */ - goto axis_calc; - } - } + float axis[3]; + /* avoid calculating the angle */ + float angle_sin; + float angle_cos; + + BLI_ASSERT_UNIT_V3(v1); + BLI_ASSERT_UNIT_V3(v2); + + cross_v3_v3v3(axis, v1, v2); + + angle_sin = normalize_v3(axis); + angle_cos = dot_v3v3(v1, v2); + + if (angle_sin > FLT_EPSILON) { + axis_calc: + BLI_ASSERT_UNIT_V3(axis); + axis_angle_normalized_to_mat3_ex(m, axis, angle_sin, angle_cos); + BLI_ASSERT_UNIT_M3(m); + } + else { + if (angle_cos > 0.0f) { + /* Same vectors, zero rotation... */ + unit_m3(m); + } + else { + /* Colinear but opposed vectors, 180 rotation... */ + ortho_v3_v3(axis, v1); + normalize_v3(axis); + angle_sin = 0.0f; /* sin(M_PI) */ + angle_cos = -1.0f; /* cos(M_PI) */ + goto axis_calc; + } + } } /* note: expects vectors to be normalized */ void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]) { - float axis[3]; + float axis[3]; - cross_v3_v3v3(axis, v1, v2); + cross_v3_v3v3(axis, v1, v2); - if (normalize_v3(axis) > FLT_EPSILON) { - float angle; + if (normalize_v3(axis) > FLT_EPSILON) { + float angle; - angle = angle_normalized_v3v3(v1, v2); + angle = angle_normalized_v3v3(v1, v2); - axis_angle_normalized_to_quat(q, axis, angle); - } - else { - /* degenerate case */ + axis_angle_normalized_to_quat(q, axis, angle); + } + else { + /* degenerate case */ - if (dot_v3v3(v1, v2) > 0.0f) { - /* Same vectors, zero rotation... */ - unit_qt(q); - } - else { - /* Colinear but opposed vectors, 180 rotation... */ - ortho_v3_v3(axis, v1); - axis_angle_to_quat(q, axis, (float)M_PI); - } - } + if (dot_v3v3(v1, v2) > 0.0f) { + /* Same vectors, zero rotation... */ + unit_qt(q); + } + else { + /* Colinear but opposed vectors, 180 rotation... */ + ortho_v3_v3(axis, v1); + axis_angle_to_quat(q, axis, (float)M_PI); + } + } } void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]) { - float tquat[4]; + float tquat[4]; - conjugate_qt_qt(tquat, q1); + conjugate_qt_qt(tquat, q1); - mul_qt_fl(tquat, 1.0f / dot_qtqt(tquat, tquat)); + mul_qt_fl(tquat, 1.0f / dot_qtqt(tquat, tquat)); - mul_qt_qtqt(q, tquat, q2); + mul_qt_qtqt(q, tquat, q2); } - /* -------------------------------------------------------------------- */ /** \name Quaternion Angle * @@ -543,39 +545,39 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q float angle_normalized_qt(const float q[4]) { - BLI_ASSERT_UNIT_QUAT(q); - return 2.0f * saacos(q[0]); + BLI_ASSERT_UNIT_QUAT(q); + return 2.0f * saacos(q[0]); } float angle_qt(const float q[4]) { - float tquat[4]; + float tquat[4]; - normalize_qt_qt(tquat, q); + normalize_qt_qt(tquat, q); - return angle_normalized_qt(tquat); + return angle_normalized_qt(tquat); } float angle_normalized_qtqt(const float q1[4], const float q2[4]) { - float qdelta[4]; + float qdelta[4]; - BLI_ASSERT_UNIT_QUAT(q1); - BLI_ASSERT_UNIT_QUAT(q2); + BLI_ASSERT_UNIT_QUAT(q1); + BLI_ASSERT_UNIT_QUAT(q2); - rotation_between_quats_to_quat(qdelta, q1, q2); + rotation_between_quats_to_quat(qdelta, q1, q2); - return angle_normalized_qt(qdelta); + return angle_normalized_qt(qdelta); } float angle_qtqt(const float q1[4], const float q2[4]) { - float quat1[4], quat2[4]; + float quat1[4], quat2[4]; - normalize_qt_qt(quat1, q1); - normalize_qt_qt(quat2, q2); + normalize_qt_qt(quat1, q1); + normalize_qt_qt(quat2, q2); - return angle_normalized_qtqt(quat1, quat2); + return angle_normalized_qtqt(quat1, quat2); } /** \} */ @@ -592,148 +594,160 @@ float angle_qtqt(const float q1[4], const float q2[4]) float angle_signed_normalized_qt(const float q[4]) { - BLI_ASSERT_UNIT_QUAT(q); - if (q[0] >= 0.0f) { - return 2.0f * saacos(q[0]); - } - else { - return -2.0f * saacos(-q[0]); - } + BLI_ASSERT_UNIT_QUAT(q); + if (q[0] >= 0.0f) { + return 2.0f * saacos(q[0]); + } + else { + return -2.0f * saacos(-q[0]); + } } float angle_signed_normalized_qtqt(const float q1[4], const float q2[4]) { - if (dot_qtqt(q1, q2) >= 0.0f) { - return angle_normalized_qtqt(q1, q2); - } - else { - float q2_copy[4]; - negate_v4_v4(q2_copy, q2); - return -angle_normalized_qtqt(q1, q2_copy); - } + if (dot_qtqt(q1, q2) >= 0.0f) { + return angle_normalized_qtqt(q1, q2); + } + else { + float q2_copy[4]; + negate_v4_v4(q2_copy, q2); + return -angle_normalized_qtqt(q1, q2_copy); + } } float angle_signed_qt(const float q[4]) { - float tquat[4]; + float tquat[4]; - normalize_qt_qt(tquat, q); + normalize_qt_qt(tquat, q); - return angle_signed_normalized_qt(tquat); + return angle_signed_normalized_qt(tquat); } float angle_signed_qtqt(const float q1[4], const float q2[4]) { - if (dot_qtqt(q1, q2) >= 0.0f) { - return angle_qtqt(q1, q2); - } - else { - float q2_copy[4]; - negate_v4_v4(q2_copy, q2); - return -angle_qtqt(q1, q2_copy); - } + if (dot_qtqt(q1, q2) >= 0.0f) { + return angle_qtqt(q1, q2); + } + else { + float q2_copy[4]; + negate_v4_v4(q2_copy, q2); + return -angle_qtqt(q1, q2_copy); + } } /** \} */ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag) { - const float eps = 1e-4f; - float nor[3], tvec[3]; - float angle, si, co, len; - - assert(axis >= 0 && axis <= 5); - assert(upflag >= 0 && upflag <= 2); - - /* first set the quat to unit */ - unit_qt(q); - - len = len_v3(vec); - - if (UNLIKELY(len == 0.0f)) { - return; - } - - /* rotate to axis */ - if (axis > 2) { - copy_v3_v3(tvec, vec); - axis = (short)(axis - 3); - } - else { - negate_v3_v3(tvec, vec); - } - - /* nasty! I need a good routine for this... - * problem is a rotation of an Y axis to the negative Y-axis for example. - */ - - if (axis == 0) { /* x-axis */ - nor[0] = 0.0; - nor[1] = -tvec[2]; - nor[2] = tvec[1]; - - if (fabsf(tvec[1]) + fabsf(tvec[2]) < eps) { - nor[1] = 1.0f; - } - - co = tvec[0]; - } - else if (axis == 1) { /* y-axis */ - nor[0] = tvec[2]; - nor[1] = 0.0; - nor[2] = -tvec[0]; - - if (fabsf(tvec[0]) + fabsf(tvec[2]) < eps) { - nor[2] = 1.0f; - } - - co = tvec[1]; - } - else { /* z-axis */ - nor[0] = -tvec[1]; - nor[1] = tvec[0]; - nor[2] = 0.0; - - if (fabsf(tvec[0]) + fabsf(tvec[1]) < eps) { - nor[0] = 1.0f; - } - - co = tvec[2]; - } - co /= len; - - normalize_v3(nor); - - axis_angle_normalized_to_quat(q, nor, saacos(co)); - - if (axis != upflag) { - float mat[3][3]; - float q2[4]; - const float *fp = mat[2]; - quat_to_mat3(mat, q); - - if (axis == 0) { - if (upflag == 1) { angle = 0.5f * atan2f(fp[2], fp[1]); } - else { angle = -0.5f * atan2f(fp[1], fp[2]); } - } - else if (axis == 1) { - if (upflag == 0) { angle = -0.5f * atan2f(fp[2], fp[0]); } - else { angle = 0.5f * atan2f(fp[0], fp[2]); } - } - else { - if (upflag == 0) { angle = 0.5f * atan2f(-fp[1], -fp[0]); } - else { angle = -0.5f * atan2f(-fp[0], -fp[1]); } - } - - co = cosf(angle); - si = sinf(angle) / len; - q2[0] = co; - q2[1] = tvec[0] * si; - q2[2] = tvec[1] * si; - q2[3] = tvec[2] * si; - - mul_qt_qtqt(q, q2, q); - } + const float eps = 1e-4f; + float nor[3], tvec[3]; + float angle, si, co, len; + + assert(axis >= 0 && axis <= 5); + assert(upflag >= 0 && upflag <= 2); + + /* first set the quat to unit */ + unit_qt(q); + + len = len_v3(vec); + + if (UNLIKELY(len == 0.0f)) { + return; + } + + /* rotate to axis */ + if (axis > 2) { + copy_v3_v3(tvec, vec); + axis = (short)(axis - 3); + } + else { + negate_v3_v3(tvec, vec); + } + + /* nasty! I need a good routine for this... + * problem is a rotation of an Y axis to the negative Y-axis for example. + */ + + if (axis == 0) { /* x-axis */ + nor[0] = 0.0; + nor[1] = -tvec[2]; + nor[2] = tvec[1]; + + if (fabsf(tvec[1]) + fabsf(tvec[2]) < eps) { + nor[1] = 1.0f; + } + + co = tvec[0]; + } + else if (axis == 1) { /* y-axis */ + nor[0] = tvec[2]; + nor[1] = 0.0; + nor[2] = -tvec[0]; + + if (fabsf(tvec[0]) + fabsf(tvec[2]) < eps) { + nor[2] = 1.0f; + } + + co = tvec[1]; + } + else { /* z-axis */ + nor[0] = -tvec[1]; + nor[1] = tvec[0]; + nor[2] = 0.0; + + if (fabsf(tvec[0]) + fabsf(tvec[1]) < eps) { + nor[0] = 1.0f; + } + + co = tvec[2]; + } + co /= len; + + normalize_v3(nor); + + axis_angle_normalized_to_quat(q, nor, saacos(co)); + + if (axis != upflag) { + float mat[3][3]; + float q2[4]; + const float *fp = mat[2]; + quat_to_mat3(mat, q); + + if (axis == 0) { + if (upflag == 1) { + angle = 0.5f * atan2f(fp[2], fp[1]); + } + else { + angle = -0.5f * atan2f(fp[1], fp[2]); + } + } + else if (axis == 1) { + if (upflag == 0) { + angle = -0.5f * atan2f(fp[2], fp[0]); + } + else { + angle = 0.5f * atan2f(fp[0], fp[2]); + } + } + else { + if (upflag == 0) { + angle = 0.5f * atan2f(-fp[1], -fp[0]); + } + else { + angle = -0.5f * atan2f(-fp[0], -fp[1]); + } + } + + co = cosf(angle); + si = sinf(angle) / len; + q2[0] = co; + q2[1] = tvec[0] * si; + q2[2] = tvec[1] * si; + q2[3] = tvec[2] * si; + + mul_qt_qtqt(q, q2, q); + } } #if 0 @@ -741,42 +755,42 @@ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag) /* A & M Watt, Advanced animation and rendering techniques, 1992 ACM press */ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t) { - float omega, cosom, sinom, sc1, sc2; - - cosom = quat1[0] * quat2[0] + quat1[1] * quat2[1] + quat1[2] * quat2[2] + quat1[3] * quat2[3]; - - /* rotate around shortest angle */ - if ((1.0f + cosom) > 0.0001f) { - - if ((1.0f - cosom) > 0.0001f) { - omega = (float)acos(cosom); - sinom = sinf(omega); - sc1 = sinf((1.0 - t) * omega) / sinom; - sc2 = sinf(t * omega) / sinom; - } - else { - sc1 = 1.0f - t; - sc2 = t; - } - result[0] = sc1 * quat1[0] + sc2 * quat2[0]; - result[1] = sc1 * quat1[1] + sc2 * quat2[1]; - result[2] = sc1 * quat1[2] + sc2 * quat2[2]; - result[3] = sc1 * quat1[3] + sc2 * quat2[3]; - } - else { - result[0] = quat2[3]; - result[1] = -quat2[2]; - result[2] = quat2[1]; - result[3] = -quat2[0]; - - sc1 = sinf((1.0 - t) * M_PI_2); - sc2 = sinf(t * M_PI_2); - - result[0] = sc1 * quat1[0] + sc2 * result[0]; - result[1] = sc1 * quat1[1] + sc2 * result[1]; - result[2] = sc1 * quat1[2] + sc2 * result[2]; - result[3] = sc1 * quat1[3] + sc2 * result[3]; - } + float omega, cosom, sinom, sc1, sc2; + + cosom = quat1[0] * quat2[0] + quat1[1] * quat2[1] + quat1[2] * quat2[2] + quat1[3] * quat2[3]; + + /* rotate around shortest angle */ + if ((1.0f + cosom) > 0.0001f) { + + if ((1.0f - cosom) > 0.0001f) { + omega = (float)acos(cosom); + sinom = sinf(omega); + sc1 = sinf((1.0 - t) * omega) / sinom; + sc2 = sinf(t * omega) / sinom; + } + else { + sc1 = 1.0f - t; + sc2 = t; + } + result[0] = sc1 * quat1[0] + sc2 * quat2[0]; + result[1] = sc1 * quat1[1] + sc2 * quat2[1]; + result[2] = sc1 * quat1[2] + sc2 * quat2[2]; + result[3] = sc1 * quat1[3] + sc2 * quat2[3]; + } + else { + result[0] = quat2[3]; + result[1] = -quat2[2]; + result[2] = quat2[1]; + result[3] = -quat2[0]; + + sc1 = sinf((1.0 - t) * M_PI_2); + sc2 = sinf(t * M_PI_2); + + result[0] = sc1 * quat1[0] + sc2 * result[0]; + result[1] = sc1 * quat1[1] + sc2 * result[1]; + result[2] = sc1 * quat1[2] + sc2 * result[2]; + result[3] = sc1 * quat1[3] + sc2 * result[3]; + } } #endif @@ -790,112 +804,112 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t) */ void interp_dot_slerp(const float t, const float cosom, float r_w[2]) { - const float eps = 1e-4f; + const float eps = 1e-4f; - BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f)); + BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f)); - /* within [-1..1] range, avoid aligned axis */ - if (LIKELY(fabsf(cosom) < (1.0f - eps))) { - float omega, sinom; + /* within [-1..1] range, avoid aligned axis */ + if (LIKELY(fabsf(cosom) < (1.0f - eps))) { + float omega, sinom; - omega = acosf(cosom); - sinom = sinf(omega); - r_w[0] = sinf((1.0f - t) * omega) / sinom; - r_w[1] = sinf(t * omega) / sinom; - } - else { - /* fallback to lerp */ - r_w[0] = 1.0f - t; - r_w[1] = t; - } + omega = acosf(cosom); + sinom = sinf(omega); + r_w[0] = sinf((1.0f - t) * omega) / sinom; + r_w[1] = sinf(t * omega) / sinom; + } + else { + /* fallback to lerp */ + r_w[0] = 1.0f - t; + r_w[1] = t; + } } void interp_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], const float t) { - float quat[4], cosom, w[2]; + float quat[4], cosom, w[2]; - BLI_ASSERT_UNIT_QUAT(quat1); - BLI_ASSERT_UNIT_QUAT(quat2); + BLI_ASSERT_UNIT_QUAT(quat1); + BLI_ASSERT_UNIT_QUAT(quat2); - cosom = dot_qtqt(quat1, quat2); + cosom = dot_qtqt(quat1, quat2); - /* rotate around shortest angle */ - if (cosom < 0.0f) { - cosom = -cosom; - negate_v4_v4(quat, quat1); - } - else { - copy_qt_qt(quat, quat1); - } + /* rotate around shortest angle */ + if (cosom < 0.0f) { + cosom = -cosom; + negate_v4_v4(quat, quat1); + } + else { + copy_qt_qt(quat, quat1); + } - interp_dot_slerp(t, cosom, w); + interp_dot_slerp(t, cosom, w); - result[0] = w[0] * quat[0] + w[1] * quat2[0]; - result[1] = w[0] * quat[1] + w[1] * quat2[1]; - result[2] = w[0] * quat[2] + w[1] * quat2[2]; - result[3] = w[0] * quat[3] + w[1] * quat2[3]; + result[0] = w[0] * quat[0] + w[1] * quat2[0]; + result[1] = w[0] * quat[1] + w[1] * quat2[1]; + result[2] = w[0] * quat[2] + w[1] * quat2[2]; + result[3] = w[0] * quat[3] + w[1] * quat2[3]; } void add_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], const float t) { - result[0] = quat1[0] + t * quat2[0]; - result[1] = quat1[1] + t * quat2[1]; - result[2] = quat1[2] + t * quat2[2]; - result[3] = quat1[3] + t * quat2[3]; + result[0] = quat1[0] + t * quat2[0]; + result[1] = quat1[1] + t * quat2[1]; + result[2] = quat1[2] + t * quat2[2]; + result[3] = quat1[3] + t * quat2[3]; } /* same as tri_to_quat() but takes pre-computed normal from the triangle * used for ngons when we know their normal */ -void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const float v3[3], - const float no_orig[3]) +void tri_to_quat_ex( + float quat[4], const float v1[3], const float v2[3], const float v3[3], const float no_orig[3]) { - /* imaginary x-axis, y-axis triangle is being rotated */ - float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3]; + /* imaginary x-axis, y-axis triangle is being rotated */ + float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3]; - /* move z-axis to face-normal */ + /* move z-axis to face-normal */ #if 0 - normal_tri_v3(vec, v1, v2, v3); + normal_tri_v3(vec, v1, v2, v3); #else - copy_v3_v3(vec, no_orig); - (void)v3; + copy_v3_v3(vec, no_orig); + (void)v3; #endif - n[0] = vec[1]; - n[1] = -vec[0]; - n[2] = 0.0f; - normalize_v3(n); + n[0] = vec[1]; + n[1] = -vec[0]; + n[2] = 0.0f; + normalize_v3(n); - if (n[0] == 0.0f && n[1] == 0.0f) { - n[0] = 1.0f; - } + if (n[0] == 0.0f && n[1] == 0.0f) { + n[0] = 1.0f; + } - angle = -0.5f * saacos(vec[2]); - co = cosf(angle); - si = sinf(angle); - q1[0] = co; - q1[1] = n[0] * si; - q1[2] = n[1] * si; - q1[3] = 0.0f; + angle = -0.5f * saacos(vec[2]); + co = cosf(angle); + si = sinf(angle); + q1[0] = co; + q1[1] = n[0] * si; + q1[2] = n[1] * si; + q1[3] = 0.0f; - /* rotate back line v1-v2 */ - quat_to_mat3(mat, q1); - invert_m3_m3(imat, mat); - sub_v3_v3v3(vec, v2, v1); - mul_m3_v3(imat, vec); + /* rotate back line v1-v2 */ + quat_to_mat3(mat, q1); + invert_m3_m3(imat, mat); + sub_v3_v3v3(vec, v2, v1); + mul_m3_v3(imat, vec); - /* what angle has this line with x-axis? */ - vec[2] = 0.0f; - normalize_v3(vec); + /* what angle has this line with x-axis? */ + vec[2] = 0.0f; + normalize_v3(vec); - angle = 0.5f * atan2f(vec[1], vec[0]); - co = cosf(angle); - si = sinf(angle); - q2[0] = co; - q2[1] = 0.0f; - q2[2] = 0.0f; - q2[3] = si; + angle = 0.5f * atan2f(vec[1], vec[0]); + co = cosf(angle); + si = sinf(angle); + q2[0] = co; + q2[1] = 0.0f; + q2[2] = 0.0f; + q2[3] = si; - mul_qt_qtqt(quat, q1, q2); + mul_qt_qtqt(quat, q1, q2); } /** @@ -903,91 +917,94 @@ void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const f */ float tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3]) { - float vec[3]; - const float len = normal_tri_v3(vec, v1, v2, v3); + float vec[3]; + const float len = normal_tri_v3(vec, v1, v2, v3); - tri_to_quat_ex(quat, v1, v2, v3, vec); - return len; + tri_to_quat_ex(quat, v1, v2, v3, vec); + return len; } void print_qt(const char *str, const float q[4]) { - printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]); + printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]); } /******************************** Axis Angle *********************************/ void axis_angle_normalized_to_quat(float q[4], const float axis[3], const float angle) { - const float phi = 0.5f * angle; - const float si = sinf(phi); - const float co = cosf(phi); - BLI_ASSERT_UNIT_V3(axis); - q[0] = co; - mul_v3_v3fl(q + 1, axis, si); + const float phi = 0.5f * angle; + const float si = sinf(phi); + const float co = cosf(phi); + BLI_ASSERT_UNIT_V3(axis); + q[0] = co; + mul_v3_v3fl(q + 1, axis, si); } void axis_angle_to_quat(float q[4], const float axis[3], const float angle) { - float nor[3]; + float nor[3]; - if (LIKELY(normalize_v3_v3(nor, axis) != 0.0f)) { - axis_angle_normalized_to_quat(q, nor, angle); - } - else { - unit_qt(q); - } + if (LIKELY(normalize_v3_v3(nor, axis) != 0.0f)) { + axis_angle_normalized_to_quat(q, nor, angle); + } + else { + unit_qt(q); + } } /* Quaternions to Axis Angle */ void quat_to_axis_angle(float axis[3], float *angle, const float q[4]) { - float ha, si; + float ha, si; #ifdef DEBUG - if (!((ha = dot_qtqt(q, q)) == 0.0f || (fabsf(ha - 1.0f) < (float)QUAT_EPSILON))) { - fprintf(stderr, "Warning! quat_to_axis_angle() called with non-normalized: size %.8f *** report a bug ***\n", ha); - } + if (!((ha = dot_qtqt(q, q)) == 0.0f || (fabsf(ha - 1.0f) < (float)QUAT_EPSILON))) { + fprintf(stderr, + "Warning! quat_to_axis_angle() called with non-normalized: size %.8f *** report a bug " + "***\n", + ha); + } #endif - /* calculate angle/2, and sin(angle/2) */ - ha = acosf(q[0]); - si = sinf(ha); + /* calculate angle/2, and sin(angle/2) */ + ha = acosf(q[0]); + si = sinf(ha); - /* from half-angle to angle */ - *angle = ha * 2; + /* from half-angle to angle */ + *angle = ha * 2; - /* prevent division by zero for axis conversion */ - if (fabsf(si) < 0.0005f) { - si = 1.0f; - } + /* prevent division by zero for axis conversion */ + if (fabsf(si) < 0.0005f) { + si = 1.0f; + } - axis[0] = q[1] / si; - axis[1] = q[2] / si; - axis[2] = q[3] / si; - if (is_zero_v3(axis)) { - axis[1] = 1.0f; - } + axis[0] = q[1] / si; + axis[1] = q[2] / si; + axis[2] = q[3] / si; + if (is_zero_v3(axis)) { + axis[1] = 1.0f; + } } /* Axis Angle to Euler Rotation */ void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation for now... */ - axis_angle_to_quat(q, axis, angle); - quat_to_eulO(eul, order, q); + /* use quaternions as intermediate representation for now... */ + axis_angle_to_quat(q, axis, angle); + quat_to_eulO(eul, order, q); } /* Euler Rotation to Axis Angle */ void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation for now... */ - eulO_to_quat(q, eul, order); - quat_to_axis_angle(axis, angle, q); + /* use quaternions as intermediate representation for now... */ + eulO_to_quat(q, eul, order); + quat_to_axis_angle(axis, angle, q); } /** @@ -999,223 +1016,224 @@ void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const s * \param angle_sin: sin(angle) * \param angle_cos: cos(angle) */ -void axis_angle_normalized_to_mat3_ex(float mat[3][3], const float axis[3], - const float angle_sin, const float angle_cos) +void axis_angle_normalized_to_mat3_ex(float mat[3][3], + const float axis[3], + const float angle_sin, + const float angle_cos) { - float nsi[3], ico; - float n_00, n_01, n_11, n_02, n_12, n_22; + float nsi[3], ico; + float n_00, n_01, n_11, n_02, n_12, n_22; - BLI_ASSERT_UNIT_V3(axis); + BLI_ASSERT_UNIT_V3(axis); - /* now convert this to a 3x3 matrix */ + /* now convert this to a 3x3 matrix */ - ico = (1.0f - angle_cos); - nsi[0] = axis[0] * angle_sin; - nsi[1] = axis[1] * angle_sin; - nsi[2] = axis[2] * angle_sin; + ico = (1.0f - angle_cos); + nsi[0] = axis[0] * angle_sin; + nsi[1] = axis[1] * angle_sin; + nsi[2] = axis[2] * angle_sin; - n_00 = (axis[0] * axis[0]) * ico; - n_01 = (axis[0] * axis[1]) * ico; - n_11 = (axis[1] * axis[1]) * ico; - n_02 = (axis[0] * axis[2]) * ico; - n_12 = (axis[1] * axis[2]) * ico; - n_22 = (axis[2] * axis[2]) * ico; + n_00 = (axis[0] * axis[0]) * ico; + n_01 = (axis[0] * axis[1]) * ico; + n_11 = (axis[1] * axis[1]) * ico; + n_02 = (axis[0] * axis[2]) * ico; + n_12 = (axis[1] * axis[2]) * ico; + n_22 = (axis[2] * axis[2]) * ico; - mat[0][0] = n_00 + angle_cos; - mat[0][1] = n_01 + nsi[2]; - mat[0][2] = n_02 - nsi[1]; - mat[1][0] = n_01 - nsi[2]; - mat[1][1] = n_11 + angle_cos; - mat[1][2] = n_12 + nsi[0]; - mat[2][0] = n_02 + nsi[1]; - mat[2][1] = n_12 - nsi[0]; - mat[2][2] = n_22 + angle_cos; + mat[0][0] = n_00 + angle_cos; + mat[0][1] = n_01 + nsi[2]; + mat[0][2] = n_02 - nsi[1]; + mat[1][0] = n_01 - nsi[2]; + mat[1][1] = n_11 + angle_cos; + mat[1][2] = n_12 + nsi[0]; + mat[2][0] = n_02 + nsi[1]; + mat[2][1] = n_12 - nsi[0]; + mat[2][2] = n_22 + angle_cos; } void axis_angle_normalized_to_mat3(float mat[3][3], const float axis[3], const float angle) { - axis_angle_normalized_to_mat3_ex(mat, axis, sinf(angle), cosf(angle)); + axis_angle_normalized_to_mat3_ex(mat, axis, sinf(angle), cosf(angle)); } - /* axis angle to 3x3 matrix - safer version (normalization of axis performed) */ void axis_angle_to_mat3(float mat[3][3], const float axis[3], const float angle) { - float nor[3]; + float nor[3]; - /* normalize the axis first (to remove unwanted scaling) */ - if (normalize_v3_v3(nor, axis) == 0.0f) { - unit_m3(mat); - return; - } + /* normalize the axis first (to remove unwanted scaling) */ + if (normalize_v3_v3(nor, axis) == 0.0f) { + unit_m3(mat); + return; + } - axis_angle_normalized_to_mat3(mat, nor, angle); + axis_angle_normalized_to_mat3(mat, nor, angle); } /* axis angle to 4x4 matrix - safer version (normalization of axis performed) */ void axis_angle_to_mat4(float mat[4][4], const float axis[3], const float angle) { - float tmat[3][3]; + float tmat[3][3]; - axis_angle_to_mat3(tmat, axis, angle); - unit_m4(mat); - copy_m4_m3(mat, tmat); + axis_angle_to_mat3(tmat, axis, angle); + unit_m4(mat); + copy_m4_m3(mat, tmat); } /* 3x3 matrix to axis angle */ void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3]) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation */ - /* TODO: it would be nicer to go straight there... */ - mat3_normalized_to_quat(q, mat); - quat_to_axis_angle(axis, angle, q); + /* use quaternions as intermediate representation */ + /* TODO: it would be nicer to go straight there... */ + mat3_normalized_to_quat(q, mat); + quat_to_axis_angle(axis, angle, q); } void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3]) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation */ - /* TODO: it would be nicer to go straight there... */ - mat3_to_quat(q, mat); - quat_to_axis_angle(axis, angle, q); + /* use quaternions as intermediate representation */ + /* TODO: it would be nicer to go straight there... */ + mat3_to_quat(q, mat); + quat_to_axis_angle(axis, angle, q); } /* 4x4 matrix to axis angle */ void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float mat[4][4]) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation */ - /* TODO: it would be nicer to go straight there... */ - mat4_normalized_to_quat(q, mat); - quat_to_axis_angle(axis, angle, q); + /* use quaternions as intermediate representation */ + /* TODO: it would be nicer to go straight there... */ + mat4_normalized_to_quat(q, mat); + quat_to_axis_angle(axis, angle, q); } /* 4x4 matrix to axis angle */ void mat4_to_axis_angle(float axis[3], float *angle, const float mat[4][4]) { - float q[4]; + float q[4]; - /* use quaternions as intermediate representation */ - /* TODO: it would be nicer to go straight there... */ - mat4_to_quat(q, mat); - quat_to_axis_angle(axis, angle, q); + /* use quaternions as intermediate representation */ + /* TODO: it would be nicer to go straight there... */ + mat4_to_quat(q, mat); + quat_to_axis_angle(axis, angle, q); } void axis_angle_to_mat4_single(float mat[4][4], const char axis, const float angle) { - float mat3[3][3]; - axis_angle_to_mat3_single(mat3, axis, angle); - copy_m4_m3(mat, mat3); + float mat3[3][3]; + axis_angle_to_mat3_single(mat3, axis, angle); + copy_m4_m3(mat, mat3); } /* rotation matrix from a single axis */ void axis_angle_to_mat3_single(float mat[3][3], const char axis, const float angle) { - const float angle_cos = cosf(angle); - const float angle_sin = sinf(angle); - - switch (axis) { - case 'X': /* rotation around X */ - mat[0][0] = 1.0f; - mat[0][1] = 0.0f; - mat[0][2] = 0.0f; - mat[1][0] = 0.0f; - mat[1][1] = angle_cos; - mat[1][2] = angle_sin; - mat[2][0] = 0.0f; - mat[2][1] = -angle_sin; - mat[2][2] = angle_cos; - break; - case 'Y': /* rotation around Y */ - mat[0][0] = angle_cos; - mat[0][1] = 0.0f; - mat[0][2] = -angle_sin; - mat[1][0] = 0.0f; - mat[1][1] = 1.0f; - mat[1][2] = 0.0f; - mat[2][0] = angle_sin; - mat[2][1] = 0.0f; - mat[2][2] = angle_cos; - break; - case 'Z': /* rotation around Z */ - mat[0][0] = angle_cos; - mat[0][1] = angle_sin; - mat[0][2] = 0.0f; - mat[1][0] = -angle_sin; - mat[1][1] = angle_cos; - mat[1][2] = 0.0f; - mat[2][0] = 0.0f; - mat[2][1] = 0.0f; - mat[2][2] = 1.0f; - break; - default: - BLI_assert(0); - break; - } + const float angle_cos = cosf(angle); + const float angle_sin = sinf(angle); + + switch (axis) { + case 'X': /* rotation around X */ + mat[0][0] = 1.0f; + mat[0][1] = 0.0f; + mat[0][2] = 0.0f; + mat[1][0] = 0.0f; + mat[1][1] = angle_cos; + mat[1][2] = angle_sin; + mat[2][0] = 0.0f; + mat[2][1] = -angle_sin; + mat[2][2] = angle_cos; + break; + case 'Y': /* rotation around Y */ + mat[0][0] = angle_cos; + mat[0][1] = 0.0f; + mat[0][2] = -angle_sin; + mat[1][0] = 0.0f; + mat[1][1] = 1.0f; + mat[1][2] = 0.0f; + mat[2][0] = angle_sin; + mat[2][1] = 0.0f; + mat[2][2] = angle_cos; + break; + case 'Z': /* rotation around Z */ + mat[0][0] = angle_cos; + mat[0][1] = angle_sin; + mat[0][2] = 0.0f; + mat[1][0] = -angle_sin; + mat[1][1] = angle_cos; + mat[1][2] = 0.0f; + mat[2][0] = 0.0f; + mat[2][1] = 0.0f; + mat[2][2] = 1.0f; + break; + default: + BLI_assert(0); + break; + } } void angle_to_mat2(float mat[2][2], const float angle) { - const float angle_cos = cosf(angle); - const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + const float angle_sin = sinf(angle); - /* 2D rotation matrix */ - mat[0][0] = angle_cos; - mat[0][1] = angle_sin; - mat[1][0] = -angle_sin; - mat[1][1] = angle_cos; + /* 2D rotation matrix */ + mat[0][0] = angle_cos; + mat[0][1] = angle_sin; + mat[1][0] = -angle_sin; + mat[1][1] = angle_cos; } void axis_angle_to_quat_single(float q[4], const char axis, const float angle) { - const float angle_half = angle * 0.5f; - const float angle_cos = cosf(angle_half); - const float angle_sin = sinf(angle_half); - const int axis_index = (axis - 'X'); + const float angle_half = angle * 0.5f; + const float angle_cos = cosf(angle_half); + const float angle_sin = sinf(angle_half); + const int axis_index = (axis - 'X'); - assert(axis >= 'X' && axis <= 'Z'); + assert(axis >= 'X' && axis <= 'Z'); - q[0] = angle_cos; - zero_v3(q + 1); - q[axis_index + 1] = angle_sin; + q[0] = angle_cos; + zero_v3(q + 1); + q[axis_index + 1] = angle_sin; } /****************************** Exponential Map ******************************/ void quat_normalized_to_expmap(float expmap[3], const float q[4]) { - float angle; - BLI_ASSERT_UNIT_QUAT(q); + float angle; + BLI_ASSERT_UNIT_QUAT(q); - /* Obtain axis/angle representation. */ - quat_to_axis_angle(expmap, &angle, q); + /* Obtain axis/angle representation. */ + quat_to_axis_angle(expmap, &angle, q); - /* Convert to exponential map. */ - mul_v3_fl(expmap, angle); + /* Convert to exponential map. */ + mul_v3_fl(expmap, angle); } void quat_to_expmap(float expmap[3], const float q[4]) { - float q_no[4]; - normalize_qt_qt(q_no, q); - quat_normalized_to_expmap(expmap, q_no); + float q_no[4]; + normalize_qt_qt(q_no, q); + quat_normalized_to_expmap(expmap, q_no); } void expmap_to_quat(float r[4], const float expmap[3]) { - float axis[3]; - float angle; + float axis[3]; + float angle; - /* Obtain axis/angle representation. */ - if (LIKELY((angle = normalize_v3_v3(axis, expmap)) != 0.0f)) { - axis_angle_normalized_to_quat(r, axis, angle_wrap_rad(angle)); - } - else { - unit_qt(r); - } + /* Obtain axis/angle representation. */ + if (LIKELY((angle = normalize_v3_v3(axis, expmap)) != 0.0f)) { + axis_angle_normalized_to_quat(r, axis, angle_wrap_rad(angle)); + } + else { + unit_qt(r); + } } /******************************** XYZ Eulers *********************************/ @@ -1223,60 +1241,58 @@ void expmap_to_quat(float r[4], const float expmap[3]) /* XYZ order */ void eul_to_mat3(float mat[3][3], const float eul[3]) { - double ci, cj, ch, si, sj, sh, cc, cs, sc, ss; - - ci = cos(eul[0]); - cj = cos(eul[1]); - ch = cos(eul[2]); - si = sin(eul[0]); - sj = sin(eul[1]); - sh = sin(eul[2]); - cc = ci * ch; - cs = ci * sh; - sc = si * ch; - ss = si * sh; - - mat[0][0] = (float)(cj * ch); - mat[1][0] = (float)(sj * sc - cs); - mat[2][0] = (float)(sj * cc + ss); - mat[0][1] = (float)(cj * sh); - mat[1][1] = (float)(sj * ss + cc); - mat[2][1] = (float)(sj * cs - sc); - mat[0][2] = (float)-sj; - mat[1][2] = (float)(cj * si); - mat[2][2] = (float)(cj * ci); - + double ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + + ci = cos(eul[0]); + cj = cos(eul[1]); + ch = cos(eul[2]); + si = sin(eul[0]); + sj = sin(eul[1]); + sh = sin(eul[2]); + cc = ci * ch; + cs = ci * sh; + sc = si * ch; + ss = si * sh; + + mat[0][0] = (float)(cj * ch); + mat[1][0] = (float)(sj * sc - cs); + mat[2][0] = (float)(sj * cc + ss); + mat[0][1] = (float)(cj * sh); + mat[1][1] = (float)(sj * ss + cc); + mat[2][1] = (float)(sj * cs - sc); + mat[0][2] = (float)-sj; + mat[1][2] = (float)(cj * si); + mat[2][2] = (float)(cj * ci); } /* XYZ order */ void eul_to_mat4(float mat[4][4], const float eul[3]) { - double ci, cj, ch, si, sj, sh, cc, cs, sc, ss; - - ci = cos(eul[0]); - cj = cos(eul[1]); - ch = cos(eul[2]); - si = sin(eul[0]); - sj = sin(eul[1]); - sh = sin(eul[2]); - cc = ci * ch; - cs = ci * sh; - sc = si * ch; - ss = si * sh; - - mat[0][0] = (float)(cj * ch); - mat[1][0] = (float)(sj * sc - cs); - mat[2][0] = (float)(sj * cc + ss); - mat[0][1] = (float)(cj * sh); - mat[1][1] = (float)(sj * ss + cc); - mat[2][1] = (float)(sj * cs - sc); - mat[0][2] = (float)-sj; - mat[1][2] = (float)(cj * si); - mat[2][2] = (float)(cj * ci); - - - mat[3][0] = mat[3][1] = mat[3][2] = mat[0][3] = mat[1][3] = mat[2][3] = 0.0f; - mat[3][3] = 1.0f; + double ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + + ci = cos(eul[0]); + cj = cos(eul[1]); + ch = cos(eul[2]); + si = sin(eul[0]); + sj = sin(eul[1]); + sh = sin(eul[2]); + cc = ci * ch; + cs = ci * sh; + sc = si * ch; + ss = si * sh; + + mat[0][0] = (float)(cj * ch); + mat[1][0] = (float)(sj * sc - cs); + mat[2][0] = (float)(sj * cc + ss); + mat[0][1] = (float)(cj * sh); + mat[1][1] = (float)(sj * ss + cc); + mat[2][1] = (float)(sj * cs - sc); + mat[0][2] = (float)-sj; + mat[1][2] = (float)(cj * si); + mat[2][2] = (float)(cj * ci); + + mat[3][0] = mat[3][1] = mat[3][2] = mat[0][3] = mat[1][3] = mat[2][3] = 0.0f; + mat[3][3] = 1.0f; } /* returns two euler calculation methods, so we can pick the best */ @@ -1284,162 +1300,174 @@ void eul_to_mat4(float mat[4][4], const float eul[3]) /* XYZ order */ static void mat3_normalized_to_eul2(const float mat[3][3], float eul1[3], float eul2[3]) { - const float cy = hypotf(mat[0][0], mat[0][1]); + const float cy = hypotf(mat[0][0], mat[0][1]); - BLI_ASSERT_UNIT_M3(mat); + BLI_ASSERT_UNIT_M3(mat); - if (cy > 16.0f * FLT_EPSILON) { + if (cy > 16.0f * FLT_EPSILON) { - eul1[0] = atan2f(mat[1][2], mat[2][2]); - eul1[1] = atan2f(-mat[0][2], cy); - eul1[2] = atan2f(mat[0][1], mat[0][0]); + eul1[0] = atan2f(mat[1][2], mat[2][2]); + eul1[1] = atan2f(-mat[0][2], cy); + eul1[2] = atan2f(mat[0][1], mat[0][0]); - eul2[0] = atan2f(-mat[1][2], -mat[2][2]); - eul2[1] = atan2f(-mat[0][2], -cy); - eul2[2] = atan2f(-mat[0][1], -mat[0][0]); + eul2[0] = atan2f(-mat[1][2], -mat[2][2]); + eul2[1] = atan2f(-mat[0][2], -cy); + eul2[2] = atan2f(-mat[0][1], -mat[0][0]); + } + else { + eul1[0] = atan2f(-mat[2][1], mat[1][1]); + eul1[1] = atan2f(-mat[0][2], cy); + eul1[2] = 0.0f; - } - else { - eul1[0] = atan2f(-mat[2][1], mat[1][1]); - eul1[1] = atan2f(-mat[0][2], cy); - eul1[2] = 0.0f; - - copy_v3_v3(eul2, eul1); - } + copy_v3_v3(eul2, eul1); + } } /* XYZ order */ void mat3_normalized_to_eul(float eul[3], const float mat[3][3]) { - float eul1[3], eul2[3]; + float eul1[3], eul2[3]; - mat3_normalized_to_eul2(mat, eul1, eul2); + mat3_normalized_to_eul2(mat, eul1, eul2); - /* return best, which is just the one with lowest values it in */ - if (fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]) > fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2])) { - copy_v3_v3(eul, eul2); - } - else { - copy_v3_v3(eul, eul1); - } + /* return best, which is just the one with lowest values it in */ + if (fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]) > + fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2])) { + copy_v3_v3(eul, eul2); + } + else { + copy_v3_v3(eul, eul1); + } } void mat3_to_eul(float eul[3], const float mat[3][3]) { - float unit_mat[3][3]; - normalize_m3_m3(unit_mat, mat); - mat3_normalized_to_eul(eul, unit_mat); + float unit_mat[3][3]; + normalize_m3_m3(unit_mat, mat); + mat3_normalized_to_eul(eul, unit_mat); } /* XYZ order */ void mat4_normalized_to_eul(float eul[3], const float m[4][4]) { - float mat3[3][3]; - copy_m3_m4(mat3, m); - mat3_normalized_to_eul(eul, mat3); + float mat3[3][3]; + copy_m3_m4(mat3, m); + mat3_normalized_to_eul(eul, mat3); } void mat4_to_eul(float eul[3], const float m[4][4]) { - float mat3[3][3]; - copy_m3_m4(mat3, m); - mat3_to_eul(eul, mat3); + float mat3[3][3]; + copy_m3_m4(mat3, m); + mat3_to_eul(eul, mat3); } /* XYZ order */ void quat_to_eul(float eul[3], const float quat[4]) { - float unit_mat[3][3]; - quat_to_mat3(unit_mat, quat); - mat3_normalized_to_eul(eul, unit_mat); + float unit_mat[3][3]; + quat_to_mat3(unit_mat, quat); + mat3_normalized_to_eul(eul, unit_mat); } /* XYZ order */ void eul_to_quat(float quat[4], const float eul[3]) { - float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; - ti = eul[0] * 0.5f; - tj = eul[1] * 0.5f; - th = eul[2] * 0.5f; - ci = cosf(ti); - cj = cosf(tj); - ch = cosf(th); - si = sinf(ti); - sj = sinf(tj); - sh = sinf(th); - cc = ci * ch; - cs = ci * sh; - sc = si * ch; - ss = si * sh; + ti = eul[0] * 0.5f; + tj = eul[1] * 0.5f; + th = eul[2] * 0.5f; + ci = cosf(ti); + cj = cosf(tj); + ch = cosf(th); + si = sinf(ti); + sj = sinf(tj); + sh = sinf(th); + cc = ci * ch; + cs = ci * sh; + sc = si * ch; + ss = si * sh; - quat[0] = cj * cc + sj * ss; - quat[1] = cj * sc - sj * cs; - quat[2] = cj * ss + sj * cc; - quat[3] = cj * cs - sj * sc; + quat[0] = cj * cc + sj * ss; + quat[1] = cj * sc - sj * cs; + quat[2] = cj * ss + sj * cc; + quat[3] = cj * cs - sj * sc; } /* XYZ order */ void rotate_eul(float beul[3], const char axis, const float ang) { - float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; + float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; - assert(axis >= 'X' && axis <= 'Z'); + assert(axis >= 'X' && axis <= 'Z'); - eul[0] = eul[1] = eul[2] = 0.0f; - if (axis == 'X') { - eul[0] = ang; - } - else if (axis == 'Y') { - eul[1] = ang; - } - else { - eul[2] = ang; - } + eul[0] = eul[1] = eul[2] = 0.0f; + if (axis == 'X') { + eul[0] = ang; + } + else if (axis == 'Y') { + eul[1] = ang; + } + else { + eul[2] = ang; + } - eul_to_mat3(mat1, eul); - eul_to_mat3(mat2, beul); + eul_to_mat3(mat1, eul); + eul_to_mat3(mat2, beul); - mul_m3_m3m3(totmat, mat2, mat1); + mul_m3_m3m3(totmat, mat2, mat1); - mat3_to_eul(beul, totmat); + mat3_to_eul(beul, totmat); } /* order independent! */ void compatible_eul(float eul[3], const float oldrot[3]) { - /* we could use M_PI as pi_thresh: which is correct but 5.1 gives better results. - * Checked with baking actions to fcurves - campbell */ - const float pi_thresh = (5.1f); - const float pi_x2 = (2.0f * (float)M_PI); - - float deul[3]; - unsigned int i; - - /* correct differences of about 360 degrees first */ - for (i = 0; i < 3; i++) { - deul[i] = eul[i] - oldrot[i]; - if (deul[i] > pi_thresh) { - eul[i] -= floorf(( deul[i] / pi_x2) + 0.5f) * pi_x2; - deul[i] = eul[i] - oldrot[i]; - } - else if (deul[i] < -pi_thresh) { - eul[i] += floorf((-deul[i] / pi_x2) + 0.5f) * pi_x2; - deul[i] = eul[i] - oldrot[i]; - } - } - - /* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */ - if (fabsf(deul[0]) > 3.2f && fabsf(deul[1]) < 1.6f && fabsf(deul[2]) < 1.6f) { - if (deul[0] > 0.0f) { eul[0] -= pi_x2; } - else { eul[0] += pi_x2; } - } - if (fabsf(deul[1]) > 3.2f && fabsf(deul[2]) < 1.6f && fabsf(deul[0]) < 1.6f) { - if (deul[1] > 0.0f) { eul[1] -= pi_x2; } - else { eul[1] += pi_x2; } - } - if (fabsf(deul[2]) > 3.2f && fabsf(deul[0]) < 1.6f && fabsf(deul[1]) < 1.6f) { - if (deul[2] > 0.0f) { eul[2] -= pi_x2; } - else { eul[2] += pi_x2; } - } + /* we could use M_PI as pi_thresh: which is correct but 5.1 gives better results. + * Checked with baking actions to fcurves - campbell */ + const float pi_thresh = (5.1f); + const float pi_x2 = (2.0f * (float)M_PI); + + float deul[3]; + unsigned int i; + + /* correct differences of about 360 degrees first */ + for (i = 0; i < 3; i++) { + deul[i] = eul[i] - oldrot[i]; + if (deul[i] > pi_thresh) { + eul[i] -= floorf((deul[i] / pi_x2) + 0.5f) * pi_x2; + deul[i] = eul[i] - oldrot[i]; + } + else if (deul[i] < -pi_thresh) { + eul[i] += floorf((-deul[i] / pi_x2) + 0.5f) * pi_x2; + deul[i] = eul[i] - oldrot[i]; + } + } + + /* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */ + if (fabsf(deul[0]) > 3.2f && fabsf(deul[1]) < 1.6f && fabsf(deul[2]) < 1.6f) { + if (deul[0] > 0.0f) { + eul[0] -= pi_x2; + } + else { + eul[0] += pi_x2; + } + } + if (fabsf(deul[1]) > 3.2f && fabsf(deul[2]) < 1.6f && fabsf(deul[0]) < 1.6f) { + if (deul[1] > 0.0f) { + eul[1] -= pi_x2; + } + else { + eul[1] += pi_x2; + } + } + if (fabsf(deul[2]) > 3.2f && fabsf(deul[0]) < 1.6f && fabsf(deul[1]) < 1.6f) { + if (deul[2] > 0.0f) { + eul[2] -= pi_x2; + } + else { + eul[2] += pi_x2; + } + } } /* uses 2 methods to retrieve eulers, and picks the closest */ @@ -1447,37 +1475,37 @@ void compatible_eul(float eul[3], const float oldrot[3]) /* XYZ order */ void mat3_normalized_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3]) { - float eul1[3], eul2[3]; - float d1, d2; + float eul1[3], eul2[3]; + float d1, d2; - mat3_normalized_to_eul2(mat, eul1, eul2); + mat3_normalized_to_eul2(mat, eul1, eul2); - compatible_eul(eul1, oldrot); - compatible_eul(eul2, oldrot); + compatible_eul(eul1, oldrot); + compatible_eul(eul2, oldrot); - d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]); - d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]); + d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]); + d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]); - /* return best, which is just the one with lowest difference */ - if (d1 > d2) { - copy_v3_v3(eul, eul2); - } - else { - copy_v3_v3(eul, eul1); - } + /* return best, which is just the one with lowest difference */ + if (d1 > d2) { + copy_v3_v3(eul, eul2); + } + else { + copy_v3_v3(eul, eul1); + } } void mat3_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3]) { - float unit_mat[3][3]; - normalize_m3_m3(unit_mat, mat); - mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat); + float unit_mat[3][3]; + normalize_m3_m3(unit_mat, mat); + mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat); } void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float quat[4]) { - float unit_mat[3][3]; - quat_to_mat3(unit_mat, quat); - mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat); + float unit_mat[3][3]; + quat_to_mat3(unit_mat, quat); + mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat); } /************************** Arbitrary Order Eulers ***************************/ @@ -1493,21 +1521,21 @@ void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float qua /* Type for rotation order info - see wiki for derivation details */ typedef struct RotOrderInfo { - short axis[3]; - short parity; /* parity of axis permutation (even=0, odd=1) - 'n' in original code */ + short axis[3]; + short parity; /* parity of axis permutation (even=0, odd=1) - 'n' in original code */ } RotOrderInfo; /* Array of info for Rotation Order calculations * WARNING: must be kept in same order as eEulerRotationOrders */ static const RotOrderInfo rotOrders[] = { - /* i, j, k, n */ - {{0, 1, 2}, 0}, /* XYZ */ - {{0, 2, 1}, 1}, /* XZY */ - {{1, 0, 2}, 1}, /* YXZ */ - {{1, 2, 0}, 0}, /* YZX */ - {{2, 0, 1}, 0}, /* ZXY */ - {{2, 1, 0}, 1} /* ZYX */ + /* i, j, k, n */ + {{0, 1, 2}, 0}, /* XYZ */ + {{0, 2, 1}, 1}, /* XZY */ + {{1, 0, 2}, 1}, /* YXZ */ + {{1, 2, 0}, 0}, /* YZX */ + {{2, 0, 1}, 0}, /* ZXY */ + {{2, 1, 0}, 1} /* ZYX */ }; /* Get relevant pointer to rotation order set from the array @@ -1516,254 +1544,266 @@ static const RotOrderInfo rotOrders[] = { */ static const RotOrderInfo *get_rotation_order_info(const short order) { - assert(order >= 0 && order <= 6); - if (order < 1) { - return &rotOrders[0]; - } - else if (order < 6) { - return &rotOrders[order - 1]; - } - else { - return &rotOrders[5]; - } + assert(order >= 0 && order <= 6); + if (order < 1) { + return &rotOrders[0]; + } + else if (order < 6) { + return &rotOrders[order - 1]; + } + else { + return &rotOrders[5]; + } } /* Construct quaternion from Euler angles (in radians). */ void eulO_to_quat(float q[4], const float e[3], const short order) { - const RotOrderInfo *R = get_rotation_order_info(order); - short i = R->axis[0], j = R->axis[1], k = R->axis[2]; - double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; - double a[3]; + const RotOrderInfo *R = get_rotation_order_info(order); + short i = R->axis[0], j = R->axis[1], k = R->axis[2]; + double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + double a[3]; - ti = e[i] * 0.5f; - tj = e[j] * (R->parity ? -0.5f : 0.5f); - th = e[k] * 0.5f; + ti = e[i] * 0.5f; + tj = e[j] * (R->parity ? -0.5f : 0.5f); + th = e[k] * 0.5f; - ci = cos(ti); - cj = cos(tj); - ch = cos(th); - si = sin(ti); - sj = sin(tj); - sh = sin(th); + ci = cos(ti); + cj = cos(tj); + ch = cos(th); + si = sin(ti); + sj = sin(tj); + sh = sin(th); - cc = ci * ch; - cs = ci * sh; - sc = si * ch; - ss = si * sh; + cc = ci * ch; + cs = ci * sh; + sc = si * ch; + ss = si * sh; - a[i] = cj * sc - sj * cs; - a[j] = cj * ss + sj * cc; - a[k] = cj * cs - sj * sc; + a[i] = cj * sc - sj * cs; + a[j] = cj * ss + sj * cc; + a[k] = cj * cs - sj * sc; - q[0] = (float)(cj * cc + sj * ss); - q[1] = (float)(a[0]); - q[2] = (float)(a[1]); - q[3] = (float)(a[2]); + q[0] = (float)(cj * cc + sj * ss); + q[1] = (float)(a[0]); + q[2] = (float)(a[1]); + q[3] = (float)(a[2]); - if (R->parity) { - q[j + 1] = -q[j + 1]; - } + if (R->parity) { + q[j + 1] = -q[j + 1]; + } } /* Convert quaternion to Euler angles (in radians). */ void quat_to_eulO(float e[3], short const order, const float q[4]) { - float unit_mat[3][3]; + float unit_mat[3][3]; - quat_to_mat3(unit_mat, q); - mat3_normalized_to_eulO(e, order, unit_mat); + quat_to_mat3(unit_mat, q); + mat3_normalized_to_eulO(e, order, unit_mat); } /* Construct 3x3 matrix from Euler angles (in radians). */ void eulO_to_mat3(float M[3][3], const float e[3], const short order) { - const RotOrderInfo *R = get_rotation_order_info(order); - short i = R->axis[0], j = R->axis[1], k = R->axis[2]; - double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; - - if (R->parity) { - ti = -e[i]; - tj = -e[j]; - th = -e[k]; - } - else { - ti = e[i]; - tj = e[j]; - th = e[k]; - } - - ci = cos(ti); - cj = cos(tj); - ch = cos(th); - si = sin(ti); - sj = sin(tj); - sh = sin(th); - - cc = ci * ch; - cs = ci * sh; - sc = si * ch; - ss = si * sh; - - M[i][i] = (float)(cj * ch); - M[j][i] = (float)(sj * sc - cs); - M[k][i] = (float)(sj * cc + ss); - M[i][j] = (float)(cj * sh); - M[j][j] = (float)(sj * ss + cc); - M[k][j] = (float)(sj * cs - sc); - M[i][k] = (float)(-sj); - M[j][k] = (float)(cj * si); - M[k][k] = (float)(cj * ci); + const RotOrderInfo *R = get_rotation_order_info(order); + short i = R->axis[0], j = R->axis[1], k = R->axis[2]; + double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + + if (R->parity) { + ti = -e[i]; + tj = -e[j]; + th = -e[k]; + } + else { + ti = e[i]; + tj = e[j]; + th = e[k]; + } + + ci = cos(ti); + cj = cos(tj); + ch = cos(th); + si = sin(ti); + sj = sin(tj); + sh = sin(th); + + cc = ci * ch; + cs = ci * sh; + sc = si * ch; + ss = si * sh; + + M[i][i] = (float)(cj * ch); + M[j][i] = (float)(sj * sc - cs); + M[k][i] = (float)(sj * cc + ss); + M[i][j] = (float)(cj * sh); + M[j][j] = (float)(sj * ss + cc); + M[k][j] = (float)(sj * cs - sc); + M[i][k] = (float)(-sj); + M[j][k] = (float)(cj * si); + M[k][k] = (float)(cj * ci); } /* returns two euler calculation methods, so we can pick the best */ -static void mat3_normalized_to_eulo2(const float mat[3][3], float eul1[3], float eul2[3], const short order) +static void mat3_normalized_to_eulo2(const float mat[3][3], + float eul1[3], + float eul2[3], + const short order) { - const RotOrderInfo *R = get_rotation_order_info(order); - short i = R->axis[0], j = R->axis[1], k = R->axis[2]; - float cy; + const RotOrderInfo *R = get_rotation_order_info(order); + short i = R->axis[0], j = R->axis[1], k = R->axis[2]; + float cy; - BLI_ASSERT_UNIT_M3(mat); + BLI_ASSERT_UNIT_M3(mat); - cy = hypotf(mat[i][i], mat[i][j]); + cy = hypotf(mat[i][i], mat[i][j]); - if (cy > 16.0f * FLT_EPSILON) { - eul1[i] = atan2f(mat[j][k], mat[k][k]); - eul1[j] = atan2f(-mat[i][k], cy); - eul1[k] = atan2f(mat[i][j], mat[i][i]); + if (cy > 16.0f * FLT_EPSILON) { + eul1[i] = atan2f(mat[j][k], mat[k][k]); + eul1[j] = atan2f(-mat[i][k], cy); + eul1[k] = atan2f(mat[i][j], mat[i][i]); - eul2[i] = atan2f(-mat[j][k], -mat[k][k]); - eul2[j] = atan2f(-mat[i][k], -cy); - eul2[k] = atan2f(-mat[i][j], -mat[i][i]); - } - else { - eul1[i] = atan2f(-mat[k][j], mat[j][j]); - eul1[j] = atan2f(-mat[i][k], cy); - eul1[k] = 0; + eul2[i] = atan2f(-mat[j][k], -mat[k][k]); + eul2[j] = atan2f(-mat[i][k], -cy); + eul2[k] = atan2f(-mat[i][j], -mat[i][i]); + } + else { + eul1[i] = atan2f(-mat[k][j], mat[j][j]); + eul1[j] = atan2f(-mat[i][k], cy); + eul1[k] = 0; - copy_v3_v3(eul2, eul1); - } + copy_v3_v3(eul2, eul1); + } - if (R->parity) { - negate_v3(eul1); - negate_v3(eul2); - } + if (R->parity) { + negate_v3(eul1); + negate_v3(eul2); + } } /* Construct 4x4 matrix from Euler angles (in radians). */ void eulO_to_mat4(float mat[4][4], const float e[3], const short order) { - float unit_mat[3][3]; + float unit_mat[3][3]; - /* for now, we'll just do this the slow way (i.e. copying matrices) */ - eulO_to_mat3(unit_mat, e, order); - copy_m4_m3(mat, unit_mat); + /* for now, we'll just do this the slow way (i.e. copying matrices) */ + eulO_to_mat3(unit_mat, e, order); + copy_m4_m3(mat, unit_mat); } /* Convert 3x3 matrix to Euler angles (in radians). */ void mat3_normalized_to_eulO(float eul[3], const short order, const float m[3][3]) { - float eul1[3], eul2[3]; - float d1, d2; + float eul1[3], eul2[3]; + float d1, d2; - mat3_normalized_to_eulo2(m, eul1, eul2, order); + mat3_normalized_to_eulo2(m, eul1, eul2, order); - d1 = fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]); - d2 = fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2]); + d1 = fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]); + d2 = fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2]); - /* return best, which is just the one with lowest values it in */ - if (d1 > d2) { - copy_v3_v3(eul, eul2); - } - else { - copy_v3_v3(eul, eul1); - } + /* return best, which is just the one with lowest values it in */ + if (d1 > d2) { + copy_v3_v3(eul, eul2); + } + else { + copy_v3_v3(eul, eul1); + } } void mat3_to_eulO(float eul[3], const short order, const float m[3][3]) { - float unit_mat[3][3]; - normalize_m3_m3(unit_mat, m); - mat3_normalized_to_eulO(eul, order, unit_mat); + float unit_mat[3][3]; + normalize_m3_m3(unit_mat, m); + mat3_normalized_to_eulO(eul, order, unit_mat); } /* Convert 4x4 matrix to Euler angles (in radians). */ void mat4_normalized_to_eulO(float eul[3], const short order, const float m[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - /* for now, we'll just do this the slow way (i.e. copying matrices) */ - copy_m3_m4(mat3, m); - mat3_normalized_to_eulO(eul, order, mat3); + /* for now, we'll just do this the slow way (i.e. copying matrices) */ + copy_m3_m4(mat3, m); + mat3_normalized_to_eulO(eul, order, mat3); } void mat4_to_eulO(float eul[3], const short order, const float m[4][4]) { - float mat3[3][3]; - copy_m3_m4(mat3, m); - normalize_m3(mat3); - mat3_normalized_to_eulO(eul, order, mat3); + float mat3[3][3]; + copy_m3_m4(mat3, m); + normalize_m3(mat3); + mat3_normalized_to_eulO(eul, order, mat3); } - /* uses 2 methods to retrieve eulers, and picks the closest */ -void mat3_normalized_to_compatible_eulO( - float eul[3], const float oldrot[3], const short order, const float mat[3][3]) +void mat3_normalized_to_compatible_eulO(float eul[3], + const float oldrot[3], + const short order, + const float mat[3][3]) { - float eul1[3], eul2[3]; - float d1, d2; + float eul1[3], eul2[3]; + float d1, d2; - mat3_normalized_to_eulo2(mat, eul1, eul2, order); + mat3_normalized_to_eulo2(mat, eul1, eul2, order); - compatible_eul(eul1, oldrot); - compatible_eul(eul2, oldrot); + compatible_eul(eul1, oldrot); + compatible_eul(eul2, oldrot); - d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]); - d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]); + d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]); + d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]); - /* return best, which is just the one with lowest difference */ - if (d1 > d2) { - copy_v3_v3(eul, eul2); - } - else { - copy_v3_v3(eul, eul1); - } + /* return best, which is just the one with lowest difference */ + if (d1 > d2) { + copy_v3_v3(eul, eul2); + } + else { + copy_v3_v3(eul, eul1); + } } -void mat3_to_compatible_eulO( - float eul[3], const float oldrot[3], const short order, const float mat[3][3]) +void mat3_to_compatible_eulO(float eul[3], + const float oldrot[3], + const short order, + const float mat[3][3]) { - float unit_mat[3][3]; + float unit_mat[3][3]; - normalize_m3_m3(unit_mat, mat); - mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat); + normalize_m3_m3(unit_mat, mat); + mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat); } -void mat4_normalized_to_compatible_eulO( - float eul[3], const float oldrot[3], const short order, const float m[4][4]) +void mat4_normalized_to_compatible_eulO(float eul[3], + const float oldrot[3], + const short order, + const float m[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - /* for now, we'll just do this the slow way (i.e. copying matrices) */ - copy_m3_m4(mat3, m); - mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); + /* for now, we'll just do this the slow way (i.e. copying matrices) */ + copy_m3_m4(mat3, m); + mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); } -void mat4_to_compatible_eulO( - float eul[3], const float oldrot[3], const short order, const float m[4][4]) +void mat4_to_compatible_eulO(float eul[3], + const float oldrot[3], + const short order, + const float m[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - /* for now, we'll just do this the slow way (i.e. copying matrices) */ - copy_m3_m4(mat3, m); - normalize_m3(mat3); - mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); + /* for now, we'll just do this the slow way (i.e. copying matrices) */ + copy_m3_m4(mat3, m); + normalize_m3(mat3); + mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); } -void quat_to_compatible_eulO( - float eul[3], const float oldrot[3], const short order, const float quat[4]) +void quat_to_compatible_eulO(float eul[3], + const float oldrot[3], + const short order, + const float quat[4]) { - float unit_mat[3][3]; + float unit_mat[3][3]; - quat_to_mat3(unit_mat, quat); - mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat); + quat_to_mat3(unit_mat, quat); + mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat); } /* rotate the given euler by the given angle on the specified axis */ @@ -1771,52 +1811,51 @@ void quat_to_compatible_eulO( void rotate_eulO(float beul[3], const short order, char axis, float ang) { - float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; + float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; - assert(axis >= 'X' && axis <= 'Z'); + assert(axis >= 'X' && axis <= 'Z'); - zero_v3(eul); + zero_v3(eul); - if (axis == 'X') { - eul[0] = ang; - } - else if (axis == 'Y') { - eul[1] = ang; - } - else { - eul[2] = ang; - } + if (axis == 'X') { + eul[0] = ang; + } + else if (axis == 'Y') { + eul[1] = ang; + } + else { + eul[2] = ang; + } - eulO_to_mat3(mat1, eul, order); - eulO_to_mat3(mat2, beul, order); + eulO_to_mat3(mat1, eul, order); + eulO_to_mat3(mat2, beul, order); - mul_m3_m3m3(totmat, mat2, mat1); + mul_m3_m3m3(totmat, mat2, mat1); - mat3_to_eulO(beul, order, totmat); + mat3_to_eulO(beul, order, totmat); } /* the matrix is written to as 3 axis vectors */ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order) { - const RotOrderInfo *R = get_rotation_order_info(order); - - float mat[3][3]; - float teul[3]; + const RotOrderInfo *R = get_rotation_order_info(order); - /* first axis is local */ - eulO_to_mat3(mat, eul, order); - copy_v3_v3(gmat[R->axis[0]], mat[R->axis[0]]); + float mat[3][3]; + float teul[3]; - /* second axis is local minus first rotation */ - copy_v3_v3(teul, eul); - teul[R->axis[0]] = 0; - eulO_to_mat3(mat, teul, order); - copy_v3_v3(gmat[R->axis[1]], mat[R->axis[1]]); + /* first axis is local */ + eulO_to_mat3(mat, eul, order); + copy_v3_v3(gmat[R->axis[0]], mat[R->axis[0]]); + /* second axis is local minus first rotation */ + copy_v3_v3(teul, eul); + teul[R->axis[0]] = 0; + eulO_to_mat3(mat, teul, order); + copy_v3_v3(gmat[R->axis[1]], mat[R->axis[1]]); - /* Last axis is global */ - zero_v3(gmat[R->axis[2]]); - gmat[R->axis[2]][R->axis[2]] = 1; + /* Last axis is global */ + zero_v3(gmat[R->axis[2]]); + gmat[R->axis[2]][R->axis[2]] = 1; } /******************************* Dual Quaternions ****************************/ @@ -1852,431 +1891,409 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4]) { - float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3]; - float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4]; - float R[4][4], S[4][4]; + float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3]; + float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4]; + float R[4][4], S[4][4]; - /* split scaling and rotation, there is probably a faster way to do - * this, it's done like this now to correctly get negative scaling */ - mul_m4_m4m4(baseRS, mat, basemat); - mat4_to_size(scale, baseRS); + /* split scaling and rotation, there is probably a faster way to do + * this, it's done like this now to correctly get negative scaling */ + mul_m4_m4m4(baseRS, mat, basemat); + mat4_to_size(scale, baseRS); - dscale[0] = scale[0] - 1.0f; - dscale[1] = scale[1] - 1.0f; - dscale[2] = scale[2] - 1.0f; + dscale[0] = scale[0] - 1.0f; + dscale[1] = scale[1] - 1.0f; + dscale[2] = scale[2] - 1.0f; - copy_m3_m4(mat3, mat); + copy_m3_m4(mat3, mat); - if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_squared_v3(dscale) > SQUARE(1e-4f)) { - /* extract R and S */ - float tmp[4][4]; + if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || + len_squared_v3(dscale) > SQUARE(1e-4f)) { + /* extract R and S */ + float tmp[4][4]; - /* extra orthogonalize, to avoid flipping with stretched bones */ - copy_m4_m4(tmp, baseRS); - orthogonalize_m4(tmp, 1); - mat4_to_quat(basequat, tmp); + /* extra orthogonalize, to avoid flipping with stretched bones */ + copy_m4_m4(tmp, baseRS); + orthogonalize_m4(tmp, 1); + mat4_to_quat(basequat, tmp); - quat_to_mat4(baseR, basequat); - copy_v3_v3(baseR[3], baseRS[3]); + quat_to_mat4(baseR, basequat); + copy_v3_v3(baseR[3], baseRS[3]); - invert_m4_m4(baseinv, basemat); - mul_m4_m4m4(R, baseR, baseinv); + invert_m4_m4(baseinv, basemat); + mul_m4_m4m4(R, baseR, baseinv); - invert_m4_m4(baseRinv, baseR); - mul_m4_m4m4(S, baseRinv, baseRS); + invert_m4_m4(baseRinv, baseR); + mul_m4_m4m4(S, baseRinv, baseRS); - /* set scaling part */ - mul_m4_series(dq->scale, basemat, S, baseinv); - dq->scale_weight = 1.0f; - } - else { - /* matrix does not contain scaling */ - copy_m4_m4(R, mat); - dq->scale_weight = 0.0f; - } + /* set scaling part */ + mul_m4_series(dq->scale, basemat, S, baseinv); + dq->scale_weight = 1.0f; + } + else { + /* matrix does not contain scaling */ + copy_m4_m4(R, mat); + dq->scale_weight = 0.0f; + } - /* non-dual part */ - mat4_to_quat(dq->quat, R); + /* non-dual part */ + mat4_to_quat(dq->quat, R); - /* dual part */ - t = R[3]; - q = dq->quat; - dq->trans[0] = -0.5f * ( t[0] * q[1] + t[1] * q[2] + t[2] * q[3]); - dq->trans[1] = 0.5f * ( t[0] * q[0] + t[1] * q[3] - t[2] * q[2]); - dq->trans[2] = 0.5f * (-t[0] * q[3] + t[1] * q[0] + t[2] * q[1]); - dq->trans[3] = 0.5f * ( t[0] * q[2] - t[1] * q[1] + t[2] * q[0]); + /* dual part */ + t = R[3]; + q = dq->quat; + dq->trans[0] = -0.5f * (t[0] * q[1] + t[1] * q[2] + t[2] * q[3]); + dq->trans[1] = 0.5f * (t[0] * q[0] + t[1] * q[3] - t[2] * q[2]); + dq->trans[2] = 0.5f * (-t[0] * q[3] + t[1] * q[0] + t[2] * q[1]); + dq->trans[3] = 0.5f * (t[0] * q[2] - t[1] * q[1] + t[2] * q[0]); } void dquat_to_mat4(float mat[4][4], const DualQuat *dq) { - float len, q0[4]; - const float *t; + float len, q0[4]; + const float *t; - /* regular quaternion */ - copy_qt_qt(q0, dq->quat); + /* regular quaternion */ + copy_qt_qt(q0, dq->quat); - /* normalize */ - len = sqrtf(dot_qtqt(q0, q0)); - if (len != 0.0f) { - len = 1.0f / len; - } - mul_qt_fl(q0, len); + /* normalize */ + len = sqrtf(dot_qtqt(q0, q0)); + if (len != 0.0f) { + len = 1.0f / len; + } + mul_qt_fl(q0, len); - /* rotation */ - quat_to_mat4(mat, q0); + /* rotation */ + quat_to_mat4(mat, q0); - /* translation */ - t = dq->trans; - mat[3][0] = 2.0f * (-t[0] * q0[1] + t[1] * q0[0] - t[2] * q0[3] + t[3] * q0[2]) * len; - mat[3][1] = 2.0f * (-t[0] * q0[2] + t[1] * q0[3] + t[2] * q0[0] - t[3] * q0[1]) * len; - mat[3][2] = 2.0f * (-t[0] * q0[3] - t[1] * q0[2] + t[2] * q0[1] + t[3] * q0[0]) * len; + /* translation */ + t = dq->trans; + mat[3][0] = 2.0f * (-t[0] * q0[1] + t[1] * q0[0] - t[2] * q0[3] + t[3] * q0[2]) * len; + mat[3][1] = 2.0f * (-t[0] * q0[2] + t[1] * q0[3] + t[2] * q0[0] - t[3] * q0[1]) * len; + mat[3][2] = 2.0f * (-t[0] * q0[3] - t[1] * q0[2] + t[2] * q0[1] + t[3] * q0[0]) * len; - /* scaling */ - if (dq->scale_weight) { - mul_m4_m4m4(mat, mat, dq->scale); - } + /* scaling */ + if (dq->scale_weight) { + mul_m4_m4m4(mat, mat, dq->scale); + } } void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight) { - bool flipped = false; + bool flipped = false; - /* make sure we interpolate quats in the right direction */ - if (dot_qtqt(dq->quat, dqsum->quat) < 0) { - flipped = true; - weight = -weight; - } + /* make sure we interpolate quats in the right direction */ + if (dot_qtqt(dq->quat, dqsum->quat) < 0) { + flipped = true; + weight = -weight; + } - /* interpolate rotation and translation */ - dqsum->quat[0] += weight * dq->quat[0]; - dqsum->quat[1] += weight * dq->quat[1]; - dqsum->quat[2] += weight * dq->quat[2]; - dqsum->quat[3] += weight * dq->quat[3]; + /* interpolate rotation and translation */ + dqsum->quat[0] += weight * dq->quat[0]; + dqsum->quat[1] += weight * dq->quat[1]; + dqsum->quat[2] += weight * dq->quat[2]; + dqsum->quat[3] += weight * dq->quat[3]; - dqsum->trans[0] += weight * dq->trans[0]; - dqsum->trans[1] += weight * dq->trans[1]; - dqsum->trans[2] += weight * dq->trans[2]; - dqsum->trans[3] += weight * dq->trans[3]; + dqsum->trans[0] += weight * dq->trans[0]; + dqsum->trans[1] += weight * dq->trans[1]; + dqsum->trans[2] += weight * dq->trans[2]; + dqsum->trans[3] += weight * dq->trans[3]; - /* Interpolate scale - but only if there is scale present. If any dual - * quaternions without scale are added, they will be compensated for in - * normalize_dq. */ - if (dq->scale_weight) { - float wmat[4][4]; + /* Interpolate scale - but only if there is scale present. If any dual + * quaternions without scale are added, they will be compensated for in + * normalize_dq. */ + if (dq->scale_weight) { + float wmat[4][4]; - if (flipped) { - /* we don't want negative weights for scaling */ - weight = -weight; - } + if (flipped) { + /* we don't want negative weights for scaling */ + weight = -weight; + } - copy_m4_m4(wmat, (float(*)[4])dq->scale); - mul_m4_fl(wmat, weight); - add_m4_m4m4(dqsum->scale, dqsum->scale, wmat); - dqsum->scale_weight += weight; - } + copy_m4_m4(wmat, (float(*)[4])dq->scale); + mul_m4_fl(wmat, weight); + add_m4_m4m4(dqsum->scale, dqsum->scale, wmat); + dqsum->scale_weight += weight; + } } void normalize_dq(DualQuat *dq, float totweight) { - const float scale = 1.0f / totweight; + const float scale = 1.0f / totweight; - mul_qt_fl(dq->quat, scale); - mul_qt_fl(dq->trans, scale); + mul_qt_fl(dq->quat, scale); + mul_qt_fl(dq->trans, scale); - /* Handle scale if needed. */ - if (dq->scale_weight) { - /* Compensate for any dual quaternions added without scale. This is an - * optimization so that we can skip the scale part when not needed. */ - float addweight = totweight - dq->scale_weight; + /* Handle scale if needed. */ + if (dq->scale_weight) { + /* Compensate for any dual quaternions added without scale. This is an + * optimization so that we can skip the scale part when not needed. */ + float addweight = totweight - dq->scale_weight; - if (addweight) { - dq->scale[0][0] += addweight; - dq->scale[1][1] += addweight; - dq->scale[2][2] += addweight; - dq->scale[3][3] += addweight; - } + if (addweight) { + dq->scale[0][0] += addweight; + dq->scale[1][1] += addweight; + dq->scale[2][2] += addweight; + dq->scale[3][3] += addweight; + } - mul_m4_fl(dq->scale, scale); - dq->scale_weight = 1.0f; - } + mul_m4_fl(dq->scale, scale); + dq->scale_weight = 1.0f; + } } void mul_v3m3_dq(float co[3], float mat[3][3], DualQuat *dq) { - float M[3][3], t[3], scalemat[3][3], len2; - float w = dq->quat[0], x = dq->quat[1], y = dq->quat[2], z = dq->quat[3]; - float t0 = dq->trans[0], t1 = dq->trans[1], t2 = dq->trans[2], t3 = dq->trans[3]; - - /* rotation matrix */ - M[0][0] = w * w + x * x - y * y - z * z; - M[1][0] = 2 * (x * y - w * z); - M[2][0] = 2 * (x * z + w * y); - - M[0][1] = 2 * (x * y + w * z); - M[1][1] = w * w + y * y - x * x - z * z; - M[2][1] = 2 * (y * z - w * x); - - M[0][2] = 2 * (x * z - w * y); - M[1][2] = 2 * (y * z + w * x); - M[2][2] = w * w + z * z - x * x - y * y; - - len2 = dot_qtqt(dq->quat, dq->quat); - if (len2 > 0.0f) { - len2 = 1.0f / len2; - } - - /* translation */ - t[0] = 2 * (-t0 * x + w * t1 - t2 * z + y * t3); - t[1] = 2 * (-t0 * y + t1 * z - x * t3 + w * t2); - t[2] = 2 * (-t0 * z + x * t2 + w * t3 - t1 * y); - - /* apply scaling */ - if (dq->scale_weight) { - mul_m4_v3(dq->scale, co); - } - - /* apply rotation and translation */ - mul_m3_v3(M, co); - co[0] = (co[0] + t[0]) * len2; - co[1] = (co[1] + t[1]) * len2; - co[2] = (co[2] + t[2]) * len2; - - /* compute crazyspace correction mat */ - if (mat) { - if (dq->scale_weight) { - copy_m3_m4(scalemat, dq->scale); - mul_m3_m3m3(mat, M, scalemat); - } - else { - copy_m3_m3(mat, M); - } - mul_m3_fl(mat, len2); - } + float M[3][3], t[3], scalemat[3][3], len2; + float w = dq->quat[0], x = dq->quat[1], y = dq->quat[2], z = dq->quat[3]; + float t0 = dq->trans[0], t1 = dq->trans[1], t2 = dq->trans[2], t3 = dq->trans[3]; + + /* rotation matrix */ + M[0][0] = w * w + x * x - y * y - z * z; + M[1][0] = 2 * (x * y - w * z); + M[2][0] = 2 * (x * z + w * y); + + M[0][1] = 2 * (x * y + w * z); + M[1][1] = w * w + y * y - x * x - z * z; + M[2][1] = 2 * (y * z - w * x); + + M[0][2] = 2 * (x * z - w * y); + M[1][2] = 2 * (y * z + w * x); + M[2][2] = w * w + z * z - x * x - y * y; + + len2 = dot_qtqt(dq->quat, dq->quat); + if (len2 > 0.0f) { + len2 = 1.0f / len2; + } + + /* translation */ + t[0] = 2 * (-t0 * x + w * t1 - t2 * z + y * t3); + t[1] = 2 * (-t0 * y + t1 * z - x * t3 + w * t2); + t[2] = 2 * (-t0 * z + x * t2 + w * t3 - t1 * y); + + /* apply scaling */ + if (dq->scale_weight) { + mul_m4_v3(dq->scale, co); + } + + /* apply rotation and translation */ + mul_m3_v3(M, co); + co[0] = (co[0] + t[0]) * len2; + co[1] = (co[1] + t[1]) * len2; + co[2] = (co[2] + t[2]) * len2; + + /* compute crazyspace correction mat */ + if (mat) { + if (dq->scale_weight) { + copy_m3_m4(scalemat, dq->scale); + mul_m3_m3m3(mat, M, scalemat); + } + else { + copy_m3_m3(mat, M); + } + mul_m3_fl(mat, len2); + } } void copy_dq_dq(DualQuat *dq1, const DualQuat *dq2) { - memcpy(dq1, dq2, sizeof(DualQuat)); + memcpy(dq1, dq2, sizeof(DualQuat)); } /* axis matches eTrackToAxis_Modes */ void quat_apply_track(float quat[4], short axis, short upflag) { - /* rotations are hard coded to match vec_to_quat */ - const float sqrt_1_2 = (float)M_SQRT1_2; - const float quat_track[][4] = { - /* pos-y90 */ - {sqrt_1_2, 0.0, -sqrt_1_2, 0.0}, - /* Quaternion((1,0,0), radians(90)) * Quaternion((0,1,0), radians(90)) */ - {0.5, 0.5, 0.5, 0.5}, - /* pos-z90 */ - {sqrt_1_2, 0.0, 0.0, sqrt_1_2}, - /* neg-y90 */ - {sqrt_1_2, 0.0, sqrt_1_2, 0.0}, - /* Quaternion((1,0,0), radians(-90)) * Quaternion((0,1,0), radians(-90)) */ - {0.5, -0.5, -0.5, 0.5}, - /* no rotation */ - {0.0, sqrt_1_2, sqrt_1_2, 0.0}, - }; - - assert(axis >= 0 && axis <= 5); - assert(upflag >= 0 && upflag <= 2); - - mul_qt_qtqt(quat, quat, quat_track[axis]); - - if (axis > 2) { - axis = (short)(axis - 3); - } - - /* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first - * up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d - * the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */ - if (upflag != (2 - axis) >> 1) { - float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */ - q[axis + 1] = ((axis == 1)) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */ - mul_qt_qtqt(quat, quat, q); - } + /* rotations are hard coded to match vec_to_quat */ + const float sqrt_1_2 = (float)M_SQRT1_2; + const float quat_track[][4] = { + /* pos-y90 */ + {sqrt_1_2, 0.0, -sqrt_1_2, 0.0}, + /* Quaternion((1,0,0), radians(90)) * Quaternion((0,1,0), radians(90)) */ + {0.5, 0.5, 0.5, 0.5}, + /* pos-z90 */ + {sqrt_1_2, 0.0, 0.0, sqrt_1_2}, + /* neg-y90 */ + {sqrt_1_2, 0.0, sqrt_1_2, 0.0}, + /* Quaternion((1,0,0), radians(-90)) * Quaternion((0,1,0), radians(-90)) */ + {0.5, -0.5, -0.5, 0.5}, + /* no rotation */ + {0.0, sqrt_1_2, sqrt_1_2, 0.0}, + }; + + assert(axis >= 0 && axis <= 5); + assert(upflag >= 0 && upflag <= 2); + + mul_qt_qtqt(quat, quat, quat_track[axis]); + + if (axis > 2) { + axis = (short)(axis - 3); + } + + /* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first + * up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d + * the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */ + if (upflag != (2 - axis) >> 1) { + float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */ + q[axis + 1] = ((axis == 1)) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */ + mul_qt_qtqt(quat, quat, q); + } } void vec_apply_track(float vec[3], short axis) { - float tvec[3]; - - assert(axis >= 0 && axis <= 5); - - copy_v3_v3(tvec, vec); - - switch (axis) { - case 0: /* pos-x */ - /* vec[0] = 0.0; */ - vec[1] = tvec[2]; - vec[2] = -tvec[1]; - break; - case 1: /* pos-y */ - /* vec[0] = tvec[0]; */ - /* vec[1] = 0.0; */ - /* vec[2] = tvec[2]; */ - break; - case 2: /* pos-z */ - /* vec[0] = tvec[0]; */ - /* vec[1] = tvec[1]; */ - /* vec[2] = 0.0; */ - break; - case 3: /* neg-x */ - /* vec[0] = 0.0; */ - vec[1] = tvec[2]; - vec[2] = -tvec[1]; - break; - case 4: /* neg-y */ - vec[0] = -tvec[2]; - /* vec[1] = 0.0; */ - vec[2] = tvec[0]; - break; - case 5: /* neg-z */ - vec[0] = -tvec[0]; - vec[1] = -tvec[1]; - /* vec[2] = 0.0; */ - break; - } + float tvec[3]; + + assert(axis >= 0 && axis <= 5); + + copy_v3_v3(tvec, vec); + + switch (axis) { + case 0: /* pos-x */ + /* vec[0] = 0.0; */ + vec[1] = tvec[2]; + vec[2] = -tvec[1]; + break; + case 1: /* pos-y */ + /* vec[0] = tvec[0]; */ + /* vec[1] = 0.0; */ + /* vec[2] = tvec[2]; */ + break; + case 2: /* pos-z */ + /* vec[0] = tvec[0]; */ + /* vec[1] = tvec[1]; */ + /* vec[2] = 0.0; */ + break; + case 3: /* neg-x */ + /* vec[0] = 0.0; */ + vec[1] = tvec[2]; + vec[2] = -tvec[1]; + break; + case 4: /* neg-y */ + vec[0] = -tvec[2]; + /* vec[1] = 0.0; */ + vec[2] = tvec[0]; + break; + case 5: /* neg-z */ + vec[0] = -tvec[0]; + vec[1] = -tvec[1]; + /* vec[2] = 0.0; */ + break; + } } /* lens/angle conversion (radians) */ float focallength_to_fov(float focal_length, float sensor) { - return 2.0f * atanf((sensor / 2.0f) / focal_length); + return 2.0f * atanf((sensor / 2.0f) / focal_length); } float fov_to_focallength(float hfov, float sensor) { - return (sensor / 2.0f) / tanf(hfov * 0.5f); + return (sensor / 2.0f) / tanf(hfov * 0.5f); } /* 'mod_inline(-3, 4)= 1', 'fmod(-3, 4)= -3' */ static float mod_inline(float a, float b) { - return a - (b * floorf(a / b)); + return a - (b * floorf(a / b)); } float angle_wrap_rad(float angle) { - return mod_inline(angle + (float)M_PI, (float)M_PI * 2.0f) - (float)M_PI; + return mod_inline(angle + (float)M_PI, (float)M_PI * 2.0f) - (float)M_PI; } float angle_wrap_deg(float angle) { - return mod_inline(angle + 180.0f, 360.0f) - 180.0f; + return mod_inline(angle + 180.0f, 360.0f) - 180.0f; } /* returns an angle compatible with angle_compat */ float angle_compat_rad(float angle, float angle_compat) { - return angle_compat + angle_wrap_rad(angle - angle_compat); + return angle_compat + angle_wrap_rad(angle - angle_compat); } /* axis conversion */ static float _axis_convert_matrix[23][3][3] = { - {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}}, - {{-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}}, - {{-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}}, - {{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}}, - {{0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, - {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, - {{0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, - {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, - {{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}}, - {{0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}}, - {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}}, - {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}}, - {{0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}}, - {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}}, - {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}}, - {{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}}, - {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, - {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, - {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, - {{0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, - {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}}, - {{1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}}, - {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}}, + {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}}, + {{0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, + {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, + {{0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, + {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, + {{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}}, + {{0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}}, + {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}}, + {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}}, + {{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}}, + {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, + {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, + {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, + {{0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, + {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}}, + {{1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}}, + {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}}, }; static int _axis_convert_lut[23][24] = { - {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, - 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, - 0x745, 0x94D, 0x15D, 0x365}, - {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, - 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, - 0x645, 0xA4D, 0x05D, 0x465}, - {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, - 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, - 0x705, 0x50D, 0x11D, 0xB25}, - {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, - 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, - 0x685, 0x28D, 0x09D, 0x8A5}, - {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, - 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, - 0x885, 0x68D, 0x29D, 0x0A5}, - {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, - 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, - 0x8C5, 0xACD, 0x2DD, 0x4E5}, - {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, - 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, - 0x805, 0x40D, 0x21D, 0xA25}, - {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, - 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, - 0x945, 0x14D, 0x35D, 0x765}, - {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, - 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, - 0xB05, 0x70D, 0x51D, 0x125}, - {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, - 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, - 0xA05, 0x80D, 0x41D, 0x225}, - {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, - 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, - 0xAC5, 0x2CD, 0x4DD, 0x8E5}, - {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, - 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, - 0xA45, 0x04D, 0x45D, 0x665}, - {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, - 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, - 0x445, 0x64D, 0xA5D, 0x065}, - {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, - 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, - 0x4C5, 0x8CD, 0xADD, 0x2E5}, - {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, - 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, - 0x405, 0x20D, 0xA1D, 0x825}, - {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, - 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, - 0x505, 0x10D, 0xB1D, 0x725}, - {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, - 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, - 0x345, 0x74D, 0x95D, 0x165}, - {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, - 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, - 0x205, 0xA0D, 0x81D, 0x425}, - {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, - 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, - 0x2C5, 0x4CD, 0x8DD, 0xAE5}, - {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, - 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, - 0x285, 0x08D, 0x89D, 0x6A5}, - {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, - 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, - 0x085, 0x88D, 0x69D, 0x2A5}, - {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, - 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, - 0x105, 0xB0D, 0x71D, 0x525}, - {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, - 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, - 0x045, 0x44D, 0x65D, 0xA65}, + {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, 0x09A, 0x2A2, + 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, 0x745, 0x94D, 0x15D, 0x365}, + {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522, + 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465}, + {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62, + 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25}, + {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962, + 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5}, + {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162, + 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5}, + {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422, + 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5}, + {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2, + 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25}, + {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 0x29A, 0x6A2, + 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, 0x945, 0x14D, 0x35D, 0x765}, + {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, 0x45A, 0x062, + 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, 0xB05, 0x70D, 0x51D, 0x125}, + {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, 0x4DA, 0x2E2, + 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, 0xA05, 0x80D, 0x41D, 0x225}, + {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, 0x41A, 0x822, + 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, 0xAC5, 0x2CD, 0x4DD, 0x8E5}, + {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, 0x51A, 0x722, + 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, 0xA45, 0x04D, 0x45D, 0x665}, + {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, 0xB1A, 0x122, + 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, 0x445, 0x64D, 0xA5D, 0x065}, + {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, 0xA1A, 0x222, + 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, 0x4C5, 0x8CD, 0xADD, 0x2E5}, + {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, 0xADA, 0x8E2, + 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, 0x405, 0x20D, 0xA1D, 0x825}, + {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, 0xA5A, 0x662, + 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, 0x505, 0x10D, 0xB1D, 0x725}, + {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, 0x89A, 0x0A2, + 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, 0x345, 0x74D, 0x95D, 0x165}, + {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, 0x8DA, 0x4E2, + 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, 0x205, 0xA0D, 0x81D, 0x425}, + {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, 0x81A, 0xA22, + 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, 0x2C5, 0x4CD, 0x8DD, 0xAE5}, + {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, 0x95A, 0x762, + 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, 0x285, 0x08D, 0x89D, 0x6A5}, + {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, 0x75A, 0x362, + 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, 0x085, 0x88D, 0x69D, 0x2A5}, + {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, 0x65A, 0x462, + 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, 0x105, 0xB0D, 0x71D, 0x525}, + {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22, + 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65}, }; // _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5} BLI_INLINE int _axis_signed(const int axis) { - return (axis < 3) ? axis : axis - 3; + return (axis < 3) ? axis : axis - 3; } /** @@ -2284,63 +2301,56 @@ BLI_INLINE int _axis_signed(const int axis) * where the first 2 are a source and the second 2 are the target. */ bool mat3_from_axis_conversion( - int src_forward, int src_up, int dst_forward, int dst_up, - float r_mat[3][3]) -{ - // from functools import reduce - int value; - - if (src_forward == dst_forward && src_up == dst_up) { - unit_m3(r_mat); - return false; - } - - if ((_axis_signed(src_forward) == _axis_signed(src_up)) || - (_axis_signed(dst_forward) == _axis_signed(dst_up))) - { - /* we could assert here! */ - unit_m3(r_mat); - return false; - } - - value = ((src_forward << (0 * 3)) | - (src_up << (1 * 3)) | - (dst_forward << (2 * 3)) | - (dst_up << (3 * 3))); - - for (uint i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) { - for (uint j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) { - if (_axis_convert_lut[i][j] == value) { - copy_m3_m3(r_mat, _axis_convert_matrix[i]); - return true; - } - } - - } -// BLI_assert(0); - return false; + int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3]) +{ + // from functools import reduce + int value; + + if (src_forward == dst_forward && src_up == dst_up) { + unit_m3(r_mat); + return false; + } + + if ((_axis_signed(src_forward) == _axis_signed(src_up)) || + (_axis_signed(dst_forward) == _axis_signed(dst_up))) { + /* we could assert here! */ + unit_m3(r_mat); + return false; + } + + value = ((src_forward << (0 * 3)) | (src_up << (1 * 3)) | (dst_forward << (2 * 3)) | + (dst_up << (3 * 3))); + + for (uint i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) { + for (uint j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) { + if (_axis_convert_lut[i][j] == value) { + copy_m3_m3(r_mat, _axis_convert_matrix[i]); + return true; + } + } + } + // BLI_assert(0); + return false; } /** * Use when the second axis can be guessed. */ -bool mat3_from_axis_conversion_single( - int src_axis, int dst_axis, - float r_mat[3][3]) +bool mat3_from_axis_conversion_single(int src_axis, int dst_axis, float r_mat[3][3]) { - if (src_axis == dst_axis) { - unit_m3(r_mat); - return false; - } + if (src_axis == dst_axis) { + unit_m3(r_mat); + return false; + } - /* Pick predictable next axis. */ - int src_axis_next = (src_axis + 1) % 3; - int dst_axis_next = (dst_axis + 1) % 3; + /* Pick predictable next axis. */ + int src_axis_next = (src_axis + 1) % 3; + int dst_axis_next = (dst_axis + 1) % 3; - if ((src_axis < 3) != (dst_axis < 3)) { - /* Flip both axis so matrix sign remains positive. */ - dst_axis_next += 3; - } + if ((src_axis < 3) != (dst_axis < 3)) { + /* Flip both axis so matrix sign remains positive. */ + dst_axis_next += 3; + } - return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat); + return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat); } diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index 2669ac89b25..a6331aaadd8 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -39,19 +39,19 @@ * \return r_eigen_values the computed eigen values (NULL if not needed). * \return r_eigen_vectors the computed eigen vectors (NULL if not needed). */ -bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3], float r_eigen_vectors[3][3]) +bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], + float r_eigen_values[3], + float r_eigen_vectors[3][3]) { #ifndef NDEBUG - /* We must assert given matrix is self-adjoint (i.e. symmetric) */ - if ((m3[0][1] != m3[1][0]) || - (m3[0][2] != m3[2][0]) || - (m3[1][2] != m3[2][1])) - { - BLI_assert(0); - } + /* We must assert given matrix is self-adjoint (i.e. symmetric) */ + if ((m3[0][1] != m3[1][0]) || (m3[0][2] != m3[2][0]) || (m3[1][2] != m3[2][1])) { + BLI_assert(0); + } #endif - return EIG_self_adjoint_eigen_solve(3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors); + return EIG_self_adjoint_eigen_solve( + 3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors); } /** @@ -64,7 +64,7 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3 */ void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[3], float r_V[3][3]) { - EIG_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V); + EIG_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V); } /***************************** Simple Solvers ************************************/ @@ -79,48 +79,49 @@ void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[3], float r_V[3 * \param r_x: output vector, may be shared with any of the input ones * \return true if success */ -bool BLI_tridiagonal_solve(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count) +bool BLI_tridiagonal_solve( + const float *a, const float *b, const float *c, const float *d, float *r_x, const int count) { - if (count < 1) { - return false; - } + if (count < 1) { + return false; + } - size_t bytes = sizeof(double) * (unsigned)count; - double *c1 = (double *)MEM_mallocN(bytes * 2, "tridiagonal_c1d1"); - double *d1 = c1 + count; + size_t bytes = sizeof(double) * (unsigned)count; + double *c1 = (double *)MEM_mallocN(bytes * 2, "tridiagonal_c1d1"); + double *d1 = c1 + count; - if (!c1) { - return false; - } + if (!c1) { + return false; + } - int i; - double c_prev, d_prev, x_prev; + int i; + double c_prev, d_prev, x_prev; - /* forward pass */ + /* forward pass */ - c1[0] = c_prev = ((double)c[0]) / b[0]; - d1[0] = d_prev = ((double)d[0]) / b[0]; + c1[0] = c_prev = ((double)c[0]) / b[0]; + d1[0] = d_prev = ((double)d[0]) / b[0]; - for (i = 1; i < count; i++) { - double denum = b[i] - a[i] * c_prev; + for (i = 1; i < count; i++) { + double denum = b[i] - a[i] * c_prev; - c1[i] = c_prev = c[i] / denum; - d1[i] = d_prev = (d[i] - a[i] * d_prev) / denum; - } + c1[i] = c_prev = c[i] / denum; + d1[i] = d_prev = (d[i] - a[i] * d_prev) / denum; + } - /* back pass */ + /* back pass */ - x_prev = d_prev; - r_x[--i] = ((float)x_prev); + x_prev = d_prev; + r_x[--i] = ((float)x_prev); - while (--i >= 0) { - x_prev = d1[i] - c1[i] * x_prev; - r_x[i] = ((float)x_prev); - } + while (--i >= 0) { + x_prev = d1[i] - c1[i] * x_prev; + r_x[i] = ((float)x_prev); + } - MEM_freeN(c1); + MEM_freeN(c1); - return isfinite(x_prev); + return isfinite(x_prev); } /** @@ -129,53 +130,53 @@ bool BLI_tridiagonal_solve(const float *a, const float *b, const float *c, const * \param r_x: output vector, may be shared with any of the input ones * \return true if success */ -bool BLI_tridiagonal_solve_cyclic(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count) +bool BLI_tridiagonal_solve_cyclic( + const float *a, const float *b, const float *c, const float *d, float *r_x, const int count) { - if (count < 1) { - return false; - } + if (count < 1) { + return false; + } - float a0 = a[0], cN = c[count - 1]; + float a0 = a[0], cN = c[count - 1]; - /* if not really cyclic, fall back to the simple solver */ - if (a0 == 0.0f && cN == 0.0f) { - return BLI_tridiagonal_solve(a, b, c, d, r_x, count); - } + /* if not really cyclic, fall back to the simple solver */ + if (a0 == 0.0f && cN == 0.0f) { + return BLI_tridiagonal_solve(a, b, c, d, r_x, count); + } - size_t bytes = sizeof(float) * (unsigned)count; - float *tmp = (float *)MEM_mallocN(bytes * 2, "tridiagonal_ex"); - float *b2 = tmp + count; + size_t bytes = sizeof(float) * (unsigned)count; + float *tmp = (float *)MEM_mallocN(bytes * 2, "tridiagonal_ex"); + float *b2 = tmp + count; - if (!tmp) { - return false; - } + if (!tmp) { + return false; + } - /* prepare the noncyclic system; relies on tridiagonal_solve ignoring values */ - memcpy(b2, b, bytes); - b2[0] -= a0; - b2[count - 1] -= cN; + /* prepare the noncyclic system; relies on tridiagonal_solve ignoring values */ + memcpy(b2, b, bytes); + b2[0] -= a0; + b2[count - 1] -= cN; - memset(tmp, 0, bytes); - tmp[0] = a0; - tmp[count - 1] = cN; + memset(tmp, 0, bytes); + tmp[0] = a0; + tmp[count - 1] = cN; - /* solve for partial solution and adjustment vector */ - bool success = - BLI_tridiagonal_solve(a, b2, c, tmp, tmp, count) && - BLI_tridiagonal_solve(a, b2, c, d, r_x, count); + /* solve for partial solution and adjustment vector */ + bool success = BLI_tridiagonal_solve(a, b2, c, tmp, tmp, count) && + BLI_tridiagonal_solve(a, b2, c, d, r_x, count); - /* apply adjustment */ - if (success) { - float coeff = (r_x[0] + r_x[count - 1]) / (1.0f + tmp[0] + tmp[count - 1]); + /* apply adjustment */ + if (success) { + float coeff = (r_x[0] + r_x[count - 1]) / (1.0f + tmp[0] + tmp[count - 1]); - for (int i = 0; i < count; i++) { - r_x[i] -= coeff * tmp[i]; - } - } + for (int i = 0; i < count; i++) { + r_x[i] -= coeff * tmp[i]; + } + } - MEM_freeN(tmp); + MEM_freeN(tmp); - return success; + return success; } /** @@ -192,82 +193,88 @@ bool BLI_tridiagonal_solve_cyclic(const float *a, const float *b, const float *c * \param result: Final result. * \return true if success */ -bool BLI_newton3d_solve( - Newton3D_DeltaFunc func_delta, Newton3D_JacobianFunc func_jacobian, Newton3D_CorrectionFunc func_correction, void *userdata, - float epsilon, int max_iterations, bool trace, const float x_init[3], float result[3]) +bool BLI_newton3d_solve(Newton3D_DeltaFunc func_delta, + Newton3D_JacobianFunc func_jacobian, + Newton3D_CorrectionFunc func_correction, + void *userdata, + float epsilon, + int max_iterations, + bool trace, + const float x_init[3], + float result[3]) { - float fdelta[3], fdeltav, next_fdeltav; - float jacobian[3][3], step[3], x[3], x_next[3]; + float fdelta[3], fdeltav, next_fdeltav; + float jacobian[3][3], step[3], x[3], x_next[3]; - epsilon *= epsilon; + epsilon *= epsilon; - copy_v3_v3(x, x_init); + copy_v3_v3(x, x_init); - func_delta(userdata, x, fdelta); - fdeltav = len_squared_v3(fdelta); + func_delta(userdata, x, fdelta); + fdeltav = len_squared_v3(fdelta); - if (trace) { - printf("START (%g, %g, %g) %g\n", x[0], x[1], x[2], fdeltav); - } + if (trace) { + printf("START (%g, %g, %g) %g\n", x[0], x[1], x[2], fdeltav); + } - for (int i = 0; i < max_iterations && fdeltav > epsilon; i++) { - /* Newton's method step. */ - func_jacobian(userdata, x, jacobian); + for (int i = 0; i < max_iterations && fdeltav > epsilon; i++) { + /* Newton's method step. */ + func_jacobian(userdata, x, jacobian); - if (!invert_m3(jacobian)) { - return false; - } + if (!invert_m3(jacobian)) { + return false; + } - mul_v3_m3v3(step, jacobian, fdelta); - sub_v3_v3v3(x_next, x, step); + mul_v3_m3v3(step, jacobian, fdelta); + sub_v3_v3v3(x_next, x, step); - /* Custom out-of-bounds value correction. */ - if (func_correction) { - if (trace) { - printf("%3d * (%g, %g, %g)\n", i, x_next[0], x_next[1], x_next[2]); - } + /* Custom out-of-bounds value correction. */ + if (func_correction) { + if (trace) { + printf("%3d * (%g, %g, %g)\n", i, x_next[0], x_next[1], x_next[2]); + } - if (!func_correction(userdata, x, step, x_next)) { - return false; - } - } + if (!func_correction(userdata, x, step, x_next)) { + return false; + } + } - func_delta(userdata, x_next, fdelta); - next_fdeltav = len_squared_v3(fdelta); + func_delta(userdata, x_next, fdelta); + next_fdeltav = len_squared_v3(fdelta); - if (trace) { - printf("%3d ? (%g, %g, %g) %g\n", i, x_next[0], x_next[1], x_next[2], next_fdeltav); - } + if (trace) { + printf("%3d ? (%g, %g, %g) %g\n", i, x_next[0], x_next[1], x_next[2], next_fdeltav); + } - /* Line search correction. */ - while (next_fdeltav > fdeltav) { - float g0 = sqrtf(fdeltav), g1 = sqrtf(next_fdeltav); - float g01 = -g0 / len_v3(step); - float det = 2.0f * (g1 - g0 - g01); - float l = (det == 0.0f) ? 0.1f : -g01 / det; - CLAMP_MIN(l, 0.1f); + /* Line search correction. */ + while (next_fdeltav > fdeltav) { + float g0 = sqrtf(fdeltav), g1 = sqrtf(next_fdeltav); + float g01 = -g0 / len_v3(step); + float det = 2.0f * (g1 - g0 - g01); + float l = (det == 0.0f) ? 0.1f : -g01 / det; + CLAMP_MIN(l, 0.1f); - mul_v3_fl(step, l); - sub_v3_v3v3(x_next, x, step); + mul_v3_fl(step, l); + sub_v3_v3v3(x_next, x, step); - func_delta(userdata, x_next, fdelta); - next_fdeltav = len_squared_v3(fdelta); + func_delta(userdata, x_next, fdelta); + next_fdeltav = len_squared_v3(fdelta); - if (trace) { - printf("%3d . (%g, %g, %g) %g\n", i, x_next[0], x_next[1], x_next[2], next_fdeltav); - } - } + if (trace) { + printf("%3d . (%g, %g, %g) %g\n", i, x_next[0], x_next[1], x_next[2], next_fdeltav); + } + } - copy_v3_v3(x, x_next); - fdeltav = next_fdeltav; - } + copy_v3_v3(x, x_next); + fdeltav = next_fdeltav; + } - bool success = (fdeltav <= epsilon); + bool success = (fdeltav <= epsilon); - if (trace) { - printf("%s (%g, %g, %g) %g\n", success ? "OK " : "FAIL", x[0], x[1], x[2], fdeltav); - } + if (trace) { + printf("%s (%g, %g, %g) %g\n", success ? "OK " : "FAIL", x[0], x[1], x[2], fdeltav); + } - copy_v3_v3(result, x); - return success; + copy_v3_v3(result, x); + return success; } diff --git a/source/blender/blenlib/intern/math_statistics.c b/source/blender/blenlib/intern/math_statistics.c index 50fa7556134..dbfc68adb9b 100644 --- a/source/blender/blenlib/intern/math_statistics.c +++ b/source/blender/blenlib/intern/math_statistics.c @@ -32,60 +32,59 @@ /********************************** Covariance Matrices *********************************/ typedef struct CovarianceData { - const float *cos_vn; - const float *center; - float *r_covmat; - float covfac; - int n; - int nbr_cos_vn; + const float *cos_vn; + const float *center; + float *r_covmat; + float covfac; + int n; + int nbr_cos_vn; } CovarianceData; -static void covariance_m_vn_ex_task_cb( - void *__restrict userdata, - const int a, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void covariance_m_vn_ex_task_cb(void *__restrict userdata, + const int a, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - CovarianceData *data = userdata; - const float *cos_vn = data->cos_vn; - const float *center = data->center; - float *r_covmat = data->r_covmat; - const int n = data->n; - const int nbr_cos_vn = data->nbr_cos_vn; - - int k; - - /* Covariance matrices are always symmetrical, so we can compute only one half of it, - * and mirror it to the other half (at the end of the func). - * - * This allows using a flat loop of n*n with same results as imbricated one over half the matrix: - * - * for (i = 0; i < n; i++) { - * for (j = i; j < n; j++) { - * ... - * } - * } - */ - const int i = a / n; - const int j = a % n; - if (j < i) { - return; - } - - if (center) { - for (k = 0; k < nbr_cos_vn; k++) { - r_covmat[a] += (cos_vn[k * n + i] - center[i]) * (cos_vn[k * n + j] - center[j]); - } - } - else { - for (k = 0; k < nbr_cos_vn; k++) { - r_covmat[a] += cos_vn[k * n + i] * cos_vn[k * n + j]; - } - } - r_covmat[a] *= data->covfac; - if (j != i) { - /* Mirror result to other half... */ - r_covmat[j * n + i] = r_covmat[a]; - } + CovarianceData *data = userdata; + const float *cos_vn = data->cos_vn; + const float *center = data->center; + float *r_covmat = data->r_covmat; + const int n = data->n; + const int nbr_cos_vn = data->nbr_cos_vn; + + int k; + + /* Covariance matrices are always symmetrical, so we can compute only one half of it, + * and mirror it to the other half (at the end of the func). + * + * This allows using a flat loop of n*n with same results as imbricated one over half the matrix: + * + * for (i = 0; i < n; i++) { + * for (j = i; j < n; j++) { + * ... + * } + * } + */ + const int i = a / n; + const int j = a % n; + if (j < i) { + return; + } + + if (center) { + for (k = 0; k < nbr_cos_vn; k++) { + r_covmat[a] += (cos_vn[k * n + i] - center[i]) * (cos_vn[k * n + j] - center[j]); + } + } + else { + for (k = 0; k < nbr_cos_vn; k++) { + r_covmat[a] += cos_vn[k * n + i] * cos_vn[k * n + j]; + } + } + r_covmat[a] *= data->covfac; + if (j != i) { + /* Mirror result to other half... */ + r_covmat[j * n + i] = r_covmat[a]; + } } /** @@ -99,30 +98,33 @@ static void covariance_m_vn_ex_task_cb( * (i.e. get 'sample varince' instead of 'population variance'). * \return r_covmat the computed covariance matrix. */ -void BLI_covariance_m_vn_ex( - const int n, const float *cos_vn, const int nbr_cos_vn, const float *center, const bool use_sample_correction, - float *r_covmat) +void BLI_covariance_m_vn_ex(const int n, + const float *cos_vn, + const int nbr_cos_vn, + const float *center, + const bool use_sample_correction, + float *r_covmat) { - /* Note about that division: see https://en.wikipedia.org/wiki/Bessel%27s_correction. - * In a nutshell, it must be 1 / (n - 1) for 'sample data', and 1 / n for 'population data'... - */ - const float covfac = 1.0f / (float)(use_sample_correction ? nbr_cos_vn - 1 : nbr_cos_vn); - - memset(r_covmat, 0, sizeof(*r_covmat) * (size_t)(n * n)); - - CovarianceData data = { - .cos_vn = cos_vn, .center = center, .r_covmat = r_covmat, - .covfac = covfac, .n = n, .nbr_cos_vn = nbr_cos_vn, - }; - - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = ((nbr_cos_vn * n * n) >= 10000); - BLI_task_parallel_range( - 0, n * n, - &data, - covariance_m_vn_ex_task_cb, - &settings); + /* Note about that division: see https://en.wikipedia.org/wiki/Bessel%27s_correction. + * In a nutshell, it must be 1 / (n - 1) for 'sample data', and 1 / n for 'population data'... + */ + const float covfac = 1.0f / (float)(use_sample_correction ? nbr_cos_vn - 1 : nbr_cos_vn); + + memset(r_covmat, 0, sizeof(*r_covmat) * (size_t)(n * n)); + + CovarianceData data = { + .cos_vn = cos_vn, + .center = center, + .r_covmat = r_covmat, + .covfac = covfac, + .n = n, + .nbr_cos_vn = nbr_cos_vn, + }; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = ((nbr_cos_vn * n * n) >= 10000); + BLI_task_parallel_range(0, n * n, &data, covariance_m_vn_ex_task_cb, &settings); } /** @@ -133,23 +135,26 @@ void BLI_covariance_m_vn_ex( * \return r_covmat the computed covariance matrix. * \return r_center the computed center (mean) of 3D points (may be NULL). */ -void BLI_covariance_m3_v3n( - const float (*cos_v3)[3], const int nbr_cos_v3, const bool use_sample_correction, - float r_covmat[3][3], float r_center[3]) +void BLI_covariance_m3_v3n(const float (*cos_v3)[3], + const int nbr_cos_v3, + const bool use_sample_correction, + float r_covmat[3][3], + float r_center[3]) { - float center[3]; - const float mean_fac = 1.0f / (float)nbr_cos_v3; - int i; - - zero_v3(center); - for (i = 0; i < nbr_cos_v3; i++) { - /* Applying mean_fac here rather than once at the end reduce compute errors... */ - madd_v3_v3fl(center, cos_v3[i], mean_fac); - } - - if (r_center) { - copy_v3_v3(r_center, center); - } - - BLI_covariance_m_vn_ex(3, (const float *)cos_v3, nbr_cos_v3, center, use_sample_correction, (float *)r_covmat); + float center[3]; + const float mean_fac = 1.0f / (float)nbr_cos_v3; + int i; + + zero_v3(center); + for (i = 0; i < nbr_cos_v3; i++) { + /* Applying mean_fac here rather than once at the end reduce compute errors... */ + madd_v3_v3fl(center, cos_v3[i], mean_fac); + } + + if (r_center) { + copy_v3_v3(r_center, center); + } + + BLI_covariance_m_vn_ex( + 3, (const float *)cos_v3, nbr_cos_v3, center, use_sample_correction, (float *)r_covmat); } diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 0aacfd6cde1..1977558ac88 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -32,37 +32,38 @@ void interp_v2_v2v2(float target[2], const float a[2], const float b[2], const float t) { - const float s = 1.0f - t; + const float s = 1.0f - t; - target[0] = s * a[0] + t * b[0]; - target[1] = s * a[1] + t * b[1]; + target[0] = s * a[0] + t * b[0]; + target[1] = s * a[1] + t * b[1]; } /* weight 3 2D vectors, * 'w' must be unit length but is not a vector, just 3 weights */ -void interp_v2_v2v2v2(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]) +void interp_v2_v2v2v2( + float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]) { - p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; - p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; + p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; + p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; } void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const float t) { - const float s = 1.0f - t; + const float s = 1.0f - t; - target[0] = s * a[0] + t * b[0]; - target[1] = s * a[1] + t * b[1]; - target[2] = s * a[2] + t * b[2]; + target[0] = s * a[0] + t * b[0]; + target[1] = s * a[1] + t * b[1]; + target[2] = s * a[2] + t * b[2]; } void interp_v4_v4v4(float target[4], const float a[4], const float b[4], const float t) { - const float s = 1.0f - t; + const float s = 1.0f - t; - target[0] = s * a[0] + t * b[0]; - target[1] = s * a[1] + t * b[1]; - target[2] = s * a[2] + t * b[2]; - target[3] = s * a[3] + t * b[3]; + target[0] = s * a[0] + t * b[0]; + target[1] = s * a[1] + t * b[1]; + target[2] = s * a[2] + t * b[2]; + target[3] = s * a[3] + t * b[3]; } /** @@ -73,46 +74,46 @@ void interp_v4_v4v4(float target[4], const float a[4], const float b[4], const f */ bool interp_v3_v3v3_slerp(float target[3], const float a[3], const float b[3], const float t) { - float cosom, w[2]; + float cosom, w[2]; - BLI_ASSERT_UNIT_V3(a); - BLI_ASSERT_UNIT_V3(b); + BLI_ASSERT_UNIT_V3(a); + BLI_ASSERT_UNIT_V3(b); - cosom = dot_v3v3(a, b); + cosom = dot_v3v3(a, b); - /* direct opposites */ - if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) { - return false; - } + /* direct opposites */ + if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) { + return false; + } - interp_dot_slerp(t, cosom, w); + interp_dot_slerp(t, cosom, w); - target[0] = w[0] * a[0] + w[1] * b[0]; - target[1] = w[0] * a[1] + w[1] * b[1]; - target[2] = w[0] * a[2] + w[1] * b[2]; + target[0] = w[0] * a[0] + w[1] * b[0]; + target[1] = w[0] * a[1] + w[1] * b[1]; + target[2] = w[0] * a[2] + w[1] * b[2]; - return true; + return true; } bool interp_v2_v2v2_slerp(float target[2], const float a[2], const float b[2], const float t) { - float cosom, w[2]; + float cosom, w[2]; - BLI_ASSERT_UNIT_V2(a); - BLI_ASSERT_UNIT_V2(b); + BLI_ASSERT_UNIT_V2(a); + BLI_ASSERT_UNIT_V2(b); - cosom = dot_v2v2(a, b); + cosom = dot_v2v2(a, b); - /* direct opposites */ - if (UNLIKELY(cosom < (1.0f + FLT_EPSILON))) { - return false; - } + /* direct opposites */ + if (UNLIKELY(cosom < (1.0f + FLT_EPSILON))) { + return false; + } - interp_dot_slerp(t, cosom, w); + interp_dot_slerp(t, cosom, w); - target[0] = w[0] * a[0] + w[1] * b[0]; - target[1] = w[0] * a[1] + w[1] * b[1]; + target[0] = w[0] * a[0] + w[1] * b[0]; + target[1] = w[0] * a[1] + w[1] * b[1]; - return true; + return true; } /** @@ -120,171 +121,196 @@ bool interp_v2_v2v2_slerp(float target[2], const float a[2], const float b[2], c */ void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], const float t) { - if (UNLIKELY(!interp_v3_v3v3_slerp(target, a, b, t))) { - /* axis are aligned so any otho vector is acceptable */ - float ab_ortho[3]; - ortho_v3_v3(ab_ortho, a); - normalize_v3(ab_ortho); - if (t < 0.5f) { - if (UNLIKELY(!interp_v3_v3v3_slerp(target, a, ab_ortho, t * 2.0f))) { - BLI_assert(0); - copy_v3_v3(target, a); - } - } - else { - if (UNLIKELY(!interp_v3_v3v3_slerp(target, ab_ortho, b, (t - 0.5f) * 2.0f))) { - BLI_assert(0); - copy_v3_v3(target, b); - } - } - } + if (UNLIKELY(!interp_v3_v3v3_slerp(target, a, b, t))) { + /* axis are aligned so any otho vector is acceptable */ + float ab_ortho[3]; + ortho_v3_v3(ab_ortho, a); + normalize_v3(ab_ortho); + if (t < 0.5f) { + if (UNLIKELY(!interp_v3_v3v3_slerp(target, a, ab_ortho, t * 2.0f))) { + BLI_assert(0); + copy_v3_v3(target, a); + } + } + else { + if (UNLIKELY(!interp_v3_v3v3_slerp(target, ab_ortho, b, (t - 0.5f) * 2.0f))) { + BLI_assert(0); + copy_v3_v3(target, b); + } + } + } } void interp_v2_v2v2_slerp_safe(float target[2], const float a[2], const float b[2], const float t) { - if (UNLIKELY(!interp_v2_v2v2_slerp(target, a, b, t))) { - /* axis are aligned so any otho vector is acceptable */ - float ab_ortho[2]; - ortho_v2_v2(ab_ortho, a); - // normalize_v2(ab_ortho); - if (t < 0.5f) { - if (UNLIKELY(!interp_v2_v2v2_slerp(target, a, ab_ortho, t * 2.0f))) { - BLI_assert(0); - copy_v2_v2(target, a); - } - } - else { - if (UNLIKELY(!interp_v2_v2v2_slerp(target, ab_ortho, b, (t - 0.5f) * 2.0f))) { - BLI_assert(0); - copy_v2_v2(target, b); - } - } - } + if (UNLIKELY(!interp_v2_v2v2_slerp(target, a, b, t))) { + /* axis are aligned so any otho vector is acceptable */ + float ab_ortho[2]; + ortho_v2_v2(ab_ortho, a); + // normalize_v2(ab_ortho); + if (t < 0.5f) { + if (UNLIKELY(!interp_v2_v2v2_slerp(target, a, ab_ortho, t * 2.0f))) { + BLI_assert(0); + copy_v2_v2(target, a); + } + } + else { + if (UNLIKELY(!interp_v2_v2v2_slerp(target, ab_ortho, b, (t - 0.5f) * 2.0f))) { + BLI_assert(0); + copy_v2_v2(target, b); + } + } + } } /** \name Cubic curve interpolation (bezier spline). * \{ */ -void interp_v2_v2v2v2v2_cubic( - float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2], - const float u) +void interp_v2_v2v2v2v2_cubic(float p[2], + const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2], + const float u) { - float q0[2], q1[2], q2[2], r0[2], r1[2]; + float q0[2], q1[2], q2[2], r0[2], r1[2]; - interp_v2_v2v2(q0, v1, v2, u); - interp_v2_v2v2(q1, v2, v3, u); - interp_v2_v2v2(q2, v3, v4, u); + interp_v2_v2v2(q0, v1, v2, u); + interp_v2_v2v2(q1, v2, v3, u); + interp_v2_v2v2(q2, v3, v4, u); - interp_v2_v2v2(r0, q0, q1, u); - interp_v2_v2v2(r1, q1, q2, u); + interp_v2_v2v2(r0, q0, q1, u); + interp_v2_v2v2(r1, q1, q2, u); - interp_v2_v2v2(p, r0, r1, u); + interp_v2_v2v2(p, r0, r1, u); } /** \} */ /* weight 3 vectors, * 'w' must be unit length but is not a vector, just 3 weights */ -void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]) +void interp_v3_v3v3v3( + float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]) { - p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; - p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; - p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2]; + p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; + p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; + p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2]; } /* weight 3 vectors, * 'w' must be unit length but is not a vector, just 4 weights */ -void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float w[4]) +void interp_v3_v3v3v3v3(float p[3], + const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + const float w[4]) { - p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3]; - p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3]; - p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3]; + p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3]; + p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3]; + p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3]; } -void interp_v4_v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float w[3]) +void interp_v4_v4v4v4( + float p[4], const float v1[4], const float v2[4], const float v3[4], const float w[3]) { - p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; - p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; - p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2]; - p[3] = v1[3] * w[0] + v2[3] * w[1] + v3[3] * w[2]; + p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2]; + p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2]; + p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2]; + p[3] = v1[3] * w[0] + v2[3] * w[1] + v3[3] * w[2]; } -void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float v4[4], const float w[4]) +void interp_v4_v4v4v4v4(float p[4], + const float v1[4], + const float v2[4], + const float v3[4], + const float v4[4], + const float w[4]) { - p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3]; - p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3]; - p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3]; - p[3] = v1[3] * w[0] + v2[3] * w[1] + v3[3] * w[2] + v4[3] * w[3]; + p[0] = v1[0] * w[0] + v2[0] * w[1] + v3[0] * w[2] + v4[0] * w[3]; + p[1] = v1[1] * w[0] + v2[1] * w[1] + v3[1] * w[2] + v4[1] * w[3]; + p[2] = v1[2] * w[0] + v2[2] * w[1] + v3[2] * w[2] + v4[2] * w[3]; + p[3] = v1[3] * w[0] + v2[3] * w[1] + v3[3] * w[2] + v4[3] * w[3]; } -void interp_v3_v3v3v3_uv(float p[3], const float v1[3], const float v2[3], const float v3[3], const float uv[2]) +void interp_v3_v3v3v3_uv( + float p[3], const float v1[3], const float v2[3], const float v3[3], const float uv[2]) { - p[0] = v1[0] + ((v2[0] - v1[0]) * uv[0]) + ((v3[0] - v1[0]) * uv[1]); - p[1] = v1[1] + ((v2[1] - v1[1]) * uv[0]) + ((v3[1] - v1[1]) * uv[1]); - p[2] = v1[2] + ((v2[2] - v1[2]) * uv[0]) + ((v3[2] - v1[2]) * uv[1]); + p[0] = v1[0] + ((v2[0] - v1[0]) * uv[0]) + ((v3[0] - v1[0]) * uv[1]); + p[1] = v1[1] + ((v2[1] - v1[1]) * uv[0]) + ((v3[1] - v1[1]) * uv[1]); + p[2] = v1[2] + ((v2[2] - v1[2]) * uv[0]) + ((v3[2] - v1[2]) * uv[1]); } -void interp_v3_v3v3_uchar(char unsigned target[3], const unsigned char a[3], const unsigned char b[3], const float t) +void interp_v3_v3v3_uchar(char unsigned target[3], + const unsigned char a[3], + const unsigned char b[3], + const float t) { - const float s = 1.0f - t; + const float s = 1.0f - t; - target[0] = (char)floorf(s * a[0] + t * b[0]); - target[1] = (char)floorf(s * a[1] + t * b[1]); - target[2] = (char)floorf(s * a[2] + t * b[2]); + target[0] = (char)floorf(s * a[0] + t * b[0]); + target[1] = (char)floorf(s * a[1] + t * b[1]); + target[2] = (char)floorf(s * a[2] + t * b[2]); } void interp_v3_v3v3_char(char target[3], const char a[3], const char b[3], const float t) { - interp_v3_v3v3_uchar((unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); + interp_v3_v3v3_uchar( + (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); } -void interp_v4_v4v4_uchar(char unsigned target[4], const unsigned char a[4], const unsigned char b[4], const float t) +void interp_v4_v4v4_uchar(char unsigned target[4], + const unsigned char a[4], + const unsigned char b[4], + const float t) { - const float s = 1.0f - t; + const float s = 1.0f - t; - target[0] = (char)floorf(s * a[0] + t * b[0]); - target[1] = (char)floorf(s * a[1] + t * b[1]); - target[2] = (char)floorf(s * a[2] + t * b[2]); - target[3] = (char)floorf(s * a[3] + t * b[3]); + target[0] = (char)floorf(s * a[0] + t * b[0]); + target[1] = (char)floorf(s * a[1] + t * b[1]); + target[2] = (char)floorf(s * a[2] + t * b[2]); + target[3] = (char)floorf(s * a[3] + t * b[3]); } void interp_v4_v4v4_char(char target[4], const char a[4], const char b[4], const float t) { - interp_v4_v4v4_uchar((unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); + interp_v4_v4v4_uchar( + (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t); } void mid_v3_v3v3(float v[3], const float v1[3], const float v2[3]) { - v[0] = 0.5f * (v1[0] + v2[0]); - v[1] = 0.5f * (v1[1] + v2[1]); - v[2] = 0.5f * (v1[2] + v2[2]); + v[0] = 0.5f * (v1[0] + v2[0]); + v[1] = 0.5f * (v1[1] + v2[1]); + v[2] = 0.5f * (v1[2] + v2[2]); } void mid_v2_v2v2(float v[2], const float v1[2], const float v2[2]) { - v[0] = 0.5f * (v1[0] + v2[0]); - v[1] = 0.5f * (v1[1] + v2[1]); + v[0] = 0.5f * (v1[0] + v2[0]); + v[1] = 0.5f * (v1[1] + v2[1]); } void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) { - v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; - v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; - v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; + v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; + v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; + v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; } -void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +void mid_v3_v3v3v3v3( + float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - v[0] = (v1[0] + v2[0] + v3[0] + v4[0]) / 4.0f; - v[1] = (v1[1] + v2[1] + v3[1] + v4[1]) / 4.0f; - v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f; + v[0] = (v1[0] + v2[0] + v3[0] + v4[0]) / 4.0f; + v[1] = (v1[1] + v2[1] + v3[1] + v4[1]) / 4.0f; + v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f; } void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int nbr) { - const float factor = 1.0f / (float)nbr; - zero_v3(r); + const float factor = 1.0f / (float)nbr; + zero_v3(r); - for (unsigned int i = 0; i < nbr; i++) { - madd_v3_v3fl(r, vec_arr[i], factor); - } + for (unsigned int i = 0; i < nbr; i++) { + madd_v3_v3fl(r, vec_arr[i], factor); + } } /** @@ -301,21 +327,21 @@ void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int n */ void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3]) { - /* trick, we want the middle of 2 normals as well as the angle between them - * avoid multiple calculations by */ - float angle; + /* trick, we want the middle of 2 normals as well as the angle between them + * avoid multiple calculations by */ + float angle; - /* double check they are normalized */ - BLI_ASSERT_UNIT_V3(a); - BLI_ASSERT_UNIT_V3(b); + /* double check they are normalized */ + BLI_ASSERT_UNIT_V3(a); + BLI_ASSERT_UNIT_V3(b); - add_v3_v3v3(r, a, b); - angle = ((float)(1.0 / (M_PI / 2.0)) * - /* normally we would only multiply by 2, - * but instead of an angle make this 0-1 factor */ - 2.0f) * - acosf(normalize_v3(r) / 2.0f); - mul_v3_fl(r, angle); + add_v3_v3v3(r, a, b); + angle = ((float)(1.0 / (M_PI / 2.0)) * + /* normally we would only multiply by 2, + * but instead of an angle make this 0-1 factor */ + 2.0f) * + acosf(normalize_v3(r) / 2.0f); + mul_v3_fl(r, angle); } /** * Same as mid_v3_v3v3_angle_weighted @@ -323,19 +349,19 @@ void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3]) */ void mid_v3_angle_weighted(float r[3]) { - /* trick, we want the middle of 2 normals as well as the angle between them - * avoid multiple calculations by */ - float angle; + /* trick, we want the middle of 2 normals as well as the angle between them + * avoid multiple calculations by */ + float angle; - /* double check they are normalized */ - BLI_assert(len_squared_v3(r) <= 1.0f + FLT_EPSILON); + /* double check they are normalized */ + BLI_assert(len_squared_v3(r) <= 1.0f + FLT_EPSILON); - angle = ((float)(1.0 / (M_PI / 2.0)) * - /* normally we would only multiply by 2, - * but instead of an angle make this 0-1 factor */ - 2.0f) * - acosf(normalize_v3(r)); - mul_v3_fl(r, angle); + angle = ((float)(1.0 / (M_PI / 2.0)) * + /* normally we would only multiply by 2, + * but instead of an angle make this 0-1 factor */ + 2.0f) * + acosf(normalize_v3(r)); + mul_v3_fl(r, angle); } /** @@ -345,44 +371,42 @@ void mid_v3_angle_weighted(float r[3]) void flip_v4_v4v4(float v[4], const float v1[4], const float v2[4]) { - v[0] = v1[0] + (v1[0] - v2[0]); - v[1] = v1[1] + (v1[1] - v2[1]); - v[2] = v1[2] + (v1[2] - v2[2]); - v[3] = v1[3] + (v1[3] - v2[3]); + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); + v[2] = v1[2] + (v1[2] - v2[2]); + v[3] = v1[3] + (v1[3] - v2[3]); } void flip_v3_v3v3(float v[3], const float v1[3], const float v2[3]) { - v[0] = v1[0] + (v1[0] - v2[0]); - v[1] = v1[1] + (v1[1] - v2[1]); - v[2] = v1[2] + (v1[2] - v2[2]); + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); + v[2] = v1[2] + (v1[2] - v2[2]); } void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]) { - v[0] = v1[0] + (v1[0] - v2[0]); - v[1] = v1[1] + (v1[1] - v2[1]); + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); } - /********************************* Comparison ********************************/ bool is_finite_v2(const float v[2]) { - return (isfinite(v[0]) && isfinite(v[1])); + return (isfinite(v[0]) && isfinite(v[1])); } bool is_finite_v3(const float v[3]) { - return (isfinite(v[0]) && isfinite(v[1]) && isfinite(v[2])); + return (isfinite(v[0]) && isfinite(v[1]) && isfinite(v[2])); } bool is_finite_v4(const float v[4]) { - return (isfinite(v[0]) && isfinite(v[1]) && isfinite(v[2]) && isfinite(v[3])); + return (isfinite(v[0]) && isfinite(v[1]) && isfinite(v[2]) && isfinite(v[3])); } - /********************************** Angles ***********************************/ /* Return the angle in radians between vecs 1-2 and 2-3 in radians @@ -394,124 +418,124 @@ bool is_finite_v4(const float v[4]) */ float angle_v3v3v3(const float v1[3], const float v2[3], const float v3[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - sub_v3_v3v3(vec1, v2, v1); - sub_v3_v3v3(vec2, v2, v3); - normalize_v3(vec1); - normalize_v3(vec2); + sub_v3_v3v3(vec1, v2, v1); + sub_v3_v3v3(vec2, v2, v3); + normalize_v3(vec1); + normalize_v3(vec2); - return angle_normalized_v3v3(vec1, vec2); + return angle_normalized_v3v3(vec1, vec2); } /* Quicker than full angle computation */ float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - sub_v3_v3v3(vec1, p2, p1); - sub_v3_v3v3(vec2, p2, p3); - normalize_v3(vec1); - normalize_v3(vec2); + sub_v3_v3v3(vec1, p2, p1); + sub_v3_v3v3(vec2, p2, p3); + normalize_v3(vec1); + normalize_v3(vec2); - return dot_v3v3(vec1, vec2); + return dot_v3v3(vec1, vec2); } /* Return the shortest angle in radians between the 2 vectors */ float angle_v3v3(const float v1[3], const float v2[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - normalize_v3_v3(vec1, v1); - normalize_v3_v3(vec2, v2); + normalize_v3_v3(vec1, v1); + normalize_v3_v3(vec2, v2); - return angle_normalized_v3v3(vec1, vec2); + return angle_normalized_v3v3(vec1, vec2); } float angle_v2v2v2(const float v1[2], const float v2[2], const float v3[2]) { - float vec1[2], vec2[2]; + float vec1[2], vec2[2]; - vec1[0] = v2[0] - v1[0]; - vec1[1] = v2[1] - v1[1]; + vec1[0] = v2[0] - v1[0]; + vec1[1] = v2[1] - v1[1]; - vec2[0] = v2[0] - v3[0]; - vec2[1] = v2[1] - v3[1]; + vec2[0] = v2[0] - v3[0]; + vec2[1] = v2[1] - v3[1]; - normalize_v2(vec1); - normalize_v2(vec2); + normalize_v2(vec1); + normalize_v2(vec2); - return angle_normalized_v2v2(vec1, vec2); + return angle_normalized_v2v2(vec1, vec2); } /* Quicker than full angle computation */ float cos_v2v2v2(const float p1[2], const float p2[2], const float p3[2]) { - float vec1[2], vec2[2]; + float vec1[2], vec2[2]; - sub_v2_v2v2(vec1, p2, p1); - sub_v2_v2v2(vec2, p2, p3); - normalize_v2(vec1); - normalize_v2(vec2); + sub_v2_v2v2(vec1, p2, p1); + sub_v2_v2v2(vec2, p2, p3); + normalize_v2(vec1); + normalize_v2(vec2); - return dot_v2v2(vec1, vec2); + return dot_v2v2(vec1, vec2); } /* Return the shortest angle in radians between the 2 vectors */ float angle_v2v2(const float v1[2], const float v2[2]) { - float vec1[2], vec2[2]; + float vec1[2], vec2[2]; - vec1[0] = v1[0]; - vec1[1] = v1[1]; + vec1[0] = v1[0]; + vec1[1] = v1[1]; - vec2[0] = v2[0]; - vec2[1] = v2[1]; + vec2[0] = v2[0]; + vec2[1] = v2[1]; - normalize_v2(vec1); - normalize_v2(vec2); + normalize_v2(vec1); + normalize_v2(vec2); - return angle_normalized_v2v2(vec1, vec2); + return angle_normalized_v2v2(vec1, vec2); } float angle_signed_v2v2(const float v1[2], const float v2[2]) { - const float perp_dot = (v1[1] * v2[0]) - (v1[0] * v2[1]); - return atan2f(perp_dot, dot_v2v2(v1, v2)); + const float perp_dot = (v1[1] * v2[0]) - (v1[0] * v2[1]); + return atan2f(perp_dot, dot_v2v2(v1, v2)); } float angle_normalized_v3v3(const float v1[3], const float v2[3]) { - /* double check they are normalized */ - BLI_ASSERT_UNIT_V3(v1); - BLI_ASSERT_UNIT_V3(v2); + /* double check they are normalized */ + BLI_ASSERT_UNIT_V3(v1); + BLI_ASSERT_UNIT_V3(v2); - /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ - if (dot_v3v3(v1, v2) >= 0.0f) { - return 2.0f * saasin(len_v3v3(v1, v2) / 2.0f); - } - else { - float v2_n[3]; - negate_v3_v3(v2_n, v2); - return (float)M_PI - 2.0f * saasin(len_v3v3(v1, v2_n) / 2.0f); - } + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + if (dot_v3v3(v1, v2) >= 0.0f) { + return 2.0f * saasin(len_v3v3(v1, v2) / 2.0f); + } + else { + float v2_n[3]; + negate_v3_v3(v2_n, v2); + return (float)M_PI - 2.0f * saasin(len_v3v3(v1, v2_n) / 2.0f); + } } float angle_normalized_v2v2(const float v1[2], const float v2[2]) { - /* double check they are normalized */ - BLI_ASSERT_UNIT_V2(v1); - BLI_ASSERT_UNIT_V2(v2); + /* double check they are normalized */ + BLI_ASSERT_UNIT_V2(v1); + BLI_ASSERT_UNIT_V2(v2); - /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ - if (dot_v2v2(v1, v2) >= 0.0f) { - return 2.0f * saasin(len_v2v2(v1, v2) / 2.0f); - } - else { - float v2_n[2]; - negate_v2_v2(v2_n, v2); - return (float)M_PI - 2.0f * saasin(len_v2v2(v1, v2_n) / 2.0f); - } + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + if (dot_v2v2(v1, v2) >= 0.0f) { + return 2.0f * saasin(len_v2v2(v1, v2) / 2.0f); + } + else { + float v2_n[2]; + negate_v2_v2(v2_n, v2); + return (float)M_PI - 2.0f * saasin(len_v2v2(v1, v2_n) / 2.0f); + } } /** @@ -519,108 +543,115 @@ float angle_normalized_v2v2(const float v1[2], const float v2[2]) */ float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) { - float v1_proj[3], v2_proj[3]; + float v1_proj[3], v2_proj[3]; - /* project the vectors onto the axis */ - project_plane_normalized_v3_v3v3(v1_proj, v1, axis); - project_plane_normalized_v3_v3v3(v2_proj, v2, axis); + /* project the vectors onto the axis */ + project_plane_normalized_v3_v3v3(v1_proj, v1, axis); + project_plane_normalized_v3_v3v3(v2_proj, v2, axis); - return angle_v3v3(v1_proj, v2_proj); + return angle_v3v3(v1_proj, v2_proj); } float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) { - float v1_proj[3], v2_proj[3], tproj[3]; - float angle; + float v1_proj[3], v2_proj[3], tproj[3]; + float angle; - /* project the vectors onto the axis */ - project_plane_normalized_v3_v3v3(v1_proj, v1, axis); - project_plane_normalized_v3_v3v3(v2_proj, v2, axis); + /* project the vectors onto the axis */ + project_plane_normalized_v3_v3v3(v1_proj, v1, axis); + project_plane_normalized_v3_v3v3(v2_proj, v2, axis); - angle = angle_v3v3(v1_proj, v2_proj); + angle = angle_v3v3(v1_proj, v2_proj); - /* calculate the sign (reuse 'tproj') */ - cross_v3_v3v3(tproj, v2_proj, v1_proj); - if (dot_v3v3(tproj, axis) < 0.0f) { - angle = ((float)(M_PI * 2.0)) - angle; - } + /* calculate the sign (reuse 'tproj') */ + cross_v3_v3v3(tproj, v2_proj, v1_proj); + if (dot_v3v3(tproj, axis) < 0.0f) { + angle = ((float)(M_PI * 2.0)) - angle; + } - return angle; + return angle; } /** * Angle between 2 vectors defined by 3 coords, about an axis (axis can be considered a plane). */ -float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) +float angle_on_axis_v3v3v3_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float axis[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - sub_v3_v3v3(vec1, v1, v2); - sub_v3_v3v3(vec2, v3, v2); + sub_v3_v3v3(vec1, v1, v2); + sub_v3_v3v3(vec2, v3, v2); - return angle_on_axis_v3v3_v3(vec1, vec2, axis); + return angle_on_axis_v3v3_v3(vec1, vec2, axis); } -float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) +float angle_signed_on_axis_v3v3v3_v3(const float v1[3], + const float v2[3], + const float v3[3], + const float axis[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - sub_v3_v3v3(vec1, v1, v2); - sub_v3_v3v3(vec2, v3, v2); + sub_v3_v3v3(vec1, v1, v2); + sub_v3_v3v3(vec2, v3, v2); - return angle_signed_on_axis_v3v3_v3(vec1, vec2, axis); + return angle_signed_on_axis_v3v3_v3(vec1, vec2, axis); } void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]) { - float ed1[3], ed2[3], ed3[3]; + float ed1[3], ed2[3], ed3[3]; - sub_v3_v3v3(ed1, v3, v1); - sub_v3_v3v3(ed2, v1, v2); - sub_v3_v3v3(ed3, v2, v3); + sub_v3_v3v3(ed1, v3, v1); + sub_v3_v3v3(ed2, v1, v2); + sub_v3_v3v3(ed3, v2, v3); - normalize_v3(ed1); - normalize_v3(ed2); - normalize_v3(ed3); + normalize_v3(ed1); + normalize_v3(ed2); + normalize_v3(ed3); - angles[0] = (float)M_PI - angle_normalized_v3v3(ed1, ed2); - angles[1] = (float)M_PI - angle_normalized_v3v3(ed2, ed3); - // face_angles[2] = M_PI - angle_normalized_v3v3(ed3, ed1); - angles[2] = (float)M_PI - (angles[0] + angles[1]); + angles[0] = (float)M_PI - angle_normalized_v3v3(ed1, ed2); + angles[1] = (float)M_PI - angle_normalized_v3v3(ed2, ed3); + // face_angles[2] = M_PI - angle_normalized_v3v3(ed3, ed1); + angles[2] = (float)M_PI - (angles[0] + angles[1]); } -void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +void angle_quad_v3( + float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - float ed1[3], ed2[3], ed3[3], ed4[3]; + float ed1[3], ed2[3], ed3[3], ed4[3]; - sub_v3_v3v3(ed1, v4, v1); - sub_v3_v3v3(ed2, v1, v2); - sub_v3_v3v3(ed3, v2, v3); - sub_v3_v3v3(ed4, v3, v4); + sub_v3_v3v3(ed1, v4, v1); + sub_v3_v3v3(ed2, v1, v2); + sub_v3_v3v3(ed3, v2, v3); + sub_v3_v3v3(ed4, v3, v4); - normalize_v3(ed1); - normalize_v3(ed2); - normalize_v3(ed3); - normalize_v3(ed4); + normalize_v3(ed1); + normalize_v3(ed2); + normalize_v3(ed3); + normalize_v3(ed4); - angles[0] = (float)M_PI - angle_normalized_v3v3(ed1, ed2); - angles[1] = (float)M_PI - angle_normalized_v3v3(ed2, ed3); - angles[2] = (float)M_PI - angle_normalized_v3v3(ed3, ed4); - angles[3] = (float)M_PI - angle_normalized_v3v3(ed4, ed1); + angles[0] = (float)M_PI - angle_normalized_v3v3(ed1, ed2); + angles[1] = (float)M_PI - angle_normalized_v3v3(ed2, ed3); + angles[2] = (float)M_PI - angle_normalized_v3v3(ed3, ed4); + angles[3] = (float)M_PI - angle_normalized_v3v3(ed4, ed1); } void angle_poly_v3(float *angles, const float *verts[3], int len) { - int i; - float vec[3][3]; + int i; + float vec[3][3]; - sub_v3_v3v3(vec[2], verts[len - 1], verts[0]); - normalize_v3(vec[2]); - for (i = 0; i < len; i++) { - sub_v3_v3v3(vec[i % 3], verts[i % len], verts[(i + 1) % len]); - normalize_v3(vec[i % 3]); - angles[i] = (float)M_PI - angle_normalized_v3v3(vec[(i + 2) % 3], vec[i % 3]); - } + sub_v3_v3v3(vec[2], verts[len - 1], verts[0]); + normalize_v3(vec[2]); + for (i = 0; i < len; i++) { + sub_v3_v3v3(vec[i % 3], verts[i % len], verts[(i + 1) % len]); + normalize_v3(vec[i % 3]); + angles[i] = (float)M_PI - angle_normalized_v3v3(vec[(i + 2) % 3], vec[i % 3]); + } } /********************************* Geometry **********************************/ @@ -630,10 +661,10 @@ void angle_poly_v3(float *angles, const float *verts[3], int len) */ void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]) { - const float mul = dot_v2v2(p, v_proj) / dot_v2v2(v_proj, v_proj); + const float mul = dot_v2v2(p, v_proj) / dot_v2v2(v_proj, v_proj); - out[0] = mul * v_proj[0]; - out[1] = mul * v_proj[1]; + out[0] = mul * v_proj[0]; + out[1] = mul * v_proj[1]; } /** @@ -641,11 +672,11 @@ void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]) */ void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]) { - const float mul = dot_v3v3(p, v_proj) / dot_v3v3(v_proj, v_proj); + const float mul = dot_v3v3(p, v_proj) / dot_v3v3(v_proj, v_proj); - out[0] = mul * v_proj[0]; - out[1] = mul * v_proj[1]; - out[2] = mul * v_proj[2]; + out[0] = mul * v_proj[0]; + out[1] = mul * v_proj[1]; + out[2] = mul * v_proj[2]; } /** @@ -653,11 +684,11 @@ void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]) */ void project_v2_v2v2_normalized(float out[2], const float p[2], const float v_proj[2]) { - BLI_ASSERT_UNIT_V2(v_proj); - const float mul = dot_v2v2(p, v_proj); + BLI_ASSERT_UNIT_V2(v_proj); + const float mul = dot_v2v2(p, v_proj); - out[0] = mul * v_proj[0]; - out[1] = mul * v_proj[1]; + out[0] = mul * v_proj[0]; + out[1] = mul * v_proj[1]; } /** @@ -665,12 +696,12 @@ void project_v2_v2v2_normalized(float out[2], const float p[2], const float v_pr */ void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3]) { - BLI_ASSERT_UNIT_V3(v_proj); - const float mul = dot_v3v3(p, v_proj); + BLI_ASSERT_UNIT_V3(v_proj); + const float mul = dot_v3v3(p, v_proj); - out[0] = mul * v_proj[0]; - out[1] = mul * v_proj[1]; - out[2] = mul * v_proj[2]; + out[0] = mul * v_proj[0]; + out[1] = mul * v_proj[1]; + out[2] = mul * v_proj[2]; } /** @@ -688,64 +719,64 @@ void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_pr */ void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3]) { - const float mul = dot_v3v3(p, v_plane) / dot_v3v3(v_plane, v_plane); + const float mul = dot_v3v3(p, v_plane) / dot_v3v3(v_plane, v_plane); - out[0] = p[0] - (mul * v_plane[0]); - out[1] = p[1] - (mul * v_plane[1]); - out[2] = p[2] - (mul * v_plane[2]); + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); + out[2] = p[2] - (mul * v_plane[2]); } void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2]) { - const float mul = dot_v2v2(p, v_plane) / dot_v2v2(v_plane, v_plane); + const float mul = dot_v2v2(p, v_plane) / dot_v2v2(v_plane, v_plane); - out[0] = p[0] - (mul * v_plane[0]); - out[1] = p[1] - (mul * v_plane[1]); + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); } void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3]) { - BLI_ASSERT_UNIT_V3(v_plane); - const float mul = dot_v3v3(p, v_plane); + BLI_ASSERT_UNIT_V3(v_plane); + const float mul = dot_v3v3(p, v_plane); - out[0] = p[0] - (mul * v_plane[0]); - out[1] = p[1] - (mul * v_plane[1]); - out[2] = p[2] - (mul * v_plane[2]); + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); + out[2] = p[2] - (mul * v_plane[2]); } void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2]) { - BLI_ASSERT_UNIT_V2(v_plane); - const float mul = dot_v2v2(p, v_plane); + BLI_ASSERT_UNIT_V2(v_plane); + const float mul = dot_v2v2(p, v_plane); - out[0] = p[0] - (mul * v_plane[0]); - out[1] = p[1] - (mul * v_plane[1]); + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); } /* project a vector on a plane defined by normal and a plane point p */ void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]) { - float vector[3]; - float mul; + float vector[3]; + float mul; - sub_v3_v3v3(vector, out, plane_co); - mul = dot_v3v3(vector, plane_no) / len_squared_v3(plane_no); + sub_v3_v3v3(vector, out, plane_co); + mul = dot_v3v3(vector, plane_no) / len_squared_v3(plane_no); - mul_v3_v3fl(vector, plane_no, mul); + mul_v3_v3fl(vector, plane_no, mul); - sub_v3_v3(out, vector); + sub_v3_v3(out, vector); } /* Returns a vector bisecting the angle at v2 formed by v1, v2 and v3 */ void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const float v3[3]) { - float d_12[3], d_23[3]; - sub_v3_v3v3(d_12, v2, v1); - sub_v3_v3v3(d_23, v3, v2); - normalize_v3(d_12); - normalize_v3(d_23); - add_v3_v3v3(out, d_12, d_23); - normalize_v3(out); + float d_12[3], d_23[3]; + sub_v3_v3v3(d_12, v2, v1); + sub_v3_v3v3(d_23, v3, v2); + normalize_v3(d_12); + normalize_v3(d_23); + add_v3_v3v3(out, d_12, d_23); + normalize_v3(out); } /** @@ -766,13 +797,13 @@ void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const */ void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3]) { - const float dot2 = 2.0f * dot_v3v3(v, normal); + const float dot2 = 2.0f * dot_v3v3(v, normal); - BLI_ASSERT_UNIT_V3(normal); + BLI_ASSERT_UNIT_V3(normal); - out[0] = v[0] - (dot2 * normal[0]); - out[1] = v[1] - (dot2 * normal[1]); - out[2] = v[2] - (dot2 * normal[2]); + out[0] = v[0] - (dot2 * normal[0]); + out[1] = v[1] - (dot2 * normal[1]); + out[2] = v[2] - (dot2 * normal[2]); } /** @@ -782,27 +813,27 @@ void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3]) */ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]) { - const float eps = FLT_EPSILON; - const float f = len_squared_v2(n); + const float eps = FLT_EPSILON; + const float f = len_squared_v2(n); - if (f > eps) { - const float d = 1.0f / sqrtf(f); + if (f > eps) { + const float d = 1.0f / sqrtf(f); - BLI_assert(isfinite(d)); + BLI_assert(isfinite(d)); - r_n1[0] = n[1] * d; - r_n1[1] = -n[0] * d; - r_n1[2] = 0.0f; - r_n2[0] = -n[2] * r_n1[1]; - r_n2[1] = n[2] * r_n1[0]; - r_n2[2] = n[0] * r_n1[1] - n[1] * r_n1[0]; - } - else { - /* degenerate case */ - r_n1[0] = (n[2] < 0.0f) ? -1.0f : 1.0f; - r_n1[1] = r_n1[2] = r_n2[0] = r_n2[2] = 0.0f; - r_n2[1] = 1.0f; - } + r_n1[0] = n[1] * d; + r_n1[1] = -n[0] * d; + r_n1[2] = 0.0f; + r_n2[0] = -n[2] * r_n1[1]; + r_n2[1] = n[2] * r_n1[0]; + r_n2[2] = n[0] * r_n1[1] - n[1] * r_n1[0]; + } + else { + /* degenerate case */ + r_n1[0] = (n[2] < 0.0f) ? -1.0f : 1.0f; + r_n1[1] = r_n1[2] = r_n2[0] = r_n2[2] = 0.0f; + r_n2[1] = 1.0f; + } } /** @@ -812,27 +843,27 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]) */ void ortho_v3_v3(float out[3], const float v[3]) { - const int axis = axis_dominant_v3_single(v); - - BLI_assert(out != v); - - switch (axis) { - case 0: - out[0] = -v[1] - v[2]; - out[1] = v[0]; - out[2] = v[0]; - break; - case 1: - out[0] = v[1]; - out[1] = -v[0] - v[2]; - out[2] = v[1]; - break; - case 2: - out[0] = v[2]; - out[1] = v[2]; - out[2] = -v[0] - v[1]; - break; - } + const int axis = axis_dominant_v3_single(v); + + BLI_assert(out != v); + + switch (axis) { + case 0: + out[0] = -v[1] - v[2]; + out[1] = v[0]; + out[2] = v[0]; + break; + case 1: + out[0] = v[1]; + out[1] = -v[0] - v[2]; + out[2] = v[1]; + break; + case 2: + out[0] = v[2]; + out[1] = v[2]; + out[2] = -v[0] - v[1]; + break; + } } /** @@ -840,10 +871,10 @@ void ortho_v3_v3(float out[3], const float v[3]) */ void ortho_v2_v2(float out[2], const float v[2]) { - BLI_assert(out != v); + BLI_assert(out != v); - out[0] = -v[1]; - out[1] = v[0]; + out[0] = -v[1]; + out[1] = v[0]; } /** @@ -851,146 +882,179 @@ void ortho_v2_v2(float out[2], const float v[2]) */ void rotate_v2_v2fl(float r[2], const float p[2], const float angle) { - const float co = cosf(angle); - const float si = sinf(angle); + const float co = cosf(angle); + const float si = sinf(angle); - BLI_assert(r != p); + BLI_assert(r != p); - r[0] = co * p[0] - si * p[1]; - r[1] = si * p[0] + co * p[1]; + r[0] = co * p[0] - si * p[1]; + r[1] = si * p[0] + co * p[1]; } /** * Rotate a point \a p by \a angle around an arbitrary unit length \a axis. * http://local.wasp.uwa.edu.au/~pbourke/geometry/ */ -void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle) +void rotate_normalized_v3_v3v3fl(float out[3], + const float p[3], + const float axis[3], + const float angle) { - const float costheta = cosf(angle); - const float sintheta = sinf(angle); + const float costheta = cosf(angle); + const float sintheta = sinf(angle); - /* double check they are normalized */ - BLI_ASSERT_UNIT_V3(axis); + /* double check they are normalized */ + BLI_ASSERT_UNIT_V3(axis); - out[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + - (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + - (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]); + out[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + + (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + + (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]); - out[1] = (((1 - costheta) * axis[0] * axis[1] + axis[2] * sintheta) * p[0]) + - ((costheta + (1 - costheta) * axis[1] * axis[1]) * p[1]) + - (((1 - costheta) * axis[1] * axis[2] - axis[0] * sintheta) * p[2]); + out[1] = (((1 - costheta) * axis[0] * axis[1] + axis[2] * sintheta) * p[0]) + + ((costheta + (1 - costheta) * axis[1] * axis[1]) * p[1]) + + (((1 - costheta) * axis[1] * axis[2] - axis[0] * sintheta) * p[2]); - out[2] = (((1 - costheta) * axis[0] * axis[2] - axis[1] * sintheta) * p[0]) + - (((1 - costheta) * axis[1] * axis[2] + axis[0] * sintheta) * p[1]) + - ((costheta + (1 - costheta) * axis[2] * axis[2]) * p[2]); + out[2] = (((1 - costheta) * axis[0] * axis[2] - axis[1] * sintheta) * p[0]) + + (((1 - costheta) * axis[1] * axis[2] + axis[0] * sintheta) * p[1]) + + ((costheta + (1 - costheta) * axis[2] * axis[2]) * p[2]); } void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle) { - BLI_assert(r != p); + BLI_assert(r != p); - float axis_n[3]; + float axis_n[3]; - normalize_v3_v3(axis_n, axis); + normalize_v3_v3(axis_n, axis); - rotate_normalized_v3_v3v3fl(r, p, axis_n, angle); + rotate_normalized_v3_v3v3fl(r, p, axis_n, angle); } /*********************************** Other ***********************************/ void print_v2(const char *str, const float v[2]) { - printf("%s: %.8f %.8f\n", str, v[0], v[1]); + printf("%s: %.8f %.8f\n", str, v[0], v[1]); } void print_v3(const char *str, const float v[3]) { - printf("%s: %.8f %.8f %.8f\n", str, v[0], v[1], v[2]); + printf("%s: %.8f %.8f %.8f\n", str, v[0], v[1], v[2]); } void print_v4(const char *str, const float v[4]) { - printf("%s: %.8f %.8f %.8f %.8f\n", str, v[0], v[1], v[2], v[3]); + printf("%s: %.8f %.8f %.8f %.8f\n", str, v[0], v[1], v[2], v[3]); } void print_vn(const char *str, const float v[], const int n) { - int i = 0; - printf("%s[%d]:", str, n); - while (i < n) { - printf(" %.8f", v[i++]); - } - printf("\n"); + int i = 0; + printf("%s[%d]:", str, n); + while (i < n) { + printf(" %.8f", v[i++]); + } + printf("\n"); } void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]) { - if (min[0] > vec[0]) { min[0] = vec[0]; } - if (min[1] > vec[1]) { min[1] = vec[1]; } - if (min[2] > vec[2]) { min[2] = vec[2]; } - - if (max[0] < vec[0]) { max[0] = vec[0]; } - if (max[1] < vec[1]) { max[1] = vec[1]; } - if (max[2] < vec[2]) { max[2] = vec[2]; } + if (min[0] > vec[0]) { + min[0] = vec[0]; + } + if (min[1] > vec[1]) { + min[1] = vec[1]; + } + if (min[2] > vec[2]) { + min[2] = vec[2]; + } + + if (max[0] < vec[0]) { + max[0] = vec[0]; + } + if (max[1] < vec[1]) { + max[1] = vec[1]; + } + if (max[2] < vec[2]) { + max[2] = vec[2]; + } } void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]) { - if (min[0] > vec[0]) { min[0] = vec[0]; } - if (min[1] > vec[1]) { min[1] = vec[1]; } + if (min[0] > vec[0]) { + min[0] = vec[0]; + } + if (min[1] > vec[1]) { + min[1] = vec[1]; + } - if (max[0] < vec[0]) { max[0] = vec[0]; } - if (max[1] < vec[1]) { max[1] = vec[1]; } + if (max[0] < vec[0]) { + max[0] = vec[0]; + } + if (max[1] < vec[1]) { + max[1] = vec[1]; + } } void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float (*vec_arr)[3], int nbr) { - while (nbr--) { - minmax_v3v3_v3(r_min, r_max, *vec_arr++); - } + while (nbr--) { + minmax_v3v3_v3(r_min, r_max, *vec_arr++); + } } /** ensure \a v1 is \a dist from \a v2 */ void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist) { - if (!equals_v3v3(v2, v1)) { - float nor[3]; + if (!equals_v3v3(v2, v1)) { + float nor[3]; - sub_v3_v3v3(nor, v1, v2); - normalize_v3(nor); - madd_v3_v3v3fl(v1, v2, nor, dist); - } + sub_v3_v3v3(nor, v1, v2); + normalize_v3(nor); + madd_v3_v3v3fl(v1, v2, nor, dist); + } } void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist) { - if (!equals_v2v2(v2, v1)) { - float nor[2]; + if (!equals_v2v2(v2, v1)) { + float nor[2]; - sub_v2_v2v2(nor, v1, v2); - normalize_v2(nor); - madd_v2_v2v2fl(v1, v2, nor, dist); - } + sub_v2_v2v2(nor, v1, v2); + normalize_v2(nor); + madd_v2_v2v2fl(v1, v2, nor, dist); + } } void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) { - float v[3]; - copy_v3_v3(v, axis_values); - -#define SWAP_AXIS(a, b) { \ - SWAP(float, v[a], v[b]); \ - SWAP(int, r_axis_order[a], r_axis_order[b]); \ -} (void)0 - - if (v[0] < v[1]) { - if (v[2] < v[0]) { SWAP_AXIS(0, 2); } - } - else { - if (v[1] < v[2]) { SWAP_AXIS(0, 1); } - else { SWAP_AXIS(0, 2); } - } - if (v[2] < v[1]) { SWAP_AXIS(1, 2); } + float v[3]; + copy_v3_v3(v, axis_values); + +#define SWAP_AXIS(a, b) \ + { \ + SWAP(float, v[a], v[b]); \ + SWAP(int, r_axis_order[a], r_axis_order[b]); \ + } \ + (void)0 + + if (v[0] < v[1]) { + if (v[2] < v[0]) { + SWAP_AXIS(0, 2); + } + } + else { + if (v[1] < v[2]) { + SWAP_AXIS(0, 1); + } + else { + SWAP_AXIS(0, 2); + } + } + if (v[2] < v[1]) { + SWAP_AXIS(1, 2); + } #undef SWAP_AXIS } @@ -999,280 +1063,297 @@ void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) MINLINE double sqr_db(double f) { - return f * f; + return f * f; } double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) { - double d = 0.0f; - const float *array_pt_a = array_src_a + (size - 1); - const float *array_pt_b = array_src_b + (size - 1); - int i = size; - while (i--) { - d += (double)(*(array_pt_a--) * *(array_pt_b--)); - } - return d; + double d = 0.0f; + const float *array_pt_a = array_src_a + (size - 1); + const float *array_pt_b = array_src_b + (size - 1); + int i = size; + while (i--) { + d += (double)(*(array_pt_a--) * *(array_pt_b--)); + } + return d; } double len_squared_vn(const float *array, const int size) { - double d = 0.0f; - const float *array_pt = array + (size - 1); - int i = size; - while (i--) { - d += sqr_db((double)(*(array_pt--))); - } - return d; + double d = 0.0f; + const float *array_pt = array + (size - 1); + int i = size; + while (i--) { + d += sqr_db((double)(*(array_pt--))); + } + return d; } float normalize_vn_vn(float *array_tar, const float *array_src, const int size) { - const double d = len_squared_vn(array_src, size); - float d_sqrt; - if (d > 1.0e-35) { - d_sqrt = (float)sqrt(d); - mul_vn_vn_fl(array_tar, array_src, size, 1.0f / d_sqrt); - } - else { - copy_vn_fl(array_tar, size, 0.0f); - d_sqrt = 0.0f; - } - return d_sqrt; + const double d = len_squared_vn(array_src, size); + float d_sqrt; + if (d > 1.0e-35) { + d_sqrt = (float)sqrt(d); + mul_vn_vn_fl(array_tar, array_src, size, 1.0f / d_sqrt); + } + else { + copy_vn_fl(array_tar, size, 0.0f); + d_sqrt = 0.0f; + } + return d_sqrt; } float normalize_vn(float *array_tar, const int size) { - return normalize_vn_vn(array_tar, array_tar, size); + return normalize_vn_vn(array_tar, array_tar, size); } void range_vn_i(int *array_tar, const int size, const int start) { - int *array_pt = array_tar + (size - 1); - int j = start + (size - 1); - int i = size; - while (i--) { - *(array_pt--) = j--; - } + int *array_pt = array_tar + (size - 1); + int j = start + (size - 1); + int i = size; + while (i--) { + *(array_pt--) = j--; + } } void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start) { - unsigned int *array_pt = array_tar + (size - 1); - unsigned int j = start + (unsigned int)(size - 1); - int i = size; - while (i--) { - *(array_pt--) = j--; - } + unsigned int *array_pt = array_tar + (size - 1); + unsigned int j = start + (unsigned int)(size - 1); + int i = size; + while (i--) { + *(array_pt--) = j--; + } } void range_vn_fl(float *array_tar, const int size, const float start, const float step) { - float *array_pt = array_tar + (size - 1); - int i = size; - while (i--) { - *(array_pt--) = start + step * (float)(i); - } + float *array_pt = array_tar + (size - 1); + int i = size; + while (i--) { + *(array_pt--) = start + step * (float)(i); + } } void negate_vn(float *array_tar, const int size) { - float *array_pt = array_tar + (size - 1); - int i = size; - while (i--) { - *(array_pt--) *= -1.0f; - } + float *array_pt = array_tar + (size - 1); + int i = size; + while (i--) { + *(array_pt--) *= -1.0f; + } } void negate_vn_vn(float *array_tar, const float *array_src, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) = -*(src--); - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) = -*(src--); + } } void mul_vn_vn(float *array_tar, const float *array_src, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) *= *(src--); - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) *= *(src--); + } } -void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) +void mul_vn_vnvn(float *array_tar, + const float *array_src_a, + const float *array_src_b, + const int size) { - float *tar = array_tar + (size - 1); - const float *src_a = array_src_a + (size - 1); - const float *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) * *(src_b--); - } + float *tar = array_tar + (size - 1); + const float *src_a = array_src_a + (size - 1); + const float *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) * *(src_b--); + } } void mul_vn_fl(float *array_tar, const int size, const float f) { - float *array_pt = array_tar + (size - 1); - int i = size; - while (i--) { - *(array_pt--) *= f; - } + float *array_pt = array_tar + (size - 1); + int i = size; + while (i--) { + *(array_pt--) *= f; + } } void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src--) * f; - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src--) * f; + } } void add_vn_vn(float *array_tar, const float *array_src, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) += *(src--); - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) += *(src--); + } } -void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) +void add_vn_vnvn(float *array_tar, + const float *array_src_a, + const float *array_src_b, + const int size) { - float *tar = array_tar + (size - 1); - const float *src_a = array_src_a + (size - 1); - const float *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) + *(src_b--); - } + float *tar = array_tar + (size - 1); + const float *src_a = array_src_a + (size - 1); + const float *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) + *(src_b--); + } } void madd_vn_vn(float *array_tar, const float *array_src, const float f, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) += *(src--) * f; - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) += *(src--) * f; + } } -void madd_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const float f, const int size) +void madd_vn_vnvn(float *array_tar, + const float *array_src_a, + const float *array_src_b, + const float f, + const int size) { - float *tar = array_tar + (size - 1); - const float *src_a = array_src_a + (size - 1); - const float *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) + (*(src_b--) * f); - } + float *tar = array_tar + (size - 1); + const float *src_a = array_src_a + (size - 1); + const float *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) + (*(src_b--) * f); + } } void sub_vn_vn(float *array_tar, const float *array_src, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) -= *(src--); - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) -= *(src--); + } } -void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) +void sub_vn_vnvn(float *array_tar, + const float *array_src_a, + const float *array_src_b, + const int size) { - float *tar = array_tar + (size - 1); - const float *src_a = array_src_a + (size - 1); - const float *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) - *(src_b--); - } + float *tar = array_tar + (size - 1); + const float *src_a = array_src_a + (size - 1); + const float *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) - *(src_b--); + } } void msub_vn_vn(float *array_tar, const float *array_src, const float f, const int size) { - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) -= *(src--) * f; - } + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) -= *(src--) * f; + } } -void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const float f, const int size) +void msub_vn_vnvn(float *array_tar, + const float *array_src_a, + const float *array_src_b, + const float f, + const int size) { - float *tar = array_tar + (size - 1); - const float *src_a = array_src_a + (size - 1); - const float *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) - (*(src_b--) * f); - } + float *tar = array_tar + (size - 1); + const float *src_a = array_src_a + (size - 1); + const float *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) - (*(src_b--) * f); + } } void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size) { - const float s = 1.0f - t; - float *tar = array_tar + (size - 1); - const float *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar) = (s * *(tar)) + (t * *(src)); - tar--; - src--; - } + const float s = 1.0f - t; + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar) = (s * *(tar)) + (t * *(src)); + tar--; + src--; + } } void copy_vn_i(int *array_tar, const int size, const int val) { - int *tar = array_tar + (size - 1); - int i = size; - while (i--) { - *(tar--) = val; - } + int *tar = array_tar + (size - 1); + int i = size; + while (i--) { + *(tar--) = val; + } } void copy_vn_short(short *array_tar, const int size, const short val) { - short *tar = array_tar + (size - 1); - int i = size; - while (i--) { - *(tar--) = val; - } + short *tar = array_tar + (size - 1); + int i = size; + while (i--) { + *(tar--) = val; + } } void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val) { - unsigned short *tar = array_tar + (size - 1); - int i = size; - while (i--) { - *(tar--) = val; - } + unsigned short *tar = array_tar + (size - 1); + int i = size; + while (i--) { + *(tar--) = val; + } } void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val) { - unsigned char *tar = array_tar + (size - 1); - int i = size; - while (i--) { - *(tar--) = val; - } + unsigned char *tar = array_tar + (size - 1); + int i = size; + while (i--) { + *(tar--) = val; + } } void copy_vn_fl(float *array_tar, const int size, const float val) { - float *tar = array_tar + (size - 1); - int i = size; - while (i--) { - *(tar--) = val; - } + float *tar = array_tar + (size - 1); + int i = size; + while (i--) { + *(tar--) = val; + } } /** \name Double precision versions 'db'. @@ -1280,32 +1361,35 @@ void copy_vn_fl(float *array_tar, const int size, const float val) void add_vn_vn_d(double *array_tar, const double *array_src, const int size) { - double *tar = array_tar + (size - 1); - const double *src = array_src + (size - 1); - int i = size; - while (i--) { - *(tar--) += *(src--); - } + double *tar = array_tar + (size - 1); + const double *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar--) += *(src--); + } } -void add_vn_vnvn_d(double *array_tar, const double *array_src_a, const double *array_src_b, const int size) +void add_vn_vnvn_d(double *array_tar, + const double *array_src_a, + const double *array_src_b, + const int size) { - double *tar = array_tar + (size - 1); - const double *src_a = array_src_a + (size - 1); - const double *src_b = array_src_b + (size - 1); - int i = size; - while (i--) { - *(tar--) = *(src_a--) + *(src_b--); - } + double *tar = array_tar + (size - 1); + const double *src_a = array_src_a + (size - 1); + const double *src_b = array_src_b + (size - 1); + int i = size; + while (i--) { + *(tar--) = *(src_a--) + *(src_b--); + } } void mul_vn_db(double *array_tar, const int size, const double f) { - double *array_pt = array_tar + (size - 1); - int i = size; - while (i--) { - *(array_pt--) *= f; - } + double *array_pt = array_tar + (size - 1); + int i = size; + while (i--) { + *(array_pt--) *= f; + } } /** \} */ diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index f22b2a7a457..865c2f5dc25 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -33,508 +33,507 @@ MINLINE void zero_v2(float r[2]) { - r[0] = 0.0f; - r[1] = 0.0f; + r[0] = 0.0f; + r[1] = 0.0f; } MINLINE void zero_v3(float r[3]) { - r[0] = 0.0f; - r[1] = 0.0f; - r[2] = 0.0f; + r[0] = 0.0f; + r[1] = 0.0f; + r[2] = 0.0f; } MINLINE void zero_v4(float r[4]) { - r[0] = 0.0f; - r[1] = 0.0f; - r[2] = 0.0f; - r[3] = 0.0f; + r[0] = 0.0f; + r[1] = 0.0f; + r[2] = 0.0f; + r[3] = 0.0f; } MINLINE void copy_v2_v2(float r[2], const float a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3(float r[3], const float a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v3fl_v3s(float r[3], const short a[3]) { - r[0] = (float)a[0]; - r[1] = (float)a[1]; - r[2] = (float)a[2]; + r[0] = (float)a[0]; + r[1] = (float)a[1]; + r[2] = (float)a[2]; } MINLINE void copy_v4_v4(float r[4], const float a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } MINLINE void copy_v2_fl(float r[2], float f) { - r[0] = f; - r[1] = f; + r[0] = f; + r[1] = f; } MINLINE void copy_v3_fl(float r[3], float f) { - r[0] = f; - r[1] = f; - r[2] = f; + r[0] = f; + r[1] = f; + r[2] = f; } MINLINE void copy_v4_fl(float r[4], float f) { - r[0] = f; - r[1] = f; - r[2] = f; - r[3] = f; + r[0] = f; + r[1] = f; + r[2] = f; + r[3] = f; } /* unsigned char */ MINLINE void copy_v2_v2_uchar(unsigned char r[2], const unsigned char a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } /* char */ MINLINE void copy_v2_v2_char(char r[2], const char a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3_char(char r[3], const char a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v4_v4_char(char r[4], const char a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } /* short */ MINLINE void copy_v2_v2_short(short r[2], const short a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3_short(short r[3], const short a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v4_v4_short(short r[4], const short a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } /* int */ MINLINE void zero_v3_int(int r[3]) { - r[0] = 0; - r[1] = 0; - r[2] = 0; + r[0] = 0; + r[1] = 0; + r[2] = 0; } MINLINE void copy_v2_v2_int(int r[2], const int a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3_int(int r[3], const int a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v4_v4_int(int r[4], const int a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } /* double */ MINLINE void zero_v3_db(double r[3]) { - r[0] = 0.0; - r[1] = 0.0; - r[2] = 0.0; + r[0] = 0.0; + r[1] = 0.0; + r[2] = 0.0; } MINLINE void copy_v2_v2_db(double r[2], const double a[2]) { - r[0] = a[0]; - r[1] = a[1]; + r[0] = a[0]; + r[1] = a[1]; } MINLINE void copy_v3_v3_db(double r[3], const double a[3]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; } MINLINE void copy_v4_v4_db(double r[4], const double a[4]) { - r[0] = a[0]; - r[1] = a[1]; - r[2] = a[2]; - r[3] = a[3]; + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; } /* int <-> float */ MINLINE void round_v2i_v2fl(int r[2], const float a[2]) { - r[0] = (int)roundf(a[0]); - r[1] = (int)roundf(a[1]); + r[0] = (int)roundf(a[0]); + r[1] = (int)roundf(a[1]); } MINLINE void copy_v2fl_v2i(float r[2], const int a[2]) { - r[0] = (float)a[0]; - r[1] = (float)a[1]; + r[0] = (float)a[0]; + r[1] = (float)a[1]; } /* double -> float */ MINLINE void copy_v2fl_v2db(float r[2], const double a[2]) { - r[0] = (float)a[0]; - r[1] = (float)a[1]; + r[0] = (float)a[0]; + r[1] = (float)a[1]; } MINLINE void copy_v3fl_v3db(float r[3], const double a[3]) { - r[0] = (float)a[0]; - r[1] = (float)a[1]; - r[2] = (float)a[2]; + r[0] = (float)a[0]; + r[1] = (float)a[1]; + r[2] = (float)a[2]; } MINLINE void copy_v4fl_v4db(float r[4], const double a[4]) { - r[0] = (float)a[0]; - r[1] = (float)a[1]; - r[2] = (float)a[2]; - r[3] = (float)a[3]; + r[0] = (float)a[0]; + r[1] = (float)a[1]; + r[2] = (float)a[2]; + r[3] = (float)a[3]; } /* float -> double */ MINLINE void copy_v2db_v2fl(double r[2], const float a[2]) { - r[0] = (double)a[0]; - r[1] = (double)a[1]; + r[0] = (double)a[0]; + r[1] = (double)a[1]; } MINLINE void copy_v3db_v3fl(double r[3], const float a[3]) { - r[0] = (double)a[0]; - r[1] = (double)a[1]; - r[2] = (double)a[2]; + r[0] = (double)a[0]; + r[1] = (double)a[1]; + r[2] = (double)a[2]; } MINLINE void copy_v4db_v4fl(double r[4], const float a[4]) { - r[0] = (double)a[0]; - r[1] = (double)a[1]; - r[2] = (double)a[2]; - r[3] = (double)a[3]; + r[0] = (double)a[0]; + r[1] = (double)a[1]; + r[2] = (double)a[2]; + r[3] = (double)a[3]; } MINLINE void swap_v2_v2(float a[2], float b[2]) { - SWAP(float, a[0], b[0]); - SWAP(float, a[1], b[1]); + SWAP(float, a[0], b[0]); + SWAP(float, a[1], b[1]); } MINLINE void swap_v3_v3(float a[3], float b[3]) { - SWAP(float, a[0], b[0]); - SWAP(float, a[1], b[1]); - SWAP(float, a[2], b[2]); + SWAP(float, a[0], b[0]); + SWAP(float, a[1], b[1]); + SWAP(float, a[2], b[2]); } MINLINE void swap_v4_v4(float a[4], float b[4]) { - SWAP(float, a[0], b[0]); - SWAP(float, a[1], b[1]); - SWAP(float, a[2], b[2]); - SWAP(float, a[3], b[3]); + SWAP(float, a[0], b[0]); + SWAP(float, a[1], b[1]); + SWAP(float, a[2], b[2]); + SWAP(float, a[3], b[3]); } /* float args -> vec */ MINLINE void copy_v2_fl2(float v[2], float x, float y) { - v[0] = x; - v[1] = y; + v[0] = x; + v[1] = y; } MINLINE void copy_v3_fl3(float v[3], float x, float y, float z) { - v[0] = x; - v[1] = y; - v[2] = z; + v[0] = x; + v[1] = y; + v[2] = z; } MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w) { - v[0] = x; - v[1] = y; - v[2] = z; - v[3] = w; + v[0] = x; + v[1] = y; + v[2] = z; + v[3] = w; } /********************************* Arithmetic ********************************/ MINLINE void add_v2_fl(float r[2], float f) { - r[0] += f; - r[1] += f; + r[0] += f; + r[1] += f; } - MINLINE void add_v3_fl(float r[3], float f) { - r[0] += f; - r[1] += f; - r[2] += f; + r[0] += f; + r[1] += f; + r[2] += f; } MINLINE void add_v4_fl(float r[4], float f) { - r[0] += f; - r[1] += f; - r[2] += f; - r[3] += f; + r[0] += f; + r[1] += f; + r[2] += f; + r[3] += f; } MINLINE void add_v2_v2(float r[2], const float a[2]) { - r[0] += a[0]; - r[1] += a[1]; + r[0] += a[0]; + r[1] += a[1]; } MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]) { - r[0] = a[0] + b[0]; - r[1] = a[1] + b[1]; + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; } MINLINE void add_v2_v2v2_int(int r[2], const int a[2], const int b[2]) { - r[0] = a[0] + b[0]; - r[1] = a[1] + b[1]; + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; } MINLINE void add_v3_v3(float r[3], const float a[3]) { - r[0] += a[0]; - r[1] += a[1]; - r[2] += a[2]; + r[0] += a[0]; + r[1] += a[1]; + r[2] += a[2]; } MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3]) { - r[0] = a[0] + b[0]; - r[1] = a[1] + b[1]; - r[2] = a[2] + b[2]; + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; } MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3]) { - r[0] = a[0] + (float)b[0]; - r[1] = a[1] + (float)b[1]; - r[2] = a[2] + (float)b[2]; + r[0] = a[0] + (float)b[0]; + r[1] = a[1] + (float)b[1]; + r[2] = a[2] + (float)b[2]; } MINLINE void add_v3fl_v3fl_v3s(float r[3], const float a[3], const short b[3]) { - r[0] = a[0] + (float)b[0]; - r[1] = a[1] + (float)b[1]; - r[2] = a[2] + (float)b[2]; + r[0] = a[0] + (float)b[0]; + r[1] = a[1] + (float)b[1]; + r[2] = a[2] + (float)b[2]; } MINLINE void add_v4_v4(float r[4], const float a[4]) { - r[0] += a[0]; - r[1] += a[1]; - r[2] += a[2]; - r[3] += a[3]; + r[0] += a[0]; + r[1] += a[1]; + r[2] += a[2]; + r[3] += a[3]; } MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]) { - r[0] = a[0] + b[0]; - r[1] = a[1] + b[1]; - r[2] = a[2] + b[2]; - r[3] = a[3] + b[3]; + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; + r[3] = a[3] + b[3]; } MINLINE void sub_v2_v2(float r[2], const float a[2]) { - r[0] -= a[0]; - r[1] -= a[1]; + r[0] -= a[0]; + r[1] -= a[1]; } MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]) { - r[0] = a[0] - b[0]; - r[1] = a[1] - b[1]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; } MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2]) { - r[0] = a[0] - b[0]; - r[1] = a[1] - b[1]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; } MINLINE void sub_v3_v3(float r[3], const float a[3]) { - r[0] -= a[0]; - r[1] -= a[1]; - r[2] -= a[2]; + r[0] -= a[0]; + r[1] -= a[1]; + r[2] -= a[2]; } MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3]) { - r[0] = a[0] - b[0]; - r[1] = a[1] - b[1]; - r[2] = a[2] - b[2]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; } MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3]) { - r[0] = a[0] - b[0]; - r[1] = a[1] - b[1]; - r[2] = a[2] - b[2]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; } MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3]) { - r[0] = (double)a[0] - (double)b[0]; - r[1] = (double)a[1] - (double)b[1]; - r[2] = (double)a[2] - (double)b[2]; + r[0] = (double)a[0] - (double)b[0]; + r[1] = (double)a[1] - (double)b[1]; + r[2] = (double)a[2] - (double)b[2]; } MINLINE void sub_v4_v4(float r[4], const float a[4]) { - r[0] -= a[0]; - r[1] -= a[1]; - r[2] -= a[2]; - r[3] -= a[3]; + r[0] -= a[0]; + r[1] -= a[1]; + r[2] -= a[2]; + r[3] -= a[3]; } MINLINE void sub_v4_v4v4(float r[4], const float a[4], const float b[4]) { - r[0] = a[0] - b[0]; - r[1] = a[1] - b[1]; - r[2] = a[2] - b[2]; - r[3] = a[3] - b[3]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; + r[3] = a[3] - b[3]; } MINLINE void mul_v2_fl(float r[2], float f) { - r[0] *= f; - r[1] *= f; + r[0] *= f; + r[1] *= f; } MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f) { - r[0] = a[0] * f; - r[1] = a[1] * f; + r[0] = a[0] * f; + r[1] = a[1] * f; } MINLINE void mul_v3_fl(float r[3], float f) { - r[0] *= f; - r[1] *= f; - r[2] *= f; + r[0] *= f; + r[1] *= f; + r[2] *= f; } MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f) { - r[0] = a[0] * f; - r[1] = a[1] * f; - r[2] = a[2] * f; + r[0] = a[0] * f; + r[1] = a[1] * f; + r[2] = a[2] * f; } MINLINE void mul_v2_v2(float r[2], const float a[2]) { - r[0] *= a[0]; - r[1] *= a[1]; + r[0] *= a[0]; + r[1] *= a[1]; } MINLINE void mul_v3_v3(float r[3], const float a[3]) { - r[0] *= a[0]; - r[1] *= a[1]; - r[2] *= a[2]; + r[0] *= a[0]; + r[1] *= a[1]; + r[2] *= a[2]; } MINLINE void mul_v4_fl(float r[4], float f) { - r[0] *= f; - r[1] *= f; - r[2] *= f; - r[3] *= f; + r[0] *= f; + r[1] *= f; + r[2] *= f; + r[3] *= f; } MINLINE void mul_v4_v4(float r[4], const float a[4]) { - r[0] *= a[0]; - r[1] *= a[1]; - r[2] *= a[2]; - r[3] *= a[3]; + r[0] *= a[0]; + r[1] *= a[1]; + r[2] *= a[2]; + r[3] *= a[3]; } MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f) { - r[0] = a[0] * f; - r[1] = a[1] * f; - r[2] = a[2] * f; - r[3] = a[3] * f; + r[0] = a[0] * f; + r[1] = a[1] * f; + r[2] = a[2] * f; + r[3] = a[3] * f; } /** @@ -548,18 +547,18 @@ MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f) MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]) { - BLI_assert(r != vec); + BLI_assert(r != vec); - r[0] = mat[0] * vec[0] + (+mat[1]) * vec[1]; - r[1] = mat[1] * vec[0] + (-mat[0]) * vec[1]; + r[0] = mat[0] * vec[0] + (+mat[1]) * vec[1]; + r[1] = mat[1] * vec[0] + (-mat[0]) * vec[1]; } MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]) { - BLI_assert(r != vec); + BLI_assert(r != vec); - r[0] = mat[0] * vec[0] + (-mat[1]) * vec[1]; - r[1] = mat[1] * vec[0] + (+mat[0]) * vec[1]; + r[0] = mat[0] * vec[0] + (-mat[1]) * vec[1]; + r[1] = mat[1] * vec[0] + (+mat[0]) * vec[1]; } /** @@ -576,9 +575,7 @@ MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]) */ MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) { - return (mat[0][3] * co[0]) + - (mat[1][3] * co[1]) + - (mat[2][3] * co[2]) + mat[3][3]; + return (mat[0][3] * co[0]) + (mat[1][3] * co[1]) + (mat[2][3] * co[2]) + mat[3][3]; } /** @@ -586,15 +583,15 @@ MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) */ MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) { - return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; + return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; } MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3]) { - return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; + return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; } MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) { - return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; + return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; } /** @@ -603,260 +600,263 @@ MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) */ MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) { - return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; + return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; } MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) { - return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; + return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; } MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) { - return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; + return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; } MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f) { - r[0] += a[0] * f; - r[1] += a[1] * f; + r[0] += a[0] * f; + r[1] += a[1] * f; } MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f) { - r[0] += a[0] * f; - r[1] += a[1] * f; - r[2] += a[2] * f; + r[0] += a[0] * f; + r[1] += a[1] * f; + r[2] += a[2] * f; } MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]) { - r[0] += a[0] * b[0]; - r[1] += a[1] * b[1]; - r[2] += a[2] * b[2]; + r[0] += a[0] * b[0]; + r[1] += a[1] * b[1]; + r[2] += a[2] * b[2]; } MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f) { - r[0] = a[0] + b[0] * f; - r[1] = a[1] + b[1] * f; + r[0] = a[0] + b[0] * f; + r[1] = a[1] + b[1] * f; } MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f) { - r[0] = a[0] + b[0] * f; - r[1] = a[1] + b[1] * f; - r[2] = a[2] + b[2] * f; + r[0] = a[0] + b[0] * f; + r[1] = a[1] + b[1] * f; + r[2] = a[2] + b[2] * f; } MINLINE void madd_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]) { - r[0] = a[0] + b[0] * c[0]; - r[1] = a[1] + b[1] * c[1]; - r[2] = a[2] + b[2] * c[2]; + r[0] = a[0] + b[0] * c[0]; + r[1] = a[1] + b[1] * c[1]; + r[2] = a[2] + b[2] * c[2]; } -MINLINE void madd_v3fl_v3fl_v3fl_v3i(float r[3], const float a[3], const float b[3], const int c[3]) +MINLINE void madd_v3fl_v3fl_v3fl_v3i(float r[3], + const float a[3], + const float b[3], + const int c[3]) { - r[0] = a[0] + b[0] * (float)c[0]; - r[1] = a[1] + b[1] * (float)c[1]; - r[2] = a[2] + b[2] * (float)c[2]; + r[0] = a[0] + b[0] * (float)c[0]; + r[1] = a[1] + b[1] * (float)c[1]; + r[2] = a[2] + b[2] * (float)c[2]; } MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f) { - r[0] += a[0] * f; - r[1] += a[1] * f; - r[2] += a[2] * f; - r[3] += a[3] * f; + r[0] += a[0] * f; + r[1] += a[1] * f; + r[2] += a[2] * f; + r[3] += a[3] * f; } MINLINE void madd_v4_v4v4(float r[4], const float a[4], const float b[4]) { - r[0] += a[0] * b[0]; - r[1] += a[1] * b[1]; - r[2] += a[2] * b[2]; - r[3] += a[3] * b[3]; + r[0] += a[0] * b[0]; + r[1] += a[1] * b[1]; + r[2] += a[2] * b[2]; + r[3] += a[3] * b[3]; } MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3]) { - r[0] = v1[0] * v2[0]; - r[1] = v1[1] * v2[1]; - r[2] = v1[2] * v2[2]; + r[0] = v1[0] * v2[0]; + r[1] = v1[1] * v2[1]; + r[2] = v1[2] * v2[2]; } MINLINE void mul_v2_v2v2(float r[2], const float a[2], const float b[2]) { - r[0] = a[0] * b[0]; - r[1] = a[1] * b[1]; + r[0] = a[0] * b[0]; + r[1] = a[1] * b[1]; } MINLINE void negate_v2(float r[2]) { - r[0] = -r[0]; - r[1] = -r[1]; + r[0] = -r[0]; + r[1] = -r[1]; } MINLINE void negate_v2_v2(float r[2], const float a[2]) { - r[0] = -a[0]; - r[1] = -a[1]; + r[0] = -a[0]; + r[1] = -a[1]; } MINLINE void negate_v3(float r[3]) { - r[0] = -r[0]; - r[1] = -r[1]; - r[2] = -r[2]; + r[0] = -r[0]; + r[1] = -r[1]; + r[2] = -r[2]; } MINLINE void negate_v3_v3(float r[3], const float a[3]) { - r[0] = -a[0]; - r[1] = -a[1]; - r[2] = -a[2]; + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; } MINLINE void negate_v4(float r[4]) { - r[0] = -r[0]; - r[1] = -r[1]; - r[2] = -r[2]; - r[3] = -r[3]; + r[0] = -r[0]; + r[1] = -r[1]; + r[2] = -r[2]; + r[3] = -r[3]; } MINLINE void negate_v4_v4(float r[4], const float a[4]) { - r[0] = -a[0]; - r[1] = -a[1]; - r[2] = -a[2]; - r[3] = -a[3]; + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; } /* could add more... */ MINLINE void negate_v3_short(short r[3]) { - r[0] = (short)-r[0]; - r[1] = (short)-r[1]; - r[2] = (short)-r[2]; + r[0] = (short)-r[0]; + r[1] = (short)-r[1]; + r[2] = (short)-r[2]; } MINLINE void negate_v3_db(double r[3]) { - r[0] = -r[0]; - r[1] = -r[1]; - r[2] = -r[2]; + r[0] = -r[0]; + r[1] = -r[1]; + r[2] = -r[2]; } MINLINE void invert_v2(float r[2]) { - BLI_assert(!ELEM(0.0f, r[0], r[1])); - r[0] = 1.0f / r[0]; - r[1] = 1.0f / r[1]; + BLI_assert(!ELEM(0.0f, r[0], r[1])); + r[0] = 1.0f / r[0]; + r[1] = 1.0f / r[1]; } MINLINE void invert_v3(float r[3]) { - BLI_assert(!ELEM(0.0f, r[0], r[1], r[2])); - r[0] = 1.0f / r[0]; - r[1] = 1.0f / r[1]; - r[2] = 1.0f / r[2]; + BLI_assert(!ELEM(0.0f, r[0], r[1], r[2])); + r[0] = 1.0f / r[0]; + r[1] = 1.0f / r[1]; + r[2] = 1.0f / r[2]; } MINLINE void abs_v2(float r[2]) { - r[0] = fabsf(r[0]); - r[1] = fabsf(r[1]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); } MINLINE void abs_v2_v2(float r[2], const float a[2]) { - r[0] = fabsf(a[0]); - r[1] = fabsf(a[1]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); } MINLINE void abs_v3(float r[3]) { - r[0] = fabsf(r[0]); - r[1] = fabsf(r[1]); - r[2] = fabsf(r[2]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); + r[2] = fabsf(r[2]); } MINLINE void abs_v3_v3(float r[3], const float a[3]) { - r[0] = fabsf(a[0]); - r[1] = fabsf(a[1]); - r[2] = fabsf(a[2]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); + r[2] = fabsf(a[2]); } MINLINE void abs_v4(float r[4]) { - r[0] = fabsf(r[0]); - r[1] = fabsf(r[1]); - r[2] = fabsf(r[2]); - r[3] = fabsf(r[3]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); + r[2] = fabsf(r[2]); + r[3] = fabsf(r[3]); } MINLINE void abs_v4_v4(float r[4], const float a[4]) { - r[0] = fabsf(a[0]); - r[1] = fabsf(a[1]); - r[2] = fabsf(a[2]); - r[3] = fabsf(a[3]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); + r[2] = fabsf(a[2]); + r[3] = fabsf(a[3]); } MINLINE float dot_v2v2(const float a[2], const float b[2]) { - return a[0] * b[0] + a[1] * b[1]; + return a[0] * b[0] + a[1] * b[1]; } MINLINE float dot_v3v3(const float a[3], const float b[3]) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3]) { - float vec1[3], vec2[3]; + float vec1[3], vec2[3]; - sub_v3_v3v3(vec1, a, p); - sub_v3_v3v3(vec2, b, p); - if (is_zero_v3(vec1) || is_zero_v3(vec2)) { - return 0.0f; - } - return dot_v3v3(vec1, vec2); + sub_v3_v3v3(vec1, a, p); + sub_v3_v3v3(vec2, b, p); + if (is_zero_v3(vec1) || is_zero_v3(vec2)) { + return 0.0f; + } + return dot_v3v3(vec1, vec2); } MINLINE float dot_v4v4(const float a[4], const float b[4]) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; } MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) { - return a[0] * (double)b[0] + a[1] * (double)b[1] + a[2] * (double)b[2]; + return a[0] * (double)b[0] + a[1] * (double)b[1] + a[2] * (double)b[2]; } MINLINE float cross_v2v2(const float a[2], const float b[2]) { - return a[0] * b[1] - a[1] * b[0]; + return a[0] * b[1] - a[1] * b[0]; } MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]) { - BLI_assert(r != a && r != b); - r[0] = a[1] * b[2] - a[2] * b[1]; - r[1] = a[2] * b[0] - a[0] * b[2]; - r[2] = a[0] * b[1] - a[1] * b[0]; + BLI_assert(r != a && r != b); + r[0] = a[1] * b[2] - a[2] * b[1]; + r[1] = a[2] * b[0] - a[0] * b[2]; + r[2] = a[0] * b[1] - a[1] * b[0]; } /* cross product suffers from severe precision loss when vectors are * nearly parallel or opposite; doing the computation in double helps a lot */ MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3]) { - BLI_assert(r != a && r != b); - r[0] = (float)((double)a[1] * (double)b[2] - (double)a[2] * (double)b[1]); - r[1] = (float)((double)a[2] * (double)b[0] - (double)a[0] * (double)b[2]); - r[2] = (float)((double)a[0] * (double)b[1] - (double)a[1] * (double)b[0]); + BLI_assert(r != a && r != b); + r[0] = (float)((double)a[1] * (double)b[2] - (double)a[2] * (double)b[1]); + r[1] = (float)((double)a[2] * (double)b[0] - (double)a[0] * (double)b[2]); + r[2] = (float)((double)a[0] * (double)b[1] - (double)a[1] * (double)b[0]); } /* Newell's Method */ @@ -865,276 +865,273 @@ MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3 * could use a better name */ MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]) { - n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); - n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); - n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); + n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); + n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); + n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); } MINLINE void star_m3_v3(float rmat[3][3], float a[3]) { - rmat[0][0] = rmat[1][1] = rmat[2][2] = 0.0; - rmat[0][1] = -a[2]; - rmat[0][2] = a[1]; - rmat[1][0] = a[2]; - rmat[1][2] = -a[0]; - rmat[2][0] = -a[1]; - rmat[2][1] = a[0]; + rmat[0][0] = rmat[1][1] = rmat[2][2] = 0.0; + rmat[0][1] = -a[2]; + rmat[0][2] = a[1]; + rmat[1][0] = a[2]; + rmat[1][2] = -a[0]; + rmat[2][0] = -a[1]; + rmat[2][1] = a[0]; } /*********************************** Length **********************************/ MINLINE float len_squared_v2(const float v[2]) { - return v[0] * v[0] + v[1] * v[1]; + return v[0] * v[0] + v[1] * v[1]; } MINLINE float len_squared_v3(const float v[3]) { - return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; } MINLINE float len_manhattan_v2(const float v[2]) { - return fabsf(v[0]) + fabsf(v[1]); + return fabsf(v[0]) + fabsf(v[1]); } MINLINE int len_manhattan_v2_int(const int v[2]) { - return abs(v[0]) + abs(v[1]); + return abs(v[0]) + abs(v[1]); } MINLINE float len_manhattan_v3(const float v[3]) { - return fabsf(v[0]) + fabsf(v[1]) + fabsf(v[2]); + return fabsf(v[0]) + fabsf(v[1]) + fabsf(v[2]); } MINLINE float len_v2(const float v[2]) { - return sqrtf(v[0] * v[0] + v[1] * v[1]); + return sqrtf(v[0] * v[0] + v[1] * v[1]); } MINLINE float len_v2v2(const float v1[2], const float v2[2]) { - float x, y; + float x, y; - x = v1[0] - v2[0]; - y = v1[1] - v2[1]; - return sqrtf(x * x + y * y); + x = v1[0] - v2[0]; + y = v1[1] - v2[1]; + return sqrtf(x * x + y * y); } MINLINE float len_v2v2_int(const int v1[2], const int v2[2]) { - float x, y; + float x, y; - x = (float)(v1[0] - v2[0]); - y = (float)(v1[1] - v2[1]); - return sqrtf(x * x + y * y); + x = (float)(v1[0] - v2[0]); + y = (float)(v1[1] - v2[1]); + return sqrtf(x * x + y * y); } MINLINE float len_v3(const float a[3]) { - return sqrtf(dot_v3v3(a, a)); + return sqrtf(dot_v3v3(a, a)); } MINLINE float len_squared_v2v2(const float a[2], const float b[2]) { - float d[2]; + float d[2]; - sub_v2_v2v2(d, b, a); - return dot_v2v2(d, d); + sub_v2_v2v2(d, b, a); + return dot_v2v2(d, d); } MINLINE float len_squared_v3v3(const float a[3], const float b[3]) { - float d[3]; + float d[3]; - sub_v3_v3v3(d, b, a); - return dot_v3v3(d, d); + sub_v3_v3v3(d, b, a); + return dot_v3v3(d, d); } MINLINE float len_squared_v4v4(const float a[4], const float b[4]) { - float d[4]; + float d[4]; - sub_v4_v4v4(d, b, a); - return dot_v4v4(d, d); + sub_v4_v4v4(d, b, a); + return dot_v4v4(d, d); } MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) { - float d[2]; + float d[2]; - sub_v2_v2v2(d, b, a); - return len_manhattan_v2(d); + sub_v2_v2v2(d, b, a); + return len_manhattan_v2(d); } MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) { - int d[2]; + int d[2]; - sub_v2_v2v2_int(d, b, a); - return len_manhattan_v2_int(d); + sub_v2_v2v2_int(d, b, a); + return len_manhattan_v2_int(d); } MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) { - float d[3]; + float d[3]; - sub_v3_v3v3(d, b, a); - return len_manhattan_v3(d); + sub_v3_v3v3(d, b, a); + return len_manhattan_v3(d); } MINLINE float len_v3v3(const float a[3], const float b[3]) { - float d[3]; + float d[3]; - sub_v3_v3v3(d, b, a); - return len_v3(d); + sub_v3_v3v3(d, b, a); + return len_v3(d); } MINLINE float normalize_v2_v2_length(float r[2], const float a[2], const float unit_length) { - float d = dot_v2v2(a, a); + float d = dot_v2v2(a, a); - if (d > 1.0e-35f) { - d = sqrtf(d); - mul_v2_v2fl(r, a, unit_length / d); - } - else { - zero_v2(r); - d = 0.0f; - } + if (d > 1.0e-35f) { + d = sqrtf(d); + mul_v2_v2fl(r, a, unit_length / d); + } + else { + zero_v2(r); + d = 0.0f; + } - return d; + return d; } MINLINE float normalize_v2_v2(float r[2], const float a[2]) { - return normalize_v2_v2_length(r, a, 1.0f); + return normalize_v2_v2_length(r, a, 1.0f); } MINLINE float normalize_v2(float n[2]) { - return normalize_v2_v2(n, n); + return normalize_v2_v2(n, n); } MINLINE float normalize_v2_length(float n[2], const float unit_length) { - return normalize_v2_v2_length(n, n, unit_length); + return normalize_v2_v2_length(n, n, unit_length); } MINLINE float normalize_v3_v3_length(float r[3], const float a[3], const float unit_length) { - float d = dot_v3v3(a, a); + float d = dot_v3v3(a, a); - /* a larger value causes normalize errors in a - * scaled down models with camera extreme close */ - if (d > 1.0e-35f) { - d = sqrtf(d); - mul_v3_v3fl(r, a, unit_length / d); - } - else { - zero_v3(r); - d = 0.0f; - } + /* a larger value causes normalize errors in a + * scaled down models with camera extreme close */ + if (d > 1.0e-35f) { + d = sqrtf(d); + mul_v3_v3fl(r, a, unit_length / d); + } + else { + zero_v3(r); + d = 0.0f; + } - return d; + return d; } MINLINE float normalize_v3_v3(float r[3], const float a[3]) { - return normalize_v3_v3_length(r, a, 1.0f); + return normalize_v3_v3_length(r, a, 1.0f); } MINLINE double normalize_v3_length_d(double n[3], const double unit_length) { - double d = n[0] * n[0] + n[1] * n[1] + n[2] * n[2]; + double d = n[0] * n[0] + n[1] * n[1] + n[2] * n[2]; - /* a larger value causes normalize errors in a - * scaled down models with camera extreme close */ - if (d > 1.0e-35) { - double mul; + /* a larger value causes normalize errors in a + * scaled down models with camera extreme close */ + if (d > 1.0e-35) { + double mul; - d = sqrt(d); - mul = unit_length / d; + d = sqrt(d); + mul = unit_length / d; - n[0] *= mul; - n[1] *= mul; - n[2] *= mul; - } - else { - n[0] = n[1] = n[2] = 0; - d = 0.0; - } + n[0] *= mul; + n[1] *= mul; + n[2] *= mul; + } + else { + n[0] = n[1] = n[2] = 0; + d = 0.0; + } - return d; + return d; } MINLINE double normalize_v3_d(double n[3]) { - return normalize_v3_length_d(n, 1.0); + return normalize_v3_length_d(n, 1.0); } MINLINE float normalize_v3_length(float n[3], const float unit_length) { - return normalize_v3_v3_length(n, n, unit_length); + return normalize_v3_v3_length(n, n, unit_length); } MINLINE float normalize_v3(float n[3]) { - return normalize_v3_v3(n, n); + return normalize_v3_v3(n, n); } MINLINE void normal_float_to_short_v2(short out[2], const float in[2]) { - out[0] = (short) (in[0] * 32767.0f); - out[1] = (short) (in[1] * 32767.0f); + out[0] = (short)(in[0] * 32767.0f); + out[1] = (short)(in[1] * 32767.0f); } MINLINE void normal_short_to_float_v3(float out[3], const short in[3]) { - out[0] = in[0] * (1.0f / 32767.0f); - out[1] = in[1] * (1.0f / 32767.0f); - out[2] = in[2] * (1.0f / 32767.0f); + out[0] = in[0] * (1.0f / 32767.0f); + out[1] = in[1] * (1.0f / 32767.0f); + out[2] = in[2] * (1.0f / 32767.0f); } MINLINE void normal_float_to_short_v3(short out[3], const float in[3]) { - out[0] = (short) (in[0] * 32767.0f); - out[1] = (short) (in[1] * 32767.0f); - out[2] = (short) (in[2] * 32767.0f); + out[0] = (short)(in[0] * 32767.0f); + out[1] = (short)(in[1] * 32767.0f); + out[2] = (short)(in[2] * 32767.0f); } MINLINE void normal_float_to_short_v4(short out[4], const float in[4]) { - out[0] = (short) (in[0] * 32767.0f); - out[1] = (short) (in[1] * 32767.0f); - out[2] = (short) (in[2] * 32767.0f); - out[3] = (short) (in[3] * 32767.0f); + out[0] = (short)(in[0] * 32767.0f); + out[1] = (short)(in[1] * 32767.0f); + out[2] = (short)(in[2] * 32767.0f); + out[3] = (short)(in[3] * 32767.0f); } - /********************************* Comparison ********************************/ - MINLINE bool is_zero_v2(const float v[2]) { - return (v[0] == 0.0f && v[1] == 0.0f); + return (v[0] == 0.0f && v[1] == 0.0f); } MINLINE bool is_zero_v3(const float v[3]) { - return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f); + return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f); } MINLINE bool is_zero_v4(const float v[4]) { - return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f && v[3] == 0.0f); + return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f && v[3] == 0.0f); } MINLINE bool is_one_v3(const float v[3]) { - return (v[0] == 1.0f && v[1] == 1.0f && v[2] == 1.0f); + return (v[0] == 1.0f && v[1] == 1.0f && v[2] == 1.0f); } - /** \name Vector Comparison * * \note use ``value <= limit``, so a limit of zero doesn't fail on an exact match. @@ -1142,67 +1139,71 @@ MINLINE bool is_one_v3(const float v[3]) MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) { - return ((v1[0] == v2[0]) && (v1[1] == v2[1])); + return ((v1[0] == v2[0]) && (v1[1] == v2[1])); } MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) { - return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2])); + return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2])); } MINLINE bool equals_v4v4(const float v1[4], const float v2[4]) { - return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3])); + return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3])); } MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit) { - return (compare_ff(v1[0], v2[0], limit) && - compare_ff(v1[1], v2[1], limit)); + return (compare_ff(v1[0], v2[0], limit) && compare_ff(v1[1], v2[1], limit)); } MINLINE bool compare_v3v3(const float v1[3], const float v2[3], const float limit) { - return (compare_ff(v1[0], v2[0], limit) && - compare_ff(v1[1], v2[1], limit) && - compare_ff(v1[2], v2[2], limit)); + return (compare_ff(v1[0], v2[0], limit) && compare_ff(v1[1], v2[1], limit) && + compare_ff(v1[2], v2[2], limit)); } MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit) { - return (compare_ff(v1[0], v2[0], limit) && - compare_ff(v1[1], v2[1], limit) && - compare_ff(v1[2], v2[2], limit) && - compare_ff(v1[3], v2[3], limit)); + return (compare_ff(v1[0], v2[0], limit) && compare_ff(v1[1], v2[1], limit) && + compare_ff(v1[2], v2[2], limit) && compare_ff(v1[3], v2[3], limit)); } -MINLINE bool compare_v2v2_relative(const float v1[2], const float v2[2], const float limit, const int max_ulps) +MINLINE bool compare_v2v2_relative(const float v1[2], + const float v2[2], + const float limit, + const int max_ulps) { - return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && - compare_ff_relative(v1[1], v2[1], limit, max_ulps)); + return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && + compare_ff_relative(v1[1], v2[1], limit, max_ulps)); } -MINLINE bool compare_v3v3_relative(const float v1[3], const float v2[3], const float limit, const int max_ulps) +MINLINE bool compare_v3v3_relative(const float v1[3], + const float v2[3], + const float limit, + const int max_ulps) { - return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && - compare_ff_relative(v1[1], v2[1], limit, max_ulps) && - compare_ff_relative(v1[2], v2[2], limit, max_ulps)); + return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && + compare_ff_relative(v1[1], v2[1], limit, max_ulps) && + compare_ff_relative(v1[2], v2[2], limit, max_ulps)); } -MINLINE bool compare_v4v4_relative(const float v1[4], const float v2[4], const float limit, const int max_ulps) +MINLINE bool compare_v4v4_relative(const float v1[4], + const float v2[4], + const float limit, + const int max_ulps) { - return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && - compare_ff_relative(v1[1], v2[1], limit, max_ulps) && - compare_ff_relative(v1[2], v2[2], limit, max_ulps) && - compare_ff_relative(v1[3], v2[3], limit, max_ulps)); + return (compare_ff_relative(v1[0], v2[0], limit, max_ulps) && + compare_ff_relative(v1[1], v2[1], limit, max_ulps) && + compare_ff_relative(v1[2], v2[2], limit, max_ulps) && + compare_ff_relative(v1[3], v2[3], limit, max_ulps)); } - MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float limit) { - float d[3]; - sub_v3_v3v3(d, v1, v2); - return (dot_v3v3(d, d) <= (limit * limit)); + float d[3]; + sub_v3_v3v3(d, v1, v2); + return (dot_v3v3(d, d) <= (limit * limit)); } /** @@ -1219,8 +1220,7 @@ MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float */ MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) { - return (((l1[0] - pt[0]) * (l2[1] - pt[1])) - - ((l2[0] - pt[0]) * (l1[1] - pt[1]))); + return (((l1[0] - pt[0]) * (l2[1] - pt[1])) - ((l2[0] - pt[0]) * (l1[1] - pt[1]))); } /** \} */ diff --git a/source/blender/blenlib/intern/memory_utils.c b/source/blender/blenlib/intern/memory_utils.c index b0cfe709be8..91e75861dde 100644 --- a/source/blender/blenlib/intern/memory_utils.c +++ b/source/blender/blenlib/intern/memory_utils.c @@ -35,12 +35,12 @@ */ bool BLI_memory_is_zero(const void *s, const size_t nbytes) { - const char *s_byte = s; - const char *s_end = (const char *)s + nbytes; + const char *s_byte = s; + const char *s_end = (const char *)s + nbytes; - while ((s_byte != s_end) && (*s_byte == 0)) { - s_byte++; - } + while ((s_byte != s_end) && (*s_byte == 0)) { + s_byte++; + } - return (s_byte == s_end); + return (s_byte == s_end); } diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 241c5ec954c..2fbf64e1200 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -34,224 +34,230 @@ static float noise3_perlin(float vec[3]); // #define HASHVEC(x, y, z) hashvectf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] /* needed for voronoi */ -#define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] +#define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z)&255] + (y)) & 255] + (x)) & 255] static const float hashpntf[768] = { - 0.536902, 0.020915, 0.501445, 0.216316, 0.517036, 0.822466, 0.965315, - 0.377313, 0.678764, 0.744545, 0.097731, 0.396357, 0.247202, 0.520897, - 0.613396, 0.542124, 0.146813, 0.255489, 0.810868, 0.638641, 0.980742, - 0.292316, 0.357948, 0.114382, 0.861377, 0.629634, 0.722530, 0.714103, - 0.048549, 0.075668, 0.564920, 0.162026, 0.054466, 0.411738, 0.156897, - 0.887657, 0.599368, 0.074249, 0.170277, 0.225799, 0.393154, 0.301348, - 0.057434, 0.293849, 0.442745, 0.150002, 0.398732, 0.184582, 0.915200, - 0.630984, 0.974040, 0.117228, 0.795520, 0.763238, 0.158982, 0.616211, - 0.250825, 0.906539, 0.316874, 0.676205, 0.234720, 0.667673, 0.792225, - 0.273671, 0.119363, 0.199131, 0.856716, 0.828554, 0.900718, 0.705960, - 0.635923, 0.989433, 0.027261, 0.283507, 0.113426, 0.388115, 0.900176, - 0.637741, 0.438802, 0.715490, 0.043692, 0.202640, 0.378325, 0.450325, - 0.471832, 0.147803, 0.906899, 0.524178, 0.784981, 0.051483, 0.893369, - 0.596895, 0.275635, 0.391483, 0.844673, 0.103061, 0.257322, 0.708390, - 0.504091, 0.199517, 0.660339, 0.376071, 0.038880, 0.531293, 0.216116, - 0.138672, 0.907737, 0.807994, 0.659582, 0.915264, 0.449075, 0.627128, - 0.480173, 0.380942, 0.018843, 0.211808, 0.569701, 0.082294, 0.689488, - 0.573060, 0.593859, 0.216080, 0.373159, 0.108117, 0.595539, 0.021768, - 0.380297, 0.948125, 0.377833, 0.319699, 0.315249, 0.972805, 0.792270, - 0.445396, 0.845323, 0.372186, 0.096147, 0.689405, 0.423958, 0.055675, - 0.117940, 0.328456, 0.605808, 0.631768, 0.372170, 0.213723, 0.032700, - 0.447257, 0.440661, 0.728488, 0.299853, 0.148599, 0.649212, 0.498381, - 0.049921, 0.496112, 0.607142, 0.562595, 0.990246, 0.739659, 0.108633, - 0.978156, 0.209814, 0.258436, 0.876021, 0.309260, 0.600673, 0.713597, - 0.576967, 0.641402, 0.853930, 0.029173, 0.418111, 0.581593, 0.008394, - 0.589904, 0.661574, 0.979326, 0.275724, 0.111109, 0.440472, 0.120839, - 0.521602, 0.648308, 0.284575, 0.204501, 0.153286, 0.822444, 0.300786, - 0.303906, 0.364717, 0.209038, 0.916831, 0.900245, 0.600685, 0.890002, - 0.581660, 0.431154, 0.705569, 0.551250, 0.417075, 0.403749, 0.696652, - 0.292652, 0.911372, 0.690922, 0.323718, 0.036773, 0.258976, 0.274265, - 0.225076, 0.628965, 0.351644, 0.065158, 0.080340, 0.467271, 0.130643, - 0.385914, 0.919315, 0.253821, 0.966163, 0.017439, 0.392610, 0.478792, - 0.978185, 0.072691, 0.982009, 0.097987, 0.731533, 0.401233, 0.107570, - 0.349587, 0.479122, 0.700598, 0.481751, 0.788429, 0.706864, 0.120086, - 0.562691, 0.981797, 0.001223, 0.192120, 0.451543, 0.173092, 0.108960, - 0.549594, 0.587892, 0.657534, 0.396365, 0.125153, 0.666420, 0.385823, - 0.890916, 0.436729, 0.128114, 0.369598, 0.759096, 0.044677, 0.904752, - 0.088052, 0.621148, 0.005047, 0.452331, 0.162032, 0.494238, 0.523349, - 0.741829, 0.698450, 0.452316, 0.563487, 0.819776, 0.492160, 0.004210, - 0.647158, 0.551475, 0.362995, 0.177937, 0.814722, 0.727729, 0.867126, - 0.997157, 0.108149, 0.085726, 0.796024, 0.665075, 0.362462, 0.323124, - 0.043718, 0.042357, 0.315030, 0.328954, 0.870845, 0.683186, 0.467922, - 0.514894, 0.809971, 0.631979, 0.176571, 0.366320, 0.850621, 0.505555, - 0.749551, 0.750830, 0.401714, 0.481216, 0.438393, 0.508832, 0.867971, - 0.654581, 0.058204, 0.566454, 0.084124, 0.548539, 0.902690, 0.779571, - 0.562058, 0.048082, 0.863109, 0.079290, 0.713559, 0.783496, 0.265266, - 0.672089, 0.786939, 0.143048, 0.086196, 0.876129, 0.408708, 0.229312, - 0.629995, 0.206665, 0.207308, 0.710079, 0.341704, 0.264921, 0.028748, - 0.629222, 0.470173, 0.726228, 0.125243, 0.328249, 0.794187, 0.741340, - 0.489895, 0.189396, 0.724654, 0.092841, 0.039809, 0.860126, 0.247701, - 0.655331, 0.964121, 0.672536, 0.044522, 0.690567, 0.837238, 0.631520, - 0.953734, 0.352484, 0.289026, 0.034152, 0.852575, 0.098454, 0.795529, - 0.452181, 0.826159, 0.186993, 0.820725, 0.440328, 0.922137, 0.704592, - 0.915437, 0.738183, 0.733461, 0.193798, 0.929213, 0.161390, 0.318547, - 0.888751, 0.430968, 0.740837, 0.193544, 0.872253, 0.563074, 0.274598, - 0.347805, 0.666176, 0.449831, 0.800991, 0.588727, 0.052296, 0.714761, - 0.420620, 0.570325, 0.057550, 0.210888, 0.407312, 0.662848, 0.924382, - 0.895958, 0.775198, 0.688605, 0.025721, 0.301913, 0.791408, 0.500602, - 0.831984, 0.828509, 0.642093, 0.494174, 0.525880, 0.446365, 0.440063, - 0.763114, 0.630358, 0.223943, 0.333806, 0.906033, 0.498306, 0.241278, - 0.427640, 0.772683, 0.198082, 0.225379, 0.503894, 0.436599, 0.016503, - 0.803725, 0.189878, 0.291095, 0.499114, 0.151573, 0.079031, 0.904618, - 0.708535, 0.273900, 0.067419, 0.317124, 0.936499, 0.716511, 0.543845, - 0.939909, 0.826574, 0.715090, 0.154864, 0.750150, 0.845808, 0.648108, - 0.556564, 0.644757, 0.140873, 0.799167, 0.632989, 0.444245, 0.471978, - 0.435910, 0.359793, 0.216241, 0.007633, 0.337236, 0.857863, 0.380247, - 0.092517, 0.799973, 0.919000, 0.296798, 0.096989, 0.854831, 0.165369, - 0.568475, 0.216855, 0.020457, 0.835511, 0.538039, 0.999742, 0.620226, - 0.244053, 0.060399, 0.323007, 0.294874, 0.988899, 0.384919, 0.735655, - 0.773428, 0.549776, 0.292882, 0.660611, 0.593507, 0.621118, 0.175269, - 0.682119, 0.794493, 0.868197, 0.632150, 0.807823, 0.509656, 0.482035, - 0.001780, 0.259126, 0.358002, 0.280263, 0.192985, 0.290367, 0.208111, - 0.917633, 0.114422, 0.925491, 0.981110, 0.255570, 0.974862, 0.016629, - 0.552599, 0.575741, 0.612978, 0.615965, 0.803615, 0.772334, 0.089745, - 0.838812, 0.634542, 0.113709, 0.755832, 0.577589, 0.667489, 0.529834, - 0.325660, 0.817597, 0.316557, 0.335093, 0.737363, 0.260951, 0.737073, - 0.049540, 0.735541, 0.988891, 0.299116, 0.147695, 0.417271, 0.940811, - 0.524160, 0.857968, 0.176403, 0.244835, 0.485759, 0.033353, 0.280319, - 0.750688, 0.755809, 0.924208, 0.095956, 0.962504, 0.275584, 0.173715, - 0.942716, 0.706721, 0.078464, 0.576716, 0.804667, 0.559249, 0.900611, - 0.646904, 0.432111, 0.927885, 0.383277, 0.269973, 0.114244, 0.574867, - 0.150703, 0.241855, 0.272871, 0.199950, 0.079719, 0.868566, 0.962833, - 0.789122, 0.320025, 0.905554, 0.234876, 0.991356, 0.061913, 0.732911, - 0.785960, 0.874074, 0.069035, 0.658632, 0.309901, 0.023676, 0.791603, - 0.764661, 0.661278, 0.319583, 0.829650, 0.117091, 0.903124, 0.982098, - 0.161631, 0.193576, 0.670428, 0.857390, 0.003760, 0.572578, 0.222162, - 0.114551, 0.420118, 0.530404, 0.470682, 0.525527, 0.764281, 0.040596, - 0.443275, 0.501124, 0.816161, 0.417467, 0.332172, 0.447565, 0.614591, - 0.559246, 0.805295, 0.226342, 0.155065, 0.714630, 0.160925, 0.760001, - 0.453456, 0.093869, 0.406092, 0.264801, 0.720370, 0.743388, 0.373269, - 0.403098, 0.911923, 0.897249, 0.147038, 0.753037, 0.516093, 0.739257, - 0.175018, 0.045768, 0.735857, 0.801330, 0.927708, 0.240977, 0.591870, - 0.921831, 0.540733, 0.149100, 0.423152, 0.806876, 0.397081, 0.061100, - 0.811630, 0.044899, 0.460915, 0.961202, 0.822098, 0.971524, 0.867608, - 0.773604, 0.226616, 0.686286, 0.926972, 0.411613, 0.267873, 0.081937, - 0.226124, 0.295664, 0.374594, 0.533240, 0.237876, 0.669629, 0.599083, - 0.513081, 0.878719, 0.201577, 0.721296, 0.495038, 0.079760, 0.965959, - 0.233090, 0.052496, 0.714748, 0.887844, 0.308724, 0.972885, 0.723337, - 0.453089, 0.914474, 0.704063, 0.823198, 0.834769, 0.906561, 0.919600, - 0.100601, 0.307564, 0.901977, 0.468879, 0.265376, 0.885188, 0.683875, - 0.868623, 0.081032, 0.466835, 0.199087, 0.663437, 0.812241, 0.311337, - 0.821361, 0.356628, 0.898054, 0.160781, 0.222539, 0.714889, 0.490287, - 0.984915, 0.951755, 0.964097, 0.641795, 0.815472, 0.852732, 0.862074, - 0.051108, 0.440139, 0.323207, 0.517171, 0.562984, 0.115295, 0.743103, - 0.977914, 0.337596, 0.440694, 0.535879, 0.959427, 0.351427, 0.704361, - 0.010826, 0.131162, 0.577080, 0.349572, 0.774892, 0.425796, 0.072697, - 0.500001, 0.267322, 0.909654, 0.206176, 0.223987, 0.937698, 0.323423, - 0.117501, 0.490308, 0.474372, 0.689943, 0.168671, 0.719417, 0.188928, - 0.330464, 0.265273, 0.446271, 0.171933, 0.176133, 0.474616, 0.140182, - 0.114246, 0.905043, 0.713870, 0.555261, 0.951333, + 0.536902, 0.020915, 0.501445, 0.216316, 0.517036, 0.822466, 0.965315, 0.377313, 0.678764, + 0.744545, 0.097731, 0.396357, 0.247202, 0.520897, 0.613396, 0.542124, 0.146813, 0.255489, + 0.810868, 0.638641, 0.980742, 0.292316, 0.357948, 0.114382, 0.861377, 0.629634, 0.722530, + 0.714103, 0.048549, 0.075668, 0.564920, 0.162026, 0.054466, 0.411738, 0.156897, 0.887657, + 0.599368, 0.074249, 0.170277, 0.225799, 0.393154, 0.301348, 0.057434, 0.293849, 0.442745, + 0.150002, 0.398732, 0.184582, 0.915200, 0.630984, 0.974040, 0.117228, 0.795520, 0.763238, + 0.158982, 0.616211, 0.250825, 0.906539, 0.316874, 0.676205, 0.234720, 0.667673, 0.792225, + 0.273671, 0.119363, 0.199131, 0.856716, 0.828554, 0.900718, 0.705960, 0.635923, 0.989433, + 0.027261, 0.283507, 0.113426, 0.388115, 0.900176, 0.637741, 0.438802, 0.715490, 0.043692, + 0.202640, 0.378325, 0.450325, 0.471832, 0.147803, 0.906899, 0.524178, 0.784981, 0.051483, + 0.893369, 0.596895, 0.275635, 0.391483, 0.844673, 0.103061, 0.257322, 0.708390, 0.504091, + 0.199517, 0.660339, 0.376071, 0.038880, 0.531293, 0.216116, 0.138672, 0.907737, 0.807994, + 0.659582, 0.915264, 0.449075, 0.627128, 0.480173, 0.380942, 0.018843, 0.211808, 0.569701, + 0.082294, 0.689488, 0.573060, 0.593859, 0.216080, 0.373159, 0.108117, 0.595539, 0.021768, + 0.380297, 0.948125, 0.377833, 0.319699, 0.315249, 0.972805, 0.792270, 0.445396, 0.845323, + 0.372186, 0.096147, 0.689405, 0.423958, 0.055675, 0.117940, 0.328456, 0.605808, 0.631768, + 0.372170, 0.213723, 0.032700, 0.447257, 0.440661, 0.728488, 0.299853, 0.148599, 0.649212, + 0.498381, 0.049921, 0.496112, 0.607142, 0.562595, 0.990246, 0.739659, 0.108633, 0.978156, + 0.209814, 0.258436, 0.876021, 0.309260, 0.600673, 0.713597, 0.576967, 0.641402, 0.853930, + 0.029173, 0.418111, 0.581593, 0.008394, 0.589904, 0.661574, 0.979326, 0.275724, 0.111109, + 0.440472, 0.120839, 0.521602, 0.648308, 0.284575, 0.204501, 0.153286, 0.822444, 0.300786, + 0.303906, 0.364717, 0.209038, 0.916831, 0.900245, 0.600685, 0.890002, 0.581660, 0.431154, + 0.705569, 0.551250, 0.417075, 0.403749, 0.696652, 0.292652, 0.911372, 0.690922, 0.323718, + 0.036773, 0.258976, 0.274265, 0.225076, 0.628965, 0.351644, 0.065158, 0.080340, 0.467271, + 0.130643, 0.385914, 0.919315, 0.253821, 0.966163, 0.017439, 0.392610, 0.478792, 0.978185, + 0.072691, 0.982009, 0.097987, 0.731533, 0.401233, 0.107570, 0.349587, 0.479122, 0.700598, + 0.481751, 0.788429, 0.706864, 0.120086, 0.562691, 0.981797, 0.001223, 0.192120, 0.451543, + 0.173092, 0.108960, 0.549594, 0.587892, 0.657534, 0.396365, 0.125153, 0.666420, 0.385823, + 0.890916, 0.436729, 0.128114, 0.369598, 0.759096, 0.044677, 0.904752, 0.088052, 0.621148, + 0.005047, 0.452331, 0.162032, 0.494238, 0.523349, 0.741829, 0.698450, 0.452316, 0.563487, + 0.819776, 0.492160, 0.004210, 0.647158, 0.551475, 0.362995, 0.177937, 0.814722, 0.727729, + 0.867126, 0.997157, 0.108149, 0.085726, 0.796024, 0.665075, 0.362462, 0.323124, 0.043718, + 0.042357, 0.315030, 0.328954, 0.870845, 0.683186, 0.467922, 0.514894, 0.809971, 0.631979, + 0.176571, 0.366320, 0.850621, 0.505555, 0.749551, 0.750830, 0.401714, 0.481216, 0.438393, + 0.508832, 0.867971, 0.654581, 0.058204, 0.566454, 0.084124, 0.548539, 0.902690, 0.779571, + 0.562058, 0.048082, 0.863109, 0.079290, 0.713559, 0.783496, 0.265266, 0.672089, 0.786939, + 0.143048, 0.086196, 0.876129, 0.408708, 0.229312, 0.629995, 0.206665, 0.207308, 0.710079, + 0.341704, 0.264921, 0.028748, 0.629222, 0.470173, 0.726228, 0.125243, 0.328249, 0.794187, + 0.741340, 0.489895, 0.189396, 0.724654, 0.092841, 0.039809, 0.860126, 0.247701, 0.655331, + 0.964121, 0.672536, 0.044522, 0.690567, 0.837238, 0.631520, 0.953734, 0.352484, 0.289026, + 0.034152, 0.852575, 0.098454, 0.795529, 0.452181, 0.826159, 0.186993, 0.820725, 0.440328, + 0.922137, 0.704592, 0.915437, 0.738183, 0.733461, 0.193798, 0.929213, 0.161390, 0.318547, + 0.888751, 0.430968, 0.740837, 0.193544, 0.872253, 0.563074, 0.274598, 0.347805, 0.666176, + 0.449831, 0.800991, 0.588727, 0.052296, 0.714761, 0.420620, 0.570325, 0.057550, 0.210888, + 0.407312, 0.662848, 0.924382, 0.895958, 0.775198, 0.688605, 0.025721, 0.301913, 0.791408, + 0.500602, 0.831984, 0.828509, 0.642093, 0.494174, 0.525880, 0.446365, 0.440063, 0.763114, + 0.630358, 0.223943, 0.333806, 0.906033, 0.498306, 0.241278, 0.427640, 0.772683, 0.198082, + 0.225379, 0.503894, 0.436599, 0.016503, 0.803725, 0.189878, 0.291095, 0.499114, 0.151573, + 0.079031, 0.904618, 0.708535, 0.273900, 0.067419, 0.317124, 0.936499, 0.716511, 0.543845, + 0.939909, 0.826574, 0.715090, 0.154864, 0.750150, 0.845808, 0.648108, 0.556564, 0.644757, + 0.140873, 0.799167, 0.632989, 0.444245, 0.471978, 0.435910, 0.359793, 0.216241, 0.007633, + 0.337236, 0.857863, 0.380247, 0.092517, 0.799973, 0.919000, 0.296798, 0.096989, 0.854831, + 0.165369, 0.568475, 0.216855, 0.020457, 0.835511, 0.538039, 0.999742, 0.620226, 0.244053, + 0.060399, 0.323007, 0.294874, 0.988899, 0.384919, 0.735655, 0.773428, 0.549776, 0.292882, + 0.660611, 0.593507, 0.621118, 0.175269, 0.682119, 0.794493, 0.868197, 0.632150, 0.807823, + 0.509656, 0.482035, 0.001780, 0.259126, 0.358002, 0.280263, 0.192985, 0.290367, 0.208111, + 0.917633, 0.114422, 0.925491, 0.981110, 0.255570, 0.974862, 0.016629, 0.552599, 0.575741, + 0.612978, 0.615965, 0.803615, 0.772334, 0.089745, 0.838812, 0.634542, 0.113709, 0.755832, + 0.577589, 0.667489, 0.529834, 0.325660, 0.817597, 0.316557, 0.335093, 0.737363, 0.260951, + 0.737073, 0.049540, 0.735541, 0.988891, 0.299116, 0.147695, 0.417271, 0.940811, 0.524160, + 0.857968, 0.176403, 0.244835, 0.485759, 0.033353, 0.280319, 0.750688, 0.755809, 0.924208, + 0.095956, 0.962504, 0.275584, 0.173715, 0.942716, 0.706721, 0.078464, 0.576716, 0.804667, + 0.559249, 0.900611, 0.646904, 0.432111, 0.927885, 0.383277, 0.269973, 0.114244, 0.574867, + 0.150703, 0.241855, 0.272871, 0.199950, 0.079719, 0.868566, 0.962833, 0.789122, 0.320025, + 0.905554, 0.234876, 0.991356, 0.061913, 0.732911, 0.785960, 0.874074, 0.069035, 0.658632, + 0.309901, 0.023676, 0.791603, 0.764661, 0.661278, 0.319583, 0.829650, 0.117091, 0.903124, + 0.982098, 0.161631, 0.193576, 0.670428, 0.857390, 0.003760, 0.572578, 0.222162, 0.114551, + 0.420118, 0.530404, 0.470682, 0.525527, 0.764281, 0.040596, 0.443275, 0.501124, 0.816161, + 0.417467, 0.332172, 0.447565, 0.614591, 0.559246, 0.805295, 0.226342, 0.155065, 0.714630, + 0.160925, 0.760001, 0.453456, 0.093869, 0.406092, 0.264801, 0.720370, 0.743388, 0.373269, + 0.403098, 0.911923, 0.897249, 0.147038, 0.753037, 0.516093, 0.739257, 0.175018, 0.045768, + 0.735857, 0.801330, 0.927708, 0.240977, 0.591870, 0.921831, 0.540733, 0.149100, 0.423152, + 0.806876, 0.397081, 0.061100, 0.811630, 0.044899, 0.460915, 0.961202, 0.822098, 0.971524, + 0.867608, 0.773604, 0.226616, 0.686286, 0.926972, 0.411613, 0.267873, 0.081937, 0.226124, + 0.295664, 0.374594, 0.533240, 0.237876, 0.669629, 0.599083, 0.513081, 0.878719, 0.201577, + 0.721296, 0.495038, 0.079760, 0.965959, 0.233090, 0.052496, 0.714748, 0.887844, 0.308724, + 0.972885, 0.723337, 0.453089, 0.914474, 0.704063, 0.823198, 0.834769, 0.906561, 0.919600, + 0.100601, 0.307564, 0.901977, 0.468879, 0.265376, 0.885188, 0.683875, 0.868623, 0.081032, + 0.466835, 0.199087, 0.663437, 0.812241, 0.311337, 0.821361, 0.356628, 0.898054, 0.160781, + 0.222539, 0.714889, 0.490287, 0.984915, 0.951755, 0.964097, 0.641795, 0.815472, 0.852732, + 0.862074, 0.051108, 0.440139, 0.323207, 0.517171, 0.562984, 0.115295, 0.743103, 0.977914, + 0.337596, 0.440694, 0.535879, 0.959427, 0.351427, 0.704361, 0.010826, 0.131162, 0.577080, + 0.349572, 0.774892, 0.425796, 0.072697, 0.500001, 0.267322, 0.909654, 0.206176, 0.223987, + 0.937698, 0.323423, 0.117501, 0.490308, 0.474372, 0.689943, 0.168671, 0.719417, 0.188928, + 0.330464, 0.265273, 0.446271, 0.171933, 0.176133, 0.474616, 0.140182, 0.114246, 0.905043, + 0.713870, 0.555261, 0.951333, }; -extern const unsigned char BLI_noise_hash_uchar_512[512]; /* Quiet warning. */ +extern const unsigned char BLI_noise_hash_uchar_512[512]; /* Quiet warning. */ const unsigned char BLI_noise_hash_uchar_512[512] = { - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, - 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, - 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, - 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, - 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, - 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, - 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, 0x9, - 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, - 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, - 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, - 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, - 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, - 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, - 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, - 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, - 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, - 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, - 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, - 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, - 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, - 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, - 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, - 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, - 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, - 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, - 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, - 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, + 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, + 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, + 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, + 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, + 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, + 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, + 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, + 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, + 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, + 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, }; #define hash BLI_noise_hash_uchar_512 - static const float hashvectf[768] = { - 0.33783, 0.715698, -0.611206, -0.944031, -0.326599, -0.045624, -0.101074, -0.416443, -0.903503, 0.799286, 0.49411, - -0.341949, -0.854645, 0.518036, 0.033936, 0.42514, -0.437866, -0.792114, -0.358948, 0.597046, 0.717377, -0.985413, - 0.144714, 0.089294, -0.601776, -0.33728, -0.723907, -0.449921, 0.594513, 0.666382, 0.208313, -0.10791, 0.972076, - 0.575317, 0.060425, 0.815643, 0.293365, -0.875702, -0.383453, 0.293762, 0.465759, 0.834686, -0.846008, -0.233398, - -0.47934, -0.115814, 0.143036, -0.98291, 0.204681, -0.949036, -0.239532, 0.946716, -0.263947, 0.184326, -0.235596, - 0.573822, 0.784332, 0.203705, -0.372253, -0.905487, 0.756989, -0.651031, 0.055298, 0.497803, 0.814697, -0.297363, - -0.16214, 0.063995, -0.98468, -0.329254, 0.834381, 0.441925, 0.703827, -0.527039, -0.476227, 0.956421, 0.266113, - 0.119781, 0.480133, 0.482849, 0.7323, -0.18631, 0.961212, -0.203125, -0.748474, -0.656921, -0.090393, -0.085052, - -0.165253, 0.982544, -0.76947, 0.628174, -0.115234, 0.383148, 0.537659, 0.751068, 0.616486, -0.668488, -0.415924, - -0.259979, -0.630005, 0.73175, 0.570953, -0.087952, 0.816223, -0.458008, 0.023254, 0.888611, -0.196167, 0.976563, - -0.088287, -0.263885, -0.69812, -0.665527, 0.437134, -0.892273, -0.112793, -0.621674, -0.230438, 0.748566, 0.232422, - 0.900574, -0.367249, 0.22229, -0.796143, 0.562744, -0.665497, -0.73764, 0.11377, 0.670135, 0.704803, 0.232605, - 0.895599, 0.429749, -0.114655, -0.11557, -0.474243, 0.872742, 0.621826, 0.604004, -0.498444, -0.832214, 0.012756, - 0.55426, -0.702484, 0.705994, -0.089661, -0.692017, 0.649292, 0.315399, -0.175995, -0.977997, 0.111877, 0.096954, - -0.04953, 0.994019, 0.635284, -0.606689, -0.477783, -0.261261, -0.607422, -0.750153, 0.983276, 0.165436, 0.075958, - -0.29837, 0.404083, -0.864655, -0.638672, 0.507721, 0.578156, 0.388214, 0.412079, 0.824249, 0.556183, -0.208832, - 0.804352, 0.778442, 0.562012, 0.27951, -0.616577, 0.781921, -0.091522, 0.196289, 0.051056, 0.979187, -0.121216, - 0.207153, -0.970734, -0.173401, -0.384735, 0.906555, 0.161499, -0.723236, -0.671387, 0.178497, -0.006226, -0.983887, - -0.126038, 0.15799, 0.97934, 0.830475, -0.024811, 0.556458, -0.510132, -0.76944, 0.384247, 0.81424, 0.200104, - -0.544891, -0.112549, -0.393311, -0.912445, 0.56189, 0.152222, -0.813049, 0.198914, -0.254517, -0.946381, -0.41217, - 0.690979, -0.593811, -0.407257, 0.324524, 0.853668, -0.690186, 0.366119, -0.624115, -0.428345, 0.844147, -0.322296, - -0.21228, -0.297546, -0.930756, -0.273071, 0.516113, 0.811798, 0.928314, 0.371643, 0.007233, 0.785828, -0.479218, - -0.390778, -0.704895, 0.058929, 0.706818, 0.173248, 0.203583, 0.963562, 0.422211, -0.904297, -0.062469, -0.363312, - -0.182465, 0.913605, 0.254028, -0.552307, -0.793945, -0.28891, -0.765747, -0.574554, 0.058319, 0.291382, 0.954803, - 0.946136, -0.303925, 0.111267, -0.078156, 0.443695, -0.892731, 0.182098, 0.89389, 0.409515, -0.680298, -0.213318, - 0.701141, 0.062469, 0.848389, -0.525635, -0.72879, -0.641846, 0.238342, -0.88089, 0.427673, 0.202637, -0.532501, - -0.21405, 0.818878, 0.948975, -0.305084, 0.07962, 0.925446, 0.374664, 0.055817, 0.820923, 0.565491, 0.079102, - 0.25882, 0.099792, -0.960724, -0.294617, 0.910522, 0.289978, 0.137115, 0.320038, -0.937408, -0.908386, 0.345276, - -0.235718, -0.936218, 0.138763, 0.322754, 0.366577, 0.925934, -0.090637, 0.309296, -0.686829, -0.657684, 0.66983, - 0.024445, 0.742065, -0.917999, -0.059113, -0.392059, 0.365509, 0.462158, -0.807922, 0.083374, 0.996399, -0.014801, - 0.593842, 0.253143, -0.763672, 0.974976, -0.165466, 0.148285, 0.918976, 0.137299, 0.369537, 0.294952, 0.694977, - 0.655731, 0.943085, 0.152618, -0.295319, 0.58783, -0.598236, 0.544495, 0.203796, 0.678223, 0.705994, -0.478821, - -0.661011, 0.577667, 0.719055, -0.1698, -0.673828, -0.132172, -0.965332, 0.225006, -0.981873, -0.14502, 0.121979, - 0.763458, 0.579742, 0.284546, -0.893188, 0.079681, 0.442474, -0.795776, -0.523804, 0.303802, 0.734955, 0.67804, - -0.007446, 0.15506, 0.986267, -0.056183, 0.258026, 0.571503, -0.778931, -0.681549, -0.702087, -0.206116, -0.96286, - -0.177185, 0.203613, -0.470978, -0.515106, 0.716095, -0.740326, 0.57135, 0.354095, -0.56012, -0.824982, -0.074982, - -0.507874, 0.753204, 0.417969, -0.503113, 0.038147, 0.863342, 0.594025, 0.673553, -0.439758, -0.119873, -0.005524, - -0.992737, 0.098267, -0.213776, 0.971893, -0.615631, 0.643951, 0.454163, 0.896851, -0.441071, 0.032166, -0.555023, - 0.750763, -0.358093, 0.398773, 0.304688, 0.864929, -0.722961, 0.303589, 0.620544, -0.63559, -0.621948, -0.457306, - -0.293243, 0.072327, 0.953278, -0.491638, 0.661041, -0.566772, -0.304199, -0.572083, -0.761688, 0.908081, -0.398956, - 0.127014, -0.523621, -0.549683, -0.650848, -0.932922, -0.19986, 0.299408, 0.099426, 0.140869, 0.984985, -0.020325, - -0.999756, -0.002319, 0.952667, 0.280853, -0.11615, -0.971893, 0.082581, 0.220337, 0.65921, 0.705292, -0.260651, - 0.733063, -0.175537, 0.657043, -0.555206, 0.429504, -0.712189, 0.400421, -0.89859, 0.179352, 0.750885, -0.19696, - 0.630341, 0.785675, -0.569336, 0.241821, -0.058899, -0.464111, 0.883789, 0.129608, -0.94519, 0.299622, -0.357819, - 0.907654, 0.219238, -0.842133, -0.439117, -0.312927, -0.313477, 0.84433, 0.434479, -0.241211, 0.053253, 0.968994, - 0.063873, 0.823273, 0.563965, 0.476288, 0.862152, -0.172516, 0.620941, -0.298126, 0.724915, 0.25238, -0.749359, - -0.612122, -0.577545, 0.386566, 0.718994, -0.406342, -0.737976, 0.538696, 0.04718, 0.556305, 0.82959, -0.802856, - 0.587463, 0.101166, -0.707733, -0.705963, 0.026428, 0.374908, 0.68457, 0.625092, 0.472137, 0.208405, -0.856506, - -0.703064, -0.581085, -0.409821, -0.417206, -0.736328, 0.532623, -0.447876, -0.20285, -0.870728, 0.086945, - -0.990417, 0.107086, 0.183685, 0.018341, -0.982788, 0.560638, -0.428864, 0.708282, 0.296722, -0.952576, -0.0672, - 0.135773, 0.990265, 0.030243, -0.068787, 0.654724, 0.752686, 0.762604, -0.551758, 0.337585, -0.819611, -0.407684, - 0.402466, -0.727844, -0.55072, -0.408539, -0.855774, -0.480011, 0.19281, 0.693176, -0.079285, 0.716339, 0.226013, - 0.650116, -0.725433, 0.246704, 0.953369, -0.173553, -0.970398, -0.239227, -0.03244, 0.136383, -0.394318, 0.908752, - 0.813232, 0.558167, 0.164368, 0.40451, 0.549042, -0.731323, -0.380249, -0.566711, 0.730865, 0.022156, 0.932739, - 0.359741, 0.00824, 0.996552, -0.082306, 0.956635, -0.065338, -0.283722, -0.743561, 0.008209, 0.668579, -0.859589, - -0.509674, 0.035767, -0.852234, 0.363678, -0.375977, -0.201965, -0.970795, -0.12915, 0.313477, 0.947327, 0.06546, - -0.254028, -0.528259, 0.81015, 0.628052, 0.601105, 0.49411, -0.494385, 0.868378, 0.037933, 0.275635, -0.086426, - 0.957336, -0.197937, 0.468903, -0.860748, 0.895599, 0.399384, 0.195801, 0.560791, 0.825012, -0.069214, 0.304199, - -0.849487, 0.43103, 0.096375, 0.93576, 0.339111, -0.051422, 0.408966, -0.911072, 0.330444, 0.942841, -0.042389, - -0.452362, -0.786407, 0.420563, 0.134308, -0.933472, -0.332489, 0.80191, -0.566711, -0.188934, -0.987946, -0.105988, - 0.112518, -0.24408, 0.892242, -0.379791, -0.920502, 0.229095, -0.316376, 0.7789, 0.325958, 0.535706, -0.912872, - 0.185211, -0.36377, -0.184784, 0.565369, -0.803833, -0.018463, 0.119537, 0.992615, -0.259247, -0.935608, 0.239532, - -0.82373, -0.449127, -0.345947, -0.433105, 0.659515, 0.614349, -0.822754, 0.378845, -0.423676, 0.687195, -0.674835, - -0.26889, -0.246582, -0.800842, 0.545715, -0.729187, -0.207794, 0.651978, 0.653534, -0.610443, -0.447388, 0.492584, - -0.023346, 0.869934, 0.609039, 0.009094, -0.79306, 0.962494, -0.271088, -0.00885, 0.2659, -0.004913, 0.963959, - 0.651245, 0.553619, -0.518951, 0.280548, -0.84314, 0.458618, -0.175293, -0.983215, 0.049805, 0.035339, -0.979919, - 0.196045, -0.982941, 0.164307, -0.082245, 0.233734, -0.97226, -0.005005, -0.747253, -0.611328, 0.260437, 0.645599, - 0.592773, 0.481384, 0.117706, -0.949524, -0.29068, -0.535004, -0.791901, -0.294312, -0.627167, -0.214447, 0.748718, - -0.047974, -0.813477, -0.57959, -0.175537, 0.477264, -0.860992, 0.738556, -0.414246, -0.53183, 0.562561, -0.704071, - 0.433289, -0.754944, 0.64801, -0.100586, 0.114716, 0.044525, -0.992371, 0.966003, 0.244873, -0.082764, + 0.33783, 0.715698, -0.611206, -0.944031, -0.326599, -0.045624, -0.101074, -0.416443, + -0.903503, 0.799286, 0.49411, -0.341949, -0.854645, 0.518036, 0.033936, 0.42514, + -0.437866, -0.792114, -0.358948, 0.597046, 0.717377, -0.985413, 0.144714, 0.089294, + -0.601776, -0.33728, -0.723907, -0.449921, 0.594513, 0.666382, 0.208313, -0.10791, + 0.972076, 0.575317, 0.060425, 0.815643, 0.293365, -0.875702, -0.383453, 0.293762, + 0.465759, 0.834686, -0.846008, -0.233398, -0.47934, -0.115814, 0.143036, -0.98291, + 0.204681, -0.949036, -0.239532, 0.946716, -0.263947, 0.184326, -0.235596, 0.573822, + 0.784332, 0.203705, -0.372253, -0.905487, 0.756989, -0.651031, 0.055298, 0.497803, + 0.814697, -0.297363, -0.16214, 0.063995, -0.98468, -0.329254, 0.834381, 0.441925, + 0.703827, -0.527039, -0.476227, 0.956421, 0.266113, 0.119781, 0.480133, 0.482849, + 0.7323, -0.18631, 0.961212, -0.203125, -0.748474, -0.656921, -0.090393, -0.085052, + -0.165253, 0.982544, -0.76947, 0.628174, -0.115234, 0.383148, 0.537659, 0.751068, + 0.616486, -0.668488, -0.415924, -0.259979, -0.630005, 0.73175, 0.570953, -0.087952, + 0.816223, -0.458008, 0.023254, 0.888611, -0.196167, 0.976563, -0.088287, -0.263885, + -0.69812, -0.665527, 0.437134, -0.892273, -0.112793, -0.621674, -0.230438, 0.748566, + 0.232422, 0.900574, -0.367249, 0.22229, -0.796143, 0.562744, -0.665497, -0.73764, + 0.11377, 0.670135, 0.704803, 0.232605, 0.895599, 0.429749, -0.114655, -0.11557, + -0.474243, 0.872742, 0.621826, 0.604004, -0.498444, -0.832214, 0.012756, 0.55426, + -0.702484, 0.705994, -0.089661, -0.692017, 0.649292, 0.315399, -0.175995, -0.977997, + 0.111877, 0.096954, -0.04953, 0.994019, 0.635284, -0.606689, -0.477783, -0.261261, + -0.607422, -0.750153, 0.983276, 0.165436, 0.075958, -0.29837, 0.404083, -0.864655, + -0.638672, 0.507721, 0.578156, 0.388214, 0.412079, 0.824249, 0.556183, -0.208832, + 0.804352, 0.778442, 0.562012, 0.27951, -0.616577, 0.781921, -0.091522, 0.196289, + 0.051056, 0.979187, -0.121216, 0.207153, -0.970734, -0.173401, -0.384735, 0.906555, + 0.161499, -0.723236, -0.671387, 0.178497, -0.006226, -0.983887, -0.126038, 0.15799, + 0.97934, 0.830475, -0.024811, 0.556458, -0.510132, -0.76944, 0.384247, 0.81424, + 0.200104, -0.544891, -0.112549, -0.393311, -0.912445, 0.56189, 0.152222, -0.813049, + 0.198914, -0.254517, -0.946381, -0.41217, 0.690979, -0.593811, -0.407257, 0.324524, + 0.853668, -0.690186, 0.366119, -0.624115, -0.428345, 0.844147, -0.322296, -0.21228, + -0.297546, -0.930756, -0.273071, 0.516113, 0.811798, 0.928314, 0.371643, 0.007233, + 0.785828, -0.479218, -0.390778, -0.704895, 0.058929, 0.706818, 0.173248, 0.203583, + 0.963562, 0.422211, -0.904297, -0.062469, -0.363312, -0.182465, 0.913605, 0.254028, + -0.552307, -0.793945, -0.28891, -0.765747, -0.574554, 0.058319, 0.291382, 0.954803, + 0.946136, -0.303925, 0.111267, -0.078156, 0.443695, -0.892731, 0.182098, 0.89389, + 0.409515, -0.680298, -0.213318, 0.701141, 0.062469, 0.848389, -0.525635, -0.72879, + -0.641846, 0.238342, -0.88089, 0.427673, 0.202637, -0.532501, -0.21405, 0.818878, + 0.948975, -0.305084, 0.07962, 0.925446, 0.374664, 0.055817, 0.820923, 0.565491, + 0.079102, 0.25882, 0.099792, -0.960724, -0.294617, 0.910522, 0.289978, 0.137115, + 0.320038, -0.937408, -0.908386, 0.345276, -0.235718, -0.936218, 0.138763, 0.322754, + 0.366577, 0.925934, -0.090637, 0.309296, -0.686829, -0.657684, 0.66983, 0.024445, + 0.742065, -0.917999, -0.059113, -0.392059, 0.365509, 0.462158, -0.807922, 0.083374, + 0.996399, -0.014801, 0.593842, 0.253143, -0.763672, 0.974976, -0.165466, 0.148285, + 0.918976, 0.137299, 0.369537, 0.294952, 0.694977, 0.655731, 0.943085, 0.152618, + -0.295319, 0.58783, -0.598236, 0.544495, 0.203796, 0.678223, 0.705994, -0.478821, + -0.661011, 0.577667, 0.719055, -0.1698, -0.673828, -0.132172, -0.965332, 0.225006, + -0.981873, -0.14502, 0.121979, 0.763458, 0.579742, 0.284546, -0.893188, 0.079681, + 0.442474, -0.795776, -0.523804, 0.303802, 0.734955, 0.67804, -0.007446, 0.15506, + 0.986267, -0.056183, 0.258026, 0.571503, -0.778931, -0.681549, -0.702087, -0.206116, + -0.96286, -0.177185, 0.203613, -0.470978, -0.515106, 0.716095, -0.740326, 0.57135, + 0.354095, -0.56012, -0.824982, -0.074982, -0.507874, 0.753204, 0.417969, -0.503113, + 0.038147, 0.863342, 0.594025, 0.673553, -0.439758, -0.119873, -0.005524, -0.992737, + 0.098267, -0.213776, 0.971893, -0.615631, 0.643951, 0.454163, 0.896851, -0.441071, + 0.032166, -0.555023, 0.750763, -0.358093, 0.398773, 0.304688, 0.864929, -0.722961, + 0.303589, 0.620544, -0.63559, -0.621948, -0.457306, -0.293243, 0.072327, 0.953278, + -0.491638, 0.661041, -0.566772, -0.304199, -0.572083, -0.761688, 0.908081, -0.398956, + 0.127014, -0.523621, -0.549683, -0.650848, -0.932922, -0.19986, 0.299408, 0.099426, + 0.140869, 0.984985, -0.020325, -0.999756, -0.002319, 0.952667, 0.280853, -0.11615, + -0.971893, 0.082581, 0.220337, 0.65921, 0.705292, -0.260651, 0.733063, -0.175537, + 0.657043, -0.555206, 0.429504, -0.712189, 0.400421, -0.89859, 0.179352, 0.750885, + -0.19696, 0.630341, 0.785675, -0.569336, 0.241821, -0.058899, -0.464111, 0.883789, + 0.129608, -0.94519, 0.299622, -0.357819, 0.907654, 0.219238, -0.842133, -0.439117, + -0.312927, -0.313477, 0.84433, 0.434479, -0.241211, 0.053253, 0.968994, 0.063873, + 0.823273, 0.563965, 0.476288, 0.862152, -0.172516, 0.620941, -0.298126, 0.724915, + 0.25238, -0.749359, -0.612122, -0.577545, 0.386566, 0.718994, -0.406342, -0.737976, + 0.538696, 0.04718, 0.556305, 0.82959, -0.802856, 0.587463, 0.101166, -0.707733, + -0.705963, 0.026428, 0.374908, 0.68457, 0.625092, 0.472137, 0.208405, -0.856506, + -0.703064, -0.581085, -0.409821, -0.417206, -0.736328, 0.532623, -0.447876, -0.20285, + -0.870728, 0.086945, -0.990417, 0.107086, 0.183685, 0.018341, -0.982788, 0.560638, + -0.428864, 0.708282, 0.296722, -0.952576, -0.0672, 0.135773, 0.990265, 0.030243, + -0.068787, 0.654724, 0.752686, 0.762604, -0.551758, 0.337585, -0.819611, -0.407684, + 0.402466, -0.727844, -0.55072, -0.408539, -0.855774, -0.480011, 0.19281, 0.693176, + -0.079285, 0.716339, 0.226013, 0.650116, -0.725433, 0.246704, 0.953369, -0.173553, + -0.970398, -0.239227, -0.03244, 0.136383, -0.394318, 0.908752, 0.813232, 0.558167, + 0.164368, 0.40451, 0.549042, -0.731323, -0.380249, -0.566711, 0.730865, 0.022156, + 0.932739, 0.359741, 0.00824, 0.996552, -0.082306, 0.956635, -0.065338, -0.283722, + -0.743561, 0.008209, 0.668579, -0.859589, -0.509674, 0.035767, -0.852234, 0.363678, + -0.375977, -0.201965, -0.970795, -0.12915, 0.313477, 0.947327, 0.06546, -0.254028, + -0.528259, 0.81015, 0.628052, 0.601105, 0.49411, -0.494385, 0.868378, 0.037933, + 0.275635, -0.086426, 0.957336, -0.197937, 0.468903, -0.860748, 0.895599, 0.399384, + 0.195801, 0.560791, 0.825012, -0.069214, 0.304199, -0.849487, 0.43103, 0.096375, + 0.93576, 0.339111, -0.051422, 0.408966, -0.911072, 0.330444, 0.942841, -0.042389, + -0.452362, -0.786407, 0.420563, 0.134308, -0.933472, -0.332489, 0.80191, -0.566711, + -0.188934, -0.987946, -0.105988, 0.112518, -0.24408, 0.892242, -0.379791, -0.920502, + 0.229095, -0.316376, 0.7789, 0.325958, 0.535706, -0.912872, 0.185211, -0.36377, + -0.184784, 0.565369, -0.803833, -0.018463, 0.119537, 0.992615, -0.259247, -0.935608, + 0.239532, -0.82373, -0.449127, -0.345947, -0.433105, 0.659515, 0.614349, -0.822754, + 0.378845, -0.423676, 0.687195, -0.674835, -0.26889, -0.246582, -0.800842, 0.545715, + -0.729187, -0.207794, 0.651978, 0.653534, -0.610443, -0.447388, 0.492584, -0.023346, + 0.869934, 0.609039, 0.009094, -0.79306, 0.962494, -0.271088, -0.00885, 0.2659, + -0.004913, 0.963959, 0.651245, 0.553619, -0.518951, 0.280548, -0.84314, 0.458618, + -0.175293, -0.983215, 0.049805, 0.035339, -0.979919, 0.196045, -0.982941, 0.164307, + -0.082245, 0.233734, -0.97226, -0.005005, -0.747253, -0.611328, 0.260437, 0.645599, + 0.592773, 0.481384, 0.117706, -0.949524, -0.29068, -0.535004, -0.791901, -0.294312, + -0.627167, -0.214447, 0.748718, -0.047974, -0.813477, -0.57959, -0.175537, 0.477264, + -0.860992, 0.738556, -0.414246, -0.53183, 0.562561, -0.704071, 0.433289, -0.754944, + 0.64801, -0.100586, 0.114716, 0.044525, -0.992371, 0.966003, 0.244873, -0.082764, }; /**************************/ @@ -260,55 +266,64 @@ static const float hashvectf[768] = { static float lerp(float t, float a, float b) { - return (a + t * (b - a)); + return (a + t * (b - a)); } static float npfade(float t) { - return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f)); + return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f)); } static float grad(int hash_val, float x, float y, float z) { - int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */ - float u = h < 8 ? x : y; /* INTO 12 GRADIENT DIRECTIONS. */ - float v = h < 4 ? y : h == 12 || h == 14 ? x : z; - return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); + int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */ + float u = h < 8 ? x : y; /* INTO 12 GRADIENT DIRECTIONS. */ + float v = h < 4 ? y : h == 12 || h == 14 ? x : z; + return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } /* instead of adding another permutation array, just use hash table defined above */ static float newPerlin(float x, float y, float z) { - int A, AA, AB, B, BA, BB; - float u = floor(x), v = floor(y), w = floor(z); - int X = ((int)u) & 255; - int Y = ((int)v) & 255; - int Z = ((int)w) & 255; /* FIND UNIT CUBE THAT CONTAINS POINT */ - x -= u; /* FIND RELATIVE X,Y,Z */ - y -= v; /* OF POINT IN CUBE. */ - z -= w; - u = npfade(x); /* COMPUTE FADE CURVES */ - v = npfade(y); /* FOR EACH OF X,Y,Z. */ - w = npfade(z); - A = hash[X ] + Y; AA = hash[A] + Z; AB = hash[A + 1] + Z; /* HASH COORDINATES OF */ - B = hash[X + 1] + Y; BA = hash[B] + Z; BB = hash[B + 1] + Z; /* THE 8 CUBE CORNERS, */ - return lerp(w, lerp(v, lerp(u, grad(hash[AA ], x, y, z ), /* AND ADD */ - grad(hash[BA ], x - 1, y, z )), /* BLENDED */ - lerp(u, grad(hash[AB ], x, y - 1, z ), /* RESULTS */ - grad(hash[BB ], x - 1, y - 1, z ))), /* FROM 8 */ - lerp(v, lerp(u, grad(hash[AA + 1], x, y, z - 1), /* CORNERS */ - grad(hash[BA + 1], x - 1, y, z - 1)), /* OF CUBE */ - lerp(u, grad(hash[AB + 1], x, y - 1, z - 1), - grad(hash[BB + 1], x - 1, y - 1, z - 1)))); + int A, AA, AB, B, BA, BB; + float u = floor(x), v = floor(y), w = floor(z); + int X = ((int)u) & 255; + int Y = ((int)v) & 255; + int Z = ((int)w) & 255; /* FIND UNIT CUBE THAT CONTAINS POINT */ + x -= u; /* FIND RELATIVE X,Y,Z */ + y -= v; /* OF POINT IN CUBE. */ + z -= w; + u = npfade(x); /* COMPUTE FADE CURVES */ + v = npfade(y); /* FOR EACH OF X,Y,Z. */ + w = npfade(z); + A = hash[X] + Y; + AA = hash[A] + Z; + AB = hash[A + 1] + Z; /* HASH COORDINATES OF */ + B = hash[X + 1] + Y; + BA = hash[B] + Z; + BB = hash[B + 1] + Z; /* THE 8 CUBE CORNERS, */ + return lerp( + w, + lerp(v, + lerp(u, + grad(hash[AA], x, y, z), /* AND ADD */ + grad(hash[BA], x - 1, y, z)), /* BLENDED */ + lerp(u, + grad(hash[AB], x, y - 1, z), /* RESULTS */ + grad(hash[BB], x - 1, y - 1, z))), /* FROM 8 */ + lerp(v, + lerp(u, + grad(hash[AA + 1], x, y, z - 1), /* CORNERS */ + grad(hash[BA + 1], x - 1, y, z - 1)), /* OF CUBE */ + lerp(u, grad(hash[AB + 1], x, y - 1, z - 1), grad(hash[BB + 1], x - 1, y - 1, z - 1)))); } /* for use with BLI_gNoise()/BLI_gTurbulence(), returns unsigned improved perlin noise */ static float newPerlinU(float x, float y, float z) { - return (0.5f + 0.5f * newPerlin(x, y, z)); + return (0.5f + 0.5f * newPerlin(x, y, z)); } - /**************************/ /* END OF IMPROVED PERLIN */ /**************************/ @@ -316,774 +331,512 @@ static float newPerlinU(float x, float y, float z) /* Was BLI_hnoise(), removed noisesize, so other functions can call it without scaling. */ static float orgBlenderNoise(float x, float y, float z) { - register float cn1, cn2, cn3, cn4, cn5, cn6, i; - register const float *h; - float fx, fy, fz, ox, oy, oz, jx, jy, jz; - float n = 0.5; - int ix, iy, iz, b00, b01, b10, b11, b20, b21; - - fx = floor(x); - fy = floor(y); - fz = floor(z); - - ox = x - fx; - oy = y - fy; - oz = z - fz; - - ix = (int)fx; - iy = (int)fy; - iz = (int)fz; - - jx = ox - 1; - jy = oy - 1; - jz = oz - 1; - - cn1 = ox * ox; cn2 = oy * oy; cn3 = oz * oz; - cn4 = jx * jx; cn5 = jy * jy; cn6 = jz * jz; - - cn1 = 1.0f - 3.0f * cn1 + 2.0f * cn1 * ox; - cn2 = 1.0f - 3.0f * cn2 + 2.0f * cn2 * oy; - cn3 = 1.0f - 3.0f * cn3 + 2.0f * cn3 * oz; - cn4 = 1.0f - 3.0f * cn4 - 2.0f * cn4 * jx; - cn5 = 1.0f - 3.0f * cn5 - 2.0f * cn5 * jy; - cn6 = 1.0f - 3.0f * cn6 - 2.0f * cn6 * jz; - - b00 = hash[hash[ix & 255] + (iy & 255)]; - b10 = hash[hash[(ix + 1) & 255] + (iy & 255)]; - b01 = hash[hash[ix & 255] + ((iy + 1) & 255)]; - b11 = hash[hash[(ix + 1) & 255] + ((iy + 1) & 255)]; - - b20 = iz & 255; b21 = (iz + 1) & 255; - - /* 0 */ - i = (cn1 * cn2 * cn3); - h = hashvectf + 3 * hash[b20 + b00]; - n += i * (h[0] * ox + h[1] * oy + h[2] * oz); - /* 1 */ - i = (cn1 * cn2 * cn6); - h = hashvectf + 3 * hash[b21 + b00]; - n += i * (h[0] * ox + h[1] * oy + h[2] * jz); - /* 2 */ - i = (cn1 * cn5 * cn3); - h = hashvectf + 3 * hash[b20 + b01]; - n += i * (h[0] * ox + h[1] * jy + h[2] * oz); - /* 3 */ - i = (cn1 * cn5 * cn6); - h = hashvectf + 3 * hash[b21 + b01]; - n += i * (h[0] * ox + h[1] * jy + h[2] * jz); - /* 4 */ - i = cn4 * cn2 * cn3; - h = hashvectf + 3 * hash[b20 + b10]; - n += i * (h[0] * jx + h[1] * oy + h[2] * oz); - /* 5 */ - i = cn4 * cn2 * cn6; - h = hashvectf + 3 * hash[b21 + b10]; - n += i * (h[0] * jx + h[1] * oy + h[2] * jz); - /* 6 */ - i = cn4 * cn5 * cn3; - h = hashvectf + 3 * hash[b20 + b11]; - n += i * (h[0] * jx + h[1] * jy + h[2] * oz); - /* 7 */ - i = (cn4 * cn5 * cn6); - h = hashvectf + 3 * hash[b21 + b11]; - n += i * (h[0] * jx + h[1] * jy + h[2] * jz); - - if (n < 0.0f) { n = 0.0f; } - else if (n > 1.0f) { n = 1.0f; } - return n; + register float cn1, cn2, cn3, cn4, cn5, cn6, i; + register const float *h; + float fx, fy, fz, ox, oy, oz, jx, jy, jz; + float n = 0.5; + int ix, iy, iz, b00, b01, b10, b11, b20, b21; + + fx = floor(x); + fy = floor(y); + fz = floor(z); + + ox = x - fx; + oy = y - fy; + oz = z - fz; + + ix = (int)fx; + iy = (int)fy; + iz = (int)fz; + + jx = ox - 1; + jy = oy - 1; + jz = oz - 1; + + cn1 = ox * ox; + cn2 = oy * oy; + cn3 = oz * oz; + cn4 = jx * jx; + cn5 = jy * jy; + cn6 = jz * jz; + + cn1 = 1.0f - 3.0f * cn1 + 2.0f * cn1 * ox; + cn2 = 1.0f - 3.0f * cn2 + 2.0f * cn2 * oy; + cn3 = 1.0f - 3.0f * cn3 + 2.0f * cn3 * oz; + cn4 = 1.0f - 3.0f * cn4 - 2.0f * cn4 * jx; + cn5 = 1.0f - 3.0f * cn5 - 2.0f * cn5 * jy; + cn6 = 1.0f - 3.0f * cn6 - 2.0f * cn6 * jz; + + b00 = hash[hash[ix & 255] + (iy & 255)]; + b10 = hash[hash[(ix + 1) & 255] + (iy & 255)]; + b01 = hash[hash[ix & 255] + ((iy + 1) & 255)]; + b11 = hash[hash[(ix + 1) & 255] + ((iy + 1) & 255)]; + + b20 = iz & 255; + b21 = (iz + 1) & 255; + + /* 0 */ + i = (cn1 * cn2 * cn3); + h = hashvectf + 3 * hash[b20 + b00]; + n += i * (h[0] * ox + h[1] * oy + h[2] * oz); + /* 1 */ + i = (cn1 * cn2 * cn6); + h = hashvectf + 3 * hash[b21 + b00]; + n += i * (h[0] * ox + h[1] * oy + h[2] * jz); + /* 2 */ + i = (cn1 * cn5 * cn3); + h = hashvectf + 3 * hash[b20 + b01]; + n += i * (h[0] * ox + h[1] * jy + h[2] * oz); + /* 3 */ + i = (cn1 * cn5 * cn6); + h = hashvectf + 3 * hash[b21 + b01]; + n += i * (h[0] * ox + h[1] * jy + h[2] * jz); + /* 4 */ + i = cn4 * cn2 * cn3; + h = hashvectf + 3 * hash[b20 + b10]; + n += i * (h[0] * jx + h[1] * oy + h[2] * oz); + /* 5 */ + i = cn4 * cn2 * cn6; + h = hashvectf + 3 * hash[b21 + b10]; + n += i * (h[0] * jx + h[1] * oy + h[2] * jz); + /* 6 */ + i = cn4 * cn5 * cn3; + h = hashvectf + 3 * hash[b20 + b11]; + n += i * (h[0] * jx + h[1] * jy + h[2] * oz); + /* 7 */ + i = (cn4 * cn5 * cn6); + h = hashvectf + 3 * hash[b21 + b11]; + n += i * (h[0] * jx + h[1] * jy + h[2] * jz); + + if (n < 0.0f) { + n = 0.0f; + } + else if (n > 1.0f) { + n = 1.0f; + } + return n; } /* as orgBlenderNoise(), returning signed noise */ static float orgBlenderNoiseS(float x, float y, float z) { - return (2.0f * orgBlenderNoise(x, y, z) - 1.0f); + return (2.0f * orgBlenderNoise(x, y, z) - 1.0f); } /* separated from orgBlenderNoise above, with scaling */ float BLI_hnoise(float noisesize, float x, float y, float z) { - if (noisesize == 0.0f) { - return 0.0f; - } - x = (1.0f + x) / noisesize; - y = (1.0f + y) / noisesize; - z = (1.0f + z) / noisesize; - return orgBlenderNoise(x, y, z); + if (noisesize == 0.0f) { + return 0.0f; + } + x = (1.0f + x) / noisesize; + y = (1.0f + y) / noisesize; + z = (1.0f + z) / noisesize; + return orgBlenderNoise(x, y, z); } - /* original turbulence functions */ float BLI_turbulence(float noisesize, float x, float y, float z, int nr) { - float s, d = 0.5, div = 1.0; + float s, d = 0.5, div = 1.0; - s = BLI_hnoise(noisesize, x, y, z); + s = BLI_hnoise(noisesize, x, y, z); - while (nr > 0) { + while (nr > 0) { - s += d * BLI_hnoise(noisesize * d, x, y, z); - div += d; - d *= 0.5f; + s += d * BLI_hnoise(noisesize * d, x, y, z); + div += d; + d *= 0.5f; - nr--; - } - return s / div; + nr--; + } + return s / div; } float BLI_turbulence1(float noisesize, float x, float y, float z, int nr) { - float s, d = 0.5, div = 1.0; + float s, d = 0.5, div = 1.0; - s = fabsf((-1.0f + 2.0f * BLI_hnoise(noisesize, x, y, z))); + s = fabsf((-1.0f + 2.0f * BLI_hnoise(noisesize, x, y, z))); - while (nr > 0) { + while (nr > 0) { - s += fabsf(d * (-1.0f + 2.0f * BLI_hnoise(noisesize * d, x, y, z))); - div += d; - d *= 0.5f; + s += fabsf(d * (-1.0f + 2.0f * BLI_hnoise(noisesize * d, x, y, z))); + div += d; + d *= 0.5f; - nr--; - } - return s / div; + nr--; + } + return s / div; } /* ********************* FROM PERLIN HIMSELF: ******************** */ static const char g_perlin_data_ub[512 + 2] = { - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, - 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, - 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, - 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, - 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, - 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, - 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, - 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, - 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, - 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, - 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, - 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, - 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, - 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, - 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, - 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, - 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, - 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, - 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, - 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, - 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, - 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, - 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, - 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, - 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, - 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, - 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, - 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, - 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, - 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, - 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, - 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, - 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, - 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, - 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, - 0xB9, 0xCE, 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, - 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, - 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, - 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, - 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, - 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, + 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, + 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, + 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, + 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, + 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, + 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, + 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, + 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, + 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, + 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, + 0xA2, 0xA0, }; - static const float g_perlin_data_v3[512 + 2][3] = { - {0.33783, 0.715698, -0.611206}, - {-0.944031, -0.326599, -0.045624}, - {-0.101074, -0.416443, -0.903503}, - {0.799286, 0.49411, -0.341949}, - {-0.854645, 0.518036, 0.033936}, - {0.42514, -0.437866, -0.792114}, - {-0.358948, 0.597046, 0.717377}, - {-0.985413, 0.144714, 0.089294}, - {-0.601776, -0.33728, -0.723907}, - {-0.449921, 0.594513, 0.666382}, - {0.208313, -0.10791, 0.972076}, - {0.575317, 0.060425, 0.815643}, - {0.293365, -0.875702, -0.383453}, - {0.293762, 0.465759, 0.834686}, - {-0.846008, -0.233398, -0.47934}, - {-0.115814, 0.143036, -0.98291}, - {0.204681, -0.949036, -0.239532}, - {0.946716, -0.263947, 0.184326}, - {-0.235596, 0.573822, 0.784332}, - {0.203705, -0.372253, -0.905487}, - {0.756989, -0.651031, 0.055298}, - {0.497803, 0.814697, -0.297363}, - {-0.16214, 0.063995, -0.98468}, - {-0.329254, 0.834381, 0.441925}, - {0.703827, -0.527039, -0.476227}, - {0.956421, 0.266113, 0.119781}, - {0.480133, 0.482849, 0.7323}, - {-0.18631, 0.961212, -0.203125}, - {-0.748474, -0.656921, -0.090393}, - {-0.085052, -0.165253, 0.982544}, - {-0.76947, 0.628174, -0.115234}, - {0.383148, 0.537659, 0.751068}, - {0.616486, -0.668488, -0.415924}, - {-0.259979, -0.630005, 0.73175}, - {0.570953, -0.087952, 0.816223}, - {-0.458008, 0.023254, 0.888611}, - {-0.196167, 0.976563, -0.088287}, - {-0.263885, -0.69812, -0.665527}, - {0.437134, -0.892273, -0.112793}, - {-0.621674, -0.230438, 0.748566}, - {0.232422, 0.900574, -0.367249}, - {0.22229, -0.796143, 0.562744}, - {-0.665497, -0.73764, 0.11377}, - {0.670135, 0.704803, 0.232605}, - {0.895599, 0.429749, -0.114655}, - {-0.11557, -0.474243, 0.872742}, - {0.621826, 0.604004, -0.498444}, - {-0.832214, 0.012756, 0.55426}, - {-0.702484, 0.705994, -0.089661}, - {-0.692017, 0.649292, 0.315399}, - {-0.175995, -0.977997, 0.111877}, - {0.096954, -0.04953, 0.994019}, - {0.635284, -0.606689, -0.477783}, - {-0.261261, -0.607422, -0.750153}, - {0.983276, 0.165436, 0.075958}, - {-0.29837, 0.404083, -0.864655}, - {-0.638672, 0.507721, 0.578156}, - {0.388214, 0.412079, 0.824249}, - {0.556183, -0.208832, 0.804352}, - {0.778442, 0.562012, 0.27951}, - {-0.616577, 0.781921, -0.091522}, - {0.196289, 0.051056, 0.979187}, - {-0.121216, 0.207153, -0.970734}, - {-0.173401, -0.384735, 0.906555}, - {0.161499, -0.723236, -0.671387}, - {0.178497, -0.006226, -0.983887}, - {-0.126038, 0.15799, 0.97934}, - {0.830475, -0.024811, 0.556458}, - {-0.510132, -0.76944, 0.384247}, - {0.81424, 0.200104, -0.544891}, - {-0.112549, -0.393311, -0.912445}, - {0.56189, 0.152222, -0.813049}, - {0.198914, -0.254517, -0.946381}, - {-0.41217, 0.690979, -0.593811}, - {-0.407257, 0.324524, 0.853668}, - {-0.690186, 0.366119, -0.624115}, - {-0.428345, 0.844147, -0.322296}, - {-0.21228, -0.297546, -0.930756}, - {-0.273071, 0.516113, 0.811798}, - {0.928314, 0.371643, 0.007233}, - {0.785828, -0.479218, -0.390778}, - {-0.704895, 0.058929, 0.706818}, - {0.173248, 0.203583, 0.963562}, - {0.422211, -0.904297, -0.062469}, - {-0.363312, -0.182465, 0.913605}, - {0.254028, -0.552307, -0.793945}, - {-0.28891, -0.765747, -0.574554}, - {0.058319, 0.291382, 0.954803}, - {0.946136, -0.303925, 0.111267}, - {-0.078156, 0.443695, -0.892731}, - {0.182098, 0.89389, 0.409515}, - {-0.680298, -0.213318, 0.701141}, - {0.062469, 0.848389, -0.525635}, - {-0.72879, -0.641846, 0.238342}, - {-0.88089, 0.427673, 0.202637}, - {-0.532501, -0.21405, 0.818878}, - {0.948975, -0.305084, 0.07962}, - {0.925446, 0.374664, 0.055817}, - {0.820923, 0.565491, 0.079102}, - {0.25882, 0.099792, -0.960724}, - {-0.294617, 0.910522, 0.289978}, - {0.137115, 0.320038, -0.937408}, - {-0.908386, 0.345276, -0.235718}, - {-0.936218, 0.138763, 0.322754}, - {0.366577, 0.925934, -0.090637}, - {0.309296, -0.686829, -0.657684}, - {0.66983, 0.024445, 0.742065}, - {-0.917999, -0.059113, -0.392059}, - {0.365509, 0.462158, -0.807922}, - {0.083374, 0.996399, -0.014801}, - {0.593842, 0.253143, -0.763672}, - {0.974976, -0.165466, 0.148285}, - {0.918976, 0.137299, 0.369537}, - {0.294952, 0.694977, 0.655731}, - {0.943085, 0.152618, -0.295319}, - {0.58783, -0.598236, 0.544495}, - {0.203796, 0.678223, 0.705994}, - {-0.478821, -0.661011, 0.577667}, - {0.719055, -0.1698, -0.673828}, - {-0.132172, -0.965332, 0.225006}, - {-0.981873, -0.14502, 0.121979}, - {0.763458, 0.579742, 0.284546}, - {-0.893188, 0.079681, 0.442474}, - {-0.795776, -0.523804, 0.303802}, - {0.734955, 0.67804, -0.007446}, - {0.15506, 0.986267, -0.056183}, - {0.258026, 0.571503, -0.778931}, - {-0.681549, -0.702087, -0.206116}, - {-0.96286, -0.177185, 0.203613}, - {-0.470978, -0.515106, 0.716095}, - {-0.740326, 0.57135, 0.354095}, - {-0.56012, -0.824982, -0.074982}, - {-0.507874, 0.753204, 0.417969}, - {-0.503113, 0.038147, 0.863342}, - {0.594025, 0.673553, -0.439758}, - {-0.119873, -0.005524, -0.992737}, - {0.098267, -0.213776, 0.971893}, - {-0.615631, 0.643951, 0.454163}, - {0.896851, -0.441071, 0.032166}, - {-0.555023, 0.750763, -0.358093}, - {0.398773, 0.304688, 0.864929}, - {-0.722961, 0.303589, 0.620544}, - {-0.63559, -0.621948, -0.457306}, - {-0.293243, 0.072327, 0.953278}, - {-0.491638, 0.661041, -0.566772}, - {-0.304199, -0.572083, -0.761688}, - {0.908081, -0.398956, 0.127014}, - {-0.523621, -0.549683, -0.650848}, - {-0.932922, -0.19986, 0.299408}, - {0.099426, 0.140869, 0.984985}, - {-0.020325, -0.999756, -0.002319}, - {0.952667, 0.280853, -0.11615}, - {-0.971893, 0.082581, 0.220337}, - {0.65921, 0.705292, -0.260651}, - {0.733063, -0.175537, 0.657043}, - {-0.555206, 0.429504, -0.712189}, - {0.400421, -0.89859, 0.179352}, - {0.750885, -0.19696, 0.630341}, - {0.785675, -0.569336, 0.241821}, - {-0.058899, -0.464111, 0.883789}, - {0.129608, -0.94519, 0.299622}, - {-0.357819, 0.907654, 0.219238}, - {-0.842133, -0.439117, -0.312927}, - {-0.313477, 0.84433, 0.434479}, - {-0.241211, 0.053253, 0.968994}, - {0.063873, 0.823273, 0.563965}, - {0.476288, 0.862152, -0.172516}, - {0.620941, -0.298126, 0.724915}, - {0.25238, -0.749359, -0.612122}, - {-0.577545, 0.386566, 0.718994}, - {-0.406342, -0.737976, 0.538696}, - {0.04718, 0.556305, 0.82959}, - {-0.802856, 0.587463, 0.101166}, - {-0.707733, -0.705963, 0.026428}, - {0.374908, 0.68457, 0.625092}, - {0.472137, 0.208405, -0.856506}, - {-0.703064, -0.581085, -0.409821}, - {-0.417206, -0.736328, 0.532623}, - {-0.447876, -0.20285, -0.870728}, - {0.086945, -0.990417, 0.107086}, - {0.183685, 0.018341, -0.982788}, - {0.560638, -0.428864, 0.708282}, - {0.296722, -0.952576, -0.0672}, - {0.135773, 0.990265, 0.030243}, - {-0.068787, 0.654724, 0.752686}, - {0.762604, -0.551758, 0.337585}, - {-0.819611, -0.407684, 0.402466}, - {-0.727844, -0.55072, -0.408539}, - {-0.855774, -0.480011, 0.19281}, - {0.693176, -0.079285, 0.716339}, - {0.226013, 0.650116, -0.725433}, - {0.246704, 0.953369, -0.173553}, - {-0.970398, -0.239227, -0.03244}, - {0.136383, -0.394318, 0.908752}, - {0.813232, 0.558167, 0.164368}, - {0.40451, 0.549042, -0.731323}, - {-0.380249, -0.566711, 0.730865}, - {0.022156, 0.932739, 0.359741}, - {0.00824, 0.996552, -0.082306}, - {0.956635, -0.065338, -0.283722}, - {-0.743561, 0.008209, 0.668579}, - {-0.859589, -0.509674, 0.035767}, - {-0.852234, 0.363678, -0.375977}, - {-0.201965, -0.970795, -0.12915}, - {0.313477, 0.947327, 0.06546}, - {-0.254028, -0.528259, 0.81015}, - {0.628052, 0.601105, 0.49411}, - {-0.494385, 0.868378, 0.037933}, - {0.275635, -0.086426, 0.957336}, - {-0.197937, 0.468903, -0.860748}, - {0.895599, 0.399384, 0.195801}, - {0.560791, 0.825012, -0.069214}, - {0.304199, -0.849487, 0.43103}, - {0.096375, 0.93576, 0.339111}, - {-0.051422, 0.408966, -0.911072}, - {0.330444, 0.942841, -0.042389}, - {-0.452362, -0.786407, 0.420563}, - {0.134308, -0.933472, -0.332489}, - {0.80191, -0.566711, -0.188934}, - {-0.987946, -0.105988, 0.112518}, - {-0.24408, 0.892242, -0.379791}, - {-0.920502, 0.229095, -0.316376}, - {0.7789, 0.325958, 0.535706}, - {-0.912872, 0.185211, -0.36377}, - {-0.184784, 0.565369, -0.803833}, - {-0.018463, 0.119537, 0.992615}, - {-0.259247, -0.935608, 0.239532}, - {-0.82373, -0.449127, -0.345947}, - {-0.433105, 0.659515, 0.614349}, - {-0.822754, 0.378845, -0.423676}, - {0.687195, -0.674835, -0.26889}, - {-0.246582, -0.800842, 0.545715}, - {-0.729187, -0.207794, 0.651978}, - {0.653534, -0.610443, -0.447388}, - {0.492584, -0.023346, 0.869934}, - {0.609039, 0.009094, -0.79306}, - {0.962494, -0.271088, -0.00885}, - {0.2659, -0.004913, 0.963959}, - {0.651245, 0.553619, -0.518951}, - {0.280548, -0.84314, 0.458618}, - {-0.175293, -0.983215, 0.049805}, - {0.035339, -0.979919, 0.196045}, - {-0.982941, 0.164307, -0.082245}, - {0.233734, -0.97226, -0.005005}, - {-0.747253, -0.611328, 0.260437}, - {0.645599, 0.592773, 0.481384}, - {0.117706, -0.949524, -0.29068}, - {-0.535004, -0.791901, -0.294312}, - {-0.627167, -0.214447, 0.748718}, - {-0.047974, -0.813477, -0.57959}, - {-0.175537, 0.477264, -0.860992}, - {0.738556, -0.414246, -0.53183}, - {0.562561, -0.704071, 0.433289}, - {-0.754944, 0.64801, -0.100586}, - {0.114716, 0.044525, -0.992371}, - {0.966003, 0.244873, -0.082764}, - {0.33783, 0.715698, -0.611206}, - {-0.944031, -0.326599, -0.045624}, - {-0.101074, -0.416443, -0.903503}, - {0.799286, 0.49411, -0.341949}, - {-0.854645, 0.518036, 0.033936}, - {0.42514, -0.437866, -0.792114}, - {-0.358948, 0.597046, 0.717377}, - {-0.985413, 0.144714, 0.089294}, - {-0.601776, -0.33728, -0.723907}, - {-0.449921, 0.594513, 0.666382}, - {0.208313, -0.10791, 0.972076}, - {0.575317, 0.060425, 0.815643}, - {0.293365, -0.875702, -0.383453}, - {0.293762, 0.465759, 0.834686}, - {-0.846008, -0.233398, -0.47934}, - {-0.115814, 0.143036, -0.98291}, - {0.204681, -0.949036, -0.239532}, - {0.946716, -0.263947, 0.184326}, - {-0.235596, 0.573822, 0.784332}, - {0.203705, -0.372253, -0.905487}, - {0.756989, -0.651031, 0.055298}, - {0.497803, 0.814697, -0.297363}, - {-0.16214, 0.063995, -0.98468}, - {-0.329254, 0.834381, 0.441925}, - {0.703827, -0.527039, -0.476227}, - {0.956421, 0.266113, 0.119781}, - {0.480133, 0.482849, 0.7323}, - {-0.18631, 0.961212, -0.203125}, - {-0.748474, -0.656921, -0.090393}, - {-0.085052, -0.165253, 0.982544}, - {-0.76947, 0.628174, -0.115234}, - {0.383148, 0.537659, 0.751068}, - {0.616486, -0.668488, -0.415924}, - {-0.259979, -0.630005, 0.73175}, - {0.570953, -0.087952, 0.816223}, - {-0.458008, 0.023254, 0.888611}, - {-0.196167, 0.976563, -0.088287}, - {-0.263885, -0.69812, -0.665527}, - {0.437134, -0.892273, -0.112793}, - {-0.621674, -0.230438, 0.748566}, - {0.232422, 0.900574, -0.367249}, - {0.22229, -0.796143, 0.562744}, - {-0.665497, -0.73764, 0.11377}, - {0.670135, 0.704803, 0.232605}, - {0.895599, 0.429749, -0.114655}, - {-0.11557, -0.474243, 0.872742}, - {0.621826, 0.604004, -0.498444}, - {-0.832214, 0.012756, 0.55426}, - {-0.702484, 0.705994, -0.089661}, - {-0.692017, 0.649292, 0.315399}, - {-0.175995, -0.977997, 0.111877}, - {0.096954, -0.04953, 0.994019}, - {0.635284, -0.606689, -0.477783}, - {-0.261261, -0.607422, -0.750153}, - {0.983276, 0.165436, 0.075958}, - {-0.29837, 0.404083, -0.864655}, - {-0.638672, 0.507721, 0.578156}, - {0.388214, 0.412079, 0.824249}, - {0.556183, -0.208832, 0.804352}, - {0.778442, 0.562012, 0.27951}, - {-0.616577, 0.781921, -0.091522}, - {0.196289, 0.051056, 0.979187}, - {-0.121216, 0.207153, -0.970734}, - {-0.173401, -0.384735, 0.906555}, - {0.161499, -0.723236, -0.671387}, - {0.178497, -0.006226, -0.983887}, - {-0.126038, 0.15799, 0.97934}, - {0.830475, -0.024811, 0.556458}, - {-0.510132, -0.76944, 0.384247}, - {0.81424, 0.200104, -0.544891}, - {-0.112549, -0.393311, -0.912445}, - {0.56189, 0.152222, -0.813049}, - {0.198914, -0.254517, -0.946381}, - {-0.41217, 0.690979, -0.593811}, - {-0.407257, 0.324524, 0.853668}, - {-0.690186, 0.366119, -0.624115}, - {-0.428345, 0.844147, -0.322296}, - {-0.21228, -0.297546, -0.930756}, - {-0.273071, 0.516113, 0.811798}, - {0.928314, 0.371643, 0.007233}, - {0.785828, -0.479218, -0.390778}, - {-0.704895, 0.058929, 0.706818}, - {0.173248, 0.203583, 0.963562}, - {0.422211, -0.904297, -0.062469}, - {-0.363312, -0.182465, 0.913605}, - {0.254028, -0.552307, -0.793945}, - {-0.28891, -0.765747, -0.574554}, - {0.058319, 0.291382, 0.954803}, - {0.946136, -0.303925, 0.111267}, - {-0.078156, 0.443695, -0.892731}, - {0.182098, 0.89389, 0.409515}, - {-0.680298, -0.213318, 0.701141}, - {0.062469, 0.848389, -0.525635}, - {-0.72879, -0.641846, 0.238342}, - {-0.88089, 0.427673, 0.202637}, - {-0.532501, -0.21405, 0.818878}, - {0.948975, -0.305084, 0.07962}, - {0.925446, 0.374664, 0.055817}, - {0.820923, 0.565491, 0.079102}, - {0.25882, 0.099792, -0.960724}, - {-0.294617, 0.910522, 0.289978}, - {0.137115, 0.320038, -0.937408}, - {-0.908386, 0.345276, -0.235718}, - {-0.936218, 0.138763, 0.322754}, - {0.366577, 0.925934, -0.090637}, - {0.309296, -0.686829, -0.657684}, - {0.66983, 0.024445, 0.742065}, - {-0.917999, -0.059113, -0.392059}, - {0.365509, 0.462158, -0.807922}, - {0.083374, 0.996399, -0.014801}, - {0.593842, 0.253143, -0.763672}, - {0.974976, -0.165466, 0.148285}, - {0.918976, 0.137299, 0.369537}, - {0.294952, 0.694977, 0.655731}, - {0.943085, 0.152618, -0.295319}, - {0.58783, -0.598236, 0.544495}, - {0.203796, 0.678223, 0.705994}, - {-0.478821, -0.661011, 0.577667}, - {0.719055, -0.1698, -0.673828}, - {-0.132172, -0.965332, 0.225006}, - {-0.981873, -0.14502, 0.121979}, - {0.763458, 0.579742, 0.284546}, - {-0.893188, 0.079681, 0.442474}, - {-0.795776, -0.523804, 0.303802}, - {0.734955, 0.67804, -0.007446}, - {0.15506, 0.986267, -0.056183}, - {0.258026, 0.571503, -0.778931}, - {-0.681549, -0.702087, -0.206116}, - {-0.96286, -0.177185, 0.203613}, - {-0.470978, -0.515106, 0.716095}, - {-0.740326, 0.57135, 0.354095}, - {-0.56012, -0.824982, -0.074982}, - {-0.507874, 0.753204, 0.417969}, - {-0.503113, 0.038147, 0.863342}, - {0.594025, 0.673553, -0.439758}, - {-0.119873, -0.005524, -0.992737}, - {0.098267, -0.213776, 0.971893}, - {-0.615631, 0.643951, 0.454163}, - {0.896851, -0.441071, 0.032166}, - {-0.555023, 0.750763, -0.358093}, - {0.398773, 0.304688, 0.864929}, - {-0.722961, 0.303589, 0.620544}, - {-0.63559, -0.621948, -0.457306}, - {-0.293243, 0.072327, 0.953278}, - {-0.491638, 0.661041, -0.566772}, - {-0.304199, -0.572083, -0.761688}, - {0.908081, -0.398956, 0.127014}, - {-0.523621, -0.549683, -0.650848}, - {-0.932922, -0.19986, 0.299408}, - {0.099426, 0.140869, 0.984985}, - {-0.020325, -0.999756, -0.002319}, - {0.952667, 0.280853, -0.11615}, - {-0.971893, 0.082581, 0.220337}, - {0.65921, 0.705292, -0.260651}, - {0.733063, -0.175537, 0.657043}, - {-0.555206, 0.429504, -0.712189}, - {0.400421, -0.89859, 0.179352}, - {0.750885, -0.19696, 0.630341}, - {0.785675, -0.569336, 0.241821}, - {-0.058899, -0.464111, 0.883789}, - {0.129608, -0.94519, 0.299622}, - {-0.357819, 0.907654, 0.219238}, - {-0.842133, -0.439117, -0.312927}, - {-0.313477, 0.84433, 0.434479}, - {-0.241211, 0.053253, 0.968994}, - {0.063873, 0.823273, 0.563965}, - {0.476288, 0.862152, -0.172516}, - {0.620941, -0.298126, 0.724915}, - {0.25238, -0.749359, -0.612122}, - {-0.577545, 0.386566, 0.718994}, - {-0.406342, -0.737976, 0.538696}, - {0.04718, 0.556305, 0.82959}, - {-0.802856, 0.587463, 0.101166}, - {-0.707733, -0.705963, 0.026428}, - {0.374908, 0.68457, 0.625092}, - {0.472137, 0.208405, -0.856506}, - {-0.703064, -0.581085, -0.409821}, - {-0.417206, -0.736328, 0.532623}, - {-0.447876, -0.20285, -0.870728}, - {0.086945, -0.990417, 0.107086}, - {0.183685, 0.018341, -0.982788}, - {0.560638, -0.428864, 0.708282}, - {0.296722, -0.952576, -0.0672}, - {0.135773, 0.990265, 0.030243}, - {-0.068787, 0.654724, 0.752686}, - {0.762604, -0.551758, 0.337585}, - {-0.819611, -0.407684, 0.402466}, - {-0.727844, -0.55072, -0.408539}, - {-0.855774, -0.480011, 0.19281}, - {0.693176, -0.079285, 0.716339}, - {0.226013, 0.650116, -0.725433}, - {0.246704, 0.953369, -0.173553}, - {-0.970398, -0.239227, -0.03244}, - {0.136383, -0.394318, 0.908752}, - {0.813232, 0.558167, 0.164368}, - {0.40451, 0.549042, -0.731323}, - {-0.380249, -0.566711, 0.730865}, - {0.022156, 0.932739, 0.359741}, - {0.00824, 0.996552, -0.082306}, - {0.956635, -0.065338, -0.283722}, - {-0.743561, 0.008209, 0.668579}, - {-0.859589, -0.509674, 0.035767}, - {-0.852234, 0.363678, -0.375977}, - {-0.201965, -0.970795, -0.12915}, - {0.313477, 0.947327, 0.06546}, - {-0.254028, -0.528259, 0.81015}, - {0.628052, 0.601105, 0.49411}, - {-0.494385, 0.868378, 0.037933}, - {0.275635, -0.086426, 0.957336}, - {-0.197937, 0.468903, -0.860748}, - {0.895599, 0.399384, 0.195801}, - {0.560791, 0.825012, -0.069214}, - {0.304199, -0.849487, 0.43103}, - {0.096375, 0.93576, 0.339111}, - {-0.051422, 0.408966, -0.911072}, - {0.330444, 0.942841, -0.042389}, - {-0.452362, -0.786407, 0.420563}, - {0.134308, -0.933472, -0.332489}, - {0.80191, -0.566711, -0.188934}, - {-0.987946, -0.105988, 0.112518}, - {-0.24408, 0.892242, -0.379791}, - {-0.920502, 0.229095, -0.316376}, - {0.7789, 0.325958, 0.535706}, - {-0.912872, 0.185211, -0.36377}, - {-0.184784, 0.565369, -0.803833}, - {-0.018463, 0.119537, 0.992615}, - {-0.259247, -0.935608, 0.239532}, - {-0.82373, -0.449127, -0.345947}, - {-0.433105, 0.659515, 0.614349}, - {-0.822754, 0.378845, -0.423676}, - {0.687195, -0.674835, -0.26889}, - {-0.246582, -0.800842, 0.545715}, - {-0.729187, -0.207794, 0.651978}, - {0.653534, -0.610443, -0.447388}, - {0.492584, -0.023346, 0.869934}, - {0.609039, 0.009094, -0.79306}, - {0.962494, -0.271088, -0.00885}, - {0.2659, -0.004913, 0.963959}, - {0.651245, 0.553619, -0.518951}, - {0.280548, -0.84314, 0.458618}, - {-0.175293, -0.983215, 0.049805}, - {0.035339, -0.979919, 0.196045}, - {-0.982941, 0.164307, -0.082245}, - {0.233734, -0.97226, -0.005005}, - {-0.747253, -0.611328, 0.260437}, - {0.645599, 0.592773, 0.481384}, - {0.117706, -0.949524, -0.29068}, - {-0.535004, -0.791901, -0.294312}, - {-0.627167, -0.214447, 0.748718}, - {-0.047974, -0.813477, -0.57959}, - {-0.175537, 0.477264, -0.860992}, - {0.738556, -0.414246, -0.53183}, - {0.562561, -0.704071, 0.433289}, - {-0.754944, 0.64801, -0.100586}, - {0.114716, 0.044525, -0.992371}, - {0.966003, 0.244873, -0.082764}, - {0.33783, 0.715698, -0.611206}, - {-0.944031, -0.326599, -0.045624}, + {0.33783, 0.715698, -0.611206}, {-0.944031, -0.326599, -0.045624}, + {-0.101074, -0.416443, -0.903503}, {0.799286, 0.49411, -0.341949}, + {-0.854645, 0.518036, 0.033936}, {0.42514, -0.437866, -0.792114}, + {-0.358948, 0.597046, 0.717377}, {-0.985413, 0.144714, 0.089294}, + {-0.601776, -0.33728, -0.723907}, {-0.449921, 0.594513, 0.666382}, + {0.208313, -0.10791, 0.972076}, {0.575317, 0.060425, 0.815643}, + {0.293365, -0.875702, -0.383453}, {0.293762, 0.465759, 0.834686}, + {-0.846008, -0.233398, -0.47934}, {-0.115814, 0.143036, -0.98291}, + {0.204681, -0.949036, -0.239532}, {0.946716, -0.263947, 0.184326}, + {-0.235596, 0.573822, 0.784332}, {0.203705, -0.372253, -0.905487}, + {0.756989, -0.651031, 0.055298}, {0.497803, 0.814697, -0.297363}, + {-0.16214, 0.063995, -0.98468}, {-0.329254, 0.834381, 0.441925}, + {0.703827, -0.527039, -0.476227}, {0.956421, 0.266113, 0.119781}, + {0.480133, 0.482849, 0.7323}, {-0.18631, 0.961212, -0.203125}, + {-0.748474, -0.656921, -0.090393}, {-0.085052, -0.165253, 0.982544}, + {-0.76947, 0.628174, -0.115234}, {0.383148, 0.537659, 0.751068}, + {0.616486, -0.668488, -0.415924}, {-0.259979, -0.630005, 0.73175}, + {0.570953, -0.087952, 0.816223}, {-0.458008, 0.023254, 0.888611}, + {-0.196167, 0.976563, -0.088287}, {-0.263885, -0.69812, -0.665527}, + {0.437134, -0.892273, -0.112793}, {-0.621674, -0.230438, 0.748566}, + {0.232422, 0.900574, -0.367249}, {0.22229, -0.796143, 0.562744}, + {-0.665497, -0.73764, 0.11377}, {0.670135, 0.704803, 0.232605}, + {0.895599, 0.429749, -0.114655}, {-0.11557, -0.474243, 0.872742}, + {0.621826, 0.604004, -0.498444}, {-0.832214, 0.012756, 0.55426}, + {-0.702484, 0.705994, -0.089661}, {-0.692017, 0.649292, 0.315399}, + {-0.175995, -0.977997, 0.111877}, {0.096954, -0.04953, 0.994019}, + {0.635284, -0.606689, -0.477783}, {-0.261261, -0.607422, -0.750153}, + {0.983276, 0.165436, 0.075958}, {-0.29837, 0.404083, -0.864655}, + {-0.638672, 0.507721, 0.578156}, {0.388214, 0.412079, 0.824249}, + {0.556183, -0.208832, 0.804352}, {0.778442, 0.562012, 0.27951}, + {-0.616577, 0.781921, -0.091522}, {0.196289, 0.051056, 0.979187}, + {-0.121216, 0.207153, -0.970734}, {-0.173401, -0.384735, 0.906555}, + {0.161499, -0.723236, -0.671387}, {0.178497, -0.006226, -0.983887}, + {-0.126038, 0.15799, 0.97934}, {0.830475, -0.024811, 0.556458}, + {-0.510132, -0.76944, 0.384247}, {0.81424, 0.200104, -0.544891}, + {-0.112549, -0.393311, -0.912445}, {0.56189, 0.152222, -0.813049}, + {0.198914, -0.254517, -0.946381}, {-0.41217, 0.690979, -0.593811}, + {-0.407257, 0.324524, 0.853668}, {-0.690186, 0.366119, -0.624115}, + {-0.428345, 0.844147, -0.322296}, {-0.21228, -0.297546, -0.930756}, + {-0.273071, 0.516113, 0.811798}, {0.928314, 0.371643, 0.007233}, + {0.785828, -0.479218, -0.390778}, {-0.704895, 0.058929, 0.706818}, + {0.173248, 0.203583, 0.963562}, {0.422211, -0.904297, -0.062469}, + {-0.363312, -0.182465, 0.913605}, {0.254028, -0.552307, -0.793945}, + {-0.28891, -0.765747, -0.574554}, {0.058319, 0.291382, 0.954803}, + {0.946136, -0.303925, 0.111267}, {-0.078156, 0.443695, -0.892731}, + {0.182098, 0.89389, 0.409515}, {-0.680298, -0.213318, 0.701141}, + {0.062469, 0.848389, -0.525635}, {-0.72879, -0.641846, 0.238342}, + {-0.88089, 0.427673, 0.202637}, {-0.532501, -0.21405, 0.818878}, + {0.948975, -0.305084, 0.07962}, {0.925446, 0.374664, 0.055817}, + {0.820923, 0.565491, 0.079102}, {0.25882, 0.099792, -0.960724}, + {-0.294617, 0.910522, 0.289978}, {0.137115, 0.320038, -0.937408}, + {-0.908386, 0.345276, -0.235718}, {-0.936218, 0.138763, 0.322754}, + {0.366577, 0.925934, -0.090637}, {0.309296, -0.686829, -0.657684}, + {0.66983, 0.024445, 0.742065}, {-0.917999, -0.059113, -0.392059}, + {0.365509, 0.462158, -0.807922}, {0.083374, 0.996399, -0.014801}, + {0.593842, 0.253143, -0.763672}, {0.974976, -0.165466, 0.148285}, + {0.918976, 0.137299, 0.369537}, {0.294952, 0.694977, 0.655731}, + {0.943085, 0.152618, -0.295319}, {0.58783, -0.598236, 0.544495}, + {0.203796, 0.678223, 0.705994}, {-0.478821, -0.661011, 0.577667}, + {0.719055, -0.1698, -0.673828}, {-0.132172, -0.965332, 0.225006}, + {-0.981873, -0.14502, 0.121979}, {0.763458, 0.579742, 0.284546}, + {-0.893188, 0.079681, 0.442474}, {-0.795776, -0.523804, 0.303802}, + {0.734955, 0.67804, -0.007446}, {0.15506, 0.986267, -0.056183}, + {0.258026, 0.571503, -0.778931}, {-0.681549, -0.702087, -0.206116}, + {-0.96286, -0.177185, 0.203613}, {-0.470978, -0.515106, 0.716095}, + {-0.740326, 0.57135, 0.354095}, {-0.56012, -0.824982, -0.074982}, + {-0.507874, 0.753204, 0.417969}, {-0.503113, 0.038147, 0.863342}, + {0.594025, 0.673553, -0.439758}, {-0.119873, -0.005524, -0.992737}, + {0.098267, -0.213776, 0.971893}, {-0.615631, 0.643951, 0.454163}, + {0.896851, -0.441071, 0.032166}, {-0.555023, 0.750763, -0.358093}, + {0.398773, 0.304688, 0.864929}, {-0.722961, 0.303589, 0.620544}, + {-0.63559, -0.621948, -0.457306}, {-0.293243, 0.072327, 0.953278}, + {-0.491638, 0.661041, -0.566772}, {-0.304199, -0.572083, -0.761688}, + {0.908081, -0.398956, 0.127014}, {-0.523621, -0.549683, -0.650848}, + {-0.932922, -0.19986, 0.299408}, {0.099426, 0.140869, 0.984985}, + {-0.020325, -0.999756, -0.002319}, {0.952667, 0.280853, -0.11615}, + {-0.971893, 0.082581, 0.220337}, {0.65921, 0.705292, -0.260651}, + {0.733063, -0.175537, 0.657043}, {-0.555206, 0.429504, -0.712189}, + {0.400421, -0.89859, 0.179352}, {0.750885, -0.19696, 0.630341}, + {0.785675, -0.569336, 0.241821}, {-0.058899, -0.464111, 0.883789}, + {0.129608, -0.94519, 0.299622}, {-0.357819, 0.907654, 0.219238}, + {-0.842133, -0.439117, -0.312927}, {-0.313477, 0.84433, 0.434479}, + {-0.241211, 0.053253, 0.968994}, {0.063873, 0.823273, 0.563965}, + {0.476288, 0.862152, -0.172516}, {0.620941, -0.298126, 0.724915}, + {0.25238, -0.749359, -0.612122}, {-0.577545, 0.386566, 0.718994}, + {-0.406342, -0.737976, 0.538696}, {0.04718, 0.556305, 0.82959}, + {-0.802856, 0.587463, 0.101166}, {-0.707733, -0.705963, 0.026428}, + {0.374908, 0.68457, 0.625092}, {0.472137, 0.208405, -0.856506}, + {-0.703064, -0.581085, -0.409821}, {-0.417206, -0.736328, 0.532623}, + {-0.447876, -0.20285, -0.870728}, {0.086945, -0.990417, 0.107086}, + {0.183685, 0.018341, -0.982788}, {0.560638, -0.428864, 0.708282}, + {0.296722, -0.952576, -0.0672}, {0.135773, 0.990265, 0.030243}, + {-0.068787, 0.654724, 0.752686}, {0.762604, -0.551758, 0.337585}, + {-0.819611, -0.407684, 0.402466}, {-0.727844, -0.55072, -0.408539}, + {-0.855774, -0.480011, 0.19281}, {0.693176, -0.079285, 0.716339}, + {0.226013, 0.650116, -0.725433}, {0.246704, 0.953369, -0.173553}, + {-0.970398, -0.239227, -0.03244}, {0.136383, -0.394318, 0.908752}, + {0.813232, 0.558167, 0.164368}, {0.40451, 0.549042, -0.731323}, + {-0.380249, -0.566711, 0.730865}, {0.022156, 0.932739, 0.359741}, + {0.00824, 0.996552, -0.082306}, {0.956635, -0.065338, -0.283722}, + {-0.743561, 0.008209, 0.668579}, {-0.859589, -0.509674, 0.035767}, + {-0.852234, 0.363678, -0.375977}, {-0.201965, -0.970795, -0.12915}, + {0.313477, 0.947327, 0.06546}, {-0.254028, -0.528259, 0.81015}, + {0.628052, 0.601105, 0.49411}, {-0.494385, 0.868378, 0.037933}, + {0.275635, -0.086426, 0.957336}, {-0.197937, 0.468903, -0.860748}, + {0.895599, 0.399384, 0.195801}, {0.560791, 0.825012, -0.069214}, + {0.304199, -0.849487, 0.43103}, {0.096375, 0.93576, 0.339111}, + {-0.051422, 0.408966, -0.911072}, {0.330444, 0.942841, -0.042389}, + {-0.452362, -0.786407, 0.420563}, {0.134308, -0.933472, -0.332489}, + {0.80191, -0.566711, -0.188934}, {-0.987946, -0.105988, 0.112518}, + {-0.24408, 0.892242, -0.379791}, {-0.920502, 0.229095, -0.316376}, + {0.7789, 0.325958, 0.535706}, {-0.912872, 0.185211, -0.36377}, + {-0.184784, 0.565369, -0.803833}, {-0.018463, 0.119537, 0.992615}, + {-0.259247, -0.935608, 0.239532}, {-0.82373, -0.449127, -0.345947}, + {-0.433105, 0.659515, 0.614349}, {-0.822754, 0.378845, -0.423676}, + {0.687195, -0.674835, -0.26889}, {-0.246582, -0.800842, 0.545715}, + {-0.729187, -0.207794, 0.651978}, {0.653534, -0.610443, -0.447388}, + {0.492584, -0.023346, 0.869934}, {0.609039, 0.009094, -0.79306}, + {0.962494, -0.271088, -0.00885}, {0.2659, -0.004913, 0.963959}, + {0.651245, 0.553619, -0.518951}, {0.280548, -0.84314, 0.458618}, + {-0.175293, -0.983215, 0.049805}, {0.035339, -0.979919, 0.196045}, + {-0.982941, 0.164307, -0.082245}, {0.233734, -0.97226, -0.005005}, + {-0.747253, -0.611328, 0.260437}, {0.645599, 0.592773, 0.481384}, + {0.117706, -0.949524, -0.29068}, {-0.535004, -0.791901, -0.294312}, + {-0.627167, -0.214447, 0.748718}, {-0.047974, -0.813477, -0.57959}, + {-0.175537, 0.477264, -0.860992}, {0.738556, -0.414246, -0.53183}, + {0.562561, -0.704071, 0.433289}, {-0.754944, 0.64801, -0.100586}, + {0.114716, 0.044525, -0.992371}, {0.966003, 0.244873, -0.082764}, + {0.33783, 0.715698, -0.611206}, {-0.944031, -0.326599, -0.045624}, + {-0.101074, -0.416443, -0.903503}, {0.799286, 0.49411, -0.341949}, + {-0.854645, 0.518036, 0.033936}, {0.42514, -0.437866, -0.792114}, + {-0.358948, 0.597046, 0.717377}, {-0.985413, 0.144714, 0.089294}, + {-0.601776, -0.33728, -0.723907}, {-0.449921, 0.594513, 0.666382}, + {0.208313, -0.10791, 0.972076}, {0.575317, 0.060425, 0.815643}, + {0.293365, -0.875702, -0.383453}, {0.293762, 0.465759, 0.834686}, + {-0.846008, -0.233398, -0.47934}, {-0.115814, 0.143036, -0.98291}, + {0.204681, -0.949036, -0.239532}, {0.946716, -0.263947, 0.184326}, + {-0.235596, 0.573822, 0.784332}, {0.203705, -0.372253, -0.905487}, + {0.756989, -0.651031, 0.055298}, {0.497803, 0.814697, -0.297363}, + {-0.16214, 0.063995, -0.98468}, {-0.329254, 0.834381, 0.441925}, + {0.703827, -0.527039, -0.476227}, {0.956421, 0.266113, 0.119781}, + {0.480133, 0.482849, 0.7323}, {-0.18631, 0.961212, -0.203125}, + {-0.748474, -0.656921, -0.090393}, {-0.085052, -0.165253, 0.982544}, + {-0.76947, 0.628174, -0.115234}, {0.383148, 0.537659, 0.751068}, + {0.616486, -0.668488, -0.415924}, {-0.259979, -0.630005, 0.73175}, + {0.570953, -0.087952, 0.816223}, {-0.458008, 0.023254, 0.888611}, + {-0.196167, 0.976563, -0.088287}, {-0.263885, -0.69812, -0.665527}, + {0.437134, -0.892273, -0.112793}, {-0.621674, -0.230438, 0.748566}, + {0.232422, 0.900574, -0.367249}, {0.22229, -0.796143, 0.562744}, + {-0.665497, -0.73764, 0.11377}, {0.670135, 0.704803, 0.232605}, + {0.895599, 0.429749, -0.114655}, {-0.11557, -0.474243, 0.872742}, + {0.621826, 0.604004, -0.498444}, {-0.832214, 0.012756, 0.55426}, + {-0.702484, 0.705994, -0.089661}, {-0.692017, 0.649292, 0.315399}, + {-0.175995, -0.977997, 0.111877}, {0.096954, -0.04953, 0.994019}, + {0.635284, -0.606689, -0.477783}, {-0.261261, -0.607422, -0.750153}, + {0.983276, 0.165436, 0.075958}, {-0.29837, 0.404083, -0.864655}, + {-0.638672, 0.507721, 0.578156}, {0.388214, 0.412079, 0.824249}, + {0.556183, -0.208832, 0.804352}, {0.778442, 0.562012, 0.27951}, + {-0.616577, 0.781921, -0.091522}, {0.196289, 0.051056, 0.979187}, + {-0.121216, 0.207153, -0.970734}, {-0.173401, -0.384735, 0.906555}, + {0.161499, -0.723236, -0.671387}, {0.178497, -0.006226, -0.983887}, + {-0.126038, 0.15799, 0.97934}, {0.830475, -0.024811, 0.556458}, + {-0.510132, -0.76944, 0.384247}, {0.81424, 0.200104, -0.544891}, + {-0.112549, -0.393311, -0.912445}, {0.56189, 0.152222, -0.813049}, + {0.198914, -0.254517, -0.946381}, {-0.41217, 0.690979, -0.593811}, + {-0.407257, 0.324524, 0.853668}, {-0.690186, 0.366119, -0.624115}, + {-0.428345, 0.844147, -0.322296}, {-0.21228, -0.297546, -0.930756}, + {-0.273071, 0.516113, 0.811798}, {0.928314, 0.371643, 0.007233}, + {0.785828, -0.479218, -0.390778}, {-0.704895, 0.058929, 0.706818}, + {0.173248, 0.203583, 0.963562}, {0.422211, -0.904297, -0.062469}, + {-0.363312, -0.182465, 0.913605}, {0.254028, -0.552307, -0.793945}, + {-0.28891, -0.765747, -0.574554}, {0.058319, 0.291382, 0.954803}, + {0.946136, -0.303925, 0.111267}, {-0.078156, 0.443695, -0.892731}, + {0.182098, 0.89389, 0.409515}, {-0.680298, -0.213318, 0.701141}, + {0.062469, 0.848389, -0.525635}, {-0.72879, -0.641846, 0.238342}, + {-0.88089, 0.427673, 0.202637}, {-0.532501, -0.21405, 0.818878}, + {0.948975, -0.305084, 0.07962}, {0.925446, 0.374664, 0.055817}, + {0.820923, 0.565491, 0.079102}, {0.25882, 0.099792, -0.960724}, + {-0.294617, 0.910522, 0.289978}, {0.137115, 0.320038, -0.937408}, + {-0.908386, 0.345276, -0.235718}, {-0.936218, 0.138763, 0.322754}, + {0.366577, 0.925934, -0.090637}, {0.309296, -0.686829, -0.657684}, + {0.66983, 0.024445, 0.742065}, {-0.917999, -0.059113, -0.392059}, + {0.365509, 0.462158, -0.807922}, {0.083374, 0.996399, -0.014801}, + {0.593842, 0.253143, -0.763672}, {0.974976, -0.165466, 0.148285}, + {0.918976, 0.137299, 0.369537}, {0.294952, 0.694977, 0.655731}, + {0.943085, 0.152618, -0.295319}, {0.58783, -0.598236, 0.544495}, + {0.203796, 0.678223, 0.705994}, {-0.478821, -0.661011, 0.577667}, + {0.719055, -0.1698, -0.673828}, {-0.132172, -0.965332, 0.225006}, + {-0.981873, -0.14502, 0.121979}, {0.763458, 0.579742, 0.284546}, + {-0.893188, 0.079681, 0.442474}, {-0.795776, -0.523804, 0.303802}, + {0.734955, 0.67804, -0.007446}, {0.15506, 0.986267, -0.056183}, + {0.258026, 0.571503, -0.778931}, {-0.681549, -0.702087, -0.206116}, + {-0.96286, -0.177185, 0.203613}, {-0.470978, -0.515106, 0.716095}, + {-0.740326, 0.57135, 0.354095}, {-0.56012, -0.824982, -0.074982}, + {-0.507874, 0.753204, 0.417969}, {-0.503113, 0.038147, 0.863342}, + {0.594025, 0.673553, -0.439758}, {-0.119873, -0.005524, -0.992737}, + {0.098267, -0.213776, 0.971893}, {-0.615631, 0.643951, 0.454163}, + {0.896851, -0.441071, 0.032166}, {-0.555023, 0.750763, -0.358093}, + {0.398773, 0.304688, 0.864929}, {-0.722961, 0.303589, 0.620544}, + {-0.63559, -0.621948, -0.457306}, {-0.293243, 0.072327, 0.953278}, + {-0.491638, 0.661041, -0.566772}, {-0.304199, -0.572083, -0.761688}, + {0.908081, -0.398956, 0.127014}, {-0.523621, -0.549683, -0.650848}, + {-0.932922, -0.19986, 0.299408}, {0.099426, 0.140869, 0.984985}, + {-0.020325, -0.999756, -0.002319}, {0.952667, 0.280853, -0.11615}, + {-0.971893, 0.082581, 0.220337}, {0.65921, 0.705292, -0.260651}, + {0.733063, -0.175537, 0.657043}, {-0.555206, 0.429504, -0.712189}, + {0.400421, -0.89859, 0.179352}, {0.750885, -0.19696, 0.630341}, + {0.785675, -0.569336, 0.241821}, {-0.058899, -0.464111, 0.883789}, + {0.129608, -0.94519, 0.299622}, {-0.357819, 0.907654, 0.219238}, + {-0.842133, -0.439117, -0.312927}, {-0.313477, 0.84433, 0.434479}, + {-0.241211, 0.053253, 0.968994}, {0.063873, 0.823273, 0.563965}, + {0.476288, 0.862152, -0.172516}, {0.620941, -0.298126, 0.724915}, + {0.25238, -0.749359, -0.612122}, {-0.577545, 0.386566, 0.718994}, + {-0.406342, -0.737976, 0.538696}, {0.04718, 0.556305, 0.82959}, + {-0.802856, 0.587463, 0.101166}, {-0.707733, -0.705963, 0.026428}, + {0.374908, 0.68457, 0.625092}, {0.472137, 0.208405, -0.856506}, + {-0.703064, -0.581085, -0.409821}, {-0.417206, -0.736328, 0.532623}, + {-0.447876, -0.20285, -0.870728}, {0.086945, -0.990417, 0.107086}, + {0.183685, 0.018341, -0.982788}, {0.560638, -0.428864, 0.708282}, + {0.296722, -0.952576, -0.0672}, {0.135773, 0.990265, 0.030243}, + {-0.068787, 0.654724, 0.752686}, {0.762604, -0.551758, 0.337585}, + {-0.819611, -0.407684, 0.402466}, {-0.727844, -0.55072, -0.408539}, + {-0.855774, -0.480011, 0.19281}, {0.693176, -0.079285, 0.716339}, + {0.226013, 0.650116, -0.725433}, {0.246704, 0.953369, -0.173553}, + {-0.970398, -0.239227, -0.03244}, {0.136383, -0.394318, 0.908752}, + {0.813232, 0.558167, 0.164368}, {0.40451, 0.549042, -0.731323}, + {-0.380249, -0.566711, 0.730865}, {0.022156, 0.932739, 0.359741}, + {0.00824, 0.996552, -0.082306}, {0.956635, -0.065338, -0.283722}, + {-0.743561, 0.008209, 0.668579}, {-0.859589, -0.509674, 0.035767}, + {-0.852234, 0.363678, -0.375977}, {-0.201965, -0.970795, -0.12915}, + {0.313477, 0.947327, 0.06546}, {-0.254028, -0.528259, 0.81015}, + {0.628052, 0.601105, 0.49411}, {-0.494385, 0.868378, 0.037933}, + {0.275635, -0.086426, 0.957336}, {-0.197937, 0.468903, -0.860748}, + {0.895599, 0.399384, 0.195801}, {0.560791, 0.825012, -0.069214}, + {0.304199, -0.849487, 0.43103}, {0.096375, 0.93576, 0.339111}, + {-0.051422, 0.408966, -0.911072}, {0.330444, 0.942841, -0.042389}, + {-0.452362, -0.786407, 0.420563}, {0.134308, -0.933472, -0.332489}, + {0.80191, -0.566711, -0.188934}, {-0.987946, -0.105988, 0.112518}, + {-0.24408, 0.892242, -0.379791}, {-0.920502, 0.229095, -0.316376}, + {0.7789, 0.325958, 0.535706}, {-0.912872, 0.185211, -0.36377}, + {-0.184784, 0.565369, -0.803833}, {-0.018463, 0.119537, 0.992615}, + {-0.259247, -0.935608, 0.239532}, {-0.82373, -0.449127, -0.345947}, + {-0.433105, 0.659515, 0.614349}, {-0.822754, 0.378845, -0.423676}, + {0.687195, -0.674835, -0.26889}, {-0.246582, -0.800842, 0.545715}, + {-0.729187, -0.207794, 0.651978}, {0.653534, -0.610443, -0.447388}, + {0.492584, -0.023346, 0.869934}, {0.609039, 0.009094, -0.79306}, + {0.962494, -0.271088, -0.00885}, {0.2659, -0.004913, 0.963959}, + {0.651245, 0.553619, -0.518951}, {0.280548, -0.84314, 0.458618}, + {-0.175293, -0.983215, 0.049805}, {0.035339, -0.979919, 0.196045}, + {-0.982941, 0.164307, -0.082245}, {0.233734, -0.97226, -0.005005}, + {-0.747253, -0.611328, 0.260437}, {0.645599, 0.592773, 0.481384}, + {0.117706, -0.949524, -0.29068}, {-0.535004, -0.791901, -0.294312}, + {-0.627167, -0.214447, 0.748718}, {-0.047974, -0.813477, -0.57959}, + {-0.175537, 0.477264, -0.860992}, {0.738556, -0.414246, -0.53183}, + {0.562561, -0.704071, 0.433289}, {-0.754944, 0.64801, -0.100586}, + {0.114716, 0.044525, -0.992371}, {0.966003, 0.244873, -0.082764}, + {0.33783, 0.715698, -0.611206}, {-0.944031, -0.326599, -0.045624}, }; -#define SETUP(val, b0, b1, r0, r1) \ - { \ - t = val + 10000.0f; \ - b0 = ((int)t) & 255; \ - b1 = (b0 + 1) & 255; \ - r0 = t - floorf(t); \ - r1 = r0 - 1.0f; \ - } (void)0 - +#define SETUP(val, b0, b1, r0, r1) \ + { \ + t = val + 10000.0f; \ + b0 = ((int)t) & 255; \ + b1 = (b0 + 1) & 255; \ + r0 = t - floorf(t); \ + r1 = r0 - 1.0f; \ + } \ + (void)0 static float noise3_perlin(float vec[3]) { - const char *p = g_perlin_data_ub; - const float (*g)[3] = g_perlin_data_v3; - int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, rz0, rz1, sx, sy, sz, a, b, c, d, t, u, v; - const float *q; - register int i, j; - - - SETUP(vec[0], bx0, bx1, rx0, rx1); - SETUP(vec[1], by0, by1, ry0, ry1); - SETUP(vec[2], bz0, bz1, rz0, rz1); - - i = p[bx0]; - j = p[bx1]; - - b00 = p[i + by0]; - b10 = p[j + by0]; - b01 = p[i + by1]; - b11 = p[j + by1]; - -#define VALUE_AT(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2]) + const char *p = g_perlin_data_ub; + const float(*g)[3] = g_perlin_data_v3; + int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; + float rx0, rx1, ry0, ry1, rz0, rz1, sx, sy, sz, a, b, c, d, t, u, v; + const float *q; + register int i, j; + + SETUP(vec[0], bx0, bx1, rx0, rx1); + SETUP(vec[1], by0, by1, ry0, ry1); + SETUP(vec[2], bz0, bz1, rz0, rz1); + + i = p[bx0]; + j = p[bx1]; + + b00 = p[i + by0]; + b10 = p[j + by0]; + b01 = p[i + by1]; + b11 = p[j + by1]; + +#define VALUE_AT(rx, ry, rz) ((rx)*q[0] + (ry)*q[1] + (rz)*q[2]) #define SURVE(t) ((t) * (t) * (3.0f - 2.0f * (t))) -/* lerp moved to improved perlin above */ + /* lerp moved to improved perlin above */ - sx = SURVE(rx0); - sy = SURVE(ry0); - sz = SURVE(rz0); + sx = SURVE(rx0); + sy = SURVE(ry0); + sz = SURVE(rz0); + q = g[b00 + bz0]; + u = VALUE_AT(rx0, ry0, rz0); + q = g[b10 + bz0]; + v = VALUE_AT(rx1, ry0, rz0); + a = lerp(sx, u, v); - q = g[b00 + bz0]; - u = VALUE_AT(rx0, ry0, rz0); - q = g[b10 + bz0]; - v = VALUE_AT(rx1, ry0, rz0); - a = lerp(sx, u, v); + q = g[b01 + bz0]; + u = VALUE_AT(rx0, ry1, rz0); + q = g[b11 + bz0]; + v = VALUE_AT(rx1, ry1, rz0); + b = lerp(sx, u, v); - q = g[b01 + bz0]; - u = VALUE_AT(rx0, ry1, rz0); - q = g[b11 + bz0]; - v = VALUE_AT(rx1, ry1, rz0); - b = lerp(sx, u, v); + c = lerp(sy, a, b); /* interpolate in y at lo x */ - c = lerp(sy, a, b); /* interpolate in y at lo x */ + q = g[b00 + bz1]; + u = VALUE_AT(rx0, ry0, rz1); + q = g[b10 + bz1]; + v = VALUE_AT(rx1, ry0, rz1); + a = lerp(sx, u, v); - q = g[b00 + bz1]; - u = VALUE_AT(rx0, ry0, rz1); - q = g[b10 + bz1]; - v = VALUE_AT(rx1, ry0, rz1); - a = lerp(sx, u, v); + q = g[b01 + bz1]; + u = VALUE_AT(rx0, ry1, rz1); + q = g[b11 + bz1]; + v = VALUE_AT(rx1, ry1, rz1); + b = lerp(sx, u, v); - q = g[b01 + bz1]; - u = VALUE_AT(rx0, ry1, rz1); - q = g[b11 + bz1]; - v = VALUE_AT(rx1, ry1, rz1); - b = lerp(sx, u, v); + d = lerp(sy, a, b); /* interpolate in y at hi x */ - d = lerp(sy, a, b); /* interpolate in y at hi x */ - - return 1.5f * lerp(sz, c, d); /* interpolate in z */ + return 1.5f * lerp(sz, c, d); /* interpolate in z */ #undef VALUE_AT #undef SURVE @@ -1092,36 +845,36 @@ static float noise3_perlin(float vec[3]) /* for use with BLI_gNoise/gTurbulence, returns signed noise */ static float orgPerlinNoise(float x, float y, float z) { - float v[3]; + float v[3]; - v[0] = x; - v[1] = y; - v[2] = z; - return noise3_perlin(v); + v[0] = x; + v[1] = y; + v[2] = z; + return noise3_perlin(v); } /* for use with BLI_gNoise/gTurbulence, returns unsigned noise */ static float orgPerlinNoiseU(float x, float y, float z) { - float v[3]; + float v[3]; - v[0] = x; - v[1] = y; - v[2] = z; - return (0.5f + 0.5f * noise3_perlin(v)); + v[0] = x; + v[1] = y; + v[2] = z; + return (0.5f + 0.5f * noise3_perlin(v)); } /* *************** CALL AS: *************** */ float BLI_hnoisep(float noisesize, float x, float y, float z) { - float vec[3]; + float vec[3]; - vec[0] = x / noisesize; - vec[1] = y / noisesize; - vec[2] = z / noisesize; + vec[0] = x / noisesize; + vec[1] = y / noisesize; + vec[2] = z / noisesize; - return noise3_perlin(vec); + return noise3_perlin(vec); } /******************/ @@ -1134,224 +887,250 @@ float BLI_hnoisep(float noisesize, float x, float y, float z) /* distance squared */ static float dist_Squared(float x, float y, float z, float e) { - (void)e; return (x * x + y * y + z * z); + (void)e; + return (x * x + y * y + z * z); } /* real distance */ static float dist_Real(float x, float y, float z, float e) { - (void)e; return sqrtf(x * x + y * y + z * z); + (void)e; + return sqrtf(x * x + y * y + z * z); } /* manhattan/taxicab/cityblock distance */ static float dist_Manhattan(float x, float y, float z, float e) { - (void)e; return (fabsf(x) + fabsf(y) + fabsf(z)); + (void)e; + return (fabsf(x) + fabsf(y) + fabsf(z)); } /* Chebychev */ static float dist_Chebychev(float x, float y, float z, float e) { - float t; - (void)e; - - x = fabsf(x); - y = fabsf(y); - z = fabsf(z); - t = (x > y) ? x : y; - return ((z > t) ? z : t); + float t; + (void)e; + + x = fabsf(x); + y = fabsf(y); + z = fabsf(z); + t = (x > y) ? x : y; + return ((z > t) ? z : t); } /* minkowski preset exponent 0.5 */ static float dist_MinkovskyH(float x, float y, float z, float e) { - float d = sqrtf(fabsf(x)) + sqrtf(fabsf(y)) + sqrtf(fabsf(z)); - (void)e; - return (d * d); + float d = sqrtf(fabsf(x)) + sqrtf(fabsf(y)) + sqrtf(fabsf(z)); + (void)e; + return (d * d); } /* minkowski preset exponent 4 */ static float dist_Minkovsky4(float x, float y, float z, float e) { - (void)e; - x *= x; - y *= y; - z *= z; - return sqrtf(sqrtf(x * x + y * y + z * z)); + (void)e; + x *= x; + y *= y; + z *= z; + return sqrtf(sqrtf(x * x + y * y + z * z)); } /* Minkowski, general case, slow, maybe too slow to be useful */ static float dist_Minkovsky(float x, float y, float z, float e) { - return powf(powf(fabsf(x), e) + powf(fabsf(y), e) + powf(fabsf(z), e), 1.0f / e); + return powf(powf(fabsf(x), e) + powf(fabsf(y), e) + powf(fabsf(z), e), 1.0f / e); } - /* Not 'pure' Worley, but the results are virtually the same. * Returns distances in da and point coords in pa */ void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype) { - int xx, yy, zz, xi, yi, zi; - float xd, yd, zd, d; - - float (*distfunc)(float, float, float, float); - switch (dtype) { - case 1: - distfunc = dist_Squared; - break; - case 2: - distfunc = dist_Manhattan; - break; - case 3: - distfunc = dist_Chebychev; - break; - case 4: - distfunc = dist_MinkovskyH; - break; - case 5: - distfunc = dist_Minkovsky4; - break; - case 6: - distfunc = dist_Minkovsky; - break; - case 0: - default: - distfunc = dist_Real; - break; - } - - xi = (int)(floor(x)); - yi = (int)(floor(y)); - zi = (int)(floor(z)); - da[0] = da[1] = da[2] = da[3] = 1e10f; - for (xx = xi - 1; xx <= xi + 1; xx++) { - for (yy = yi - 1; yy <= yi + 1; yy++) { - for (zz = zi - 1; zz <= zi + 1; zz++) { - const float *p = HASHPNT(xx, yy, zz); - xd = x - (p[0] + xx); - yd = y - (p[1] + yy); - zd = z - (p[2] + zz); - d = distfunc(xd, yd, zd, me); - if (d < da[0]) { - da[3] = da[2]; da[2] = da[1]; da[1] = da[0]; da[0] = d; - pa[9] = pa[6]; pa[10] = pa[7]; pa[11] = pa[8]; - pa[6] = pa[3]; pa[7] = pa[4]; pa[8] = pa[5]; - pa[3] = pa[0]; pa[4] = pa[1]; pa[5] = pa[2]; - pa[0] = p[0] + xx; pa[1] = p[1] + yy; pa[2] = p[2] + zz; - } - else if (d < da[1]) { - da[3] = da[2]; da[2] = da[1]; da[1] = d; - pa[9] = pa[6]; pa[10] = pa[7]; pa[11] = pa[8]; - pa[6] = pa[3]; pa[7] = pa[4]; pa[8] = pa[5]; - pa[3] = p[0] + xx; pa[4] = p[1] + yy; pa[5] = p[2] + zz; - } - else if (d < da[2]) { - da[3] = da[2]; da[2] = d; - pa[9] = pa[6]; pa[10] = pa[7]; pa[11] = pa[8]; - pa[6] = p[0] + xx; pa[7] = p[1] + yy; pa[8] = p[2] + zz; - } - else if (d < da[3]) { - da[3] = d; - pa[9] = p[0] + xx; pa[10] = p[1] + yy; pa[11] = p[2] + zz; - } - } - } - } + int xx, yy, zz, xi, yi, zi; + float xd, yd, zd, d; + + float (*distfunc)(float, float, float, float); + switch (dtype) { + case 1: + distfunc = dist_Squared; + break; + case 2: + distfunc = dist_Manhattan; + break; + case 3: + distfunc = dist_Chebychev; + break; + case 4: + distfunc = dist_MinkovskyH; + break; + case 5: + distfunc = dist_Minkovsky4; + break; + case 6: + distfunc = dist_Minkovsky; + break; + case 0: + default: + distfunc = dist_Real; + break; + } + + xi = (int)(floor(x)); + yi = (int)(floor(y)); + zi = (int)(floor(z)); + da[0] = da[1] = da[2] = da[3] = 1e10f; + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { + const float *p = HASHPNT(xx, yy, zz); + xd = x - (p[0] + xx); + yd = y - (p[1] + yy); + zd = z - (p[2] + zz); + d = distfunc(xd, yd, zd, me); + if (d < da[0]) { + da[3] = da[2]; + da[2] = da[1]; + da[1] = da[0]; + da[0] = d; + pa[9] = pa[6]; + pa[10] = pa[7]; + pa[11] = pa[8]; + pa[6] = pa[3]; + pa[7] = pa[4]; + pa[8] = pa[5]; + pa[3] = pa[0]; + pa[4] = pa[1]; + pa[5] = pa[2]; + pa[0] = p[0] + xx; + pa[1] = p[1] + yy; + pa[2] = p[2] + zz; + } + else if (d < da[1]) { + da[3] = da[2]; + da[2] = da[1]; + da[1] = d; + pa[9] = pa[6]; + pa[10] = pa[7]; + pa[11] = pa[8]; + pa[6] = pa[3]; + pa[7] = pa[4]; + pa[8] = pa[5]; + pa[3] = p[0] + xx; + pa[4] = p[1] + yy; + pa[5] = p[2] + zz; + } + else if (d < da[2]) { + da[3] = da[2]; + da[2] = d; + pa[9] = pa[6]; + pa[10] = pa[7]; + pa[11] = pa[8]; + pa[6] = p[0] + xx; + pa[7] = p[1] + yy; + pa[8] = p[2] + zz; + } + else if (d < da[3]) { + da[3] = d; + pa[9] = p[0] + xx; + pa[10] = p[1] + yy; + pa[11] = p[2] + zz; + } + } + } + } } /* returns different feature points for use in BLI_gNoise() */ static float voronoi_F1(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return da[0]; + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return da[0]; } static float voronoi_F2(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return da[1]; + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return da[1]; } static float voronoi_F3(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return da[2]; + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return da[2]; } static float voronoi_F4(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return da[3]; + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return da[3]; } static float voronoi_F1F2(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (da[1] - da[0]); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (da[1] - da[0]); } /* Crackle type pattern, just a scale/clamp of F2-F1 */ static float voronoi_Cr(float x, float y, float z) { - float t = 10 * voronoi_F1F2(x, y, z); - if (t > 1.f) { - return 1.f; - } - return t; + float t = 10 * voronoi_F1F2(x, y, z); + if (t > 1.f) { + return 1.f; + } + return t; } - /* Signed version of all 6 of the above, just 2x-1, not really correct though * (range is potentially (0, sqrt(6)). * Used in the musgrave functions */ static float voronoi_F1S(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (2.0f * da[0] - 1.0f); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (2.0f * da[0] - 1.0f); } static float voronoi_F2S(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (2.0f * da[1] - 1.0f); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (2.0f * da[1] - 1.0f); } static float voronoi_F3S(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (2.0f * da[2] - 1.0f); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (2.0f * da[2] - 1.0f); } static float voronoi_F4S(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (2.0f * da[3] - 1.0f); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (2.0f * da[3] - 1.0f); } static float voronoi_F1F2S(float x, float y, float z) { - float da[4], pa[12]; - voronoi(x, y, z, da, pa, 1, 0); - return (2.0f * (da[1] - da[0]) - 1.0f); + float da[4], pa[12]; + voronoi(x, y, z, da, pa, 1, 0); + return (2.0f * (da[1] - da[0]) - 1.0f); } /* Crackle type pattern, just a scale/clamp of F2-F1 */ static float voronoi_CrS(float x, float y, float z) { - float t = 10 * voronoi_F1F2(x, y, z); - if (t > 1.f) { - return 1.f; - } - return (2.0f * t - 1.0f); + float t = 10 * voronoi_F1F2(x, y, z); + if (t > 1.f) { + return 1.f; + } + return (2.0f * t - 1.0f); } - /***************/ /* voronoi end */ /***************/ @@ -1363,43 +1142,42 @@ static float voronoi_CrS(float x, float y, float z) /* returns unsigned cellnoise */ static float cellNoiseU(float x, float y, float z) { - /* avoid precision issues on unit coordinates */ - x = (x + 0.000001f) * 1.00001f; - y = (y + 0.000001f) * 1.00001f; - z = (z + 0.000001f) * 1.00001f; - - int xi = (int)(floor(x)); - int yi = (int)(floor(y)); - int zi = (int)(floor(z)); - unsigned int n = xi + yi * 1301 + zi * 314159; - n ^= (n << 13); - return ((float)(n * (n * n * 15731 + 789221) + 1376312589) / 4294967296.0f); + /* avoid precision issues on unit coordinates */ + x = (x + 0.000001f) * 1.00001f; + y = (y + 0.000001f) * 1.00001f; + z = (z + 0.000001f) * 1.00001f; + + int xi = (int)(floor(x)); + int yi = (int)(floor(y)); + int zi = (int)(floor(z)); + unsigned int n = xi + yi * 1301 + zi * 314159; + n ^= (n << 13); + return ((float)(n * (n * n * 15731 + 789221) + 1376312589) / 4294967296.0f); } /* idem, signed */ float cellNoise(float x, float y, float z) { - return (2.0f * cellNoiseU(x, y, z) - 1.0f); + return (2.0f * cellNoiseU(x, y, z) - 1.0f); } /* returns a vector/point/color in ca, using point hasharray directly */ void cellNoiseV(float x, float y, float z, float ca[3]) { - /* avoid precision issues on unit coordinates */ - x = (x + 0.000001f) * 1.00001f; - y = (y + 0.000001f) * 1.00001f; - z = (z + 0.000001f) * 1.00001f; - - int xi = (int)(floor(x)); - int yi = (int)(floor(y)); - int zi = (int)(floor(z)); - const float *p = HASHPNT(xi, yi, zi); - ca[0] = p[0]; - ca[1] = p[1]; - ca[2] = p[2]; + /* avoid precision issues on unit coordinates */ + x = (x + 0.000001f) * 1.00001f; + y = (y + 0.000001f) * 1.00001f; + z = (z + 0.000001f) * 1.00001f; + + int xi = (int)(floor(x)); + int yi = (int)(floor(y)); + int zi = (int)(floor(z)); + const float *p = HASHPNT(xi, yi, zi); + ca[0] = p[0]; + ca[1] = p[1]; + ca[2] = p[2]; } - /*****************/ /* end cellnoise */ /*****************/ @@ -1407,128 +1185,126 @@ void cellNoiseV(float x, float y, float z, float ca[3]) /* newnoise: generic noise function for use with different noisebases */ float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noisebasis) { - float (*noisefunc)(float, float, float); - - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoiseU; - break; - case 2: - noisefunc = newPerlinU; - break; - case 3: - noisefunc = voronoi_F1; - break; - case 4: - noisefunc = voronoi_F2; - break; - case 5: - noisefunc = voronoi_F3; - break; - case 6: - noisefunc = voronoi_F4; - break; - case 7: - noisefunc = voronoi_F1F2; - break; - case 8: - noisefunc = voronoi_Cr; - break; - case 14: - noisefunc = cellNoiseU; - break; - case 0: - default: - { - noisefunc = orgBlenderNoise; - /* add one to make return value same as BLI_hnoise */ - x += 1; - y += 1; - z += 1; - break; - } - } - - if (noisesize != 0.0f) { - noisesize = 1.0f / noisesize; - x *= noisesize; - y *= noisesize; - z *= noisesize; - } - - if (hard) { - return fabsf(2.0f * noisefunc(x, y, z) - 1.0f); - } - return noisefunc(x, y, z); + float (*noisefunc)(float, float, float); + + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoiseU; + break; + case 2: + noisefunc = newPerlinU; + break; + case 3: + noisefunc = voronoi_F1; + break; + case 4: + noisefunc = voronoi_F2; + break; + case 5: + noisefunc = voronoi_F3; + break; + case 6: + noisefunc = voronoi_F4; + break; + case 7: + noisefunc = voronoi_F1F2; + break; + case 8: + noisefunc = voronoi_Cr; + break; + case 14: + noisefunc = cellNoiseU; + break; + case 0: + default: { + noisefunc = orgBlenderNoise; + /* add one to make return value same as BLI_hnoise */ + x += 1; + y += 1; + z += 1; + break; + } + } + + if (noisesize != 0.0f) { + noisesize = 1.0f / noisesize; + x *= noisesize; + y *= noisesize; + z *= noisesize; + } + + if (hard) { + return fabsf(2.0f * noisefunc(x, y, z) - 1.0f); + } + return noisefunc(x, y, z); } /* newnoise: generic turbulence function for use with different noisebasis */ -float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int hard, int noisebasis) +float BLI_gTurbulence( + float noisesize, float x, float y, float z, int oct, int hard, int noisebasis) { - float (*noisefunc)(float, float, float); - float sum, t, amp = 1, fscale = 1; - int i; - - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoiseU; - break; - case 2: - noisefunc = newPerlinU; - break; - case 3: - noisefunc = voronoi_F1; - break; - case 4: - noisefunc = voronoi_F2; - break; - case 5: - noisefunc = voronoi_F3; - break; - case 6: - noisefunc = voronoi_F4; - break; - case 7: - noisefunc = voronoi_F1F2; - break; - case 8: - noisefunc = voronoi_Cr; - break; - case 14: - noisefunc = cellNoiseU; - break; - case 0: - default: - noisefunc = orgBlenderNoise; - x += 1; - y += 1; - z += 1; - break; - } - - if (noisesize != 0.0f) { - noisesize = 1.0f / noisesize; - x *= noisesize; - y *= noisesize; - z *= noisesize; - } - - sum = 0; - for (i = 0; i <= oct; i++, amp *= 0.5f, fscale *= 2.0f) { - t = noisefunc(fscale * x, fscale * y, fscale * z); - if (hard) { - t = fabsf(2.0f * t - 1.0f); - } - sum += t * amp; - } - - sum *= ((float)(1 << oct) / (float)((1 << (oct + 1)) - 1)); - - return sum; - + float (*noisefunc)(float, float, float); + float sum, t, amp = 1, fscale = 1; + int i; + + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoiseU; + break; + case 2: + noisefunc = newPerlinU; + break; + case 3: + noisefunc = voronoi_F1; + break; + case 4: + noisefunc = voronoi_F2; + break; + case 5: + noisefunc = voronoi_F3; + break; + case 6: + noisefunc = voronoi_F4; + break; + case 7: + noisefunc = voronoi_F1F2; + break; + case 8: + noisefunc = voronoi_Cr; + break; + case 14: + noisefunc = cellNoiseU; + break; + case 0: + default: + noisefunc = orgBlenderNoise; + x += 1; + y += 1; + z += 1; + break; + } + + if (noisesize != 0.0f) { + noisesize = 1.0f / noisesize; + x *= noisesize; + y *= noisesize; + z *= noisesize; + } + + sum = 0; + for (i = 0; i <= oct; i++, amp *= 0.5f, fscale *= 2.0f) { + t = noisefunc(fscale * x, fscale * y, fscale * z); + if (hard) { + t = fabsf(2.0f * t - 1.0f); + } + sum += t * amp; + } + + sum *= ((float)(1 << oct) / (float)((1 << (oct + 1)) - 1)); + + return sum; } - /* * The following code is based on Ken Musgrave's explanations and sample * source code in the book "Texturing and Modeling: A procedural approach" @@ -1544,64 +1320,62 @@ float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int h */ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis) { - float rmd, value = 0.0, pwr = 1.0, pwHL = powf(lacunarity, -H); - int i; - - float (*noisefunc)(float, float, float); - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoise; - break; - case 2: - noisefunc = newPerlin; - break; - case 3: - noisefunc = voronoi_F1S; - break; - case 4: - noisefunc = voronoi_F2S; - break; - case 5: - noisefunc = voronoi_F3S; - break; - case 6: - noisefunc = voronoi_F4S; - break; - case 7: - noisefunc = voronoi_F1F2S; - break; - case 8: - noisefunc = voronoi_CrS; - break; - case 14: - noisefunc = cellNoise; - break; - case 0: - default: - { - noisefunc = orgBlenderNoiseS; - break; - } - } - - for (i = 0; i < (int)octaves; i++) { - value += noisefunc(x, y, z) * pwr; - pwr *= pwHL; - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - } - - rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * noisefunc(x, y, z) * pwr; - } - - return value; + float rmd, value = 0.0, pwr = 1.0, pwHL = powf(lacunarity, -H); + int i; + + float (*noisefunc)(float, float, float); + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoise; + break; + case 2: + noisefunc = newPerlin; + break; + case 3: + noisefunc = voronoi_F1S; + break; + case 4: + noisefunc = voronoi_F2S; + break; + case 5: + noisefunc = voronoi_F3S; + break; + case 6: + noisefunc = voronoi_F4S; + break; + case 7: + noisefunc = voronoi_F1F2S; + break; + case 8: + noisefunc = voronoi_CrS; + break; + case 14: + noisefunc = cellNoise; + break; + case 0: + default: { + noisefunc = orgBlenderNoiseS; + break; + } + } + + for (i = 0; i < (int)octaves; i++) { + value += noisefunc(x, y, z) * pwr; + pwr *= pwHL; + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + } + + rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value += rmd * noisefunc(x, y, z) * pwr; + } + + return value; } /* fBm() */ - /* * Procedural multifractal evaluated at "point"; * returns value stored in "value". @@ -1616,61 +1390,61 @@ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves /* this one is in fact rather confusing, * there seem to be errors in the original source code (in all three versions of proc.text&mod), * I modified it to something that made sense to me, so it might be wrong... */ -float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis) +float mg_MultiFractal( + float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis) { - float rmd, value = 1.0, pwr = 1.0, pwHL = powf(lacunarity, -H); - int i; - - float (*noisefunc)(float, float, float); - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoise; - break; - case 2: - noisefunc = newPerlin; - break; - case 3: - noisefunc = voronoi_F1S; - break; - case 4: - noisefunc = voronoi_F2S; - break; - case 5: - noisefunc = voronoi_F3S; - break; - case 6: - noisefunc = voronoi_F4S; - break; - case 7: - noisefunc = voronoi_F1F2S; - break; - case 8: - noisefunc = voronoi_CrS; - break; - case 14: - noisefunc = cellNoise; - break; - case 0: - default: - { - noisefunc = orgBlenderNoiseS; - break; - } - } - - for (i = 0; i < (int)octaves; i++) { - value *= (pwr * noisefunc(x, y, z) + 1.0f); - pwr *= pwHL; - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - } - rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value *= (rmd * noisefunc(x, y, z) * pwr + 1.0f); - } - - return value; + float rmd, value = 1.0, pwr = 1.0, pwHL = powf(lacunarity, -H); + int i; + + float (*noisefunc)(float, float, float); + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoise; + break; + case 2: + noisefunc = newPerlin; + break; + case 3: + noisefunc = voronoi_F1S; + break; + case 4: + noisefunc = voronoi_F2S; + break; + case 5: + noisefunc = voronoi_F3S; + break; + case 6: + noisefunc = voronoi_F4S; + break; + case 7: + noisefunc = voronoi_F1F2S; + break; + case 8: + noisefunc = voronoi_CrS; + break; + case 14: + noisefunc = cellNoise; + break; + case 0: + default: { + noisefunc = orgBlenderNoiseS; + break; + } + } + + for (i = 0; i < (int)octaves; i++) { + value *= (pwr * noisefunc(x, y, z) + 1.0f); + pwr *= pwHL; + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + } + rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + value *= (rmd * noisefunc(x, y, z) * pwr + 1.0f); + } + + return value; } /* multifractal() */ @@ -1684,74 +1458,79 @@ float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, floa * ``octaves'' is the number of frequencies in the fBm * ``offset'' raises the terrain from `sea level' */ -float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, float octaves, float offset, int noisebasis) +float mg_HeteroTerrain(float x, + float y, + float z, + float H, + float lacunarity, + float octaves, + float offset, + int noisebasis) { - float value, increment, rmd; - int i; - float pwHL = powf(lacunarity, -H); - float pwr = pwHL; /* starts with i=1 instead of 0 */ - - float (*noisefunc)(float, float, float); - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoise; - break; - case 2: - noisefunc = newPerlin; - break; - case 3: - noisefunc = voronoi_F1S; - break; - case 4: - noisefunc = voronoi_F2S; - break; - case 5: - noisefunc = voronoi_F3S; - break; - case 6: - noisefunc = voronoi_F4S; - break; - case 7: - noisefunc = voronoi_F1F2S; - break; - case 8: - noisefunc = voronoi_CrS; - break; - case 14: - noisefunc = cellNoise; - break; - case 0: - default: - { - noisefunc = orgBlenderNoiseS; - break; - } - } - - /* first unscaled octave of function; later octaves are scaled */ - value = offset + noisefunc(x, y, z); - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - - for (i = 1; i < (int)octaves; i++) { - increment = (noisefunc(x, y, z) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - } - - rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - increment = (noisefunc(x, y, z) + offset) * pwr * value; - value += rmd * increment; - } - return value; + float value, increment, rmd; + int i; + float pwHL = powf(lacunarity, -H); + float pwr = pwHL; /* starts with i=1 instead of 0 */ + + float (*noisefunc)(float, float, float); + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoise; + break; + case 2: + noisefunc = newPerlin; + break; + case 3: + noisefunc = voronoi_F1S; + break; + case 4: + noisefunc = voronoi_F2S; + break; + case 5: + noisefunc = voronoi_F3S; + break; + case 6: + noisefunc = voronoi_F4S; + break; + case 7: + noisefunc = voronoi_F1F2S; + break; + case 8: + noisefunc = voronoi_CrS; + break; + case 14: + noisefunc = cellNoise; + break; + case 0: + default: { + noisefunc = orgBlenderNoiseS; + break; + } + } + + /* first unscaled octave of function; later octaves are scaled */ + value = offset + noisefunc(x, y, z); + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + + for (i = 1; i < (int)octaves; i++) { + increment = (noisefunc(x, y, z) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + } + + rmd = octaves - floorf(octaves); + if (rmd != 0.0f) { + increment = (noisefunc(x, y, z) + offset) * pwr * value; + value += rmd * increment; + } + return value; } - /* Hybrid additive/multiplicative multifractal terrain model. * * Some good parameter values to start with: @@ -1759,79 +1538,85 @@ float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, flo * H: 0.25 * offset: 0.7 */ -float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis) +float mg_HybridMultiFractal(float x, + float y, + float z, + float H, + float lacunarity, + float octaves, + float offset, + float gain, + int noisebasis) { - float result, signal, weight, rmd; - int i; - float pwHL = powf(lacunarity, -H); - float pwr = pwHL; /* starts with i=1 instead of 0 */ - float (*noisefunc)(float, float, float); - - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoise; - break; - case 2: - noisefunc = newPerlin; - break; - case 3: - noisefunc = voronoi_F1S; - break; - case 4: - noisefunc = voronoi_F2S; - break; - case 5: - noisefunc = voronoi_F3S; - break; - case 6: - noisefunc = voronoi_F4S; - break; - case 7: - noisefunc = voronoi_F1F2S; - break; - case 8: - noisefunc = voronoi_CrS; - break; - case 14: - noisefunc = cellNoise; - break; - case 0: - default: - { - noisefunc = orgBlenderNoiseS; - break; - } - } - - result = noisefunc(x, y, z) + offset; - weight = gain * result; - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - - for (i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { - if (weight > 1.0f) { - weight = 1.0f; - } - signal = (noisefunc(x, y, z) + offset) * pwr; - pwr *= pwHL; - result += weight * signal; - weight *= gain * signal; - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - } - - rmd = octaves - floorf(octaves); - if (rmd != 0.f) { - result += rmd * ((noisefunc(x, y, z) + offset) * pwr); - } - - return result; + float result, signal, weight, rmd; + int i; + float pwHL = powf(lacunarity, -H); + float pwr = pwHL; /* starts with i=1 instead of 0 */ + float (*noisefunc)(float, float, float); + + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoise; + break; + case 2: + noisefunc = newPerlin; + break; + case 3: + noisefunc = voronoi_F1S; + break; + case 4: + noisefunc = voronoi_F2S; + break; + case 5: + noisefunc = voronoi_F3S; + break; + case 6: + noisefunc = voronoi_F4S; + break; + case 7: + noisefunc = voronoi_F1F2S; + break; + case 8: + noisefunc = voronoi_CrS; + break; + case 14: + noisefunc = cellNoise; + break; + case 0: + default: { + noisefunc = orgBlenderNoiseS; + break; + } + } + + result = noisefunc(x, y, z) + offset; + weight = gain * result; + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + + for (i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + if (weight > 1.0f) { + weight = 1.0f; + } + signal = (noisefunc(x, y, z) + offset) * pwr; + pwr *= pwHL; + result += weight * signal; + weight *= gain * signal; + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + } + + rmd = octaves - floorf(octaves); + if (rmd != 0.f) { + result += rmd * ((noisefunc(x, y, z) + offset) * pwr); + } + + return result; } /* HybridMultifractal() */ - /* Ridged multifractal terrain model. * * Some good parameter values to start with: @@ -1840,70 +1625,80 @@ float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity * offset: 1.0 * gain: 2.0 */ -float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis) +float mg_RidgedMultiFractal(float x, + float y, + float z, + float H, + float lacunarity, + float octaves, + float offset, + float gain, + int noisebasis) { - float result, signal, weight; - int i; - float pwHL = powf(lacunarity, -H); - float pwr = pwHL; /* starts with i=1 instead of 0 */ - - float (*noisefunc)(float, float, float); - switch (noisebasis) { - case 1: - noisefunc = orgPerlinNoise; - break; - case 2: - noisefunc = newPerlin; - break; - case 3: - noisefunc = voronoi_F1S; - break; - case 4: - noisefunc = voronoi_F2S; - break; - case 5: - noisefunc = voronoi_F3S; - break; - case 6: - noisefunc = voronoi_F4S; - break; - case 7: - noisefunc = voronoi_F1F2S; - break; - case 8: - noisefunc = voronoi_CrS; - break; - case 14: - noisefunc = cellNoise; - break; - case 0: - default: - { - noisefunc = orgBlenderNoiseS; - break; - } - } - - signal = offset - fabsf(noisefunc(x, y, z)); - signal *= signal; - result = signal; - - - for (i = 1; i < (int)octaves; i++) { - x *= lacunarity; - y *= lacunarity; - z *= lacunarity; - weight = signal * gain; - if (weight > 1.0f) { weight = 1.0f; } - else if (weight < 0.0f) { weight = 0.0f; } - signal = offset - fabsf(noisefunc(x, y, z)); - signal *= signal; - signal *= weight; - result += signal * pwr; - pwr *= pwHL; - } - - return result; + float result, signal, weight; + int i; + float pwHL = powf(lacunarity, -H); + float pwr = pwHL; /* starts with i=1 instead of 0 */ + + float (*noisefunc)(float, float, float); + switch (noisebasis) { + case 1: + noisefunc = orgPerlinNoise; + break; + case 2: + noisefunc = newPerlin; + break; + case 3: + noisefunc = voronoi_F1S; + break; + case 4: + noisefunc = voronoi_F2S; + break; + case 5: + noisefunc = voronoi_F3S; + break; + case 6: + noisefunc = voronoi_F4S; + break; + case 7: + noisefunc = voronoi_F1F2S; + break; + case 8: + noisefunc = voronoi_CrS; + break; + case 14: + noisefunc = cellNoise; + break; + case 0: + default: { + noisefunc = orgBlenderNoiseS; + break; + } + } + + signal = offset - fabsf(noisefunc(x, y, z)); + signal *= signal; + result = signal; + + for (i = 1; i < (int)octaves; i++) { + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + weight = signal * gain; + if (weight > 1.0f) { + weight = 1.0f; + } + else if (weight < 0.0f) { + weight = 0.0f; + } + signal = offset - fabsf(noisefunc(x, y, z)); + signal *= signal; + signal *= weight; + result += signal * pwr; + pwr *= pwHL; + } + + return result; } /* RidgedMultifractal() */ /* "Variable Lacunarity Noise" @@ -1911,87 +1706,85 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity */ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nbas2) { - float rv[3]; - float (*noisefunc1)(float, float, float); - float (*noisefunc2)(float, float, float); - - switch (nbas1) { - case 1: - noisefunc1 = orgPerlinNoise; - break; - case 2: - noisefunc1 = newPerlin; - break; - case 3: - noisefunc1 = voronoi_F1S; - break; - case 4: - noisefunc1 = voronoi_F2S; - break; - case 5: - noisefunc1 = voronoi_F3S; - break; - case 6: - noisefunc1 = voronoi_F4S; - break; - case 7: - noisefunc1 = voronoi_F1F2S; - break; - case 8: - noisefunc1 = voronoi_CrS; - break; - case 14: - noisefunc1 = cellNoise; - break; - case 0: - default: - { - noisefunc1 = orgBlenderNoiseS; - break; - } - } - - switch (nbas2) { - case 1: - noisefunc2 = orgPerlinNoise; - break; - case 2: - noisefunc2 = newPerlin; - break; - case 3: - noisefunc2 = voronoi_F1S; - break; - case 4: - noisefunc2 = voronoi_F2S; - break; - case 5: - noisefunc2 = voronoi_F3S; - break; - case 6: - noisefunc2 = voronoi_F4S; - break; - case 7: - noisefunc2 = voronoi_F1F2S; - break; - case 8: - noisefunc2 = voronoi_CrS; - break; - case 14: - noisefunc2 = cellNoise; - break; - case 0: - default: - { - noisefunc2 = orgBlenderNoiseS; - break; - } - } - - /* get a random vector and scale the randomization */ - rv[0] = noisefunc1(x + 13.5f, y + 13.5f, z + 13.5f) * distortion; - rv[1] = noisefunc1(x, y, z) * distortion; - rv[2] = noisefunc1(x - 13.5f, y - 13.5f, z - 13.5f) * distortion; - return noisefunc2(x + rv[0], y + rv[1], z + rv[2]); /* distorted-domain noise */ + float rv[3]; + float (*noisefunc1)(float, float, float); + float (*noisefunc2)(float, float, float); + + switch (nbas1) { + case 1: + noisefunc1 = orgPerlinNoise; + break; + case 2: + noisefunc1 = newPerlin; + break; + case 3: + noisefunc1 = voronoi_F1S; + break; + case 4: + noisefunc1 = voronoi_F2S; + break; + case 5: + noisefunc1 = voronoi_F3S; + break; + case 6: + noisefunc1 = voronoi_F4S; + break; + case 7: + noisefunc1 = voronoi_F1F2S; + break; + case 8: + noisefunc1 = voronoi_CrS; + break; + case 14: + noisefunc1 = cellNoise; + break; + case 0: + default: { + noisefunc1 = orgBlenderNoiseS; + break; + } + } + + switch (nbas2) { + case 1: + noisefunc2 = orgPerlinNoise; + break; + case 2: + noisefunc2 = newPerlin; + break; + case 3: + noisefunc2 = voronoi_F1S; + break; + case 4: + noisefunc2 = voronoi_F2S; + break; + case 5: + noisefunc2 = voronoi_F3S; + break; + case 6: + noisefunc2 = voronoi_F4S; + break; + case 7: + noisefunc2 = voronoi_F1F2S; + break; + case 8: + noisefunc2 = voronoi_CrS; + break; + case 14: + noisefunc2 = cellNoise; + break; + case 0: + default: { + noisefunc2 = orgBlenderNoiseS; + break; + } + } + + /* get a random vector and scale the randomization */ + rv[0] = noisefunc1(x + 13.5f, y + 13.5f, z + 13.5f) * distortion; + rv[1] = noisefunc1(x, y, z) * distortion; + rv[2] = noisefunc1(x - 13.5f, y - 13.5f, z - 13.5f) * distortion; + return noisefunc2(x + rv[0], y + rv[1], z + rv[2]); /* distorted-domain noise */ } /****************/ diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 33cd844f851..64872e881f5 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -60,7 +60,7 @@ /* return true if the path is absolute ie starts with a drive specifier (eg A:\) or is a UNC path */ static bool BLI_path_is_abs(const char *name); -#endif /* WIN32 */ +#endif /* WIN32 */ // #define DEBUG_STRSIZE @@ -77,79 +77,79 @@ static bool BLI_path_is_abs(const char *name); */ int BLI_stringdec(const char *string, char *head, char *tail, ushort *r_num_len) { - uint nums = 0, nume = 0; - int i; - bool found_digit = false; - const char * const lslash = BLI_last_slash(string); - const uint string_len = strlen(string); - const uint lslash_len = lslash != NULL ? (int)(lslash - string) : 0; - uint name_end = string_len; - - while (name_end > lslash_len && string[--name_end] != '.') { - /* name ends at dot if present */ - } - if (name_end == lslash_len && string[name_end] != '.') { - name_end = string_len; - } - - for (i = name_end - 1; i >= (int)lslash_len; i--) { - if (isdigit(string[i])) { - if (found_digit) { - nums = i; - } - else { - nume = i; - nums = i; - found_digit = true; - } - } - else { - if (found_digit) { - break; - } - } - } - - if (found_digit) { - const long long int ret = strtoll(&(string[nums]), NULL, 10); - if (ret >= INT_MIN && ret <= INT_MAX) { - if (tail) { - strcpy(tail, &string[nume + 1]); - } - if (head) { - strcpy(head, string); - head[nums] = 0; - } - if (r_num_len) { - *r_num_len = nume - nums + 1; - } - return (int)ret; - } - } - - if (tail) { - strcpy(tail, string + name_end); - } - if (head) { - /* name_end points to last character of head, - * make it +1 so null-terminator is nicely placed - */ - BLI_strncpy(head, string, name_end + 1); - } - if (r_num_len) { - *r_num_len = 0; - } - return 0; + uint nums = 0, nume = 0; + int i; + bool found_digit = false; + const char *const lslash = BLI_last_slash(string); + const uint string_len = strlen(string); + const uint lslash_len = lslash != NULL ? (int)(lslash - string) : 0; + uint name_end = string_len; + + while (name_end > lslash_len && string[--name_end] != '.') { + /* name ends at dot if present */ + } + if (name_end == lslash_len && string[name_end] != '.') { + name_end = string_len; + } + + for (i = name_end - 1; i >= (int)lslash_len; i--) { + if (isdigit(string[i])) { + if (found_digit) { + nums = i; + } + else { + nume = i; + nums = i; + found_digit = true; + } + } + else { + if (found_digit) { + break; + } + } + } + + if (found_digit) { + const long long int ret = strtoll(&(string[nums]), NULL, 10); + if (ret >= INT_MIN && ret <= INT_MAX) { + if (tail) { + strcpy(tail, &string[nume + 1]); + } + if (head) { + strcpy(head, string); + head[nums] = 0; + } + if (r_num_len) { + *r_num_len = nume - nums + 1; + } + return (int)ret; + } + } + + if (tail) { + strcpy(tail, string + name_end); + } + if (head) { + /* name_end points to last character of head, + * make it +1 so null-terminator is nicely placed + */ + BLI_strncpy(head, string, name_end + 1); + } + if (r_num_len) { + *r_num_len = 0; + } + return 0; } - /** * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic * is formatted as numlen digits with leading zeroes. */ -void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) +void BLI_stringenc( + char *string, const char *head, const char *tail, unsigned short numlen, int pic) { - sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); + sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); } static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */ @@ -167,91 +167,91 @@ static int BLI_path_unc_prefix_len(const char *path); /* defined below in same f */ void BLI_cleanup_path(const char *relabase, char *path) { - ptrdiff_t a; - char *start, *eind; - if (relabase) { - BLI_path_abs(path, relabase); - } - else { - if (path[0] == '/' && path[1] == '/') { - if (path[2] == '\0') { - return; /* path is "//" - cant clean it */ - } - path = path + 2; /* leave the initial "//" untouched */ - } - } - - /* Note - * memmove(start, eind, strlen(eind) + 1); - * is the same as - * strcpy(start, eind); - * except strcpy should not be used because there is overlap, - * so use memmove's slightly more obscure syntax - Campbell - */ + ptrdiff_t a; + char *start, *eind; + if (relabase) { + BLI_path_abs(path, relabase); + } + else { + if (path[0] == '/' && path[1] == '/') { + if (path[2] == '\0') { + return; /* path is "//" - cant clean it */ + } + path = path + 2; /* leave the initial "//" untouched */ + } + } + + /* Note + * memmove(start, eind, strlen(eind) + 1); + * is the same as + * strcpy(start, eind); + * except strcpy should not be used because there is overlap, + * so use memmove's slightly more obscure syntax - Campbell + */ #ifdef WIN32 - while ( (start = strstr(path, "\\..\\")) ) { - eind = start + strlen("\\..\\") - 1; - a = start - path - 1; - while (a > 0) { - if (path[a] == '\\') { - break; - } - a--; - } - if (a < 0) { - break; - } - else { - memmove(path + a, eind, strlen(eind) + 1); - } - } - - while ( (start = strstr(path, "\\.\\")) ) { - eind = start + strlen("\\.\\") - 1; - memmove(start, eind, strlen(eind) + 1); - } - - /* remove two consecutive backslashes, but skip the UNC prefix, - * which needs to be preserved */ - while ( (start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\")) ) { - eind = start + strlen("\\\\") - 1; - memmove(start, eind, strlen(eind) + 1); - } + while ((start = strstr(path, "\\..\\"))) { + eind = start + strlen("\\..\\") - 1; + a = start - path - 1; + while (a > 0) { + if (path[a] == '\\') { + break; + } + a--; + } + if (a < 0) { + break; + } + else { + memmove(path + a, eind, strlen(eind) + 1); + } + } + + while ((start = strstr(path, "\\.\\"))) { + eind = start + strlen("\\.\\") - 1; + memmove(start, eind, strlen(eind) + 1); + } + + /* remove two consecutive backslashes, but skip the UNC prefix, + * which needs to be preserved */ + while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) { + eind = start + strlen("\\\\") - 1; + memmove(start, eind, strlen(eind) + 1); + } #else - while ( (start = strstr(path, "/../")) ) { - a = start - path - 1; - if (a > 0) { - /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */ - eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */ - while (a > 0 && path[a] != '/') { /* find start of <parent> */ - a--; - } - memmove(path + a, eind, strlen(eind) + 1); - } - else { - /* support for odd paths: eg /../home/me --> /home/me - * this is a valid path in blender but we cant handle this the usual way below - * simply strip this prefix then evaluate the path as usual. - * pythons os.path.normpath() does this */ - - /* Note: previous version of following call used an offset of 3 instead of 4, - * which meant that the "/../home/me" example actually became "home/me". - * Using offset of 3 gives behavior consistent with the abovementioned - * Python routine. */ - memmove(path, path + 3, strlen(path + 3) + 1); - } - } - - while ( (start = strstr(path, "/./")) ) { - eind = start + (3 - 1) /* strlen("/./") - 1 */; - memmove(start, eind, strlen(eind) + 1); - } - - while ( (start = strstr(path, "//")) ) { - eind = start + (2 - 1) /* strlen("//") - 1 */; - memmove(start, eind, strlen(eind) + 1); - } + while ((start = strstr(path, "/../"))) { + a = start - path - 1; + if (a > 0) { + /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */ + eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */ + while (a > 0 && path[a] != '/') { /* find start of <parent> */ + a--; + } + memmove(path + a, eind, strlen(eind) + 1); + } + else { + /* support for odd paths: eg /../home/me --> /home/me + * this is a valid path in blender but we cant handle this the usual way below + * simply strip this prefix then evaluate the path as usual. + * pythons os.path.normpath() does this */ + + /* Note: previous version of following call used an offset of 3 instead of 4, + * which meant that the "/../home/me" example actually became "home/me". + * Using offset of 3 gives behavior consistent with the abovementioned + * Python routine. */ + memmove(path, path + 3, strlen(path + 3) + 1); + } + } + + while ((start = strstr(path, "/./"))) { + eind = start + (3 - 1) /* strlen("/./") - 1 */; + memmove(start, eind, strlen(eind) + 1); + } + + while ((start = strstr(path, "//"))) { + eind = start + (2 - 1) /* strlen("//") - 1 */; + memmove(start, eind, strlen(eind) + 1); + } #endif } @@ -260,9 +260,8 @@ void BLI_cleanup_path(const char *relabase, char *path) */ void BLI_cleanup_dir(const char *relabase, char *dir) { - BLI_cleanup_path(relabase, dir); - BLI_add_slash(dir); - + BLI_cleanup_path(relabase, dir); + BLI_add_slash(dir); } /** @@ -270,11 +269,10 @@ void BLI_cleanup_dir(const char *relabase, char *dir) */ void BLI_cleanup_file(const char *relabase, char *path) { - BLI_cleanup_path(relabase, path); - BLI_del_slash(path); + BLI_cleanup_path(relabase, path); + BLI_del_slash(path); } - /** * Make given name safe to be used in paths. * @@ -296,72 +294,72 @@ void BLI_cleanup_file(const char *relabase, char *path) */ bool BLI_filename_make_safe(char *fname) { - const char *invalid = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "/\\?*:|\"<>"; - char *fn; - bool changed = false; - - if (*fname == '\0') { - return changed; - } - - for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) { - *fn = '_'; - changed = true; - } - - /* Forbid only dots. */ - for (fn = fname; *fn == '.'; fn++) { - /* pass */ - } - if (*fn == '\0') { - *fname = '_'; - changed = true; - } + const char *invalid = + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "/\\?*:|\"<>"; + char *fn; + bool changed = false; + + if (*fname == '\0') { + return changed; + } + + for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) { + *fn = '_'; + changed = true; + } + + /* Forbid only dots. */ + for (fn = fname; *fn == '.'; fn++) { + /* pass */ + } + if (*fn == '\0') { + *fname = '_'; + changed = true; + } #ifdef WIN32 - { - const size_t len = strlen(fname); - const char *invalid_names[] = { - "con", "prn", "aux", "null", - "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", - "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", - NULL, - }; - char *lower_fname = BLI_strdup(fname); - const char **iname; - - /* Forbid trailing dot (trailing space has already been replaced above). */ - if (fname[len - 1] == '.') { - fname[len - 1] = '_'; - changed = true; - } - - /* Check for forbidden names - not we have to check all combination - * of upper and lower cases, hence the usage of lower_fname - * (more efficient than using BLI_strcasestr repeatedly). */ - BLI_str_tolower_ascii(lower_fname, len); - for (iname = invalid_names; *iname; iname++) { - if (strstr(lower_fname, *iname) == lower_fname) { - const size_t iname_len = strlen(*iname); - /* Only invalid if the whole name is made of the invalid chunk, or it has an - * (assumed extension) dot just after. This means it will also catch 'valid' - * names like 'aux.foo.bar', but should be - * good enough for us! */ - if ((iname_len == len) || (lower_fname[iname_len] == '.')) { - *fname = '_'; - changed = true; - break; - } - } - } - - MEM_freeN(lower_fname); - } + { + const size_t len = strlen(fname); + const char *invalid_names[] = { + "con", "prn", "aux", "null", "com1", "com2", "com3", "com4", + "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", + "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", NULL, + }; + char *lower_fname = BLI_strdup(fname); + const char **iname; + + /* Forbid trailing dot (trailing space has already been replaced above). */ + if (fname[len - 1] == '.') { + fname[len - 1] = '_'; + changed = true; + } + + /* Check for forbidden names - not we have to check all combination + * of upper and lower cases, hence the usage of lower_fname + * (more efficient than using BLI_strcasestr repeatedly). */ + BLI_str_tolower_ascii(lower_fname, len); + for (iname = invalid_names; *iname; iname++) { + if (strstr(lower_fname, *iname) == lower_fname) { + const size_t iname_len = strlen(*iname); + /* Only invalid if the whole name is made of the invalid chunk, or it has an + * (assumed extension) dot just after. This means it will also catch 'valid' + * names like 'aux.foo.bar', but should be + * good enough for us! */ + if ((iname_len == len) || (lower_fname[iname_len] == '.')) { + *fname = '_'; + changed = true; + break; + } + } + } + + MEM_freeN(lower_fname); + } #endif - return changed; + return changed; } /** @@ -371,34 +369,35 @@ bool BLI_filename_make_safe(char *fname) */ bool BLI_path_make_safe(char *path) { - /* Simply apply BLI_filename_make_safe() over each component of the path. - * Luckily enough, same 'safe' rules applies to filenames and dirnames. */ - char *curr_slash, *curr_path = path; - bool changed = false; - bool skip_first = false; + /* Simply apply BLI_filename_make_safe() over each component of the path. + * Luckily enough, same 'safe' rules applies to filenames and dirnames. */ + char *curr_slash, *curr_path = path; + bool changed = false; + bool skip_first = false; #ifdef WIN32 - if (BLI_path_is_abs(path)) { - /* Do not make safe 'C:' in 'C:\foo\bar'... */ - skip_first = true; - } + if (BLI_path_is_abs(path)) { + /* Do not make safe 'C:' in 'C:\foo\bar'... */ + skip_first = true; + } #endif - for (curr_slash = (char *)BLI_first_slash(curr_path); curr_slash; curr_slash = (char *)BLI_first_slash(curr_path)) { - const char backup = *curr_slash; - *curr_slash = '\0'; - if (!skip_first && (*curr_path != '\0') && BLI_filename_make_safe(curr_path)) { - changed = true; - } - skip_first = false; - curr_path = curr_slash + 1; - *curr_slash = backup; - } - if (BLI_filename_make_safe(curr_path)) { - changed = true; - } - - return changed; + for (curr_slash = (char *)BLI_first_slash(curr_path); curr_slash; + curr_slash = (char *)BLI_first_slash(curr_path)) { + const char backup = *curr_slash; + *curr_slash = '\0'; + if (!skip_first && (*curr_path != '\0') && BLI_filename_make_safe(curr_path)) { + changed = true; + } + skip_first = false; + curr_path = curr_slash + 1; + *curr_slash = backup; + } + if (BLI_filename_make_safe(curr_path)) { + changed = true; + } + + return changed; } /** @@ -407,13 +406,13 @@ bool BLI_path_make_safe(char *path) */ bool BLI_path_is_rel(const char *path) { - return path[0] == '/' && path[1] == '/'; + return path[0] == '/' && path[1] == '/'; } /* return true if the path is a UNC share */ bool BLI_path_is_unc(const char *name) { - return name[0] == '\\' && name[1] == '\\'; + return name[0] == '\\' && name[1] == '\\'; } /** @@ -424,17 +423,17 @@ bool BLI_path_is_unc(const char *name) */ static int BLI_path_unc_prefix_len(const char *path) { - if (BLI_path_is_unc(path)) { - if ((path[2] == '?') && (path[3] == '\\') ) { - /* we assume long UNC path like \\?\server\share\folder etc... */ - return 4; - } - else { - return 2; - } - } - - return 0; + if (BLI_path_is_unc(path)) { + if ((path[2] == '?') && (path[3] == '\\')) { + /* we assume long UNC path like \\?\server\share\folder etc... */ + return 4; + } + else { + return 2; + } + } + + return 0; } #if defined(WIN32) @@ -442,74 +441,69 @@ static int BLI_path_unc_prefix_len(const char *path) /* return true if the path is absolute ie starts with a drive specifier (eg A:\) or is a UNC path */ static bool BLI_path_is_abs(const char *name) { - return (name[1] == ':' && (name[2] == '\\' || name[2] == '/') ) || BLI_path_is_unc(name); + return (name[1] == ':' && (name[2] == '\\' || name[2] == '/')) || BLI_path_is_unc(name); } static wchar_t *next_slash(wchar_t *path) { - wchar_t *slash = path; - while (*slash && *slash != L'\\') { - slash++; - } - return slash; + wchar_t *slash = path; + while (*slash && *slash != L'\\') { + slash++; + } + return slash; } /* adds a slash if the unc path points sto a share */ static void BLI_path_add_slash_to_share(wchar_t *uncpath) { - wchar_t *slash_after_server = next_slash(uncpath + 2); - if (*slash_after_server) { - wchar_t *slash_after_share = next_slash(slash_after_server + 1); - if (!(*slash_after_share)) { - slash_after_share[0] = L'\\'; - slash_after_share[1] = L'\0'; - } - } + wchar_t *slash_after_server = next_slash(uncpath + 2); + if (*slash_after_server) { + wchar_t *slash_after_share = next_slash(slash_after_server + 1); + if (!(*slash_after_share)) { + slash_after_share[0] = L'\\'; + slash_after_share[1] = L'\0'; + } + } } static void BLI_path_unc_to_short(wchar_t *unc) { - wchar_t tmp[PATH_MAX]; - - int len = wcslen(unc); - /* convert: - * \\?\UNC\server\share\folder\... to \\server\share\folder\... - * \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\... - */ - if ((len > 3) && - (unc[0] == L'\\') && - (unc[1] == L'\\') && - (unc[2] == L'?') && - ((unc[3] == L'\\') || (unc[3] == L'/'))) - { - if ((len > 5) && (unc[5] == L':')) { - wcsncpy(tmp, unc + 4, len - 4); - tmp[len - 4] = L'\0'; - wcscpy(unc, tmp); - } - else if ((len > 7) && (wcsncmp(&unc[4], L"UNC", 3) == 0) && - ((unc[7] == L'\\') || (unc[7] == L'/'))) - { - tmp[0] = L'\\'; - tmp[1] = L'\\'; - wcsncpy(tmp + 2, unc + 8, len - 8); - tmp[len - 6] = L'\0'; - wcscpy(unc, tmp); - } - } + wchar_t tmp[PATH_MAX]; + + int len = wcslen(unc); + /* convert: + * \\?\UNC\server\share\folder\... to \\server\share\folder\... + * \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\... + */ + if ((len > 3) && (unc[0] == L'\\') && (unc[1] == L'\\') && (unc[2] == L'?') && + ((unc[3] == L'\\') || (unc[3] == L'/'))) { + if ((len > 5) && (unc[5] == L':')) { + wcsncpy(tmp, unc + 4, len - 4); + tmp[len - 4] = L'\0'; + wcscpy(unc, tmp); + } + else if ((len > 7) && (wcsncmp(&unc[4], L"UNC", 3) == 0) && + ((unc[7] == L'\\') || (unc[7] == L'/'))) { + tmp[0] = L'\\'; + tmp[1] = L'\\'; + wcsncpy(tmp + 2, unc + 8, len - 8); + tmp[len - 6] = L'\0'; + wcscpy(unc, tmp); + } + } } void BLI_cleanup_unc(char *path, int maxlen) { - wchar_t *tmp_16 = alloc_utf16_from_8(path, 1); - BLI_cleanup_unc_16(tmp_16); - conv_utf_16_to_8(tmp_16, path, maxlen); + wchar_t *tmp_16 = alloc_utf16_from_8(path, 1); + BLI_cleanup_unc_16(tmp_16); + conv_utf_16_to_8(tmp_16, path, maxlen); } void BLI_cleanup_unc_16(wchar_t *path_16) { - BLI_path_unc_to_short(path_16); - BLI_path_add_slash_to_share(path_16); + BLI_path_unc_to_short(path_16); + BLI_path_add_slash_to_share(path_16); } #endif @@ -519,134 +513,140 @@ void BLI_cleanup_unc_16(wchar_t *path_16) */ void BLI_path_rel(char *file, const char *relfile) { - const char *lslash; - char temp[FILE_MAX]; - char res[FILE_MAX]; + const char *lslash; + char temp[FILE_MAX]; + char res[FILE_MAX]; - /* if file is already relative, bail out */ - if (BLI_path_is_rel(file)) { - return; - } + /* if file is already relative, bail out */ + if (BLI_path_is_rel(file)) { + return; + } - /* also bail out if relative path is not set */ - if (relfile[0] == '\0') { - return; - } + /* also bail out if relative path is not set */ + if (relfile[0] == '\0') { + return; + } #ifdef WIN32 - if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) { - char *ptemp; - /* fix missing volume name in relative base, - * can happen with old recent-files.txt files */ - get_default_root(temp); - ptemp = &temp[2]; - if (relfile[0] != '\\' && relfile[0] != '/') { - ptemp++; - } - BLI_strncpy(ptemp, relfile, FILE_MAX - 3); - } - else { - BLI_strncpy(temp, relfile, FILE_MAX); - } - - if (BLI_strnlen(file, 3) > 2) { - bool is_unc = BLI_path_is_unc(file); - - /* Ensure paths are both UNC paths or are both drives */ - if (BLI_path_is_unc(temp) != is_unc) { - return; - } - - /* Ensure both UNC paths are on the same share */ - if (is_unc) { - int off; - int slash = 0; - for (off = 0; temp[off] && slash < 4; off++) { - if (temp[off] != file[off]) { - return; - } - - if (temp[off] == '\\') { - slash++; - } - } - } - else if (temp[1] == ':' && file[1] == ':' && temp[0] != file[0]) { - return; - } - } + if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) { + char *ptemp; + /* fix missing volume name in relative base, + * can happen with old recent-files.txt files */ + get_default_root(temp); + ptemp = &temp[2]; + if (relfile[0] != '\\' && relfile[0] != '/') { + ptemp++; + } + BLI_strncpy(ptemp, relfile, FILE_MAX - 3); + } + else { + BLI_strncpy(temp, relfile, FILE_MAX); + } + + if (BLI_strnlen(file, 3) > 2) { + bool is_unc = BLI_path_is_unc(file); + + /* Ensure paths are both UNC paths or are both drives */ + if (BLI_path_is_unc(temp) != is_unc) { + return; + } + + /* Ensure both UNC paths are on the same share */ + if (is_unc) { + int off; + int slash = 0; + for (off = 0; temp[off] && slash < 4; off++) { + if (temp[off] != file[off]) { + return; + } + + if (temp[off] == '\\') { + slash++; + } + } + } + else if (temp[1] == ':' && file[1] == ':' && temp[0] != file[0]) { + return; + } + } #else - BLI_strncpy(temp, relfile, FILE_MAX); + BLI_strncpy(temp, relfile, FILE_MAX); #endif - BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/'); - BLI_str_replace_char(file + BLI_path_unc_prefix_len(file), '\\', '/'); + BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/'); + BLI_str_replace_char(file + BLI_path_unc_prefix_len(file), '\\', '/'); - /* remove /./ which confuse the following slash counting... */ - BLI_cleanup_path(NULL, file); - BLI_cleanup_path(NULL, temp); + /* remove /./ which confuse the following slash counting... */ + BLI_cleanup_path(NULL, file); + BLI_cleanup_path(NULL, temp); - /* the last slash in the file indicates where the path part ends */ - lslash = BLI_last_slash(temp); + /* the last slash in the file indicates where the path part ends */ + lslash = BLI_last_slash(temp); - if (lslash) { - /* find the prefix of the filename that is equal for both filenames. - * This is replaced by the two slashes at the beginning */ - const char *p = temp; - const char *q = file; - char *r = res; + if (lslash) { + /* find the prefix of the filename that is equal for both filenames. + * This is replaced by the two slashes at the beginning */ + const char *p = temp; + const char *q = file; + char *r = res; #ifdef WIN32 - while (tolower(*p) == tolower(*q)) + while (tolower(*p) == tolower(*q)) #else - while (*p == *q) + while (*p == *q) #endif - { - p++; - q++; - - /* don't search beyond the end of the string - * in the rare case they match */ - if ((*p == '\0') || (*q == '\0')) { - break; - } - } - - /* we might have passed the slash when the beginning of a dir matches - * so we rewind. Only check on the actual filename - */ - if (*q != '/') { - while ( (q >= file) && (*q != '/') ) { --q; --p; } - } - else if (*p != '/') { - while ( (p >= temp) && (*p != '/') ) { --p; --q; } - } - - r += BLI_strcpy_rlen(r, "//"); - - /* p now points to the slash that is at the beginning of the part - * where the path is different from the relative path. - * We count the number of directories we need to go up in the - * hierarchy to arrive at the common 'prefix' of the path - */ - if (p < temp) { - p = temp; - } - while (p && p < lslash) { - if (*p == '/') { - r += BLI_strcpy_rlen(r, "../"); - } - p++; - } - - /* don't copy the slash at the beginning */ - r += BLI_strcpy_rlen(r, q + 1); - -#ifdef WIN32 - BLI_str_replace_char(res + 2, '/', '\\'); + { + p++; + q++; + + /* don't search beyond the end of the string + * in the rare case they match */ + if ((*p == '\0') || (*q == '\0')) { + break; + } + } + + /* we might have passed the slash when the beginning of a dir matches + * so we rewind. Only check on the actual filename + */ + if (*q != '/') { + while ((q >= file) && (*q != '/')) { + --q; + --p; + } + } + else if (*p != '/') { + while ((p >= temp) && (*p != '/')) { + --p; + --q; + } + } + + r += BLI_strcpy_rlen(r, "//"); + + /* p now points to the slash that is at the beginning of the part + * where the path is different from the relative path. + * We count the number of directories we need to go up in the + * hierarchy to arrive at the common 'prefix' of the path + */ + if (p < temp) { + p = temp; + } + while (p && p < lslash) { + if (*p == '/') { + r += BLI_strcpy_rlen(r, "../"); + } + p++; + } + + /* don't copy the slash at the beginning */ + r += BLI_strcpy_rlen(r, q + 1); + +#ifdef WIN32 + BLI_str_replace_char(res + 2, '/', '\\'); #endif - strcpy(file, res); - } + strcpy(file, res); + } } /** @@ -664,36 +664,36 @@ void BLI_path_rel(char *file, const char *relfile) bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char *sep) { #ifdef DEBUG_STRSIZE - memset(string, 0xff, sizeof(*string) * maxlen); + memset(string, 0xff, sizeof(*string) * maxlen); #endif - const size_t string_len = strlen(string); - const size_t suffix_len = strlen(suffix); - const size_t sep_len = strlen(sep); - ssize_t a; - char extension[FILE_MAX]; - bool has_extension = false; - - if (string_len + sep_len + suffix_len >= maxlen) { - return false; - } - - for (a = string_len - 1; a >= 0; a--) { - if (string[a] == '.') { - has_extension = true; - break; - } - else if (ELEM(string[a], '/', '\\')) { - break; - } - } - - if (!has_extension) { - a = string_len; - } - - BLI_strncpy(extension, string + a, sizeof(extension)); - sprintf(string + a, "%s%s%s", sep, suffix, extension); - return true; + const size_t string_len = strlen(string); + const size_t suffix_len = strlen(suffix); + const size_t sep_len = strlen(sep); + ssize_t a; + char extension[FILE_MAX]; + bool has_extension = false; + + if (string_len + sep_len + suffix_len >= maxlen) { + return false; + } + + for (a = string_len - 1; a >= 0; a--) { + if (string[a] == '.') { + has_extension = true; + break; + } + else if (ELEM(string[a], '/', '\\')) { + break; + } + } + + if (!has_extension) { + a = string_len; + } + + BLI_strncpy(extension, string + a, sizeof(extension)); + sprintf(string + a, "%s%s%s", sep, suffix, extension); + return true; } /** @@ -702,19 +702,19 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char */ bool BLI_parent_dir(char *path) { - const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ - char tmp[FILE_MAX + 4]; - - BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); - BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */ - - if (!BLI_path_extension_check(tmp, parent_dir)) { - strcpy(path, tmp); /* We assume pardir is always shorter... */ - return true; - } - else { - return false; - } + const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ + char tmp[FILE_MAX + 4]; + + BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); + BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */ + + if (!BLI_path_extension_check(tmp, parent_dir)) { + strcpy(path, tmp); /* We assume pardir is always shorter... */ + return true; + } + else { + return false; + } } /** @@ -724,35 +724,35 @@ bool BLI_parent_dir(char *path) */ static bool stringframe_chars(const char *path, int *char_start, int *char_end) { - uint ch_sta, ch_end, i; - /* Insert current frame: file### -> file001 */ - ch_sta = ch_end = 0; - for (i = 0; path[i] != '\0'; i++) { - if (path[i] == '\\' || path[i] == '/') { - ch_end = 0; /* this is a directory name, don't use any hashes we found */ - } - else if (path[i] == '#') { - ch_sta = i; - ch_end = ch_sta + 1; - while (path[ch_end] == '#') { - ch_end++; - } - i = ch_end - 1; /* keep searching */ - - /* don't break, there may be a slash after this that invalidates the previous #'s */ - } - } - - if (ch_end) { - *char_start = ch_sta; - *char_end = ch_end; - return true; - } - else { - *char_start = -1; - *char_end = -1; - return false; - } + uint ch_sta, ch_end, i; + /* Insert current frame: file### -> file001 */ + ch_sta = ch_end = 0; + for (i = 0; path[i] != '\0'; i++) { + if (path[i] == '\\' || path[i] == '/') { + ch_end = 0; /* this is a directory name, don't use any hashes we found */ + } + else if (path[i] == '#') { + ch_sta = i; + ch_end = ch_sta + 1; + while (path[ch_end] == '#') { + ch_end++; + } + i = ch_end - 1; /* keep searching */ + + /* don't break, there may be a slash after this that invalidates the previous #'s */ + } + } + + if (ch_end) { + *char_start = ch_sta; + *char_end = ch_end; + return true; + } + else { + *char_start = -1; + *char_end = -1; + return false; + } } /** @@ -761,20 +761,20 @@ static bool stringframe_chars(const char *path, int *char_start, int *char_end) */ static void ensure_digits(char *path, int digits) { - char *file = (char *)BLI_last_slash(path); + char *file = (char *)BLI_last_slash(path); - if (file == NULL) { - file = path; - } + if (file == NULL) { + file = path; + } - if (strrchr(file, '#') == NULL) { - int len = strlen(file); + if (strrchr(file, '#') == NULL) { + int len = strlen(file); - while (digits--) { - file[len++] = '#'; - } - file[len] = '\0'; - } + while (digits--) { + file[len++] = '#'; + } + file[len] = '\0'; + } } /** @@ -783,21 +783,20 @@ static void ensure_digits(char *path, int digits) */ bool BLI_path_frame(char *path, int frame, int digits) { - int ch_sta, ch_end; - - if (digits) { - ensure_digits(path, digits); - } - - if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ - char tmp[FILE_MAX]; - BLI_snprintf(tmp, sizeof(tmp), - "%.*s%.*d%s", - ch_sta, path, ch_end - ch_sta, frame, path + ch_end); - BLI_strncpy(path, tmp, FILE_MAX); - return true; - } - return false; + int ch_sta, ch_end; + + if (digits) { + ensure_digits(path, digits); + } + + if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ + char tmp[FILE_MAX]; + BLI_snprintf( + tmp, sizeof(tmp), "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end); + BLI_strncpy(path, tmp, FILE_MAX); + return true; + } + return false; } /** @@ -807,21 +806,28 @@ bool BLI_path_frame(char *path, int frame, int digits) */ bool BLI_path_frame_range(char *path, int sta, int end, int digits) { - int ch_sta, ch_end; - - if (digits) { - ensure_digits(path, digits); - } - - if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ - char tmp[FILE_MAX]; - BLI_snprintf(tmp, sizeof(tmp), - "%.*s%.*d-%.*d%s", - ch_sta, path, ch_end - ch_sta, sta, ch_end - ch_sta, end, path + ch_end); - BLI_strncpy(path, tmp, FILE_MAX); - return true; - } - return false; + int ch_sta, ch_end; + + if (digits) { + ensure_digits(path, digits); + } + + if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ + char tmp[FILE_MAX]; + BLI_snprintf(tmp, + sizeof(tmp), + "%.*s%.*d-%.*d%s", + ch_sta, + path, + ch_end - ch_sta, + sta, + ch_end - ch_sta, + end, + path + ch_end); + BLI_strncpy(path, tmp, FILE_MAX); + return true; + } + return false; } /** @@ -829,113 +835,112 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits) */ bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits) { - if (*path) { - char *file = (char *)BLI_last_slash(path); - char *c; - int len, numdigits; + if (*path) { + char *file = (char *)BLI_last_slash(path); + char *c; + int len, numdigits; - numdigits = *r_numdigits = 0; + numdigits = *r_numdigits = 0; - if (file == NULL) { - file = path; - } + if (file == NULL) { + file = path; + } - /* first get the extension part */ - len = strlen(file); + /* first get the extension part */ + len = strlen(file); - c = file + len; + c = file + len; - /* isolate extension */ - while (--c != file) { - if (*c == '.') { - c--; - break; - } - } + /* isolate extension */ + while (--c != file) { + if (*c == '.') { + c--; + break; + } + } - /* find start of number */ - while (c != (file - 1) && isdigit(*c)) { - c--; - numdigits++; - } + /* find start of number */ + while (c != (file - 1) && isdigit(*c)) { + c--; + numdigits++; + } - if (numdigits) { - char prevchar; + if (numdigits) { + char prevchar; - c++; - prevchar = c[numdigits]; - c[numdigits] = 0; + c++; + prevchar = c[numdigits]; + c[numdigits] = 0; - /* was the number really an extension? */ - *r_frame = atoi(c); - c[numdigits] = prevchar; + /* was the number really an extension? */ + *r_frame = atoi(c); + c[numdigits] = prevchar; - *r_numdigits = numdigits; + *r_numdigits = numdigits; - return true; - } - } + return true; + } + } - return false; + return false; } void BLI_path_frame_strip(char *path, char *r_ext) { - *r_ext = '\0'; - if (*path == '\0') { - return; - } - - char *file = (char *)BLI_last_slash(path); - char *c, *suffix; - int len; - int numdigits = 0; - - if (file == NULL) { - file = path; - } - - /* first get the extension part */ - len = strlen(file); - - c = file + len; - - /* isolate extension */ - while (--c != file) { - if (*c == '.') { - c--; - break; - } - } - - suffix = c + 1; - - /* find start of number */ - while (c != (file - 1) && isdigit(*c)) { - c--; - numdigits++; - } - - c++; - - int suffix_length = len - (suffix - file); - BLI_strncpy(r_ext, suffix, suffix_length + 1); - - /* replace the number with the suffix and terminate the string */ - while (numdigits--) { - *c++ = '#'; - } - *c = '\0'; + *r_ext = '\0'; + if (*path == '\0') { + return; + } + + char *file = (char *)BLI_last_slash(path); + char *c, *suffix; + int len; + int numdigits = 0; + + if (file == NULL) { + file = path; + } + + /* first get the extension part */ + len = strlen(file); + + c = file + len; + + /* isolate extension */ + while (--c != file) { + if (*c == '.') { + c--; + break; + } + } + + suffix = c + 1; + + /* find start of number */ + while (c != (file - 1) && isdigit(*c)) { + c--; + numdigits++; + } + + c++; + + int suffix_length = len - (suffix - file); + BLI_strncpy(r_ext, suffix, suffix_length + 1); + + /* replace the number with the suffix and terminate the string */ + while (numdigits--) { + *c++ = '#'; + } + *c = '\0'; } - /** * Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range */ bool BLI_path_frame_check_chars(const char *path) { - int ch_sta, ch_end; /* dummy args */ - return stringframe_chars(path, &ch_sta, &ch_end); + int ch_sta, ch_end; /* dummy args */ + return stringframe_chars(path, &ch_sta, &ch_end); } /** @@ -944,40 +949,40 @@ bool BLI_path_frame_check_chars(const char *path) */ void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) { - /* Strip leading underscores and spaces. */ - int strip_offset = 0; - while (ELEM(name[strip_offset], '_', ' ')) { - strip_offset++; - } - - BLI_strncpy(display_name, name + strip_offset, maxlen); - - /* Replace underscores with spaces. */ - BLI_str_replace_char(display_name, '_', ' '); - - /* Strip extension. */ - BLI_path_extension_replace(display_name, maxlen, ""); - - /* Test if string has any upper case characters. */ - bool all_lower = true; - for (int i = 0; display_name[i]; i++) { - if (isupper(display_name[i])) { - all_lower = false; - break; - } - } - - if (all_lower) { - /* For full lowercase string, use title case. */ - bool prevspace = true; - for (int i = 0; display_name[i]; i++) { - if (prevspace) { - display_name[i] = toupper(display_name[i]); - } - - prevspace = isspace(display_name[i]); - } - } + /* Strip leading underscores and spaces. */ + int strip_offset = 0; + while (ELEM(name[strip_offset], '_', ' ')) { + strip_offset++; + } + + BLI_strncpy(display_name, name + strip_offset, maxlen); + + /* Replace underscores with spaces. */ + BLI_str_replace_char(display_name, '_', ' '); + + /* Strip extension. */ + BLI_path_extension_replace(display_name, maxlen, ""); + + /* Test if string has any upper case characters. */ + bool all_lower = true; + for (int i = 0; display_name[i]; i++) { + if (isupper(display_name[i])) { + all_lower = false; + break; + } + } + + if (all_lower) { + /* For full lowercase string, use title case. */ + bool prevspace = true; + for (int i = 0; display_name[i]; i++) { + if (prevspace) { + display_name[i] = toupper(display_name[i]); + } + + prevspace = isspace(display_name[i]); + } + } } /** @@ -992,109 +997,108 @@ void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) */ bool BLI_path_abs(char *path, const char *basepath) { - const bool wasrelative = BLI_path_is_rel(path); - char tmp[FILE_MAX]; - char base[FILE_MAX]; + const bool wasrelative = BLI_path_is_rel(path); + char tmp[FILE_MAX]; + char base[FILE_MAX]; #ifdef WIN32 - /* without this: "" --> "C:\" */ - if (*path == '\0') { - return wasrelative; - } - - /* we are checking here if we have an absolute path that is not in the current - * blend file as a lib main - we are basically checking for the case that a - * UNIX root '/' is passed. - */ - if (!wasrelative && !BLI_path_is_abs(path)) { - char *p = path; - get_default_root(tmp); - // get rid of the slashes at the beginning of the path - while (*p == '\\' || *p == '/') { - p++; - } - strcat(tmp, p); - } - else { - BLI_strncpy(tmp, path, FILE_MAX); - } + /* without this: "" --> "C:\" */ + if (*path == '\0') { + return wasrelative; + } + + /* we are checking here if we have an absolute path that is not in the current + * blend file as a lib main - we are basically checking for the case that a + * UNIX root '/' is passed. + */ + if (!wasrelative && !BLI_path_is_abs(path)) { + char *p = path; + get_default_root(tmp); + // get rid of the slashes at the beginning of the path + while (*p == '\\' || *p == '/') { + p++; + } + strcat(tmp, p); + } + else { + BLI_strncpy(tmp, path, FILE_MAX); + } #else - BLI_strncpy(tmp, path, sizeof(tmp)); + BLI_strncpy(tmp, path, sizeof(tmp)); - /* Check for loading a windows path on a posix system - * in this case, there is no use in trying C:/ since it - * will never exist on a unix os. - * - * Add a / prefix and lowercase the driveletter, remove the : - * C:\foo.JPG -> /c/foo.JPG */ + /* Check for loading a windows path on a posix system + * in this case, there is no use in trying C:/ since it + * will never exist on a unix os. + * + * Add a / prefix and lowercase the driveletter, remove the : + * C:\foo.JPG -> /c/foo.JPG */ - if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2] == '\\' || tmp[2] == '/') ) { - tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */ - tmp[0] = '/'; - /* '\' the slash will be converted later */ - } + if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2] == '\\' || tmp[2] == '/')) { + tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */ + tmp[0] = '/'; + /* '\' the slash will be converted later */ + } #endif - /* push slashes into unix mode - strings entering this part are - * potentially messed up: having both back- and forward slashes. - * Here we push into one conform direction, and at the end we - * push them into the system specific dir. This ensures uniformity - * of paths and solving some problems (and prevent potential future - * ones) -jesterKing. - * For UNC paths the first characters containing the UNC prefix - * shouldn't be switched as we need to distinguish them from - * paths relative to the .blend file -elubie */ - BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/'); - - /* Paths starting with // will get the blend file as their base, - * this isn't standard in any os but is used in blender all over the place */ - if (wasrelative) { - const char *lslash; - BLI_strncpy(base, basepath, sizeof(base)); - - /* file component is ignored, so don't bother with the trailing slash */ - BLI_cleanup_path(NULL, base); - lslash = BLI_last_slash(base); - BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/'); - - if (lslash) { - /* length up to and including last "/" */ - const int baselen = (int) (lslash - base) + 1; - /* use path for temp storage here, we copy back over it right away */ - BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */ - - memcpy(tmp, base, baselen); /* prefix with base up to last "/" */ - BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */ - BLI_strncpy(path, tmp, FILE_MAX); /* return as result */ - } - else { - /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */ - BLI_strncpy(path, tmp + 2, FILE_MAX); - } - } - else { - /* base ignored */ - BLI_strncpy(path, tmp, FILE_MAX); - } + /* push slashes into unix mode - strings entering this part are + * potentially messed up: having both back- and forward slashes. + * Here we push into one conform direction, and at the end we + * push them into the system specific dir. This ensures uniformity + * of paths and solving some problems (and prevent potential future + * ones) -jesterKing. + * For UNC paths the first characters containing the UNC prefix + * shouldn't be switched as we need to distinguish them from + * paths relative to the .blend file -elubie */ + BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/'); + + /* Paths starting with // will get the blend file as their base, + * this isn't standard in any os but is used in blender all over the place */ + if (wasrelative) { + const char *lslash; + BLI_strncpy(base, basepath, sizeof(base)); + + /* file component is ignored, so don't bother with the trailing slash */ + BLI_cleanup_path(NULL, base); + lslash = BLI_last_slash(base); + BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/'); + + if (lslash) { + /* length up to and including last "/" */ + const int baselen = (int)(lslash - base) + 1; + /* use path for temp storage here, we copy back over it right away */ + BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */ + + memcpy(tmp, base, baselen); /* prefix with base up to last "/" */ + BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */ + BLI_strncpy(path, tmp, FILE_MAX); /* return as result */ + } + else { + /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */ + BLI_strncpy(path, tmp + 2, FILE_MAX); + } + } + else { + /* base ignored */ + BLI_strncpy(path, tmp, FILE_MAX); + } #ifdef WIN32 - /* skip first two chars, which in case of - * absolute path will be drive:/blabla and - * in case of relpath //blabla/. So relpath - * // will be retained, rest will be nice and - * shiny win32 backward slashes :) -jesterKing - */ - BLI_str_replace_char(path + 2, '/', '\\'); + /* skip first two chars, which in case of + * absolute path will be drive:/blabla and + * in case of relpath //blabla/. So relpath + * // will be retained, rest will be nice and + * shiny win32 backward slashes :) -jesterKing + */ + BLI_str_replace_char(path + 2, '/', '\\'); #endif - /* ensure this is after correcting for path switch */ - BLI_cleanup_path(NULL, path); + /* ensure this is after correcting for path switch */ + BLI_cleanup_path(NULL, path); - return wasrelative; + return wasrelative; } - /** * Expands path relative to the current working directory, if it was relative. * Returns true if such expansion was done. @@ -1105,35 +1109,35 @@ bool BLI_path_abs(char *path, const char *basepath) bool BLI_path_cwd(char *path, const size_t maxlen) { #ifdef DEBUG_STRSIZE - memset(path, 0xff, sizeof(*path) * maxlen); + memset(path, 0xff, sizeof(*path) * maxlen); #endif - bool wasrelative = true; - const int filelen = strlen(path); + bool wasrelative = true; + const int filelen = strlen(path); #ifdef WIN32 - if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) { - wasrelative = false; - } + if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) { + wasrelative = false; + } #else - if (filelen >= 2 && path[0] == '/') { - wasrelative = false; - } + if (filelen >= 2 && path[0] == '/') { + wasrelative = false; + } #endif - if (wasrelative) { - char cwd[FILE_MAX]; - /* in case the full path to the blend isn't used */ - if (BLI_current_working_dir(cwd, sizeof(cwd))) { - char origpath[FILE_MAX]; - BLI_strncpy(origpath, path, FILE_MAX); - BLI_join_dirfile(path, maxlen, cwd, origpath); - } - else { - printf("Could not get the current working directory - $PWD for an unknown reason.\n"); - } - } - - return wasrelative; + if (wasrelative) { + char cwd[FILE_MAX]; + /* in case the full path to the blend isn't used */ + if (BLI_current_working_dir(cwd, sizeof(cwd))) { + char origpath[FILE_MAX]; + BLI_strncpy(origpath, path, FILE_MAX); + BLI_join_dirfile(path, maxlen, cwd, origpath); + } + else { + printf("Could not get the current working directory - $PWD for an unknown reason.\n"); + } + } + + return wasrelative; } #ifdef _WIN32 @@ -1144,107 +1148,104 @@ bool BLI_path_cwd(char *path, const size_t maxlen) */ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen) { - bool retval = false; - int type; - - type = BLI_exists(name); - if ((type == 0) || S_ISDIR(type)) { - /* typically 3-5, ".EXE", ".BAT"... etc */ - const int ext_max = 12; - const char *ext = BLI_getenv("PATHEXT"); - if (ext) { - const int name_len = strlen(name); - char *filename = alloca(name_len + ext_max); - char *filename_ext; - const char *ext_next; - - /* null terminated in the loop */ - memcpy(filename, name, name_len); - filename_ext = filename + name_len; - - do { - int ext_len; - ext_next = strchr(ext, ';'); - ext_len = ext_next ? ((ext_next++) - ext) : strlen(ext); - - if (LIKELY(ext_len < ext_max)) { - memcpy(filename_ext, ext, ext_len); - filename_ext[ext_len] = '\0'; - - type = BLI_exists(filename); - if (type && (!S_ISDIR(type))) { - retval = true; - BLI_strncpy(name, filename, maxlen); - break; - } - } - } while ((ext = ext_next)); - } - } - else { - retval = true; - } - - return retval; + bool retval = false; + int type; + + type = BLI_exists(name); + if ((type == 0) || S_ISDIR(type)) { + /* typically 3-5, ".EXE", ".BAT"... etc */ + const int ext_max = 12; + const char *ext = BLI_getenv("PATHEXT"); + if (ext) { + const int name_len = strlen(name); + char *filename = alloca(name_len + ext_max); + char *filename_ext; + const char *ext_next; + + /* null terminated in the loop */ + memcpy(filename, name, name_len); + filename_ext = filename + name_len; + + do { + int ext_len; + ext_next = strchr(ext, ';'); + ext_len = ext_next ? ((ext_next++) - ext) : strlen(ext); + + if (LIKELY(ext_len < ext_max)) { + memcpy(filename_ext, ext, ext_len); + filename_ext[ext_len] = '\0'; + + type = BLI_exists(filename); + if (type && (!S_ISDIR(type))) { + retval = true; + BLI_strncpy(name, filename, maxlen); + break; + } + } + } while ((ext = ext_next)); + } + } + else { + retval = true; + } + + return retval; } -#endif /* WIN32 */ +#endif /* WIN32 */ /** * Search for a binary (executable) */ -bool BLI_path_program_search( - char *fullname, const size_t maxlen, - const char *name) +bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name) { #ifdef DEBUG_STRSIZE - memset(fullname, 0xff, sizeof(*fullname) * maxlen); + memset(fullname, 0xff, sizeof(*fullname) * maxlen); #endif - const char *path; - bool retval = false; + const char *path; + bool retval = false; #ifdef _WIN32 - const char separator = ';'; + const char separator = ';'; #else - const char separator = ':'; + const char separator = ':'; #endif - path = BLI_getenv("PATH"); - if (path) { - char filename[FILE_MAX]; - const char *temp; - - do { - temp = strchr(path, separator); - if (temp) { - memcpy(filename, path, temp - path); - filename[temp - path] = 0; - path = temp + 1; - } - else { - BLI_strncpy(filename, path, sizeof(filename)); - } - - BLI_path_append(filename, maxlen, name); - if ( + path = BLI_getenv("PATH"); + if (path) { + char filename[FILE_MAX]; + const char *temp; + + do { + temp = strchr(path, separator); + if (temp) { + memcpy(filename, path, temp - path); + filename[temp - path] = 0; + path = temp + 1; + } + else { + BLI_strncpy(filename, path, sizeof(filename)); + } + + BLI_path_append(filename, maxlen, name); + if ( #ifdef _WIN32 - BLI_path_program_extensions_add_win32(filename, maxlen) + BLI_path_program_extensions_add_win32(filename, maxlen) #else - BLI_exists(filename) + BLI_exists(filename) #endif - ) - { - BLI_strncpy(fullname, filename, maxlen); - retval = true; - break; - } - } while (temp); - } - - if (retval == false) { - *fullname = '\0'; - } - - return retval; + ) { + BLI_strncpy(fullname, filename, maxlen); + retval = true; + break; + } + } while (temp); + } + + if (retval == false) { + *fullname = '\0'; + } + + return retval; } /** @@ -1253,23 +1254,22 @@ bool BLI_path_program_search( */ void BLI_setenv(const char *env, const char *val) { - /* free windows */ + /* free windows */ #if (defined(WIN32) || defined(WIN64)) - uputenv(env, val); + uputenv(env, val); #else - /* linux/osx/bsd */ - if (val) { - setenv(env, val, 1); - } - else { - unsetenv(env); - } + /* linux/osx/bsd */ + if (val) { + setenv(env, val, 1); + } + else { + unsetenv(env); + } #endif } - /** * Only set an env var if already not there. * Like Unix setenv(env, val, 0); @@ -1278,9 +1278,9 @@ void BLI_setenv(const char *env, const char *val) */ void BLI_setenv_if_new(const char *env, const char *val) { - if (BLI_getenv(env) == NULL) { - BLI_setenv(env, val); - } + if (BLI_getenv(env) == NULL) { + BLI_setenv(env, val); + } } /** @@ -1289,40 +1289,39 @@ void BLI_setenv_if_new(const char *env, const char *val) const char *BLI_getenv(const char *env) { #ifdef _MSC_VER - static char buffer[32767]; /* 32767 is the total size of the environment block on windows*/ - if (GetEnvironmentVariableA(env, buffer, sizeof(buffer))) { - return buffer; - } - else { - return NULL; - } + static char buffer[32767]; /* 32767 is the total size of the environment block on windows*/ + if (GetEnvironmentVariableA(env, buffer, sizeof(buffer))) { + return buffer; + } + else { + return NULL; + } #else - return getenv(env); + return getenv(env); #endif } - /** * Strips off nonexistent (or non-accessible) subdirectories from the end of *dir, leaving the path of * the lowest-level directory that does exist and we can read. */ void BLI_make_exist(char *dir) { - bool valid_path = true; + bool valid_path = true; - /* Loop as long as cur path is not a dir, and we can get a parent path. */ - while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_parent_dir(dir))) { - /* pass */ - } + /* Loop as long as cur path is not a dir, and we can get a parent path. */ + while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_parent_dir(dir))) { + /* pass */ + } - /* If we could not find an existing dir, use default root... */ - if (!valid_path || !dir[0]) { + /* If we could not find an existing dir, use default root... */ + if (!valid_path || !dir[0]) { #ifdef WIN32 - get_default_root(dir); + get_default_root(dir); #else - strcpy(dir, "/"); + strcpy(dir, "/"); #endif - } + } } /** @@ -1332,11 +1331,11 @@ void BLI_make_exist(char *dir) */ bool BLI_make_existing_file(const char *name) { - char di[FILE_MAX]; - BLI_split_dir_part(name, di, sizeof(di)); + char di[FILE_MAX]; + BLI_split_dir_part(name, di, sizeof(di)); - /* make if the dir doesn't exist */ - return BLI_dir_create_recursive(di); + /* make if the dir doesn't exist */ + return BLI_dir_create_recursive(di); } /** @@ -1350,137 +1349,139 @@ bool BLI_make_existing_file(const char *name) */ void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) { - int sl; - - if (string) { - /* ensure this is always set even if dir/file are NULL */ - string[0] = '\0'; - - if (ELEM(NULL, dir, file)) { - return; /* We don't want any NULLs */ - } - } - else { - return; /* string is NULL, probably shouldnt happen but return anyway */ - } - - /* Resolve relative references */ - if (relabase && dir[0] == '/' && dir[1] == '/') { - char *lslash; - - /* Get the file name, chop everything past the last slash (ie. the filename) */ - strcpy(string, relabase); - - lslash = (char *)BLI_last_slash(string); - if (lslash) { - *(lslash + 1) = 0; - } - - dir += 2; /* Skip over the relative reference */ - } + int sl; + + if (string) { + /* ensure this is always set even if dir/file are NULL */ + string[0] = '\0'; + + if (ELEM(NULL, dir, file)) { + return; /* We don't want any NULLs */ + } + } + else { + return; /* string is NULL, probably shouldnt happen but return anyway */ + } + + /* Resolve relative references */ + if (relabase && dir[0] == '/' && dir[1] == '/') { + char *lslash; + + /* Get the file name, chop everything past the last slash (ie. the filename) */ + strcpy(string, relabase); + + lslash = (char *)BLI_last_slash(string); + if (lslash) { + *(lslash + 1) = 0; + } + + dir += 2; /* Skip over the relative reference */ + } #ifdef WIN32 - else { - if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') { - BLI_strncpy(string, dir, 3); - dir += 2; - } - else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) { - string[0] = 0; - } - else { /* no drive specified */ - /* first option: get the drive from the relabase if it has one */ - if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') { - BLI_strncpy(string, relabase, 3); - string[2] = '\\'; - string[3] = '\0'; - } - else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ - get_default_root(string); - } - - /* ignore leading slashes */ - while (*dir == '/' || *dir == '\\') { - dir++; - } - } - } + else { + if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') { + BLI_strncpy(string, dir, 3); + dir += 2; + } + else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) { + string[0] = 0; + } + else { /* no drive specified */ + /* first option: get the drive from the relabase if it has one */ + if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') { + BLI_strncpy(string, relabase, 3); + string[2] = '\\'; + string[3] = '\0'; + } + else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ + get_default_root(string); + } + + /* ignore leading slashes */ + while (*dir == '/' || *dir == '\\') { + dir++; + } + } + } #endif - strcat(string, dir); + strcat(string, dir); - /* Make sure string ends in one (and only one) slash */ - /* first trim all slashes from the end of the string */ - sl = strlen(string); - while (sl > 0 && (string[sl - 1] == '/' || string[sl - 1] == '\\') ) { - string[sl - 1] = '\0'; - sl--; - } - /* since we've now removed all slashes, put back one slash at the end. */ - strcat(string, "/"); + /* Make sure string ends in one (and only one) slash */ + /* first trim all slashes from the end of the string */ + sl = strlen(string); + while (sl > 0 && (string[sl - 1] == '/' || string[sl - 1] == '\\')) { + string[sl - 1] = '\0'; + sl--; + } + /* since we've now removed all slashes, put back one slash at the end. */ + strcat(string, "/"); - while (*file && (*file == '/' || *file == '\\')) { - /* Trim slashes from the front of file */ - file++; - } + while (*file && (*file == '/' || *file == '\\')) { + /* Trim slashes from the front of file */ + file++; + } - strcat(string, file); + strcat(string, file); - /* Push all slashes to the system preferred direction */ - BLI_path_native_slash(string); + /* Push all slashes to the system preferred direction */ + BLI_path_native_slash(string); } -static bool path_extension_check_ex(const char *str, const size_t str_len, - const char *ext, const size_t ext_len) +static bool path_extension_check_ex(const char *str, + const size_t str_len, + const char *ext, + const size_t ext_len) { - BLI_assert(strlen(str) == str_len); - BLI_assert(strlen(ext) == ext_len); + BLI_assert(strlen(str) == str_len); + BLI_assert(strlen(ext) == ext_len); - return (((str_len == 0 || ext_len == 0 || ext_len >= str_len) == 0) && - (BLI_strcasecmp(ext, str + str_len - ext_len) == 0)); + return (((str_len == 0 || ext_len == 0 || ext_len >= str_len) == 0) && + (BLI_strcasecmp(ext, str + str_len - ext_len) == 0)); } /* does str end with ext. */ bool BLI_path_extension_check(const char *str, const char *ext) { - return path_extension_check_ex(str, strlen(str), ext, strlen(ext)); + return path_extension_check_ex(str, strlen(str), ext, strlen(ext)); } bool BLI_path_extension_check_n(const char *str, ...) { - const size_t str_len = strlen(str); + const size_t str_len = strlen(str); - va_list args; - const char *ext; - bool ret = false; + va_list args; + const char *ext; + bool ret = false; - va_start(args, str); + va_start(args, str); - while ((ext = (const char *) va_arg(args, void *))) { - if (path_extension_check_ex(str, str_len, ext, strlen(ext))) { - ret = true; - break; - } - } + while ((ext = (const char *)va_arg(args, void *))) { + if (path_extension_check_ex(str, str_len, ext, strlen(ext))) { + ret = true; + break; + } + } - va_end(args); + va_end(args); - return ret; + return ret; } /* does str end with any of the suffixes in *ext_array. */ bool BLI_path_extension_check_array(const char *str, const char **ext_array) { - const size_t str_len = strlen(str); - int i = 0; + const size_t str_len = strlen(str); + int i = 0; - while (ext_array[i]) { - if (path_extension_check_ex(str, str_len, ext_array[i], strlen(ext_array[i]))) { - return true; - } + while (ext_array[i]) { + if (path_extension_check_ex(str, str_len, ext_array[i], strlen(ext_array[i]))) { + return true; + } - i++; - } - return false; + i++; + } + return false; } /** @@ -1490,28 +1491,28 @@ bool BLI_path_extension_check_array(const char *str, const char **ext_array) */ bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) { - const char *ext_step = ext_fnmatch; - char pattern[16]; - - while (ext_step[0]) { - const char *ext_next; - size_t len_ext; - - if ((ext_next = strchr(ext_step, ';'))) { - len_ext = ext_next - ext_step + 1; - BLI_strncpy(pattern, ext_step, (len_ext > sizeof(pattern)) ? sizeof(pattern) : len_ext); - } - else { - len_ext = BLI_strncpy_rlen(pattern, ext_step, sizeof(pattern)); - } - - if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) { - return true; - } - ext_step += len_ext; - } - - return false; + const char *ext_step = ext_fnmatch; + char pattern[16]; + + while (ext_step[0]) { + const char *ext_next; + size_t len_ext; + + if ((ext_next = strchr(ext_step, ';'))) { + len_ext = ext_next - ext_step + 1; + BLI_strncpy(pattern, ext_step, (len_ext > sizeof(pattern)) ? sizeof(pattern) : len_ext); + } + else { + len_ext = BLI_strncpy_rlen(pattern, ext_step, sizeof(pattern)); + } + + if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) { + return true; + } + ext_step += len_ext; + } + + return false; } /** @@ -1524,28 +1525,28 @@ bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) */ bool BLI_path_extension_glob_validate(char *ext_fnmatch) { - bool only_wildcards = false; - - for (size_t i = strlen(ext_fnmatch); i-- > 0; ) { - if (ext_fnmatch[i] == ';') { - /* Group separator, we truncate here if we only had wildcards so far. - * Otherwise, all is sound and fine. */ - if (only_wildcards) { - ext_fnmatch[i] = '\0'; - return true; - } - return false; - } - if (!ELEM(ext_fnmatch[i], '?', '*')) { - /* Non-wildcard char, we can break here and consider the pattern valid. */ - return false; - } - /* So far, only wildcards in last group of the pattern... */ - only_wildcards = true; - } - /* Only one group in the pattern, so even if its only made of wildcard(s), - * it is assumed vaid. */ - return false; + bool only_wildcards = false; + + for (size_t i = strlen(ext_fnmatch); i-- > 0;) { + if (ext_fnmatch[i] == ';') { + /* Group separator, we truncate here if we only had wildcards so far. + * Otherwise, all is sound and fine. */ + if (only_wildcards) { + ext_fnmatch[i] = '\0'; + return true; + } + return false; + } + if (!ELEM(ext_fnmatch[i], '?', '*')) { + /* Non-wildcard char, we can break here and consider the pattern valid. */ + return false; + } + /* So far, only wildcards in last group of the pattern... */ + only_wildcards = true; + } + /* Only one group in the pattern, so even if its only made of wildcard(s), + * it is assumed vaid. */ + return false; } /** @@ -1555,28 +1556,28 @@ bool BLI_path_extension_glob_validate(char *ext_fnmatch) bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) { #ifdef DEBUG_STRSIZE - memset(path, 0xff, sizeof(*path) * maxlen); + memset(path, 0xff, sizeof(*path) * maxlen); #endif - const size_t path_len = strlen(path); - const size_t ext_len = strlen(ext); - ssize_t a; - - for (a = path_len - 1; a >= 0; a--) { - if (ELEM(path[a], '.', '/', '\\')) { - break; - } - } - - if ((a < 0) || (path[a] != '.')) { - a = path_len; - } - - if (a + ext_len >= maxlen) { - return false; - } - - memcpy(path + a, ext, ext_len + 1); - return true; + const size_t path_len = strlen(path); + const size_t ext_len = strlen(ext); + ssize_t a; + + for (a = path_len - 1; a >= 0; a--) { + if (ELEM(path[a], '.', '/', '\\')) { + break; + } + } + + if ((a < 0) || (path[a] != '.')) { + a = path_len; + } + + if (a + ext_len >= maxlen) { + return false; + } + + memcpy(path + a, ext, ext_len + 1); + return true; } /** @@ -1585,46 +1586,46 @@ bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) { #ifdef DEBUG_STRSIZE - memset(path, 0xff, sizeof(*path) * maxlen); + memset(path, 0xff, sizeof(*path) * maxlen); #endif - const size_t path_len = strlen(path); - const size_t ext_len = strlen(ext); - ssize_t a; - - /* first check the extension is already there */ - if ((ext_len <= path_len) && (STREQ(path + (path_len - ext_len), ext))) { - return true; - } - - for (a = path_len - 1; a >= 0; a--) { - if (path[a] == '.') { - path[a] = '\0'; - } - else { - break; - } - } - a++; - - if (a + ext_len >= maxlen) { - return false; - } - - memcpy(path + a, ext, ext_len + 1); - return true; + const size_t path_len = strlen(path); + const size_t ext_len = strlen(ext); + ssize_t a; + + /* first check the extension is already there */ + if ((ext_len <= path_len) && (STREQ(path + (path_len - ext_len), ext))) { + return true; + } + + for (a = path_len - 1; a >= 0; a--) { + if (path[a] == '.') { + path[a] = '\0'; + } + else { + break; + } + } + a++; + + if (a + ext_len >= maxlen) { + return false; + } + + memcpy(path + a, ext, ext_len + 1); + return true; } bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename) { #ifdef DEBUG_STRSIZE - memset(filepath, 0xff, sizeof(*filepath) * maxlen); + memset(filepath, 0xff, sizeof(*filepath) * maxlen); #endif - char *c = (char *)BLI_last_slash(filepath); - if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) { - strcpy(c ? &c[1] : filepath, filename); - return true; - } - return false; + char *c = (char *)BLI_last_slash(filepath); + if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) { + strcpy(c ? &c[1] : filepath, filename); + return true; + } + return false; } /** @@ -1635,28 +1636,29 @@ bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename) * - Doesn't use CWD, or deal with relative paths. * - Only fill's in \a dir and \a file when they are non NULL. * */ -void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen) +void BLI_split_dirfile( + const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen) { #ifdef DEBUG_STRSIZE - memset(dir, 0xff, sizeof(*dir) * dirlen); - memset(file, 0xff, sizeof(*file) * filelen); + memset(dir, 0xff, sizeof(*dir) * dirlen); + memset(file, 0xff, sizeof(*file) * filelen); #endif - const char *lslash_str = BLI_last_slash(string); - const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0; - - if (dir) { - if (lslash) { - /* +1 to include the slash and the last char */ - BLI_strncpy(dir, string, MIN2(dirlen, lslash + 1)); - } - else { - dir[0] = '\0'; - } - } - - if (file) { - BLI_strncpy(file, string + lslash, filelen); - } + const char *lslash_str = BLI_last_slash(string); + const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0; + + if (dir) { + if (lslash) { + /* +1 to include the slash and the last char */ + BLI_strncpy(dir, string, MIN2(dirlen, lslash + 1)); + } + else { + dir[0] = '\0'; + } + } + + if (file) { + BLI_strncpy(file, string + lslash, filelen); + } } /** @@ -1664,7 +1666,7 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d */ void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) { - BLI_split_dirfile(string, dir, NULL, dirlen, 0); + BLI_split_dirfile(string, dir, NULL, dirlen, 0); } /** @@ -1672,7 +1674,7 @@ void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) */ void BLI_split_file_part(const char *string, char *file, const size_t filelen) { - BLI_split_dirfile(string, NULL, file, 0, filelen); + BLI_split_dirfile(string, NULL, file, 0, filelen); } /** @@ -1680,59 +1682,62 @@ void BLI_split_file_part(const char *string, char *file, const size_t filelen) */ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) { - size_t dirlen = BLI_strnlen(dst, maxlen); + size_t dirlen = BLI_strnlen(dst, maxlen); - /* inline BLI_add_slash */ - if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { - dst[dirlen++] = SEP; - dst[dirlen] = '\0'; - } + /* inline BLI_add_slash */ + if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { + dst[dirlen++] = SEP; + dst[dirlen] = '\0'; + } - if (dirlen >= maxlen) { - return; /* fills the path */ - } + if (dirlen >= maxlen) { + return; /* fills the path */ + } - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); + BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } /** * Simple appending of filename to dir, does not check for valid path! * Puts result into *dst, which may be same area as *dir. */ -void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) +void BLI_join_dirfile(char *__restrict dst, + const size_t maxlen, + const char *__restrict dir, + const char *__restrict file) { #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxlen); + memset(dst, 0xff, sizeof(*dst) * maxlen); #endif - size_t dirlen = BLI_strnlen(dir, maxlen); - - /* args can't match */ - BLI_assert(!ELEM(dst, dir, file)); - - if (dirlen == maxlen) { - memcpy(dst, dir, dirlen); - dst[dirlen - 1] = '\0'; - return; /* dir fills the path */ - } - else { - memcpy(dst, dir, dirlen + 1); - } - - if (dirlen + 1 >= maxlen) { - return; /* fills the path */ - } - - /* inline BLI_add_slash */ - if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) { - dst[dirlen++] = SEP; - dst[dirlen] = '\0'; - } - - if (dirlen >= maxlen) { - return; /* fills the path */ - } - - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); + size_t dirlen = BLI_strnlen(dir, maxlen); + + /* args can't match */ + BLI_assert(!ELEM(dst, dir, file)); + + if (dirlen == maxlen) { + memcpy(dst, dir, dirlen); + dst[dirlen - 1] = '\0'; + return; /* dir fills the path */ + } + else { + memcpy(dst, dir, dirlen + 1); + } + + if (dirlen + 1 >= maxlen) { + return; /* fills the path */ + } + + /* inline BLI_add_slash */ + if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) { + dst[dirlen++] = SEP; + dst[dirlen] = '\0'; + } + + if (dirlen >= maxlen) { + return; /* fills the path */ + } + + BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } /** @@ -1745,81 +1750,81 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) { #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * dst_len); + memset(dst, 0xff, sizeof(*dst) * dst_len); #endif - if (UNLIKELY(dst_len == 0)) { - return 0; - } - const size_t dst_last = dst_len - 1; - size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); - - if (ofs == dst_last) { - return ofs; - } - - /* remove trailing slashes, unless there are _only_ trailing slashes - * (allow "//" as the first argument). */ - bool has_trailing_slash = false; - if (ofs != 0) { - size_t len = ofs; - while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { - len -= 1; - } - if (len != 0) { - ofs = len; - } - has_trailing_slash = (path[len] != '\0'); - } - - va_list args; - va_start(args, path); - while ((path = (const char *) va_arg(args, const char *))) { - has_trailing_slash = false; - const char *path_init = path; - while (ELEM(path[0], SEP, ALTSEP)) { - path++; - } - size_t len = strlen(path); - if (len != 0) { - while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { - len -= 1; - } - - if (len != 0) { - /* the very first path may have a slash at the end */ - if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { - dst[ofs++] = SEP; - if (ofs == dst_last) { - break; - } - } - has_trailing_slash = (path[len] != '\0'); - if (ofs + len >= dst_last) { - len = dst_last - ofs; - } - memcpy(&dst[ofs], path, len); - ofs += len; - if (ofs == dst_last) { - break; - } - } - } - else { - has_trailing_slash = (path_init != path); - } - } - va_end(args); - - if (has_trailing_slash) { - if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { - dst[ofs++] = SEP; - } - } - - BLI_assert(ofs <= dst_last); - dst[ofs] = '\0'; - - return ofs; + if (UNLIKELY(dst_len == 0)) { + return 0; + } + const size_t dst_last = dst_len - 1; + size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); + + if (ofs == dst_last) { + return ofs; + } + + /* remove trailing slashes, unless there are _only_ trailing slashes + * (allow "//" as the first argument). */ + bool has_trailing_slash = false; + if (ofs != 0) { + size_t len = ofs; + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + if (len != 0) { + ofs = len; + } + has_trailing_slash = (path[len] != '\0'); + } + + va_list args; + va_start(args, path); + while ((path = (const char *)va_arg(args, const char *))) { + has_trailing_slash = false; + const char *path_init = path; + while (ELEM(path[0], SEP, ALTSEP)) { + path++; + } + size_t len = strlen(path); + if (len != 0) { + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + + if (len != 0) { + /* the very first path may have a slash at the end */ + if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { + dst[ofs++] = SEP; + if (ofs == dst_last) { + break; + } + } + has_trailing_slash = (path[len] != '\0'); + if (ofs + len >= dst_last) { + len = dst_last - ofs; + } + memcpy(&dst[ofs], path, len); + ofs += len; + if (ofs == dst_last) { + break; + } + } + } + else { + has_trailing_slash = (path_init != path); + } + } + va_end(args); + + if (has_trailing_slash) { + if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { + dst[ofs++] = SEP; + } + } + + BLI_assert(ofs <= dst_last); + dst[ofs] = '\0'; + + return ofs; } /** @@ -1830,8 +1835,8 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat */ const char *BLI_path_basename(const char *path) { - const char * const filename = BLI_last_slash(path); - return filename ? filename + 1 : path; + const char *const filename = BLI_last_slash(path); + return filename ? filename + 1 : path; } /** @@ -1845,58 +1850,58 @@ const char *BLI_path_basename(const char *path) */ bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len) { - if (index >= 0) { - int index_step = 0; - int prev = -1; - int i = 0; - while (true) { - const char c = path[i]; - if (ELEM(c, SEP, ALTSEP, '\0')) { - if (prev + 1 != i) { - prev += 1; - if (index_step == index) { - *r_offset = prev; - *r_len = i - prev; - /* printf("!!! %d %d\n", start, end); */ - return true; - } - index_step += 1; - } - if (c == '\0') { - break; - } - prev = i; - } - i += 1; - } - return false; - } - else { - /* negative number, reverse where -1 is the last element */ - int index_step = -1; - int prev = strlen(path); - int i = prev - 1; - while (true) { - const char c = i >= 0 ? path[i] : '\0'; - if (ELEM(c, SEP, ALTSEP, '\0')) { - if (prev - 1 != i) { - i += 1; - if (index_step == index) { - *r_offset = i; - *r_len = prev - i; - return true; - } - index_step -= 1; - } - if (c == '\0') { - break; - } - prev = i; - } - i -= 1; - } - return false; - } + if (index >= 0) { + int index_step = 0; + int prev = -1; + int i = 0; + while (true) { + const char c = path[i]; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev + 1 != i) { + prev += 1; + if (index_step == index) { + *r_offset = prev; + *r_len = i - prev; + /* printf("!!! %d %d\n", start, end); */ + return true; + } + index_step += 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i += 1; + } + return false; + } + else { + /* negative number, reverse where -1 is the last element */ + int index_step = -1; + int prev = strlen(path); + int i = prev - 1; + while (true) { + const char c = i >= 0 ? path[i] : '\0'; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev - 1 != i) { + i += 1; + if (index_step == index) { + *r_offset = i; + *r_len = prev - i; + return true; + } + index_step -= 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i -= 1; + } + return false; + } } /** @@ -1904,17 +1909,17 @@ bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, in */ const char *BLI_first_slash(const char *string) { - const char * const ffslash = strchr(string, '/'); - const char * const fbslash = strchr(string, '\\'); + const char *const ffslash = strchr(string, '/'); + const char *const fbslash = strchr(string, '\\'); - if (!ffslash) { - return fbslash; - } - else if (!fbslash) { - return ffslash; - } + if (!ffslash) { + return fbslash; + } + else if (!fbslash) { + return ffslash; + } - return (ffslash < fbslash) ? ffslash : fbslash; + return (ffslash < fbslash) ? ffslash : fbslash; } /** @@ -1922,17 +1927,17 @@ const char *BLI_first_slash(const char *string) */ const char *BLI_last_slash(const char *string) { - const char * const lfslash = strrchr(string, '/'); - const char * const lbslash = strrchr(string, '\\'); + const char *const lfslash = strrchr(string, '/'); + const char *const lbslash = strrchr(string, '\\'); - if (!lfslash) { - return lbslash; - } - else if (!lbslash) { - return lfslash; - } + if (!lfslash) { + return lbslash; + } + else if (!lbslash) { + return lfslash; + } - return (lfslash > lbslash) ? lfslash : lbslash; + return (lfslash > lbslash) ? lfslash : lbslash; } /** @@ -1941,13 +1946,13 @@ const char *BLI_last_slash(const char *string) */ int BLI_add_slash(char *string) { - int len = strlen(string); - if (len == 0 || string[len - 1] != SEP) { - string[len] = SEP; - string[len + 1] = '\0'; - return len + 1; - } - return len; + int len = strlen(string); + if (len == 0 || string[len - 1] != SEP) { + string[len] = SEP; + string[len + 1] = '\0'; + return len + 1; + } + return len; } /** @@ -1955,16 +1960,16 @@ int BLI_add_slash(char *string) */ void BLI_del_slash(char *string) { - int len = strlen(string); - while (len) { - if (string[len - 1] == SEP) { - string[len - 1] = '\0'; - len--; - } - else { - break; - } - } + int len = strlen(string); + while (len) { + if (string[len - 1] == SEP) { + string[len - 1] = '\0'; + len--; + } + else { + break; + } + } } /** @@ -1973,10 +1978,10 @@ void BLI_del_slash(char *string) void BLI_path_native_slash(char *path) { #ifdef WIN32 - if (path && BLI_strnlen(path, 3) > 2) { - BLI_str_replace_char(path + 2, '/', '\\'); - } + if (path && BLI_strnlen(path, 3) > 2) { + BLI_str_replace_char(path + 2, '/', '\\'); + } #else - BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/'); + BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/'); #endif } diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index 4044ebad56b..1538b5922b1 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -49,7 +49,7 @@ #include "BLI_memarena.h" #include "BLI_alloca.h" -#include "BLI_polyfill_2d.h" /* own include */ +#include "BLI_polyfill_2d.h" /* own include */ #include "BLI_strict_flags.h" @@ -72,7 +72,6 @@ # include "PIL_time_utildefines.h" #endif - typedef signed char eSign; #ifdef USE_KDTREE @@ -99,93 +98,91 @@ typedef bool axis_t; /* use for sorting */ typedef struct KDTreeNode2D_head { - uint neg, pos; - uint index; + uint neg, pos; + uint index; } KDTreeNode2D_head; typedef struct KDTreeNode2D { - uint neg, pos; - uint index; - axis_t axis; /* range is only (0-1) */ - ushort flag; - uint parent; + uint neg, pos; + uint index; + axis_t axis; /* range is only (0-1) */ + ushort flag; + uint parent; } KDTreeNode2D; struct KDTree2D { - KDTreeNode2D *nodes; - const float (*coords)[2]; - uint root; - uint totnode; - uint *nodes_map; /* index -> node lookup */ + KDTreeNode2D *nodes; + const float (*coords)[2]; + uint root; + uint totnode; + uint *nodes_map; /* index -> node lookup */ }; struct KDRange2D { - float min, max; + float min, max; }; -#endif /* USE_KDTREE */ +#endif /* USE_KDTREE */ enum { - CONCAVE = -1, - TANGENTIAL = 0, - CONVEX = 1, + CONCAVE = -1, + TANGENTIAL = 0, + CONVEX = 1, }; typedef struct PolyFill { - struct PolyIndex *indices; /* vertex aligned */ + struct PolyIndex *indices; /* vertex aligned */ - const float (*coords)[2]; - uint coords_tot; + const float (*coords)[2]; + uint coords_tot; #ifdef USE_CONVEX_SKIP - uint coords_tot_concave; + uint coords_tot_concave; #endif - /* A polygon with n vertices has a triangulation of n-2 triangles. */ - uint (*tris)[3]; - uint tris_tot; + /* A polygon with n vertices has a triangulation of n-2 triangles. */ + uint (*tris)[3]; + uint tris_tot; #ifdef USE_KDTREE - struct KDTree2D kdtree; + struct KDTree2D kdtree; #endif } PolyFill; - /* circular linklist */ typedef struct PolyIndex { - struct PolyIndex *next, *prev; - uint index; - eSign sign; + struct PolyIndex *next, *prev; + uint index; + eSign sign; } PolyIndex; - /* based on libgdx 2013-11-28, apache 2.0 licensed */ static void pf_coord_sign_calc(PolyFill *pf, PolyIndex *pi); -static PolyIndex *pf_ear_tip_find( - PolyFill *pf +static PolyIndex *pf_ear_tip_find(PolyFill *pf #ifdef USE_CLIP_EVEN - , PolyIndex *pi_ear_init + , + PolyIndex *pi_ear_init #endif #ifdef USE_CLIP_SWEEP - , bool reverse + , + bool reverse #endif - ); - -static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip); -static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip); +); +static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip); +static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip); BLI_INLINE eSign signum_enum(float a) { - if (UNLIKELY(a == 0.0f)) { - return 0; - } - else if (a > 0.0f) { - return 1; - } - else { - return -1; - } + if (UNLIKELY(a == 0.0f)) { + return 0; + } + else if (a > 0.0f) { + return 1; + } + else { + return -1; + } } /** @@ -196,407 +193,386 @@ BLI_INLINE eSign signum_enum(float a) */ BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2]) { - return ((v1[0] * (v2[1] - v3[1])) + - (v2[0] * (v3[1] - v1[1])) + - (v3[0] * (v1[1] - v2[1]))); + return ((v1[0] * (v2[1] - v3[1])) + (v2[0] * (v3[1] - v1[1])) + (v3[0] * (v1[1] - v2[1]))); } - static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2]) { - return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1)); + return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1)); } - #ifdef USE_KDTREE -#define KDNODE_UNSET ((uint)-1) +# define KDNODE_UNSET ((uint)-1) enum { - KDNODE_FLAG_REMOVED = (1 << 0), + KDNODE_FLAG_REMOVED = (1 << 0), }; -static void kdtree2d_new( - struct KDTree2D *tree, - uint tot, - const float (*coords)[2]) +static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[2]) { - /* set by caller */ - // tree->nodes = nodes; - tree->coords = coords; - tree->root = KDNODE_UNSET; - tree->totnode = tot; + /* set by caller */ + // tree->nodes = nodes; + tree->coords = coords; + tree->root = KDNODE_UNSET; + tree->totnode = tot; } /** * no need for kdtree2d_insert, since we know the coords array. */ -static void kdtree2d_init( - struct KDTree2D *tree, - const uint coords_tot, - const PolyIndex *indices) +static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const PolyIndex *indices) { - KDTreeNode2D *node; - uint i; - - for (i = 0, node = tree->nodes; i < coords_tot; i++) { - if (indices[i].sign != CONVEX) { - node->neg = node->pos = KDNODE_UNSET; - node->index = indices[i].index; - node->axis = 0; - node->flag = 0; - node++; - } - } - - BLI_assert(tree->totnode == (uint)(node - tree->nodes)); + KDTreeNode2D *node; + uint i; + + for (i = 0, node = tree->nodes; i < coords_tot; i++) { + if (indices[i].sign != CONVEX) { + node->neg = node->pos = KDNODE_UNSET; + node->index = indices[i].index; + node->axis = 0; + node->flag = 0; + node++; + } + } + + BLI_assert(tree->totnode == (uint)(node - tree->nodes)); } static uint kdtree2d_balance_recursive( - KDTreeNode2D *nodes, uint totnode, axis_t axis, - const float (*coords)[2], const uint ofs) + KDTreeNode2D *nodes, uint totnode, axis_t axis, const float (*coords)[2], const uint ofs) { - KDTreeNode2D *node; - uint neg, pos, median, i, j; - - if (totnode <= 0) { - return KDNODE_UNSET; - } - else if (totnode == 1) { - return 0 + ofs; - } - - /* quicksort style sorting around median */ - neg = 0; - pos = totnode - 1; - median = totnode / 2; - - while (pos > neg) { - const float co = coords[nodes[pos].index][axis]; - i = neg - 1; - j = pos; - - while (1) { - while (coords[nodes[++i].index][axis] < co) { /* pass */ } - while (coords[nodes[--j].index][axis] > co && j > neg) { /* pass */ } - - if (i >= j) { - break; - } - SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[j]); - } - - SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[pos]); - if (i >= median) { - pos = i - 1; - } - if (i <= median) { - neg = i + 1; - } - } - - /* set node and sort subnodes */ - node = &nodes[median]; - node->axis = axis; - axis = !axis; - node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs); - node->pos = kdtree2d_balance_recursive(&nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs); - - return median + ofs; + KDTreeNode2D *node; + uint neg, pos, median, i, j; + + if (totnode <= 0) { + return KDNODE_UNSET; + } + else if (totnode == 1) { + return 0 + ofs; + } + + /* quicksort style sorting around median */ + neg = 0; + pos = totnode - 1; + median = totnode / 2; + + while (pos > neg) { + const float co = coords[nodes[pos].index][axis]; + i = neg - 1; + j = pos; + + while (1) { + while (coords[nodes[++i].index][axis] < co) { /* pass */ + } + while (coords[nodes[--j].index][axis] > co && j > neg) { /* pass */ + } + + if (i >= j) { + break; + } + SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[j]); + } + + SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[pos]); + if (i >= median) { + pos = i - 1; + } + if (i <= median) { + neg = i + 1; + } + } + + /* set node and sort subnodes */ + node = &nodes[median]; + node->axis = axis; + axis = !axis; + node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs); + node->pos = kdtree2d_balance_recursive( + &nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs); + + return median + ofs; } -static void kdtree2d_balance( - struct KDTree2D *tree) +static void kdtree2d_balance(struct KDTree2D *tree) { - tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0); + tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0); } - -static void kdtree2d_init_mapping( - struct KDTree2D *tree) +static void kdtree2d_init_mapping(struct KDTree2D *tree) { - uint i; - KDTreeNode2D *node; - - for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) { - if (node->neg != KDNODE_UNSET) { - tree->nodes[node->neg].parent = i; - } - if (node->pos != KDNODE_UNSET) { - tree->nodes[node->pos].parent = i; - } - - /* build map */ - BLI_assert(tree->nodes_map[node->index] == KDNODE_UNSET); - tree->nodes_map[node->index] = i; - } - - tree->nodes[tree->root].parent = KDNODE_UNSET; + uint i; + KDTreeNode2D *node; + + for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) { + if (node->neg != KDNODE_UNSET) { + tree->nodes[node->neg].parent = i; + } + if (node->pos != KDNODE_UNSET) { + tree->nodes[node->pos].parent = i; + } + + /* build map */ + BLI_assert(tree->nodes_map[node->index] == KDNODE_UNSET); + tree->nodes_map[node->index] = i; + } + + tree->nodes[tree->root].parent = KDNODE_UNSET; } -static void kdtree2d_node_remove( - struct KDTree2D *tree, - uint index) +static void kdtree2d_node_remove(struct KDTree2D *tree, uint index) { - uint node_index = tree->nodes_map[index]; - KDTreeNode2D *node; - - if (node_index == KDNODE_UNSET) { - return; - } - else { - tree->nodes_map[index] = KDNODE_UNSET; - } - - node = &tree->nodes[node_index]; - tree->totnode -= 1; - - BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0); - node->flag |= KDNODE_FLAG_REMOVED; - - while ((node->neg == KDNODE_UNSET) && - (node->pos == KDNODE_UNSET) && - (node->parent != KDNODE_UNSET)) - { - KDTreeNode2D *node_parent = &tree->nodes[node->parent]; - - BLI_assert((uint)(node - tree->nodes) == node_index); - if (node_parent->neg == node_index) { - node_parent->neg = KDNODE_UNSET; - } - else { - BLI_assert(node_parent->pos == node_index); - node_parent->pos = KDNODE_UNSET; - } - - if (node_parent->flag & KDNODE_FLAG_REMOVED) { - node_index = node->parent; - node = node_parent; - } - else { - break; - } - } + uint node_index = tree->nodes_map[index]; + KDTreeNode2D *node; + + if (node_index == KDNODE_UNSET) { + return; + } + else { + tree->nodes_map[index] = KDNODE_UNSET; + } + + node = &tree->nodes[node_index]; + tree->totnode -= 1; + + BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0); + node->flag |= KDNODE_FLAG_REMOVED; + + while ((node->neg == KDNODE_UNSET) && (node->pos == KDNODE_UNSET) && + (node->parent != KDNODE_UNSET)) { + KDTreeNode2D *node_parent = &tree->nodes[node->parent]; + + BLI_assert((uint)(node - tree->nodes) == node_index); + if (node_parent->neg == node_index) { + node_parent->neg = KDNODE_UNSET; + } + else { + BLI_assert(node_parent->pos == node_index); + node_parent->pos = KDNODE_UNSET; + } + + if (node_parent->flag & KDNODE_FLAG_REMOVED) { + node_index = node->parent; + node = node_parent; + } + else { + break; + } + } } -static bool kdtree2d_isect_tri_recursive( - const struct KDTree2D *tree, - const uint tri_index[3], - const float *tri_coords[3], - const float tri_center[2], - const struct KDRange2D bounds[2], - const KDTreeNode2D *node) +static bool kdtree2d_isect_tri_recursive(const struct KDTree2D *tree, + const uint tri_index[3], + const float *tri_coords[3], + const float tri_center[2], + const struct KDRange2D bounds[2], + const KDTreeNode2D *node) { - const float *co = tree->coords[node->index]; - - /* bounds then triangle intersect */ - if ((node->flag & KDNODE_FLAG_REMOVED) == 0) { - /* bounding box test first */ - if ((co[0] >= bounds[0].min) && - (co[0] <= bounds[0].max) && - (co[1] >= bounds[1].min) && - (co[1] <= bounds[1].max)) - { - if ((span_tri_v2_sign(tri_coords[0], tri_coords[1], co) != CONCAVE) && - (span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) && - (span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE)) - { - if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) { - return true; - } - } - } - } - -#define KDTREE2D_ISECT_TRI_RECURSE_NEG \ - (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \ - (kdtree2d_isect_tri_recursive(tree, tri_index, tri_coords, tri_center, bounds, \ - &tree->nodes[node->neg]))) -#define KDTREE2D_ISECT_TRI_RECURSE_POS \ - (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \ - (kdtree2d_isect_tri_recursive(tree, tri_index, tri_coords, tri_center, bounds, \ - &tree->nodes[node->pos]))) - - if (tri_center[node->axis] > co[node->axis]) { - if (KDTREE2D_ISECT_TRI_RECURSE_POS) { - return true; - } - if (KDTREE2D_ISECT_TRI_RECURSE_NEG) { - return true; - } - } - else { - if (KDTREE2D_ISECT_TRI_RECURSE_NEG) { - return true; - } - if (KDTREE2D_ISECT_TRI_RECURSE_POS) { - return true; - } - } - -#undef KDTREE2D_ISECT_TRI_RECURSE_NEG -#undef KDTREE2D_ISECT_TRI_RECURSE_POS - - BLI_assert(node->index != KDNODE_UNSET); - - return false; + const float *co = tree->coords[node->index]; + + /* bounds then triangle intersect */ + if ((node->flag & KDNODE_FLAG_REMOVED) == 0) { + /* bounding box test first */ + if ((co[0] >= bounds[0].min) && (co[0] <= bounds[0].max) && (co[1] >= bounds[1].min) && + (co[1] <= bounds[1].max)) { + if ((span_tri_v2_sign(tri_coords[0], tri_coords[1], co) != CONCAVE) && + (span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) && + (span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE)) { + if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) { + return true; + } + } + } + } + +# define KDTREE2D_ISECT_TRI_RECURSE_NEG \ + (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \ + (kdtree2d_isect_tri_recursive( \ + tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->neg]))) +# define KDTREE2D_ISECT_TRI_RECURSE_POS \ + (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \ + (kdtree2d_isect_tri_recursive( \ + tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->pos]))) + + if (tri_center[node->axis] > co[node->axis]) { + if (KDTREE2D_ISECT_TRI_RECURSE_POS) { + return true; + } + if (KDTREE2D_ISECT_TRI_RECURSE_NEG) { + return true; + } + } + else { + if (KDTREE2D_ISECT_TRI_RECURSE_NEG) { + return true; + } + if (KDTREE2D_ISECT_TRI_RECURSE_POS) { + return true; + } + } + +# undef KDTREE2D_ISECT_TRI_RECURSE_NEG +# undef KDTREE2D_ISECT_TRI_RECURSE_POS + + BLI_assert(node->index != KDNODE_UNSET); + + return false; } -static bool kdtree2d_isect_tri( - struct KDTree2D *tree, - const uint ind[3]) +static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3]) { - const float *vs[3]; - uint i; - struct KDRange2D bounds[2] = { - {FLT_MAX, -FLT_MAX}, - {FLT_MAX, -FLT_MAX}, - }; - float tri_center[2] = {0.0f, 0.0f}; + const float *vs[3]; + uint i; + struct KDRange2D bounds[2] = { + {FLT_MAX, -FLT_MAX}, + {FLT_MAX, -FLT_MAX}, + }; + float tri_center[2] = {0.0f, 0.0f}; - for (i = 0; i < 3; i++) { - vs[i] = tree->coords[ind[i]]; + for (i = 0; i < 3; i++) { + vs[i] = tree->coords[ind[i]]; - add_v2_v2(tri_center, vs[i]); + add_v2_v2(tri_center, vs[i]); - CLAMP_MAX(bounds[0].min, vs[i][0]); - CLAMP_MIN(bounds[0].max, vs[i][0]); - CLAMP_MAX(bounds[1].min, vs[i][1]); - CLAMP_MIN(bounds[1].max, vs[i][1]); - } + CLAMP_MAX(bounds[0].min, vs[i][0]); + CLAMP_MIN(bounds[0].max, vs[i][0]); + CLAMP_MAX(bounds[1].min, vs[i][1]); + CLAMP_MIN(bounds[1].max, vs[i][1]); + } - mul_v2_fl(tri_center, 1.0f / 3.0f); + mul_v2_fl(tri_center, 1.0f / 3.0f); - return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]); + return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]); } -#endif /* USE_KDTREE */ - +#endif /* USE_KDTREE */ static uint *pf_tri_add(PolyFill *pf) { - return pf->tris[pf->tris_tot++]; + return pf->tris[pf->tris_tot++]; } static void pf_coord_remove(PolyFill *pf, PolyIndex *pi) { #ifdef USE_KDTREE - /* avoid double lookups, since convex coords are ignored when testing intersections */ - if (pf->kdtree.totnode) { - kdtree2d_node_remove(&pf->kdtree, pi->index); - } + /* avoid double lookups, since convex coords are ignored when testing intersections */ + if (pf->kdtree.totnode) { + kdtree2d_node_remove(&pf->kdtree, pi->index); + } #endif - pi->next->prev = pi->prev; - pi->prev->next = pi->next; + pi->next->prev = pi->prev; + pi->prev->next = pi->next; - if (UNLIKELY(pf->indices == pi)) { - pf->indices = pi->next; - } + if (UNLIKELY(pf->indices == pi)) { + pf->indices = pi->next; + } #ifdef DEBUG - pi->index = (uint)-1; - pi->next = pi->prev = NULL; + pi->index = (uint)-1; + pi->next = pi->prev = NULL; #endif - pf->coords_tot -= 1; + pf->coords_tot -= 1; } static void pf_triangulate(PolyFill *pf) { - /* localize */ - PolyIndex *pi_ear; + /* localize */ + PolyIndex *pi_ear; #ifdef USE_CLIP_EVEN - PolyIndex *pi_ear_init = pf->indices; + PolyIndex *pi_ear_init = pf->indices; #endif #ifdef USE_CLIP_SWEEP - bool reverse = false; + bool reverse = false; #endif - while (pf->coords_tot > 3) { - PolyIndex *pi_prev, *pi_next; - eSign sign_orig_prev, sign_orig_next; + while (pf->coords_tot > 3) { + PolyIndex *pi_prev, *pi_next; + eSign sign_orig_prev, sign_orig_next; - pi_ear = pf_ear_tip_find( - pf + pi_ear = pf_ear_tip_find(pf #ifdef USE_CLIP_EVEN - , pi_ear_init + , + pi_ear_init #endif #ifdef USE_CLIP_SWEEP - , reverse + , + reverse #endif - ); + ); #ifdef USE_CONVEX_SKIP - if (pi_ear->sign != CONVEX) { - pf->coords_tot_concave -= 1; - } + if (pi_ear->sign != CONVEX) { + pf->coords_tot_concave -= 1; + } #endif - pi_prev = pi_ear->prev; - pi_next = pi_ear->next; + pi_prev = pi_ear->prev; + pi_next = pi_ear->next; - pf_ear_tip_cut(pf, pi_ear); + pf_ear_tip_cut(pf, pi_ear); - /* The type of the two vertices adjacent to the clipped vertex may have changed. */ - sign_orig_prev = pi_prev->sign; - sign_orig_next = pi_next->sign; + /* The type of the two vertices adjacent to the clipped vertex may have changed. */ + sign_orig_prev = pi_prev->sign; + sign_orig_next = pi_next->sign; - /* check if any verts became convex the (else if) - * case is highly unlikely but may happen with degenerate polygons */ - if (sign_orig_prev != CONVEX) { - pf_coord_sign_calc(pf, pi_prev); + /* check if any verts became convex the (else if) + * case is highly unlikely but may happen with degenerate polygons */ + if (sign_orig_prev != CONVEX) { + pf_coord_sign_calc(pf, pi_prev); #ifdef USE_CONVEX_SKIP - if (pi_prev->sign == CONVEX) { - pf->coords_tot_concave -= 1; -#ifdef USE_KDTREE - kdtree2d_node_remove(&pf->kdtree, pi_prev->index); -#endif - } -#endif - } - if (sign_orig_next != CONVEX) { - pf_coord_sign_calc(pf, pi_next); + if (pi_prev->sign == CONVEX) { + pf->coords_tot_concave -= 1; +# ifdef USE_KDTREE + kdtree2d_node_remove(&pf->kdtree, pi_prev->index); +# endif + } +#endif + } + if (sign_orig_next != CONVEX) { + pf_coord_sign_calc(pf, pi_next); #ifdef USE_CONVEX_SKIP - if (pi_next->sign == CONVEX) { - pf->coords_tot_concave -= 1; -#ifdef USE_KDTREE - kdtree2d_node_remove(&pf->kdtree, pi_next->index); + if (pi_next->sign == CONVEX) { + pf->coords_tot_concave -= 1; +# ifdef USE_KDTREE + kdtree2d_node_remove(&pf->kdtree, pi_next->index); +# endif + } #endif - } -#endif - } + } #ifdef USE_CLIP_EVEN -#ifdef USE_CLIP_SWEEP - pi_ear_init = reverse ? pi_prev->prev : pi_next->next; -#else - pi_ear_init = pi_next->next; -#endif +# ifdef USE_CLIP_SWEEP + pi_ear_init = reverse ? pi_prev->prev : pi_next->next; +# else + pi_ear_init = pi_next->next; +# endif #endif #ifdef USE_CLIP_EVEN -#ifdef USE_CLIP_SWEEP - if (pi_ear_init->sign != CONVEX) { - /* take the extra step since this ear isn't a good candidate */ - pi_ear_init = reverse ? pi_ear_init->prev : pi_ear_init->next; - reverse = !reverse; - } -#endif +# ifdef USE_CLIP_SWEEP + if (pi_ear_init->sign != CONVEX) { + /* take the extra step since this ear isn't a good candidate */ + pi_ear_init = reverse ? pi_ear_init->prev : pi_ear_init->next; + reverse = !reverse; + } +# endif #else - if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) { - reverse = !reverse; - } -#endif - - } - - if (pf->coords_tot == 3) { - uint *tri = pf_tri_add(pf); - pi_ear = pf->indices; - tri[0] = pi_ear->index; pi_ear = pi_ear->next; - tri[1] = pi_ear->index; pi_ear = pi_ear->next; - tri[2] = pi_ear->index; - } + if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) { + reverse = !reverse; + } +#endif + } + + if (pf->coords_tot == 3) { + uint *tri = pf_tri_add(pf); + pi_ear = pf->indices; + tri[0] = pi_ear->index; + pi_ear = pi_ear->next; + tri[1] = pi_ear->index; + pi_ear = pi_ear->next; + tri[2] = pi_ear->index; + } } /** @@ -604,319 +580,311 @@ static void pf_triangulate(PolyFill *pf) */ static void pf_coord_sign_calc(PolyFill *pf, PolyIndex *pi) { - /* localize */ - const float (*coords)[2] = pf->coords; + /* localize */ + const float(*coords)[2] = pf->coords; - pi->sign = span_tri_v2_sign( - coords[pi->prev->index], - coords[pi->index], - coords[pi->next->index]); + pi->sign = span_tri_v2_sign(coords[pi->prev->index], coords[pi->index], coords[pi->next->index]); } -static PolyIndex *pf_ear_tip_find( - PolyFill *pf +static PolyIndex *pf_ear_tip_find(PolyFill *pf #ifdef USE_CLIP_EVEN - , PolyIndex *pi_ear_init + , + PolyIndex *pi_ear_init #endif #ifdef USE_CLIP_SWEEP - , bool reverse + , + bool reverse #endif - ) +) { - /* localize */ - const uint coords_tot = pf->coords_tot; - PolyIndex *pi_ear; + /* localize */ + const uint coords_tot = pf->coords_tot; + PolyIndex *pi_ear; - uint i; + uint i; #ifdef USE_CLIP_EVEN - pi_ear = pi_ear_init; + pi_ear = pi_ear_init; #else - pi_ear = pf->indices; + pi_ear = pf->indices; #endif - i = coords_tot; - while (i--) { - if (pf_ear_tip_check(pf, pi_ear)) { - return pi_ear; - } + i = coords_tot; + while (i--) { + if (pf_ear_tip_check(pf, pi_ear)) { + return pi_ear; + } #ifdef USE_CLIP_SWEEP - pi_ear = reverse ? pi_ear->prev : pi_ear->next; + pi_ear = reverse ? pi_ear->prev : pi_ear->next; #else - pi_ear = pi_ear->next; -#endif - } - - /* Desperate mode: if no vertex is an ear tip, - * we are dealing with a degenerate polygon (e.g. nearly collinear). - * Note that the input was not necessarily degenerate, - * but we could have made it so by clipping some valid ears. - * - * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons", - * Algorithmica (1998), - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291 - * - * Return a convex or tangential vertex if one exists. - */ + pi_ear = pi_ear->next; +#endif + } + + /* Desperate mode: if no vertex is an ear tip, + * we are dealing with a degenerate polygon (e.g. nearly collinear). + * Note that the input was not necessarily degenerate, + * but we could have made it so by clipping some valid ears. + * + * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons", + * Algorithmica (1998), + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291 + * + * Return a convex or tangential vertex if one exists. + */ #ifdef USE_CLIP_EVEN - pi_ear = pi_ear_init; + pi_ear = pi_ear_init; #else - pi_ear = pf->indices; + pi_ear = pf->indices; #endif - i = coords_tot; - while (i--) { - if (pi_ear->sign != CONCAVE) { - return pi_ear; - } - pi_ear = pi_ear->next; - } + i = coords_tot; + while (i--) { + if (pi_ear->sign != CONCAVE) { + return pi_ear; + } + pi_ear = pi_ear->next; + } - /* If all vertices are concave, just return the last one. */ - return pi_ear; + /* If all vertices are concave, just return the last one. */ + return pi_ear; } static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) { #ifndef USE_KDTREE - /* localize */ - const float (*coords)[2] = pf->coords; - PolyIndex *pi_curr; + /* localize */ + const float(*coords)[2] = pf->coords; + PolyIndex *pi_curr; - const float *v1, *v2, *v3; + const float *v1, *v2, *v3; #endif #if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE) - uint coords_tot_concave_checked = 0; + uint coords_tot_concave_checked = 0; #endif - #ifdef USE_CONVEX_SKIP -#ifdef USE_CONVEX_SKIP_TEST - /* check if counting is wrong */ - { - uint coords_tot_concave_test = 0; - PolyIndex *pi_iter = pi_ear_tip; - do { - if (pi_iter->sign != CONVEX) { - coords_tot_concave_test += 1; - } - } while ((pi_iter = pi_iter->next) != pi_ear_tip); - BLI_assert(coords_tot_concave_test == pf->coords_tot_concave); - } -#endif - - /* fast-path for circles */ - if (pf->coords_tot_concave == 0) { - return true; - } -#endif - - if (UNLIKELY(pi_ear_tip->sign == CONCAVE)) { - return false; - } +# ifdef USE_CONVEX_SKIP_TEST + /* check if counting is wrong */ + { + uint coords_tot_concave_test = 0; + PolyIndex *pi_iter = pi_ear_tip; + do { + if (pi_iter->sign != CONVEX) { + coords_tot_concave_test += 1; + } + } while ((pi_iter = pi_iter->next) != pi_ear_tip); + BLI_assert(coords_tot_concave_test == pf->coords_tot_concave); + } +# endif + + /* fast-path for circles */ + if (pf->coords_tot_concave == 0) { + return true; + } +#endif + + if (UNLIKELY(pi_ear_tip->sign == CONCAVE)) { + return false; + } #ifdef USE_KDTREE - { - const uint ind[3] = { - pi_ear_tip->index, - pi_ear_tip->next->index, - pi_ear_tip->prev->index}; - - if (kdtree2d_isect_tri(&pf->kdtree, ind)) { - return false; - } - } -#else + { + const uint ind[3] = {pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index}; - v1 = coords[pi_ear_tip->prev->index]; - v2 = coords[pi_ear_tip->index]; - v3 = coords[pi_ear_tip->next->index]; - - /* Check if any point is inside the triangle formed by previous, current and next vertices. - * Only consider vertices that are not part of this triangle, - * or else we'll always find one inside. */ - - for (pi_curr = pi_ear_tip->next->next; pi_curr != pi_ear_tip->prev; pi_curr = pi_curr->next) { - /* Concave vertices can obviously be inside the candidate ear, - * but so can tangential vertices if they coincide with one of the triangle's vertices. */ - if (pi_curr->sign != CONVEX) { - const float *v = coords[pi_curr->index]; - /* Because the polygon has clockwise winding order, - * the area sign will be positive if the point is strictly inside. - * It will be 0 on the edge, which we want to include as well. */ - - /* note: check (v3, v1) first since it fails _far_ more often then the other 2 checks - * (those fail equally). - * It's logical - the chance is low that points exist on the - * same side as the ear we're clipping off. */ - if ((span_tri_v2_sign(v3, v1, v) != CONCAVE) && - (span_tri_v2_sign(v1, v2, v) != CONCAVE) && - (span_tri_v2_sign(v2, v3, v) != CONCAVE)) - { - return false; - } - -#ifdef USE_CONVEX_SKIP - coords_tot_concave_checked += 1; - if (coords_tot_concave_checked == pf->coords_tot_concave) { - break; - } -#endif - } - } -#endif /* USE_KDTREE */ + if (kdtree2d_isect_tri(&pf->kdtree, ind)) { + return false; + } + } +#else - return true; + v1 = coords[pi_ear_tip->prev->index]; + v2 = coords[pi_ear_tip->index]; + v3 = coords[pi_ear_tip->next->index]; + + /* Check if any point is inside the triangle formed by previous, current and next vertices. + * Only consider vertices that are not part of this triangle, + * or else we'll always find one inside. */ + + for (pi_curr = pi_ear_tip->next->next; pi_curr != pi_ear_tip->prev; pi_curr = pi_curr->next) { + /* Concave vertices can obviously be inside the candidate ear, + * but so can tangential vertices if they coincide with one of the triangle's vertices. */ + if (pi_curr->sign != CONVEX) { + const float *v = coords[pi_curr->index]; + /* Because the polygon has clockwise winding order, + * the area sign will be positive if the point is strictly inside. + * It will be 0 on the edge, which we want to include as well. */ + + /* note: check (v3, v1) first since it fails _far_ more often then the other 2 checks + * (those fail equally). + * It's logical - the chance is low that points exist on the + * same side as the ear we're clipping off. */ + if ((span_tri_v2_sign(v3, v1, v) != CONCAVE) && (span_tri_v2_sign(v1, v2, v) != CONCAVE) && + (span_tri_v2_sign(v2, v3, v) != CONCAVE)) { + return false; + } + +# ifdef USE_CONVEX_SKIP + coords_tot_concave_checked += 1; + if (coords_tot_concave_checked == pf->coords_tot_concave) { + break; + } +# endif + } + } +#endif /* USE_KDTREE */ + + return true; } static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) { - uint *tri = pf_tri_add(pf); + uint *tri = pf_tri_add(pf); - tri[0] = pi_ear_tip->prev->index; - tri[1] = pi_ear_tip->index; - tri[2] = pi_ear_tip->next->index; + tri[0] = pi_ear_tip->prev->index; + tri[1] = pi_ear_tip->index; + tri[2] = pi_ear_tip->next->index; - pf_coord_remove(pf, pi_ear_tip); + pf_coord_remove(pf, pi_ear_tip); } /** * Initializes the #PolyFill structure before tessellating with #polyfill_calc. */ -static void polyfill_prepare( - PolyFill *pf, - const float (*coords)[2], - const uint coords_tot, - int coords_sign, - uint (*r_tris)[3], - PolyIndex *r_indices) +static void polyfill_prepare(PolyFill *pf, + const float (*coords)[2], + const uint coords_tot, + int coords_sign, + uint (*r_tris)[3], + PolyIndex *r_indices) { - /* localize */ - PolyIndex *indices = r_indices; + /* localize */ + PolyIndex *indices = r_indices; - uint i; + uint i; - /* assign all polyfill members here */ - pf->indices = r_indices; - pf->coords = coords; - pf->coords_tot = coords_tot; + /* assign all polyfill members here */ + pf->indices = r_indices; + pf->coords = coords; + pf->coords_tot = coords_tot; #ifdef USE_CONVEX_SKIP - pf->coords_tot_concave = 0; + pf->coords_tot_concave = 0; #endif - pf->tris = r_tris; - pf->tris_tot = 0; + pf->tris = r_tris; + pf->tris_tot = 0; - if (coords_sign == 0) { - coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1; - } - else { - /* check we're passing in correcty args */ + if (coords_sign == 0) { + coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1; + } + else { + /* check we're passing in correcty args */ #ifdef USE_STRICT_ASSERT -#ifndef NDEBUG - if (coords_sign == 1) { - BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f); - } - else { - BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f); - } -#endif -#endif - } - - if (coords_sign == 1) { - for (i = 0; i < coords_tot; i++) { - indices[i].next = &indices[i + 1]; - indices[i].prev = &indices[i - 1]; - indices[i].index = i; - } - } - else { - /* reversed */ - uint n = coords_tot - 1; - for (i = 0; i < coords_tot; i++) { - indices[i].next = &indices[i + 1]; - indices[i].prev = &indices[i - 1]; - indices[i].index = (n - i); - } - } - indices[0].prev = &indices[coords_tot - 1]; - indices[coords_tot - 1].next = &indices[0]; - - for (i = 0; i < coords_tot; i++) { - PolyIndex *pi = &indices[i]; - pf_coord_sign_calc(pf, pi); +# ifndef NDEBUG + if (coords_sign == 1) { + BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f); + } + else { + BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f); + } +# endif +#endif + } + + if (coords_sign == 1) { + for (i = 0; i < coords_tot; i++) { + indices[i].next = &indices[i + 1]; + indices[i].prev = &indices[i - 1]; + indices[i].index = i; + } + } + else { + /* reversed */ + uint n = coords_tot - 1; + for (i = 0; i < coords_tot; i++) { + indices[i].next = &indices[i + 1]; + indices[i].prev = &indices[i - 1]; + indices[i].index = (n - i); + } + } + indices[0].prev = &indices[coords_tot - 1]; + indices[coords_tot - 1].next = &indices[0]; + + for (i = 0; i < coords_tot; i++) { + PolyIndex *pi = &indices[i]; + pf_coord_sign_calc(pf, pi); #ifdef USE_CONVEX_SKIP - if (pi->sign != CONVEX) { - pf->coords_tot_concave += 1; - } + if (pi->sign != CONVEX) { + pf->coords_tot_concave += 1; + } #endif - } + } } -static void polyfill_calc( - PolyFill *pf) +static void polyfill_calc(PolyFill *pf) { #ifdef USE_KDTREE -#ifdef USE_CONVEX_SKIP - if (pf->coords_tot_concave) -#endif - { - kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords); - kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices); - kdtree2d_balance(&pf->kdtree); - kdtree2d_init_mapping(&pf->kdtree); - } -#endif - - pf_triangulate(pf); +# ifdef USE_CONVEX_SKIP + if (pf->coords_tot_concave) +# endif + { + kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords); + kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices); + kdtree2d_balance(&pf->kdtree); + kdtree2d_init_mapping(&pf->kdtree); + } +#endif + + pf_triangulate(pf); } /** * A version of #BLI_polyfill_calc that uses a memory arena to avoid re-allocations. */ -void BLI_polyfill_calc_arena( - const float (*coords)[2], - const uint coords_tot, - const int coords_sign, - uint (*r_tris)[3], +void BLI_polyfill_calc_arena(const float (*coords)[2], + const uint coords_tot, + const int coords_sign, + uint (*r_tris)[3], - struct MemArena *arena) + struct MemArena *arena) { - PolyFill pf; - PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot); + PolyFill pf; + PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot); #ifdef DEBUG_TIME - TIMEIT_START(polyfill2d); + TIMEIT_START(polyfill2d); #endif - polyfill_prepare( - &pf, - coords, coords_tot, coords_sign, - r_tris, - /* cache */ - indices); + polyfill_prepare(&pf, + coords, + coords_tot, + coords_sign, + r_tris, + /* cache */ + indices); #ifdef USE_KDTREE - if (pf.coords_tot_concave) { - pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave); - pf.kdtree.nodes_map = memset(BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot), - 0xff, sizeof(*pf.kdtree.nodes_map) * coords_tot); - } - else { - pf.kdtree.totnode = 0; - } + if (pf.coords_tot_concave) { + pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave); + pf.kdtree.nodes_map = memset( + BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot), + 0xff, + sizeof(*pf.kdtree.nodes_map) * coords_tot); + } + else { + pf.kdtree.totnode = 0; + } #endif - polyfill_calc(&pf); + polyfill_calc(&pf); - /* indices are no longer needed, - * caller can clear arena */ + /* indices are no longer needed, + * caller can clear arena */ #ifdef DEBUG_TIME - TIMEIT_END(polyfill2d); + TIMEIT_END(polyfill2d); #endif } @@ -933,40 +901,41 @@ void BLI_polyfill_calc_arena( * Indices are guaranteed to be assigned to unique triangles, with valid indices, * even in the case of degenerate input (self intersecting polygons, zero area ears... etc). */ -void BLI_polyfill_calc( - const float (*coords)[2], - const uint coords_tot, - const int coords_sign, - uint (*r_tris)[3]) +void BLI_polyfill_calc(const float (*coords)[2], + const uint coords_tot, + const int coords_sign, + uint (*r_tris)[3]) { - PolyFill pf; - PolyIndex *indices = BLI_array_alloca(indices, coords_tot); + PolyFill pf; + PolyIndex *indices = BLI_array_alloca(indices, coords_tot); #ifdef DEBUG_TIME - TIMEIT_START(polyfill2d); + TIMEIT_START(polyfill2d); #endif - polyfill_prepare( - &pf, - coords, coords_tot, coords_sign, - r_tris, - /* cache */ - indices); + polyfill_prepare(&pf, + coords, + coords_tot, + coords_sign, + r_tris, + /* cache */ + indices); #ifdef USE_KDTREE - if (pf.coords_tot_concave) { - pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave); - pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot), - 0xff, sizeof(*pf.kdtree.nodes_map) * coords_tot); - } - else { - pf.kdtree.totnode = 0; - } + if (pf.coords_tot_concave) { + pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave); + pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot), + 0xff, + sizeof(*pf.kdtree.nodes_map) * coords_tot); + } + else { + pf.kdtree.totnode = 0; + } #endif - polyfill_calc(&pf); + polyfill_calc(&pf); #ifdef DEBUG_TIME - TIMEIT_END(polyfill2d); + TIMEIT_END(polyfill2d); #endif } diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 17af81af866..2ca19d173c2 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -40,57 +40,57 @@ #include "BLI_memarena.h" #include "BLI_heap.h" -#include "BLI_polyfill_2d_beautify.h" /* own include */ +#include "BLI_polyfill_2d_beautify.h" /* own include */ #include "BLI_strict_flags.h" /* Used to find matching edges. */ struct OrderEdge { - uint verts[2]; - uint e_half; + uint verts[2]; + uint e_half; }; /* Half edge used for rotating in-place. */ struct HalfEdge { - uint v; - uint e_next; - uint e_radial; - uint base_index; + uint v; + uint e_next; + uint e_radial; + uint base_index; }; static int oedge_cmp(const void *a1, const void *a2) { - const struct OrderEdge *x1 = a1, *x2 = a2; - if (x1->verts[0] > x2->verts[0]) { - return 1; - } - else if (x1->verts[0] < x2->verts[0]) { - return -1; - } - - if (x1->verts[1] > x2->verts[1]) { - return 1; - } - else if (x1->verts[1] < x2->verts[1]) { - return -1; - } - - /* only for pradictability */ - if (x1->e_half > x2->e_half) { - return 1; - } - else if (x1->e_half < x2->e_half) { - return -1; - } - /* Should never get here, no two edges should be the same. */ - BLI_assert(false); - return 0; + const struct OrderEdge *x1 = a1, *x2 = a2; + if (x1->verts[0] > x2->verts[0]) { + return 1; + } + else if (x1->verts[0] < x2->verts[0]) { + return -1; + } + + if (x1->verts[1] > x2->verts[1]) { + return 1; + } + else if (x1->verts[1] < x2->verts[1]) { + return -1; + } + + /* only for pradictability */ + if (x1->e_half > x2->e_half) { + return 1; + } + else if (x1->e_half < x2->e_half) { + return -1; + } + /* Should never get here, no two edges should be the same. */ + BLI_assert(false); + return 0; } BLI_INLINE bool is_boundary_edge(uint i_a, uint i_b, const uint coord_last) { - BLI_assert(i_a < i_b); - return ((i_a + 1 == i_b) || UNLIKELY((i_a == 0) && (i_b == coord_last))); + BLI_assert(i_a < i_b); + return ((i_a + 1 == i_b) || UNLIKELY((i_a == 0) && (i_b == coord_last))); } /** * Assuming we have 2 triangles sharing an edge (2 - 4), @@ -102,206 +102,200 @@ BLI_INLINE bool is_boundary_edge(uint i_a, uint i_b, const uint coord_last) * * \return (negative number means the edge can be rotated, lager == better). */ -float BLI_polyfill_beautify_quad_rotate_calc_ex( - const float v1[2], const float v2[2], const float v3[2], const float v4[2], - const bool lock_degenerate) +float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2], + const bool lock_degenerate) { - /* not a loop (only to be able to break out) */ - do { - /* Allow very small faces to be considered non-zero. */ - const float eps_zero_area = 1e-12f; - const float area_2x_234 = cross_tri_v2(v2, v3, v4); - const float area_2x_241 = cross_tri_v2(v2, v4, v1); - - const float area_2x_123 = cross_tri_v2(v1, v2, v3); - const float area_2x_134 = cross_tri_v2(v1, v3, v4); - - BLI_assert((ELEM(v1, v2, v3, v4) == false) && - (ELEM(v2, v1, v3, v4) == false) && - (ELEM(v3, v1, v2, v4) == false) && - (ELEM(v4, v1, v2, v3) == false)); - /* - * Test for unusable (1-3) state. - * - Area sign flipping to check faces aren't going to point in opposite directions. - * - Area epsilon check that the one of the faces won't be zero area. - */ - if ((area_2x_123 >= 0.0f) != (area_2x_134 >= 0.0f)) { - break; - } - else if ((fabsf(area_2x_123) <= eps_zero_area) || (fabsf(area_2x_134) <= eps_zero_area)) { - break; - } - - /* Test for unusable (2-4) state (same as above). */ - if ((area_2x_234 >= 0.0f) != (area_2x_241 >= 0.0f)) { - if (lock_degenerate) { - break; - } - else { - return -FLT_MAX; /* always rotate */ - } - } - else if ((fabsf(area_2x_234) <= eps_zero_area) || (fabsf(area_2x_241) <= eps_zero_area)) { - return -FLT_MAX; /* always rotate */ - } - - { - /* testing rule: the area divided by the perimeter, - * check if (1-3) beats the existing (2-4) edge rotation */ - float area_a, area_b; - float prim_a, prim_b; - float fac_24, fac_13; - - float len_12, len_23, len_34, len_41, len_24, len_13; - - /* edges around the quad */ - len_12 = len_v2v2(v1, v2); - len_23 = len_v2v2(v2, v3); - len_34 = len_v2v2(v3, v4); - len_41 = len_v2v2(v4, v1); - /* edges crossing the quad interior */ - len_13 = len_v2v2(v1, v3); - len_24 = len_v2v2(v2, v4); - - /* note, area is in fact (area * 2), - * but in this case its OK, since we're comparing ratios */ - - /* edge (2-4), current state */ - area_a = fabsf(area_2x_234); - area_b = fabsf(area_2x_241); - prim_a = len_23 + len_34 + len_24; - prim_b = len_41 + len_12 + len_24; - fac_24 = (area_a / prim_a) + (area_b / prim_b); - - /* edge (1-3), new state */ - area_a = fabsf(area_2x_123); - area_b = fabsf(area_2x_134); - prim_a = len_12 + len_23 + len_13; - prim_b = len_34 + len_41 + len_13; - fac_13 = (area_a / prim_a) + (area_b / prim_b); - - /* negative number if (1-3) is an improved state */ - return fac_24 - fac_13; - } - } while (false); - - return FLT_MAX; + /* not a loop (only to be able to break out) */ + do { + /* Allow very small faces to be considered non-zero. */ + const float eps_zero_area = 1e-12f; + const float area_2x_234 = cross_tri_v2(v2, v3, v4); + const float area_2x_241 = cross_tri_v2(v2, v4, v1); + + const float area_2x_123 = cross_tri_v2(v1, v2, v3); + const float area_2x_134 = cross_tri_v2(v1, v3, v4); + + BLI_assert((ELEM(v1, v2, v3, v4) == false) && (ELEM(v2, v1, v3, v4) == false) && + (ELEM(v3, v1, v2, v4) == false) && (ELEM(v4, v1, v2, v3) == false)); + /* + * Test for unusable (1-3) state. + * - Area sign flipping to check faces aren't going to point in opposite directions. + * - Area epsilon check that the one of the faces won't be zero area. + */ + if ((area_2x_123 >= 0.0f) != (area_2x_134 >= 0.0f)) { + break; + } + else if ((fabsf(area_2x_123) <= eps_zero_area) || (fabsf(area_2x_134) <= eps_zero_area)) { + break; + } + + /* Test for unusable (2-4) state (same as above). */ + if ((area_2x_234 >= 0.0f) != (area_2x_241 >= 0.0f)) { + if (lock_degenerate) { + break; + } + else { + return -FLT_MAX; /* always rotate */ + } + } + else if ((fabsf(area_2x_234) <= eps_zero_area) || (fabsf(area_2x_241) <= eps_zero_area)) { + return -FLT_MAX; /* always rotate */ + } + + { + /* testing rule: the area divided by the perimeter, + * check if (1-3) beats the existing (2-4) edge rotation */ + float area_a, area_b; + float prim_a, prim_b; + float fac_24, fac_13; + + float len_12, len_23, len_34, len_41, len_24, len_13; + + /* edges around the quad */ + len_12 = len_v2v2(v1, v2); + len_23 = len_v2v2(v2, v3); + len_34 = len_v2v2(v3, v4); + len_41 = len_v2v2(v4, v1); + /* edges crossing the quad interior */ + len_13 = len_v2v2(v1, v3); + len_24 = len_v2v2(v2, v4); + + /* note, area is in fact (area * 2), + * but in this case its OK, since we're comparing ratios */ + + /* edge (2-4), current state */ + area_a = fabsf(area_2x_234); + area_b = fabsf(area_2x_241); + prim_a = len_23 + len_34 + len_24; + prim_b = len_41 + len_12 + len_24; + fac_24 = (area_a / prim_a) + (area_b / prim_b); + + /* edge (1-3), new state */ + area_a = fabsf(area_2x_123); + area_b = fabsf(area_2x_134); + prim_a = len_12 + len_23 + len_13; + prim_b = len_34 + len_41 + len_13; + fac_13 = (area_a / prim_a) + (area_b / prim_b); + + /* negative number if (1-3) is an improved state */ + return fac_24 - fac_13; + } + } while (false); + + return FLT_MAX; } -static float polyedge_rotate_beauty_calc( - const float (*coords)[2], - const struct HalfEdge *edges, - const struct HalfEdge *e_a) +static float polyedge_rotate_beauty_calc(const float (*coords)[2], + const struct HalfEdge *edges, + const struct HalfEdge *e_a) { - const struct HalfEdge *e_b = &edges[e_a->e_radial]; + const struct HalfEdge *e_b = &edges[e_a->e_radial]; - const struct HalfEdge *e_a_other = &edges[edges[e_a->e_next].e_next]; - const struct HalfEdge *e_b_other = &edges[edges[e_b->e_next].e_next]; + const struct HalfEdge *e_a_other = &edges[edges[e_a->e_next].e_next]; + const struct HalfEdge *e_b_other = &edges[edges[e_b->e_next].e_next]; - const float *v1, *v2, *v3, *v4; + const float *v1, *v2, *v3, *v4; - v1 = coords[e_a_other->v]; - v2 = coords[e_a->v]; - v3 = coords[e_b_other->v]; - v4 = coords[e_b->v]; + v1 = coords[e_a_other->v]; + v2 = coords[e_a->v]; + v3 = coords[e_b_other->v]; + v4 = coords[e_b->v]; - return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4); + return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4); } -static void polyedge_beauty_cost_update_single( - const float (*coords)[2], - const struct HalfEdge *edges, - struct HalfEdge *e, - Heap *eheap, HeapNode **eheap_table) +static void polyedge_beauty_cost_update_single(const float (*coords)[2], + const struct HalfEdge *edges, + struct HalfEdge *e, + Heap *eheap, + HeapNode **eheap_table) { - const uint i = e->base_index; - /* recalculate edge */ - const float cost = polyedge_rotate_beauty_calc(coords, edges, e); - /* We can get cases where both choices generate very small negative costs, - * which leads to infinite loop. Anyway, costs above that are not worth recomputing, - * maybe we could even optimize it to a smaller limit? - * Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully? - * See T43578, T49478. */ - if (cost < -1e-6f) { - BLI_heap_insert_or_update(eheap, &eheap_table[i], cost, e); - } - else { - if (eheap_table[i]) { - BLI_heap_remove(eheap, eheap_table[i]); - eheap_table[i] = NULL; - } - } + const uint i = e->base_index; + /* recalculate edge */ + const float cost = polyedge_rotate_beauty_calc(coords, edges, e); + /* We can get cases where both choices generate very small negative costs, + * which leads to infinite loop. Anyway, costs above that are not worth recomputing, + * maybe we could even optimize it to a smaller limit? + * Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully? + * See T43578, T49478. */ + if (cost < -1e-6f) { + BLI_heap_insert_or_update(eheap, &eheap_table[i], cost, e); + } + else { + if (eheap_table[i]) { + BLI_heap_remove(eheap, eheap_table[i]); + eheap_table[i] = NULL; + } + } } -static void polyedge_beauty_cost_update( - const float (*coords)[2], - struct HalfEdge *edges, - struct HalfEdge *e, - Heap *eheap, HeapNode **eheap_table) +static void polyedge_beauty_cost_update(const float (*coords)[2], + struct HalfEdge *edges, + struct HalfEdge *e, + Heap *eheap, + HeapNode **eheap_table) { - struct HalfEdge *e_arr[4]; - e_arr[0] = &edges[e->e_next]; - e_arr[1] = &edges[e_arr[0]->e_next]; - - e = &edges[e->e_radial]; - e_arr[2] = &edges[e->e_next]; - e_arr[3] = &edges[e_arr[2]->e_next]; - - for (uint i = 0; i < 4; i++) { - if (e_arr[i] && e_arr[i]->base_index != UINT_MAX) { - polyedge_beauty_cost_update_single( - coords, edges, - e_arr[i], - eheap, eheap_table); - } - } + struct HalfEdge *e_arr[4]; + e_arr[0] = &edges[e->e_next]; + e_arr[1] = &edges[e_arr[0]->e_next]; + + e = &edges[e->e_radial]; + e_arr[2] = &edges[e->e_next]; + e_arr[3] = &edges[e_arr[2]->e_next]; + + for (uint i = 0; i < 4; i++) { + if (e_arr[i] && e_arr[i]->base_index != UINT_MAX) { + polyedge_beauty_cost_update_single(coords, edges, e_arr[i], eheap, eheap_table); + } + } } -static void polyedge_rotate( - struct HalfEdge *edges, - struct HalfEdge *e) +static void polyedge_rotate(struct HalfEdge *edges, struct HalfEdge *e) { - /** CCW winding, rotate internal edge to new vertical state. - * - * \code{.unparsed} - * Before After - * X X - * / \ /|\ - * e4/ \e5 e4/ | \e5 - * / e3 \ / | \ - * X ------- X -> X e0|e3 X - * \ e0 / \ | / - * e2\ /e1 e2\ | /e1 - * \ / \|/ - * X X - * \endcode - */ - struct HalfEdge *ed[6]; - uint ed_index[6]; - - ed_index[0] = (uint)(e - edges); - ed[0] = &edges[ed_index[0]]; - ed_index[1] = ed[0]->e_next; - ed[1] = &edges[ed_index[1]]; - ed_index[2] = ed[1]->e_next; - ed[2] = &edges[ed_index[2]]; - - ed_index[3] = e->e_radial; - ed[3] = &edges[ed_index[3]]; - ed_index[4] = ed[3]->e_next; - ed[4] = &edges[ed_index[4]]; - ed_index[5] = ed[4]->e_next; - ed[5] = &edges[ed_index[5]]; - - ed[0]->e_next = ed_index[2]; - ed[1]->e_next = ed_index[3]; - ed[2]->e_next = ed_index[4]; - ed[3]->e_next = ed_index[5]; - ed[4]->e_next = ed_index[0]; - ed[5]->e_next = ed_index[1]; - - ed[0]->v = ed[5]->v; - ed[3]->v = ed[2]->v; + /** CCW winding, rotate internal edge to new vertical state. + * + * \code{.unparsed} + * Before After + * X X + * / \ /|\ + * e4/ \e5 e4/ | \e5 + * / e3 \ / | \ + * X ------- X -> X e0|e3 X + * \ e0 / \ | / + * e2\ /e1 e2\ | /e1 + * \ / \|/ + * X X + * \endcode + */ + struct HalfEdge *ed[6]; + uint ed_index[6]; + + ed_index[0] = (uint)(e - edges); + ed[0] = &edges[ed_index[0]]; + ed_index[1] = ed[0]->e_next; + ed[1] = &edges[ed_index[1]]; + ed_index[2] = ed[1]->e_next; + ed[2] = &edges[ed_index[2]]; + + ed_index[3] = e->e_radial; + ed[3] = &edges[ed_index[3]]; + ed_index[4] = ed[3]->e_next; + ed[4] = &edges[ed_index[4]]; + ed_index[5] = ed[4]->e_next; + ed[5] = &edges[ed_index[5]]; + + ed[0]->e_next = ed_index[2]; + ed[1]->e_next = ed_index[3]; + ed[2]->e_next = ed_index[4]; + ed[3]->e_next = ed_index[5]; + ed[4]->e_next = ed_index[0]; + ed[5]->e_next = ed_index[1]; + + ed[0]->v = ed[5]->v; + ed[3]->v = ed[2]->v; } /** @@ -310,126 +304,124 @@ static void polyedge_rotate( * so any edges running along contiguous (wrapped) indices, * are ignored since the edges wont share 2 faces. */ -void BLI_polyfill_beautify( - const float (*coords)[2], - const uint coords_tot, - uint (*tris)[3], +void BLI_polyfill_beautify(const float (*coords)[2], + const uint coords_tot, + uint (*tris)[3], - /* structs for reuse */ - MemArena *arena, Heap *eheap) + /* structs for reuse */ + MemArena *arena, + Heap *eheap) { - const uint coord_last = coords_tot - 1; - const uint tris_len = coords_tot - 2; - /* internal edges only (between 2 tris) */ - const uint edges_len = tris_len - 1; - - HeapNode **eheap_table; - - const uint half_edges_len = 3 * tris_len; - struct HalfEdge *half_edges = BLI_memarena_alloc(arena, sizeof(*half_edges) * half_edges_len); - struct OrderEdge *order_edges = BLI_memarena_alloc(arena, sizeof(struct OrderEdge) * 2 * edges_len); - uint order_edges_len = 0; - - /* first build edges */ - for (uint i = 0; i < tris_len; i++) { - for (uint j_curr = 0, j_prev = 2; j_curr < 3; j_prev = j_curr++) { - const uint e_index_prev = (i * 3) + j_prev; - const uint e_index_curr = (i * 3) + j_curr; - - half_edges[e_index_prev].v = tris[i][j_prev]; - half_edges[e_index_prev].e_next = e_index_curr; - half_edges[e_index_prev].e_radial = UINT_MAX; - half_edges[e_index_prev].base_index = UINT_MAX; - - uint e_pair[2] = {tris[i][j_prev], tris[i][j_curr]}; - if (e_pair[0] > e_pair[1]) { - SWAP(uint, e_pair[0], e_pair[1]); - } - - /* ensure internal edges. */ - if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) { - order_edges[order_edges_len].verts[0] = e_pair[0]; - order_edges[order_edges_len].verts[1] = e_pair[1]; - order_edges[order_edges_len].e_half = e_index_prev; - order_edges_len += 1; - } - } - } - BLI_assert(edges_len * 2 == order_edges_len); - - qsort(order_edges, order_edges_len, sizeof(struct OrderEdge), oedge_cmp); - - for (uint i = 0, base_index = 0; i < order_edges_len; base_index++) { - const struct OrderEdge *oe_a = &order_edges[i++]; - const struct OrderEdge *oe_b = &order_edges[i++]; - BLI_assert(oe_a->verts[0] == oe_a->verts[0] && oe_a->verts[1] == oe_a->verts[1]); - half_edges[oe_a->e_half].e_radial = oe_b->e_half; - half_edges[oe_b->e_half].e_radial = oe_a->e_half; - half_edges[oe_a->e_half].base_index = base_index; - half_edges[oe_b->e_half].base_index = base_index; - } - /* order_edges could be freed now. */ - - /* Now perform iterative rotations. */ + const uint coord_last = coords_tot - 1; + const uint tris_len = coords_tot - 2; + /* internal edges only (between 2 tris) */ + const uint edges_len = tris_len - 1; + + HeapNode **eheap_table; + + const uint half_edges_len = 3 * tris_len; + struct HalfEdge *half_edges = BLI_memarena_alloc(arena, sizeof(*half_edges) * half_edges_len); + struct OrderEdge *order_edges = BLI_memarena_alloc(arena, + sizeof(struct OrderEdge) * 2 * edges_len); + uint order_edges_len = 0; + + /* first build edges */ + for (uint i = 0; i < tris_len; i++) { + for (uint j_curr = 0, j_prev = 2; j_curr < 3; j_prev = j_curr++) { + const uint e_index_prev = (i * 3) + j_prev; + const uint e_index_curr = (i * 3) + j_curr; + + half_edges[e_index_prev].v = tris[i][j_prev]; + half_edges[e_index_prev].e_next = e_index_curr; + half_edges[e_index_prev].e_radial = UINT_MAX; + half_edges[e_index_prev].base_index = UINT_MAX; + + uint e_pair[2] = {tris[i][j_prev], tris[i][j_curr]}; + if (e_pair[0] > e_pair[1]) { + SWAP(uint, e_pair[0], e_pair[1]); + } + + /* ensure internal edges. */ + if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) { + order_edges[order_edges_len].verts[0] = e_pair[0]; + order_edges[order_edges_len].verts[1] = e_pair[1]; + order_edges[order_edges_len].e_half = e_index_prev; + order_edges_len += 1; + } + } + } + BLI_assert(edges_len * 2 == order_edges_len); + + qsort(order_edges, order_edges_len, sizeof(struct OrderEdge), oedge_cmp); + + for (uint i = 0, base_index = 0; i < order_edges_len; base_index++) { + const struct OrderEdge *oe_a = &order_edges[i++]; + const struct OrderEdge *oe_b = &order_edges[i++]; + BLI_assert(oe_a->verts[0] == oe_a->verts[0] && oe_a->verts[1] == oe_a->verts[1]); + half_edges[oe_a->e_half].e_radial = oe_b->e_half; + half_edges[oe_b->e_half].e_radial = oe_a->e_half; + half_edges[oe_a->e_half].base_index = base_index; + half_edges[oe_b->e_half].base_index = base_index; + } + /* order_edges could be freed now. */ + + /* Now perform iterative rotations. */ #if 0 - eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_len); + eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_len); #else - /* We can re-use this since its big enough. */ - eheap_table = (void *)order_edges; - order_edges = NULL; + /* We can re-use this since its big enough. */ + eheap_table = (void *)order_edges; + order_edges = NULL; #endif - /* Build heap. */ - { - struct HalfEdge *e = half_edges; - for (uint i = 0; i < half_edges_len; i++, e++) { - /* Accounts for boundary edged too (UINT_MAX). */ - if (e->e_radial < i) { - const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e); - if (cost < 0.0f) { - eheap_table[e->base_index] = BLI_heap_insert(eheap, cost, e); - } - else { - eheap_table[e->base_index] = NULL; - } - } - } - } - - while (BLI_heap_is_empty(eheap) == false) { - struct HalfEdge *e = BLI_heap_pop_min(eheap); - eheap_table[e->base_index] = NULL; - - polyedge_rotate(half_edges, e); - - /* recalculate faces connected on the heap */ - polyedge_beauty_cost_update( - coords, half_edges, - e, - eheap, eheap_table); - } - - BLI_heap_clear(eheap, NULL); - - /* MEM_freeN(eheap_table); */ /* arena */ - - /* get tris from half edge. */ - uint tri_index = 0; - for (uint i = 0; i < half_edges_len; i++) { - struct HalfEdge *e = &half_edges[i]; - if (e->v != UINT_MAX) { - uint *tri = tris[tri_index++]; - - tri[0] = e->v; - e->v = UINT_MAX; - - e = &half_edges[e->e_next]; - tri[1] = e->v; - e->v = UINT_MAX; - - e = &half_edges[e->e_next]; - tri[2] = e->v; - e->v = UINT_MAX; - } - } + /* Build heap. */ + { + struct HalfEdge *e = half_edges; + for (uint i = 0; i < half_edges_len; i++, e++) { + /* Accounts for boundary edged too (UINT_MAX). */ + if (e->e_radial < i) { + const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e); + if (cost < 0.0f) { + eheap_table[e->base_index] = BLI_heap_insert(eheap, cost, e); + } + else { + eheap_table[e->base_index] = NULL; + } + } + } + } + + while (BLI_heap_is_empty(eheap) == false) { + struct HalfEdge *e = BLI_heap_pop_min(eheap); + eheap_table[e->base_index] = NULL; + + polyedge_rotate(half_edges, e); + + /* recalculate faces connected on the heap */ + polyedge_beauty_cost_update(coords, half_edges, e, eheap, eheap_table); + } + + BLI_heap_clear(eheap, NULL); + + /* MEM_freeN(eheap_table); */ /* arena */ + + /* get tris from half edge. */ + uint tri_index = 0; + for (uint i = 0; i < half_edges_len; i++) { + struct HalfEdge *e = &half_edges[i]; + if (e->v != UINT_MAX) { + uint *tri = tris[tri_index++]; + + tri[0] = e->v; + e->v = UINT_MAX; + + e = &half_edges[e->e_next]; + tri[1] = e->v; + e->v = UINT_MAX; + + e = &half_edges[e->e_next]; + tri[2] = e->v; + e->v = UINT_MAX; + } + } } diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index 8d5998786f4..0a1ff9f8116 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -35,43 +35,42 @@ #include "BLI_math.h" #include "BLI_strict_flags.h" -#include "BLI_quadric.h" /* own include */ - +#include "BLI_quadric.h" /* own include */ #define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(double)) void BLI_quadric_from_plane(Quadric *q, const double v[4]) { - q->a2 = v[0] * v[0]; - q->b2 = v[1] * v[1]; - q->c2 = v[2] * v[2]; + q->a2 = v[0] * v[0]; + q->b2 = v[1] * v[1]; + q->c2 = v[2] * v[2]; - q->ab = v[0] * v[1]; - q->ac = v[0] * v[2]; - q->bc = v[1] * v[2]; + q->ab = v[0] * v[1]; + q->ac = v[0] * v[2]; + q->bc = v[1] * v[2]; - q->ad = v[0] * v[3]; - q->bd = v[1] * v[3]; - q->cd = v[2] * v[3]; + q->ad = v[0] * v[3]; + q->bd = v[1] * v[3]; + q->cd = v[2] * v[3]; - q->d2 = v[3] * v[3]; + q->d2 = v[3] * v[3]; } -#if 0 /* UNUSED */ +#if 0 /* UNUSED */ static void quadric_to_tensor_m3(const Quadric *q, double m[3][3]) { - m[0][0] = q->a2; - m[0][1] = q->ab; - m[0][2] = q->ac; + m[0][0] = q->a2; + m[0][1] = q->ab; + m[0][2] = q->ac; - m[1][0] = q->ab; - m[1][1] = q->b2; - m[1][2] = q->bc; + m[1][0] = q->ab; + m[1][1] = q->b2; + m[1][2] = q->bc; - m[2][0] = q->ac; - m[2][1] = q->bc; - m[2][2] = q->c2; + m[2][0] = q->ac; + m[2][1] = q->bc; + m[2][2] = q->c2; } #endif @@ -87,79 +86,77 @@ static void quadric_to_tensor_m3(const Quadric *q, double m[3][3]) */ static bool quadric_to_tensor_m3_inverse(const Quadric *q, double m[3][3], double epsilon) { - const double det = - (q->a2 * (q->b2 * q->c2 - q->bc * q->bc) - - q->ab * (q->ab * q->c2 - q->ac * q->bc) + - q->ac * (q->ab * q->bc - q->ac * q->b2)); - - if (fabs(det) > epsilon) { - const double invdet = 1.0 / det; - - m[0][0] = (q->b2 * q->c2 - q->bc * q->bc) * invdet; - m[1][0] = (q->bc * q->ac - q->ab * q->c2) * invdet; - m[2][0] = (q->ab * q->bc - q->b2 * q->ac) * invdet; - - m[0][1] = (q->ac * q->bc - q->ab * q->c2) * invdet; - m[1][1] = (q->a2 * q->c2 - q->ac * q->ac) * invdet; - m[2][1] = (q->ab * q->ac - q->a2 * q->bc) * invdet; - - m[0][2] = (q->ab * q->bc - q->ac * q->b2) * invdet; - m[1][2] = (q->ac * q->ab - q->a2 * q->bc) * invdet; - m[2][2] = (q->a2 * q->b2 - q->ab * q->ab) * invdet; - - return true; - } - else { - return false; - } + const double det = (q->a2 * (q->b2 * q->c2 - q->bc * q->bc) - + q->ab * (q->ab * q->c2 - q->ac * q->bc) + + q->ac * (q->ab * q->bc - q->ac * q->b2)); + + if (fabs(det) > epsilon) { + const double invdet = 1.0 / det; + + m[0][0] = (q->b2 * q->c2 - q->bc * q->bc) * invdet; + m[1][0] = (q->bc * q->ac - q->ab * q->c2) * invdet; + m[2][0] = (q->ab * q->bc - q->b2 * q->ac) * invdet; + + m[0][1] = (q->ac * q->bc - q->ab * q->c2) * invdet; + m[1][1] = (q->a2 * q->c2 - q->ac * q->ac) * invdet; + m[2][1] = (q->ab * q->ac - q->a2 * q->bc) * invdet; + + m[0][2] = (q->ab * q->bc - q->ac * q->b2) * invdet; + m[1][2] = (q->ac * q->ab - q->a2 * q->bc) * invdet; + m[2][2] = (q->a2 * q->b2 - q->ab * q->ab) * invdet; + + return true; + } + else { + return false; + } } void BLI_quadric_to_vector_v3(const Quadric *q, double v[3]) { - v[0] = q->ad; - v[1] = q->bd; - v[2] = q->cd; + v[0] = q->ad; + v[1] = q->bd; + v[2] = q->cd; } void BLI_quadric_clear(Quadric *q) { - memset(q, 0, sizeof(*q)); + memset(q, 0, sizeof(*q)); } void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b) { - add_vn_vn_d((double *)a, (double *)b, QUADRIC_FLT_TOT); + add_vn_vn_d((double *)a, (double *)b, QUADRIC_FLT_TOT); } void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b) { - add_vn_vnvn_d((double *)r, (const double *)a, (const double *)b, QUADRIC_FLT_TOT); + add_vn_vnvn_d((double *)r, (const double *)a, (const double *)b, QUADRIC_FLT_TOT); } void BLI_quadric_mul(Quadric *a, const double scalar) { - mul_vn_db((double *)a, QUADRIC_FLT_TOT, scalar); + mul_vn_db((double *)a, QUADRIC_FLT_TOT, scalar); } double BLI_quadric_evaluate(const Quadric *q, const double v[3]) { - return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + (q->ad * 2 * v[0]) + - (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + (q->bd * 2 * v[1]) + - (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) + - (q->d2)); + return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + + (q->ad * 2 * v[0]) + (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + + (q->bd * 2 * v[1]) + (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) + (q->d2)); } bool BLI_quadric_optimize(const Quadric *q, double v[3], const double epsilon) { - double m[3][3]; - - if (quadric_to_tensor_m3_inverse(q, m, epsilon)) { - BLI_quadric_to_vector_v3(q, v); - mul_m3_v3_db(m, v); - negate_v3_db(v); - return true; - } - else { - return false; - } + double m[3][3]; + + if (quadric_to_tensor_m3_inverse(q, m, epsilon)) { + BLI_quadric_to_vector_v3(q, v); + mul_m3_v3_db(m, v); + negate_v3_db(v); + return true; + } + else { + return false; + } } diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 352bfe5dab6..9f47ada47d1 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -21,7 +21,6 @@ * \ingroup bli */ - #include <stdlib.h> #include <string.h> #include <math.h> @@ -39,30 +38,30 @@ #include "BLI_sys_types.h" #include "BLI_strict_flags.h" -#define MULTIPLIER 0x5DEECE66Dll -#define MASK 0x0000FFFFFFFFFFFFll -#define MASK_BYTES 2 +#define MULTIPLIER 0x5DEECE66Dll +#define MASK 0x0000FFFFFFFFFFFFll +#define MASK_BYTES 2 -#define ADDEND 0xB -#define LOWSEED 0x330E +#define ADDEND 0xB +#define LOWSEED 0x330E -extern unsigned char BLI_noise_hash_uchar_512[512]; /* noise.c */ +extern unsigned char BLI_noise_hash_uchar_512[512]; /* noise.c */ #define hash BLI_noise_hash_uchar_512 /** * Random Number Generator. */ struct RNG { - uint64_t X; + uint64_t X; }; RNG *BLI_rng_new(unsigned int seed) { - RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); + RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); - BLI_rng_seed(rng, seed); + BLI_rng_seed(rng, seed); - return rng; + return rng; } /** @@ -70,26 +69,26 @@ RNG *BLI_rng_new(unsigned int seed) */ RNG *BLI_rng_new_srandom(unsigned int seed) { - RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); + RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); - BLI_rng_srandom(rng, seed); + BLI_rng_srandom(rng, seed); - return rng; + return rng; } RNG *BLI_rng_copy(RNG *rng) { - return MEM_dupallocN(rng); + return MEM_dupallocN(rng); } void BLI_rng_free(RNG *rng) { - MEM_freeN(rng); + MEM_freeN(rng); } void BLI_rng_seed(RNG *rng, unsigned int seed) { - rng->X = (((uint64_t) seed) << 16) | LOWSEED; + rng->X = (((uint64_t)seed) << 16) | LOWSEED; } /** @@ -97,67 +96,67 @@ void BLI_rng_seed(RNG *rng, unsigned int seed) */ void BLI_rng_srandom(RNG *rng, unsigned int seed) { - BLI_rng_seed(rng, seed + hash[seed & 255]); - seed = BLI_rng_get_uint(rng); - BLI_rng_seed(rng, seed + hash[seed & 255]); - seed = BLI_rng_get_uint(rng); - BLI_rng_seed(rng, seed + hash[seed & 255]); + BLI_rng_seed(rng, seed + hash[seed & 255]); + seed = BLI_rng_get_uint(rng); + BLI_rng_seed(rng, seed + hash[seed & 255]); + seed = BLI_rng_get_uint(rng); + BLI_rng_seed(rng, seed + hash[seed & 255]); } BLI_INLINE void rng_step(RNG *rng) { - rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK; + rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK; } void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) { - size_t last_len = 0; - size_t trim_len = bytes_len; + size_t last_len = 0; + size_t trim_len = bytes_len; #define RAND_STRIDE (sizeof(rng->X) - MASK_BYTES) - if (trim_len > RAND_STRIDE) { - last_len = trim_len % RAND_STRIDE; - trim_len = trim_len - last_len; - } - else { - trim_len = 0; - last_len = bytes_len; - } - - const char *data_src = (void *)&(rng->X); - size_t i = 0; - while (i != trim_len) { - BLI_assert(i < trim_len); + if (trim_len > RAND_STRIDE) { + last_len = trim_len % RAND_STRIDE; + trim_len = trim_len - last_len; + } + else { + trim_len = 0; + last_len = bytes_len; + } + + const char *data_src = (void *)&(rng->X); + size_t i = 0; + while (i != trim_len) { + BLI_assert(i < trim_len); #ifdef __BIG_ENDIAN__ - for (size_t j = (RAND_STRIDE + MASK_BYTES) - 1; j != MASK_BYTES - 1; j--) + for (size_t j = (RAND_STRIDE + MASK_BYTES) - 1; j != MASK_BYTES - 1; j--) #else - for (size_t j = 0; j != RAND_STRIDE; j++) + for (size_t j = 0; j != RAND_STRIDE; j++) #endif - { - bytes[i++] = data_src[j]; - } - rng_step(rng); - } - if (last_len) { - for (size_t j = 0; j != last_len; j++) { - bytes[i++] = data_src[j]; - } - } + { + bytes[i++] = data_src[j]; + } + rng_step(rng); + } + if (last_len) { + for (size_t j = 0; j != last_len; j++) { + bytes[i++] = data_src[j]; + } + } #undef RAND_STRIDE } int BLI_rng_get_int(RNG *rng) { - rng_step(rng); - return (int) (rng->X >> 17); + rng_step(rng); + return (int)(rng->X >> 17); } unsigned int BLI_rng_get_uint(RNG *rng) { - rng_step(rng); - return (unsigned int) (rng->X >> 17); + rng_step(rng); + return (unsigned int)(rng->X >> 17); } /** @@ -165,7 +164,7 @@ unsigned int BLI_rng_get_uint(RNG *rng) */ double BLI_rng_get_double(RNG *rng) { - return (double) BLI_rng_get_int(rng) / 0x80000000; + return (double)BLI_rng_get_int(rng) / 0x80000000; } /** @@ -173,80 +172,79 @@ double BLI_rng_get_double(RNG *rng) */ float BLI_rng_get_float(RNG *rng) { - return (float) BLI_rng_get_int(rng) / 0x80000000; + return (float)BLI_rng_get_int(rng) / 0x80000000; } void BLI_rng_get_float_unit_v2(RNG *rng, float v[2]) { - float a = (float)(M_PI * 2.0) * BLI_rng_get_float(rng); - v[0] = cosf(a); - v[1] = sinf(a); + float a = (float)(M_PI * 2.0) * BLI_rng_get_float(rng); + v[0] = cosf(a); + v[1] = sinf(a); } void BLI_rng_get_float_unit_v3(RNG *rng, float v[3]) { - float r; - v[2] = (2.0f * BLI_rng_get_float(rng)) - 1.0f; - if ((r = 1.0f - (v[2] * v[2])) > 0.0f) { - float a = (float)(M_PI * 2.0) * BLI_rng_get_float(rng); - r = sqrtf(r); - v[0] = r * cosf(a); - v[1] = r * sinf(a); - } - else { - v[2] = 1.0f; - } + float r; + v[2] = (2.0f * BLI_rng_get_float(rng)) - 1.0f; + if ((r = 1.0f - (v[2] * v[2])) > 0.0f) { + float a = (float)(M_PI * 2.0) * BLI_rng_get_float(rng); + r = sqrtf(r); + v[0] = r * cosf(a); + v[1] = r * sinf(a); + } + else { + v[2] = 1.0f; + } } /** * Generate a random point inside given tri. */ void BLI_rng_get_tri_sample_float_v2( - RNG *rng, const float v1[2], const float v2[2], const float v3[2], - float r_pt[2]) + RNG *rng, const float v1[2], const float v2[2], const float v3[2], float r_pt[2]) { - float u = BLI_rng_get_float(rng); - float v = BLI_rng_get_float(rng); + float u = BLI_rng_get_float(rng); + float v = BLI_rng_get_float(rng); - float side_u[2], side_v[2]; + float side_u[2], side_v[2]; - if ((u + v) > 1.0f) { - u = 1.0f - u; - v = 1.0f - v; - } + if ((u + v) > 1.0f) { + u = 1.0f - u; + v = 1.0f - v; + } - sub_v2_v2v2(side_u, v2, v1); - sub_v2_v2v2(side_v, v3, v1); + sub_v2_v2v2(side_u, v2, v1); + sub_v2_v2v2(side_v, v3, v1); - copy_v2_v2(r_pt, v1); - madd_v2_v2fl(r_pt, side_u, u); - madd_v2_v2fl(r_pt, side_v, v); + copy_v2_v2(r_pt, v1); + madd_v2_v2fl(r_pt, side_u, u); + madd_v2_v2fl(r_pt, side_v, v); } void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot) { - const size_t elem_size = (size_t)elem_size_i; - unsigned int i = elem_tot; - void *temp; + const size_t elem_size = (size_t)elem_size_i; + unsigned int i = elem_tot; + void *temp; - if (elem_tot <= 1) { - return; - } + if (elem_tot <= 1) { + return; + } - temp = malloc(elem_size); + temp = malloc(elem_size); - while (i--) { - unsigned int j = BLI_rng_get_uint(rng) % elem_tot; - if (i != j) { - void *iElem = (unsigned char *)data + i * elem_size_i; - void *jElem = (unsigned char *)data + j * elem_size_i; - memcpy(temp, iElem, elem_size); - memcpy(iElem, jElem, elem_size); - memcpy(jElem, temp, elem_size); - } - } + while (i--) { + unsigned int j = BLI_rng_get_uint(rng) % elem_tot; + if (i != j) { + void *iElem = (unsigned char *)data + i * elem_size_i; + void *jElem = (unsigned char *)data + j * elem_size_i; + memcpy(temp, iElem, elem_size); + memcpy(iElem, jElem, elem_size); + memcpy(jElem, temp, elem_size); + } + } - free(temp); + free(temp); } /** @@ -256,9 +254,9 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig */ void BLI_rng_skip(RNG *rng, int n) { - while (n--) { - rng_step(rng); - } + while (n--) { + rng_step(rng); + } } /***/ @@ -266,29 +264,32 @@ void BLI_rng_skip(RNG *rng, int n) /* fill an array with random numbers */ void BLI_array_frand(float *ar, int count, unsigned int seed) { - RNG rng; + RNG rng; - BLI_rng_srandom(&rng, seed); + BLI_rng_srandom(&rng, seed); - for (int i = 0; i < count; i++) { - ar[i] = BLI_rng_get_float(&rng); - } + for (int i = 0; i < count; i++) { + ar[i] = BLI_rng_get_float(&rng); + } } float BLI_hash_frand(unsigned int seed) { - RNG rng; + RNG rng; - BLI_rng_srandom(&rng, seed); - return BLI_rng_get_float(&rng); + BLI_rng_srandom(&rng, seed); + return BLI_rng_get_float(&rng); } -void BLI_array_randomize(void *data, unsigned int elem_size, unsigned int elem_tot, unsigned int seed) +void BLI_array_randomize(void *data, + unsigned int elem_size, + unsigned int elem_tot, + unsigned int seed) { - RNG rng; + RNG rng; - BLI_rng_seed(&rng, seed); - BLI_rng_shuffle_array(&rng, data, elem_size, elem_tot); + BLI_rng_seed(&rng, seed); + BLI_rng_shuffle_array(&rng, data, elem_size, elem_tot); } /* ********* for threaded random ************** */ @@ -297,51 +298,51 @@ static RNG rng_tab[BLENDER_MAX_THREADS]; void BLI_thread_srandom(int thread, unsigned int seed) { - if (thread >= BLENDER_MAX_THREADS) { - thread = 0; - } + if (thread >= BLENDER_MAX_THREADS) { + thread = 0; + } - BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); - seed = BLI_rng_get_uint(&rng_tab[thread]); - BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); - seed = BLI_rng_get_uint(&rng_tab[thread]); - BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + seed = BLI_rng_get_uint(&rng_tab[thread]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + seed = BLI_rng_get_uint(&rng_tab[thread]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); } int BLI_thread_rand(int thread) { - return BLI_rng_get_int(&rng_tab[thread]); + return BLI_rng_get_int(&rng_tab[thread]); } float BLI_thread_frand(int thread) { - return BLI_rng_get_float(&rng_tab[thread]); + return BLI_rng_get_float(&rng_tab[thread]); } struct RNG_THREAD_ARRAY { - RNG rng_tab[BLENDER_MAX_THREADS]; + RNG rng_tab[BLENDER_MAX_THREADS]; }; RNG_THREAD_ARRAY *BLI_rng_threaded_new(void) { - unsigned int i; - RNG_THREAD_ARRAY *rngarr = MEM_mallocN(sizeof(RNG_THREAD_ARRAY), "random_array"); + unsigned int i; + RNG_THREAD_ARRAY *rngarr = MEM_mallocN(sizeof(RNG_THREAD_ARRAY), "random_array"); - for (i = 0; i < BLENDER_MAX_THREADS; i++) { - BLI_rng_srandom(&rngarr->rng_tab[i], (unsigned int)clock()); - } + for (i = 0; i < BLENDER_MAX_THREADS; i++) { + BLI_rng_srandom(&rngarr->rng_tab[i], (unsigned int)clock()); + } - return rngarr; + return rngarr; } void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr) { - MEM_freeN(rngarr); + MEM_freeN(rngarr); } int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) { - return BLI_rng_get_int(&rngarr->rng_tab[thread]); + return BLI_rng_get_int(&rngarr->rng_tab[thread]); } /* ********* Low-discrepancy sequences ************** */ @@ -350,101 +351,101 @@ int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) * "Instant Radiosity", Keller A. */ BLI_INLINE double halton_ex(double invprimes, double *offset) { - double e = fabs((1.0 - *offset) - 1e-10); + double e = fabs((1.0 - *offset) - 1e-10); - if (invprimes >= e) { - double lasth; - double h = invprimes; + if (invprimes >= e) { + double lasth; + double h = invprimes; - do { - lasth = h; - h *= invprimes; - } while (h >= e); + do { + lasth = h; + h *= invprimes; + } while (h >= e); - *offset += ((lasth + h) - 1.0); - } - else { - *offset += invprimes; - } + *offset += ((lasth + h) - 1.0); + } + else { + *offset += invprimes; + } - return *offset; + return *offset; } void BLI_halton_1d(unsigned int prime, double offset, int n, double *r) { - const double invprime = 1.0 / (double)prime; + const double invprime = 1.0 / (double)prime; - *r = 0.0; + *r = 0.0; - for (int s = 0; s < n; s++) { - *r = halton_ex(invprime, &offset); - } + for (int s = 0; s < n; s++) { + *r = halton_ex(invprime, &offset); + } } void BLI_halton_2d(unsigned int prime[2], double offset[2], int n, double *r) { - const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; - r[0] = r[1] = 0.0; + r[0] = r[1] = 0.0; - for (int s = 0; s < n; s++) { - for (int i = 0; i < 2; i++) { - r[i] = halton_ex(invprimes[i], &offset[i]); - } - } + for (int s = 0; s < n; s++) { + for (int i = 0; i < 2; i++) { + r[i] = halton_ex(invprimes[i], &offset[i]); + } + } } void BLI_halton_3d(unsigned int prime[3], double offset[3], int n, double *r) { - const double invprimes[3] = {1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]}; + const double invprimes[3] = { + 1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]}; - r[0] = r[1] = r[2] = 0.0; + r[0] = r[1] = r[2] = 0.0; - for (int s = 0; s < n; s++) { - for (int i = 0; i < 3; i++) { - r[i] = halton_ex(invprimes[i], &offset[i]); - } - } + for (int s = 0; s < n; s++) { + for (int i = 0; i < 3; i++) { + r[i] = halton_ex(invprimes[i], &offset[i]); + } + } } void BLI_halton_2d_sequence(unsigned int prime[2], double offset[2], int n, double *r) { - const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; - for (int s = 0; s < n; s++) { - for (int i = 0; i < 2; i++) { - r[s * 2 + i] = halton_ex(invprimes[i], &offset[i]); - } - } + for (int s = 0; s < n; s++) { + for (int i = 0; i < 2; i++) { + r[s * 2 + i] = halton_ex(invprimes[i], &offset[i]); + } + } } - /* From "Sampling with Hammersley and Halton Points" TT Wong * Appendix: Source Code 1 */ BLI_INLINE double radical_inverse(unsigned int n) { - double u = 0; + double u = 0; - /* This reverse the bitwise representation - * around the decimal point. */ - for (double p = 0.5; n; p *= 0.5, n >>= 1) { - if (n & 1) { - u += p; - } - } + /* This reverse the bitwise representation + * around the decimal point. */ + for (double p = 0.5; n; p *= 0.5, n >>= 1) { + if (n & 1) { + u += p; + } + } - return u; + return u; } void BLI_hammersley_1d(unsigned int n, double *r) { - *r = radical_inverse(n); + *r = radical_inverse(n); } void BLI_hammersley_2d_sequence(unsigned int n, double *r) { - for (unsigned int s = 0; s < n; s++) { - r[s * 2 + 0] = (double)(s + 0.5) / (double)n; - r[s * 2 + 1] = radical_inverse(s); - } + for (unsigned int s = 0; s < n; s++) { + r[s * 2 + 0] = (double)(s + 0.5) / (double)n; + r[s * 2 + 1] = radical_inverse(s); + } } diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 9437380a09d..2723e1708cb 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -47,76 +47,124 @@ static void unit_m4(float m[4][4]); */ bool BLI_rcti_is_empty(const rcti *rect) { - return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); + return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); } bool BLI_rctf_is_empty(const rctf *rect) { - return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); + return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); } bool BLI_rcti_isect_x(const rcti *rect, const int x) { - if (x < rect->xmin) { return false; } - if (x > rect->xmax) { return false; } - return true; + if (x < rect->xmin) { + return false; + } + if (x > rect->xmax) { + return false; + } + return true; } bool BLI_rcti_isect_y(const rcti *rect, const int y) { - if (y < rect->ymin) { return false; } - if (y > rect->ymax) { return false; } - return true; + if (y < rect->ymin) { + return false; + } + if (y > rect->ymax) { + return false; + } + return true; } bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y) { - if (x < rect->xmin) { return false; } - if (x > rect->xmax) { return false; } - if (y < rect->ymin) { return false; } - if (y > rect->ymax) { return false; } - return true; + if (x < rect->xmin) { + return false; + } + if (x > rect->xmax) { + return false; + } + if (y < rect->ymin) { + return false; + } + if (y > rect->ymax) { + return false; + } + return true; } bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2]) { - if (xy[0] < rect->xmin) { return false; } - if (xy[0] > rect->xmax) { return false; } - if (xy[1] < rect->ymin) { return false; } - if (xy[1] > rect->ymax) { return false; } - return true; + if (xy[0] < rect->xmin) { + return false; + } + if (xy[0] > rect->xmax) { + return false; + } + if (xy[1] < rect->ymin) { + return false; + } + if (xy[1] > rect->ymax) { + return false; + } + return true; } bool BLI_rctf_isect_x(const rctf *rect, const float x) { - if (x < rect->xmin) { return false; } - if (x > rect->xmax) { return false; } - return true; + if (x < rect->xmin) { + return false; + } + if (x > rect->xmax) { + return false; + } + return true; } bool BLI_rctf_isect_y(const rctf *rect, const float y) { - if (y < rect->ymin) { return false; } - if (y > rect->ymax) { return false; } - return true; + if (y < rect->ymin) { + return false; + } + if (y > rect->ymax) { + return false; + } + return true; } bool BLI_rctf_isect_pt(const rctf *rect, const float x, const float y) { - if (x < rect->xmin) { return false; } - if (x > rect->xmax) { return false; } - if (y < rect->ymin) { return false; } - if (y > rect->ymax) { return false; } - return true; + if (x < rect->xmin) { + return false; + } + if (x > rect->xmax) { + return false; + } + if (y < rect->ymin) { + return false; + } + if (y > rect->ymax) { + return false; + } + return true; } bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2]) { - if (xy[0] < rect->xmin) { return false; } - if (xy[0] > rect->xmax) { return false; } - if (xy[1] < rect->ymin) { return false; } - if (xy[1] > rect->ymax) { return false; } - return true; + if (xy[0] < rect->xmin) { + return false; + } + if (xy[0] > rect->xmax) { + return false; + } + if (xy[1] < rect->ymin) { + return false; + } + if (xy[1] > rect->ymax) { + return false; + } + return true; } /** @@ -125,30 +173,46 @@ bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2]) int BLI_rcti_length_x(const rcti *rect, const int x) { - if (x < rect->xmin) { return rect->xmin - x; } - if (x > rect->xmax) { return x - rect->xmax; } - return 0; + if (x < rect->xmin) { + return rect->xmin - x; + } + if (x > rect->xmax) { + return x - rect->xmax; + } + return 0; } int BLI_rcti_length_y(const rcti *rect, const int y) { - if (y < rect->ymin) { return rect->ymin - y; } - if (y > rect->ymax) { return y - rect->ymax; } - return 0; + if (y < rect->ymin) { + return rect->ymin - y; + } + if (y > rect->ymax) { + return y - rect->ymax; + } + return 0; } float BLI_rctf_length_x(const rctf *rect, const float x) { - if (x < rect->xmin) { return rect->xmin - x; } - if (x > rect->xmax) { return x - rect->xmax; } - return 0.0f; + if (x < rect->xmin) { + return rect->xmin - x; + } + if (x > rect->xmax) { + return x - rect->xmax; + } + return 0.0f; } float BLI_rctf_length_y(const rctf *rect, const float y) { - if (y < rect->ymin) { return rect->ymin - y; } - if (y > rect->ymax) { return y - rect->ymax; } - return 0.0f; + if (y < rect->ymin) { + return rect->ymin - y; + } + if (y > rect->ymax) { + return y - rect->ymax; + } + return 0.0f; } /** @@ -156,267 +220,334 @@ float BLI_rctf_length_y(const rctf *rect, const float y) */ bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b) { - return ((rct_a->xmin <= rct_b->xmin) && - (rct_a->xmax >= rct_b->xmax) && - (rct_a->ymin <= rct_b->ymin) && - (rct_a->ymax >= rct_b->ymax)); + return ((rct_a->xmin <= rct_b->xmin) && (rct_a->xmax >= rct_b->xmax) && + (rct_a->ymin <= rct_b->ymin) && (rct_a->ymax >= rct_b->ymax)); } bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b) { - return ((rct_a->xmin <= rct_b->xmin) && - (rct_a->xmax >= rct_b->xmax) && - (rct_a->ymin <= rct_b->ymin) && - (rct_a->ymax >= rct_b->ymax)); + return ((rct_a->xmin <= rct_b->xmin) && (rct_a->xmax >= rct_b->xmax) && + (rct_a->ymin <= rct_b->ymin) && (rct_a->ymax >= rct_b->ymax)); } - /* based closely on 'isect_seg_seg_v2_int', * but in modified so corner cases are treated as intersections */ static int isect_segments_i(const int v1[2], const int v2[2], const int v3[2], const int v4[2]) { - const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); - if (div == 0.0) { - return 1; /* co-linear */ - } - else { - const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0); - } -} -static int isect_segments_fl(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) -{ - const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); - if (div == 0.0) { - return 1; /* co-linear */ - } - else { - const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0); - } + const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - + (v2[1] - v1[1]) * (v4[0] - v3[0])); + if (div == 0.0) { + return 1; /* co-linear */ + } + else { + const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - + (v1[0] - v3[0]) * (v4[1] - v3[1])) / + div; + const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - + (v1[0] - v3[0]) * (v2[1] - v1[1])) / + div; + return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0); + } +} +static int isect_segments_fl(const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2]) +{ + const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - + (v2[1] - v1[1]) * (v4[0] - v3[0])); + if (div == 0.0) { + return 1; /* co-linear */ + } + else { + const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - + (v1[0] - v3[0]) * (v4[1] - v3[1])) / + div; + const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - + (v1[0] - v3[0]) * (v2[1] - v1[1])) / + div; + return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0); + } } bool BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) { - /* first do outside-bounds check for both points of the segment */ - if (s1[0] < rect->xmin && s2[0] < rect->xmin) { return false; } - if (s1[0] > rect->xmax && s2[0] > rect->xmax) { return false; } - if (s1[1] < rect->ymin && s2[1] < rect->ymin) { return false; } - if (s1[1] > rect->ymax && s2[1] > rect->ymax) { return false; } - - /* if either points intersect then we definetly intersect */ - if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) { - return true; - } - else { - /* both points are outside but may insersect the rect */ - int tvec1[2]; - int tvec2[2]; - /* diagonal: [/] */ - tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; - tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; - if (isect_segments_i(s1, s2, tvec1, tvec2)) { - return true; - } - - /* diagonal: [\] */ - tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; - tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; - if (isect_segments_i(s1, s2, tvec1, tvec2)) { - return true; - } - - /* no intersection */ - return false; - } + /* first do outside-bounds check for both points of the segment */ + if (s1[0] < rect->xmin && s2[0] < rect->xmin) { + return false; + } + if (s1[0] > rect->xmax && s2[0] > rect->xmax) { + return false; + } + if (s1[1] < rect->ymin && s2[1] < rect->ymin) { + return false; + } + if (s1[1] > rect->ymax && s2[1] > rect->ymax) { + return false; + } + + /* if either points intersect then we definetly intersect */ + if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) { + return true; + } + else { + /* both points are outside but may insersect the rect */ + int tvec1[2]; + int tvec2[2]; + /* diagonal: [/] */ + tvec1[0] = rect->xmin; + tvec1[1] = rect->ymin; + tvec2[0] = rect->xmin; + tvec2[1] = rect->ymax; + if (isect_segments_i(s1, s2, tvec1, tvec2)) { + return true; + } + + /* diagonal: [\] */ + tvec1[0] = rect->xmin; + tvec1[1] = rect->ymax; + tvec2[0] = rect->xmax; + tvec2[1] = rect->ymin; + if (isect_segments_i(s1, s2, tvec1, tvec2)) { + return true; + } + + /* no intersection */ + return false; + } } bool BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2]) { - /* first do outside-bounds check for both points of the segment */ - if (s1[0] < rect->xmin && s2[0] < rect->xmin) { return false; } - if (s1[0] > rect->xmax && s2[0] > rect->xmax) { return false; } - if (s1[1] < rect->ymin && s2[1] < rect->ymin) { return false; } - if (s1[1] > rect->ymax && s2[1] > rect->ymax) { return false; } - - /* if either points intersect then we definetly intersect */ - if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) { - return true; - } - else { - /* both points are outside but may insersect the rect */ - float tvec1[2]; - float tvec2[2]; - /* diagonal: [/] */ - tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; - tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; - if (isect_segments_fl(s1, s2, tvec1, tvec2)) { - return true; - } - - /* diagonal: [\] */ - tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; - tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; - if (isect_segments_fl(s1, s2, tvec1, tvec2)) { - return true; - } - - /* no intersection */ - return false; - } + /* first do outside-bounds check for both points of the segment */ + if (s1[0] < rect->xmin && s2[0] < rect->xmin) { + return false; + } + if (s1[0] > rect->xmax && s2[0] > rect->xmax) { + return false; + } + if (s1[1] < rect->ymin && s2[1] < rect->ymin) { + return false; + } + if (s1[1] > rect->ymax && s2[1] > rect->ymax) { + return false; + } + + /* if either points intersect then we definetly intersect */ + if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) { + return true; + } + else { + /* both points are outside but may insersect the rect */ + float tvec1[2]; + float tvec2[2]; + /* diagonal: [/] */ + tvec1[0] = rect->xmin; + tvec1[1] = rect->ymin; + tvec2[0] = rect->xmin; + tvec2[1] = rect->ymax; + if (isect_segments_fl(s1, s2, tvec1, tvec2)) { + return true; + } + + /* diagonal: [\] */ + tvec1[0] = rect->xmin; + tvec1[1] = rect->ymax; + tvec2[0] = rect->xmax; + tvec2[1] = rect->ymin; + if (isect_segments_fl(s1, s2, tvec1, tvec2)) { + return true; + } + + /* no intersection */ + return false; + } } bool BLI_rcti_isect_circle(const rcti *rect, const float xy[2], const float radius) { - float dx, dy; + float dx, dy; - if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) { - dx = 0; - } - else { - dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax); - } + if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) { + dx = 0; + } + else { + dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax); + } - if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) { - dy = 0; - } - else { - dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax); - } + if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) { + dy = 0; + } + else { + dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax); + } - return dx * dx + dy * dy <= radius * radius; + return dx * dx + dy * dy <= radius * radius; } bool BLI_rctf_isect_circle(const rctf *rect, const float xy[2], const float radius) { - float dx, dy; + float dx, dy; - if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) { - dx = 0; - } - else { - dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax); - } + if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) { + dx = 0; + } + else { + dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax); + } - if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) { - dy = 0; - } - else { - dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax); - } + if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) { + dy = 0; + } + else { + dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax); + } - return dx * dx + dy * dy <= radius * radius; + return dx * dx + dy * dy <= radius * radius; } void BLI_rctf_union(rctf *rct1, const rctf *rct2) { - if (rct1->xmin > rct2->xmin) { rct1->xmin = rct2->xmin; } - if (rct1->xmax < rct2->xmax) { rct1->xmax = rct2->xmax; } - if (rct1->ymin > rct2->ymin) { rct1->ymin = rct2->ymin; } - if (rct1->ymax < rct2->ymax) { rct1->ymax = rct2->ymax; } + if (rct1->xmin > rct2->xmin) { + rct1->xmin = rct2->xmin; + } + if (rct1->xmax < rct2->xmax) { + rct1->xmax = rct2->xmax; + } + if (rct1->ymin > rct2->ymin) { + rct1->ymin = rct2->ymin; + } + if (rct1->ymax < rct2->ymax) { + rct1->ymax = rct2->ymax; + } } void BLI_rcti_union(rcti *rct1, const rcti *rct2) { - if (rct1->xmin > rct2->xmin) { rct1->xmin = rct2->xmin; } - if (rct1->xmax < rct2->xmax) { rct1->xmax = rct2->xmax; } - if (rct1->ymin > rct2->ymin) { rct1->ymin = rct2->ymin; } - if (rct1->ymax < rct2->ymax) { rct1->ymax = rct2->ymax; } + if (rct1->xmin > rct2->xmin) { + rct1->xmin = rct2->xmin; + } + if (rct1->xmax < rct2->xmax) { + rct1->xmax = rct2->xmax; + } + if (rct1->ymin > rct2->ymin) { + rct1->ymin = rct2->ymin; + } + if (rct1->ymax < rct2->ymax) { + rct1->ymax = rct2->ymax; + } } void BLI_rctf_init(rctf *rect, float xmin, float xmax, float ymin, float ymax) { - if (xmin <= xmax) { - rect->xmin = xmin; - rect->xmax = xmax; - } - else { - rect->xmax = xmin; - rect->xmin = xmax; - } - if (ymin <= ymax) { - rect->ymin = ymin; - rect->ymax = ymax; - } - else { - rect->ymax = ymin; - rect->ymin = ymax; - } + if (xmin <= xmax) { + rect->xmin = xmin; + rect->xmax = xmax; + } + else { + rect->xmax = xmin; + rect->xmin = xmax; + } + if (ymin <= ymax) { + rect->ymin = ymin; + rect->ymax = ymax; + } + else { + rect->ymax = ymin; + rect->ymin = ymax; + } } void BLI_rcti_init(rcti *rect, int xmin, int xmax, int ymin, int ymax) { - if (xmin <= xmax) { - rect->xmin = xmin; - rect->xmax = xmax; - } - else { - rect->xmax = xmin; - rect->xmin = xmax; - } - if (ymin <= ymax) { - rect->ymin = ymin; - rect->ymax = ymax; - } - else { - rect->ymax = ymin; - rect->ymin = ymax; - } + if (xmin <= xmax) { + rect->xmin = xmin; + rect->xmax = xmax; + } + else { + rect->xmax = xmin; + rect->xmin = xmax; + } + if (ymin <= ymax) { + rect->ymin = ymin; + rect->ymax = ymax; + } + else { + rect->ymax = ymin; + rect->ymin = ymax; + } } void BLI_rctf_init_pt_radius(rctf *rect, const float xy[2], float size) { - rect->xmin = xy[0] - size; - rect->xmax = xy[0] + size; - rect->ymin = xy[1] - size; - rect->ymax = xy[1] + size; + rect->xmin = xy[0] - size; + rect->xmax = xy[0] + size; + rect->ymin = xy[1] - size; + rect->ymax = xy[1] + size; } void BLI_rcti_init_pt_radius(rcti *rect, const int xy[2], int size) { - rect->xmin = xy[0] - size; - rect->xmax = xy[0] + size; - rect->ymin = xy[1] - size; - rect->ymax = xy[1] + size; + rect->xmin = xy[0] - size; + rect->xmax = xy[0] + size; + rect->ymin = xy[1] - size; + rect->ymax = xy[1] + size; } void BLI_rcti_init_minmax(rcti *rect) { - rect->xmin = rect->ymin = INT_MAX; - rect->xmax = rect->ymax = INT_MIN; + rect->xmin = rect->ymin = INT_MAX; + rect->xmax = rect->ymax = INT_MIN; } void BLI_rctf_init_minmax(rctf *rect) { - rect->xmin = rect->ymin = FLT_MAX; - rect->xmax = rect->ymax = -FLT_MAX; + rect->xmin = rect->ymin = FLT_MAX; + rect->xmax = rect->ymax = -FLT_MAX; } void BLI_rcti_do_minmax_v(rcti *rect, const int xy[2]) { - if (xy[0] < rect->xmin) { rect->xmin = xy[0]; } - if (xy[0] > rect->xmax) { rect->xmax = xy[0]; } - if (xy[1] < rect->ymin) { rect->ymin = xy[1]; } - if (xy[1] > rect->ymax) { rect->ymax = xy[1]; } + if (xy[0] < rect->xmin) { + rect->xmin = xy[0]; + } + if (xy[0] > rect->xmax) { + rect->xmax = xy[0]; + } + if (xy[1] < rect->ymin) { + rect->ymin = xy[1]; + } + if (xy[1] > rect->ymax) { + rect->ymax = xy[1]; + } } void BLI_rctf_do_minmax_v(rctf *rect, const float xy[2]) { - if (xy[0] < rect->xmin) { rect->xmin = xy[0]; } - if (xy[0] > rect->xmax) { rect->xmax = xy[0]; } - if (xy[1] < rect->ymin) { rect->ymin = xy[1]; } - if (xy[1] > rect->ymax) { rect->ymax = xy[1]; } + if (xy[0] < rect->xmin) { + rect->xmin = xy[0]; + } + if (xy[0] > rect->xmax) { + rect->xmax = xy[0]; + } + if (xy[1] < rect->ymin) { + rect->ymin = xy[1]; + } + if (xy[1] > rect->ymax) { + rect->ymax = xy[1]; + } } /* given 2 rectangles - transform a point from one to another */ -void BLI_rctf_transform_pt_v(const rctf *dst, const rctf *src, float xy_dst[2], const float xy_src[2]) +void BLI_rctf_transform_pt_v(const rctf *dst, + const rctf *src, + float xy_dst[2], + const float xy_src[2]) { - xy_dst[0] = ((xy_src[0] - src->xmin) / (src->xmax - src->xmin)); - xy_dst[0] = dst->xmin + ((dst->xmax - dst->xmin) * xy_dst[0]); + xy_dst[0] = ((xy_src[0] - src->xmin) / (src->xmax - src->xmin)); + xy_dst[0] = dst->xmin + ((dst->xmax - dst->xmin) * xy_dst[0]); - xy_dst[1] = ((xy_src[1] - src->ymin) / (src->ymax - src->ymin)); - xy_dst[1] = dst->ymin + ((dst->ymax - dst->ymin) * xy_dst[1]); + xy_dst[1] = ((xy_src[1] - src->ymin) / (src->ymax - src->ymin)); + xy_dst[1] = dst->ymin + ((dst->ymax - dst->ymin) * xy_dst[1]); } /** @@ -425,124 +556,145 @@ void BLI_rctf_transform_pt_v(const rctf *dst, const rctf *src, float xy_dst[2], * \note Multiplying a vector by this matrix does *not* give the same value as #BLI_rctf_transform_pt_v. */ void BLI_rctf_transform_calc_m4_pivot_min_ex( - const rctf *dst, const rctf *src, float matrix[4][4], - uint x, uint y) + const rctf *dst, const rctf *src, float matrix[4][4], uint x, uint y) { - BLI_assert(x < 3 && y < 3); + BLI_assert(x < 3 && y < 3); - unit_m4(matrix); + unit_m4(matrix); - matrix[x][x] = BLI_rctf_size_x(src) / BLI_rctf_size_x(dst); - matrix[y][y] = BLI_rctf_size_y(src) / BLI_rctf_size_y(dst); - matrix[3][x] = (src->xmin - dst->xmin) * matrix[x][x]; - matrix[3][y] = (src->ymin - dst->ymin) * matrix[y][y]; + matrix[x][x] = BLI_rctf_size_x(src) / BLI_rctf_size_x(dst); + matrix[y][y] = BLI_rctf_size_y(src) / BLI_rctf_size_y(dst); + matrix[3][x] = (src->xmin - dst->xmin) * matrix[x][x]; + matrix[3][y] = (src->ymin - dst->ymin) * matrix[y][y]; } -void BLI_rctf_transform_calc_m4_pivot_min( - const rctf *dst, const rctf *src, float matrix[4][4]) +void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4]) { - BLI_rctf_transform_calc_m4_pivot_min_ex(dst, src, matrix, 0, 1); + BLI_rctf_transform_calc_m4_pivot_min_ex(dst, src, matrix, 0, 1); } void BLI_rcti_translate(rcti *rect, int x, int y) { - rect->xmin += x; - rect->ymin += y; - rect->xmax += x; - rect->ymax += y; + rect->xmin += x; + rect->ymin += y; + rect->xmax += x; + rect->ymax += y; } void BLI_rctf_translate(rctf *rect, float x, float y) { - rect->xmin += x; - rect->ymin += y; - rect->xmax += x; - rect->ymax += y; + rect->xmin += x; + rect->ymin += y; + rect->xmax += x; + rect->ymax += y; } void BLI_rcti_recenter(rcti *rect, int x, int y) { - const int dx = x - BLI_rcti_cent_x(rect); - const int dy = y - BLI_rcti_cent_y(rect); - BLI_rcti_translate(rect, dx, dy); + const int dx = x - BLI_rcti_cent_x(rect); + const int dy = y - BLI_rcti_cent_y(rect); + BLI_rcti_translate(rect, dx, dy); } void BLI_rctf_recenter(rctf *rect, float x, float y) { - const float dx = x - BLI_rctf_cent_x(rect); - const float dy = y - BLI_rctf_cent_y(rect); - BLI_rctf_translate(rect, dx, dy); + const float dx = x - BLI_rctf_cent_x(rect); + const float dy = y - BLI_rctf_cent_y(rect); + BLI_rctf_translate(rect, dx, dy); } /* change width & height around the central location */ void BLI_rcti_resize(rcti *rect, int x, int y) { - rect->xmin = BLI_rcti_cent_x(rect) - (x / 2); - rect->ymin = BLI_rcti_cent_y(rect) - (y / 2); - rect->xmax = rect->xmin + x; - rect->ymax = rect->ymin + y; + rect->xmin = BLI_rcti_cent_x(rect) - (x / 2); + rect->ymin = BLI_rcti_cent_y(rect) - (y / 2); + rect->xmax = rect->xmin + x; + rect->ymax = rect->ymin + y; } void BLI_rctf_resize(rctf *rect, float x, float y) { - rect->xmin = BLI_rctf_cent_x(rect) - (x * 0.5f); - rect->ymin = BLI_rctf_cent_y(rect) - (y * 0.5f); - rect->xmax = rect->xmin + x; - rect->ymax = rect->ymin + y; + rect->xmin = BLI_rctf_cent_x(rect) - (x * 0.5f); + rect->ymin = BLI_rctf_cent_y(rect) - (y * 0.5f); + rect->xmax = rect->xmin + x; + rect->ymax = rect->ymin + y; } void BLI_rcti_scale(rcti *rect, const float scale) { - const int cent_x = BLI_rcti_cent_x(rect); - const int cent_y = BLI_rcti_cent_y(rect); - const int size_x_half = BLI_rcti_size_x(rect) * (scale * 0.5f); - const int size_y_half = BLI_rcti_size_y(rect) * (scale * 0.5f); - rect->xmin = cent_x - size_x_half; - rect->ymin = cent_y - size_y_half; - rect->xmax = cent_x + size_x_half; - rect->ymax = cent_y + size_y_half; + const int cent_x = BLI_rcti_cent_x(rect); + const int cent_y = BLI_rcti_cent_y(rect); + const int size_x_half = BLI_rcti_size_x(rect) * (scale * 0.5f); + const int size_y_half = BLI_rcti_size_y(rect) * (scale * 0.5f); + rect->xmin = cent_x - size_x_half; + rect->ymin = cent_y - size_y_half; + rect->xmax = cent_x + size_x_half; + rect->ymax = cent_y + size_y_half; } void BLI_rctf_scale(rctf *rect, const float scale) { - const float cent_x = BLI_rctf_cent_x(rect); - const float cent_y = BLI_rctf_cent_y(rect); - const float size_x_half = BLI_rctf_size_x(rect) * (scale * 0.5f); - const float size_y_half = BLI_rctf_size_y(rect) * (scale * 0.5f); - rect->xmin = cent_x - size_x_half; - rect->ymin = cent_y - size_y_half; - rect->xmax = cent_x + size_x_half; - rect->ymax = cent_y + size_y_half; + const float cent_x = BLI_rctf_cent_x(rect); + const float cent_y = BLI_rctf_cent_y(rect); + const float size_x_half = BLI_rctf_size_x(rect) * (scale * 0.5f); + const float size_y_half = BLI_rctf_size_y(rect) * (scale * 0.5f); + rect->xmin = cent_x - size_x_half; + rect->ymin = cent_y - size_y_half; + rect->xmax = cent_x + size_x_half; + rect->ymax = cent_y + size_y_half; } void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const float fac) { - const float ifac = 1.0f - fac; - rect->xmin = (rect_a->xmin * ifac) + (rect_b->xmin * fac); - rect->xmax = (rect_a->xmax * ifac) + (rect_b->xmax * fac); - rect->ymin = (rect_a->ymin * ifac) + (rect_b->ymin * fac); - rect->ymax = (rect_a->ymax * ifac) + (rect_b->ymax * fac); + const float ifac = 1.0f - fac; + rect->xmin = (rect_a->xmin * ifac) + (rect_b->xmin * fac); + rect->xmax = (rect_a->xmax * ifac) + (rect_b->xmax * fac); + rect->ymin = (rect_a->ymin * ifac) + (rect_b->ymin * fac); + rect->ymax = (rect_a->ymax * ifac) + (rect_b->ymax * fac); } /* BLI_rcti_interp() not needed yet */ - bool BLI_rctf_clamp_pt_v(const rctf *rect, float xy[2]) { - bool changed = false; - if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; } - if (xy[0] > rect->xmax) { xy[0] = rect->xmax; changed = true; } - if (xy[1] < rect->ymin) { xy[1] = rect->ymin; changed = true; } - if (xy[1] > rect->ymax) { xy[1] = rect->ymax; changed = true; } - return changed; + bool changed = false; + if (xy[0] < rect->xmin) { + xy[0] = rect->xmin; + changed = true; + } + if (xy[0] > rect->xmax) { + xy[0] = rect->xmax; + changed = true; + } + if (xy[1] < rect->ymin) { + xy[1] = rect->ymin; + changed = true; + } + if (xy[1] > rect->ymax) { + xy[1] = rect->ymax; + changed = true; + } + return changed; } bool BLI_rcti_clamp_pt_v(const rcti *rect, int xy[2]) { - bool changed = false; - if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; } - if (xy[0] > rect->xmax) { xy[0] = rect->xmax; changed = true; } - if (xy[1] < rect->ymin) { xy[1] = rect->ymin; changed = true; } - if (xy[1] > rect->ymax) { xy[1] = rect->ymax; changed = true; } - return changed; + bool changed = false; + if (xy[0] < rect->xmin) { + xy[0] = rect->xmin; + changed = true; + } + if (xy[0] > rect->xmax) { + xy[0] = rect->xmax; + changed = true; + } + if (xy[1] < rect->ymin) { + xy[1] = rect->ymin; + changed = true; + } + if (xy[1] > rect->ymax) { + xy[1] = rect->ymax; + changed = true; + } + return changed; } /** @@ -552,259 +704,272 @@ bool BLI_rcti_clamp_pt_v(const rcti *rect, int xy[2]) */ bool BLI_rctf_clamp(rctf *rect, const rctf *rect_bounds, float r_xy[2]) { - bool changed = false; - - r_xy[0] = 0.0f; - r_xy[1] = 0.0f; - - if (rect->xmin < rect_bounds->xmin) { - float ofs = rect_bounds->xmin - rect->xmin; - rect->xmin += ofs; - rect->xmax += ofs; - r_xy[0] += ofs; - changed = true; - } - - if (rect->xmax > rect_bounds->xmax) { - float ofs = rect_bounds->xmax - rect->xmax; - rect->xmin += ofs; - rect->xmax += ofs; - r_xy[0] += ofs; - changed = true; - } - - if (rect->ymin < rect_bounds->ymin) { - float ofs = rect_bounds->ymin - rect->ymin; - rect->ymin += ofs; - rect->ymax += ofs; - r_xy[1] += ofs; - changed = true; - } - - if (rect->ymax > rect_bounds->ymax) { - float ofs = rect_bounds->ymax - rect->ymax; - rect->ymin += ofs; - rect->ymax += ofs; - r_xy[1] += ofs; - changed = true; - } - - return changed; + bool changed = false; + + r_xy[0] = 0.0f; + r_xy[1] = 0.0f; + + if (rect->xmin < rect_bounds->xmin) { + float ofs = rect_bounds->xmin - rect->xmin; + rect->xmin += ofs; + rect->xmax += ofs; + r_xy[0] += ofs; + changed = true; + } + + if (rect->xmax > rect_bounds->xmax) { + float ofs = rect_bounds->xmax - rect->xmax; + rect->xmin += ofs; + rect->xmax += ofs; + r_xy[0] += ofs; + changed = true; + } + + if (rect->ymin < rect_bounds->ymin) { + float ofs = rect_bounds->ymin - rect->ymin; + rect->ymin += ofs; + rect->ymax += ofs; + r_xy[1] += ofs; + changed = true; + } + + if (rect->ymax > rect_bounds->ymax) { + float ofs = rect_bounds->ymax - rect->ymax; + rect->ymin += ofs; + rect->ymax += ofs; + r_xy[1] += ofs; + changed = true; + } + + return changed; } bool BLI_rcti_clamp(rcti *rect, const rcti *rect_bounds, int r_xy[2]) { - bool changed = false; - - r_xy[0] = 0; - r_xy[1] = 0; - - if (rect->xmin < rect_bounds->xmin) { - int ofs = rect_bounds->xmin - rect->xmin; - rect->xmin += ofs; - rect->xmax += ofs; - r_xy[0] += ofs; - changed = true; - } - - if (rect->xmax > rect_bounds->xmax) { - int ofs = rect_bounds->xmax - rect->xmax; - rect->xmin += ofs; - rect->xmax += ofs; - r_xy[0] += ofs; - changed = true; - } - - if (rect->ymin < rect_bounds->ymin) { - int ofs = rect_bounds->ymin - rect->ymin; - rect->ymin += ofs; - rect->ymax += ofs; - r_xy[1] += ofs; - changed = true; - } - - if (rect->ymax > rect_bounds->ymax) { - int ofs = rect_bounds->ymax - rect->ymax; - rect->ymin += ofs; - rect->ymax += ofs; - r_xy[1] += ofs; - changed = true; - } - - return changed; + bool changed = false; + + r_xy[0] = 0; + r_xy[1] = 0; + + if (rect->xmin < rect_bounds->xmin) { + int ofs = rect_bounds->xmin - rect->xmin; + rect->xmin += ofs; + rect->xmax += ofs; + r_xy[0] += ofs; + changed = true; + } + + if (rect->xmax > rect_bounds->xmax) { + int ofs = rect_bounds->xmax - rect->xmax; + rect->xmin += ofs; + rect->xmax += ofs; + r_xy[0] += ofs; + changed = true; + } + + if (rect->ymin < rect_bounds->ymin) { + int ofs = rect_bounds->ymin - rect->ymin; + rect->ymin += ofs; + rect->ymax += ofs; + r_xy[1] += ofs; + changed = true; + } + + if (rect->ymax > rect_bounds->ymax) { + int ofs = rect_bounds->ymax - rect->ymax; + rect->ymin += ofs; + rect->ymax += ofs; + r_xy[1] += ofs; + changed = true; + } + + return changed; } bool BLI_rctf_compare(const rctf *rect_a, const rctf *rect_b, const float limit) { - if (fabsf(rect_a->xmin - rect_b->xmin) < limit) { - if (fabsf(rect_a->xmax - rect_b->xmax) < limit) { - if (fabsf(rect_a->ymin - rect_b->ymin) < limit) { - if (fabsf(rect_a->ymax - rect_b->ymax) < limit) { - return true; - } - } - } - } + if (fabsf(rect_a->xmin - rect_b->xmin) < limit) { + if (fabsf(rect_a->xmax - rect_b->xmax) < limit) { + if (fabsf(rect_a->ymin - rect_b->ymin) < limit) { + if (fabsf(rect_a->ymax - rect_b->ymax) < limit) { + return true; + } + } + } + } - return false; + return false; } bool BLI_rcti_compare(const rcti *rect_a, const rcti *rect_b) { - if (rect_a->xmin == rect_b->xmin) { - if (rect_a->xmax == rect_b->xmax) { - if (rect_a->ymin == rect_b->ymin) { - if (rect_a->ymax == rect_b->ymax) { - return true; - } - } - } - } + if (rect_a->xmin == rect_b->xmin) { + if (rect_a->xmax == rect_b->xmax) { + if (rect_a->ymin == rect_b->ymin) { + if (rect_a->ymax == rect_b->ymax) { + return true; + } + } + } + } - return false; + return false; } bool BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest) { - float xmin, xmax; - float ymin, ymax; - - xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin); - xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax); - ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin); - ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax); - - if (xmax >= xmin && ymax >= ymin) { - if (dest) { - dest->xmin = xmin; - dest->xmax = xmax; - dest->ymin = ymin; - dest->ymax = ymax; - } - return true; - } - else { - if (dest) { - dest->xmin = 0; - dest->xmax = 0; - dest->ymin = 0; - dest->ymax = 0; - } - return false; - } + float xmin, xmax; + float ymin, ymax; + + xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin); + xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax); + ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin); + ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax); + + if (xmax >= xmin && ymax >= ymin) { + if (dest) { + dest->xmin = xmin; + dest->xmax = xmax; + dest->ymin = ymin; + dest->ymax = ymax; + } + return true; + } + else { + if (dest) { + dest->xmin = 0; + dest->xmax = 0; + dest->ymin = 0; + dest->ymax = 0; + } + return false; + } } bool BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) { - int xmin, xmax; - int ymin, ymax; - - xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin); - xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax); - ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin); - ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax); - - if (xmax >= xmin && ymax >= ymin) { - if (dest) { - dest->xmin = xmin; - dest->xmax = xmax; - dest->ymin = ymin; - dest->ymax = ymax; - } - return true; - } - else { - if (dest) { - dest->xmin = 0; - dest->xmax = 0; - dest->ymin = 0; - dest->ymax = 0; - } - return false; - } + int xmin, xmax; + int ymin, ymax; + + xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin); + xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax); + ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin); + ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax); + + if (xmax >= xmin && ymax >= ymin) { + if (dest) { + dest->xmin = xmin; + dest->xmax = xmax; + dest->ymin = ymin; + dest->ymax = ymax; + } + return true; + } + else { + if (dest) { + dest->xmin = 0; + dest->xmax = 0; + dest->ymin = 0; + dest->ymax = 0; + } + return false; + } } void BLI_rcti_rctf_copy(rcti *dst, const rctf *src) { - dst->xmin = floorf(src->xmin + 0.5f); - dst->xmax = dst->xmin + floorf(BLI_rctf_size_x(src) + 0.5f); - dst->ymin = floorf(src->ymin + 0.5f); - dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f); + dst->xmin = floorf(src->xmin + 0.5f); + dst->xmax = dst->xmin + floorf(BLI_rctf_size_x(src) + 0.5f); + dst->ymin = floorf(src->ymin + 0.5f); + dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f); } void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src) { - dst->xmin = floorf(src->xmin); - dst->xmax = floorf(src->xmax); - dst->ymin = floorf(src->ymin); - dst->ymax = floorf(src->ymax); + dst->xmin = floorf(src->xmin); + dst->xmax = floorf(src->xmax); + dst->ymin = floorf(src->ymin); + dst->ymax = floorf(src->ymax); } void BLI_rcti_rctf_copy_round(rcti *dst, const rctf *src) { - dst->xmin = floorf(src->xmin + 0.5f); - dst->xmax = floorf(src->xmax + 0.5f); - dst->ymin = floorf(src->ymin + 0.5f); - dst->ymax = floorf(src->ymax + 0.5f); + dst->xmin = floorf(src->xmin + 0.5f); + dst->xmax = floorf(src->xmax + 0.5f); + dst->ymin = floorf(src->ymin + 0.5f); + dst->ymax = floorf(src->ymax + 0.5f); } void BLI_rctf_rcti_copy(rctf *dst, const rcti *src) { - dst->xmin = src->xmin; - dst->xmax = src->xmax; - dst->ymin = src->ymin; - dst->ymax = src->ymax; + dst->xmin = src->xmin; + dst->xmax = src->xmax; + dst->ymin = src->ymin; + dst->ymax = src->ymax; } void print_rctf(const char *str, const rctf *rect) { - printf("%s: xmin %.8f, xmax %.8f, ymin %.8f, ymax %.8f (%.12fx%.12f)\n", str, - rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rctf_size_x(rect), BLI_rctf_size_y(rect)); + printf("%s: xmin %.8f, xmax %.8f, ymin %.8f, ymax %.8f (%.12fx%.12f)\n", + str, + rect->xmin, + rect->xmax, + rect->ymin, + rect->ymax, + BLI_rctf_size_x(rect), + BLI_rctf_size_y(rect)); } void print_rcti(const char *str, const rcti *rect) { - printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str, - rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)); + printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", + str, + rect->xmin, + rect->xmax, + rect->ymin, + rect->ymax, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect)); } - /* -------------------------------------------------------------------- */ /* Comprehensive math (float only) */ /** \name Rect math functions * \{ */ -#define ROTATE_SINCOS(r_vec, mat2, vec) { \ - (r_vec)[0] = (mat2)[1] * (vec)[0] + (+(mat2)[0]) * (vec)[1]; \ - (r_vec)[1] = (mat2)[0] * (vec)[0] + (-(mat2)[1]) * (vec)[1]; \ -} ((void)0) +#define ROTATE_SINCOS(r_vec, mat2, vec) \ + { \ + (r_vec)[0] = (mat2)[1] * (vec)[0] + (+(mat2)[0]) * (vec)[1]; \ + (r_vec)[1] = (mat2)[0] * (vec)[0] + (-(mat2)[1]) * (vec)[1]; \ + } \ + ((void)0) /** * Expand the rectangle to fit a rotated \a src. */ void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle) { - const float mat2[2] = {sinf(angle), cosf(angle)}; - const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)}; - float corner[2], corner_rot[2], corder_max[2]; + const float mat2[2] = {sinf(angle), cosf(angle)}; + const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)}; + float corner[2], corner_rot[2], corder_max[2]; - /* x is same for both corners */ - corner[0] = src->xmax - cent[0]; - corner[1] = src->ymax - cent[1]; - ROTATE_SINCOS(corner_rot, mat2, corner); - corder_max[0] = fabsf(corner_rot[0]); - corder_max[1] = fabsf(corner_rot[1]); + /* x is same for both corners */ + corner[0] = src->xmax - cent[0]; + corner[1] = src->ymax - cent[1]; + ROTATE_SINCOS(corner_rot, mat2, corner); + corder_max[0] = fabsf(corner_rot[0]); + corder_max[1] = fabsf(corner_rot[1]); - corner[1] *= -1; - ROTATE_SINCOS(corner_rot, mat2, corner); - corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0])); - corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1])); + corner[1] *= -1; + ROTATE_SINCOS(corner_rot, mat2, corner); + corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0])); + corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1])); - dst->xmin = cent[0] - corder_max[0]; - dst->xmax = cent[0] + corder_max[0]; - dst->ymin = cent[1] - corder_max[1]; - dst->ymax = cent[1] + corder_max[1]; + dst->xmin = cent[0] - corder_max[0]; + dst->xmax = cent[0] + corder_max[0]; + dst->ymin = cent[1] - corder_max[1]; + dst->ymax = cent[1] + corder_max[1]; } #undef ROTATE_SINCOS @@ -813,9 +978,9 @@ void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle) static void unit_m4(float m[4][4]) { - m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; - m[0][1] = m[0][2] = m[0][3] = 0.0f; - m[1][0] = m[1][2] = m[1][3] = 0.0f; - m[2][0] = m[2][1] = m[2][3] = 0.0f; - m[3][0] = m[3][1] = m[3][2] = 0.0f; + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; + m[0][1] = m[0][2] = m[0][3] = 0.0f; + m[1][0] = m[1][2] = m[1][3] = 0.0f; + m[2][0] = m[2][1] = m[2][3] = 0.0f; + m[3][0] = m[3][1] = m[3][2] = 0.0f; } diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 80b4acc90a7..9b71c9e6797 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -44,1103 +44,1122 @@ #include "BLI_memarena.h" #include "BLI_utildefines.h" -#include "BLI_scanfill.h" /* own include */ +#include "BLI_scanfill.h" /* own include */ #include "BLI_strict_flags.h" /* local types */ typedef struct PolyFill { - unsigned int edges, verts; - float min_xy[2], max_xy[2]; - unsigned short nr; - bool f; + unsigned int edges, verts; + float min_xy[2], max_xy[2]; + unsigned short nr; + bool f; } PolyFill; typedef struct ScanFillVertLink { - ScanFillVert *vert; - ScanFillEdge *edge_first, *edge_last; + ScanFillVert *vert; + ScanFillEdge *edge_first, *edge_last; } ScanFillVertLink; - /* local funcs */ -#define SF_EPSILON 0.00003f +#define SF_EPSILON 0.00003f #define SF_EPSILON_SQ (SF_EPSILON * SF_EPSILON) - /* ScanFillVert.status */ -#define SF_VERT_NEW 0 /* all new verts have this flag set */ -#define SF_VERT_AVAILABLE 1 /* available - in an edge */ -#define SF_VERT_ZERO_LEN 2 - +#define SF_VERT_NEW 0 /* all new verts have this flag set */ +#define SF_VERT_AVAILABLE 1 /* available - in an edge */ +#define SF_VERT_ZERO_LEN 2 /* ScanFillEdge.status */ /* Optionally set ScanFillEdge f to this to mark original boundary edges. * Only needed if there are internal diagonal edges passed to BLI_scanfill_calc. */ -#define SF_EDGE_NEW 0 /* all new edges have this flag set */ +#define SF_EDGE_NEW 0 /* all new edges have this flag set */ // #define SF_EDGE_BOUNDARY 1 /* UNUSED */ -#define SF_EDGE_INTERNAL 2 /* edge is created while scan-filling */ - +#define SF_EDGE_INTERNAL 2 /* edge is created while scan-filling */ /* PolyFill.status */ -#define SF_POLY_NEW 0 /* all polys initialized to this */ -#define SF_POLY_VALID 1 /* has at least 3 verts */ +#define SF_POLY_NEW 0 /* all polys initialized to this */ +#define SF_POLY_VALID 1 /* has at least 3 verts */ /* **** FUNCTIONS FOR QSORT *************************** */ - static int vergscdata(const void *a1, const void *a2) { - const ScanFillVertLink *x1 = a1, *x2 = a2; - - if (x1->vert->xy[1] < x2->vert->xy[1]) { return 1; } - else if (x1->vert->xy[1] > x2->vert->xy[1]) { return -1; } - else if (x1->vert->xy[0] > x2->vert->xy[0]) { return 1; } - else if (x1->vert->xy[0] < x2->vert->xy[0]) { return -1; } - - return 0; + const ScanFillVertLink *x1 = a1, *x2 = a2; + + if (x1->vert->xy[1] < x2->vert->xy[1]) { + return 1; + } + else if (x1->vert->xy[1] > x2->vert->xy[1]) { + return -1; + } + else if (x1->vert->xy[0] > x2->vert->xy[0]) { + return 1; + } + else if (x1->vert->xy[0] < x2->vert->xy[0]) { + return -1; + } + + return 0; } static int vergpoly(const void *a1, const void *a2) { - const PolyFill *x1 = a1, *x2 = a2; - - if (x1->min_xy[0] > x2->min_xy[0]) { return 1; } - else if (x1->min_xy[0] < x2->min_xy[0]) { return -1; } - else if (x1->min_xy[1] > x2->min_xy[1]) { return 1; } - else if (x1->min_xy[1] < x2->min_xy[1]) { return -1; } - - return 0; + const PolyFill *x1 = a1, *x2 = a2; + + if (x1->min_xy[0] > x2->min_xy[0]) { + return 1; + } + else if (x1->min_xy[0] < x2->min_xy[0]) { + return -1; + } + else if (x1->min_xy[1] > x2->min_xy[1]) { + return 1; + } + else if (x1->min_xy[1] < x2->min_xy[1]) { + return -1; + } + + return 0; } /* **** FILL ROUTINES *************************** */ ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) { - ScanFillVert *sf_v; + ScanFillVert *sf_v; - sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert)); + sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert)); - BLI_addtail(&sf_ctx->fillvertbase, sf_v); + BLI_addtail(&sf_ctx->fillvertbase, sf_v); - sf_v->tmp.p = NULL; - copy_v3_v3(sf_v->co, vec); + sf_v->tmp.p = NULL; + copy_v3_v3(sf_v->co, vec); - /* just zero out the rest */ - zero_v2(sf_v->xy); - sf_v->keyindex = 0; - sf_v->poly_nr = sf_ctx->poly_nr; - sf_v->edge_tot = 0; - sf_v->f = SF_VERT_NEW; - sf_v->user_flag = 0; + /* just zero out the rest */ + zero_v2(sf_v->xy); + sf_v->keyindex = 0; + sf_v->poly_nr = sf_ctx->poly_nr; + sf_v->edge_tot = 0; + sf_v->f = SF_VERT_NEW; + sf_v->user_flag = 0; - return sf_v; + return sf_v; } ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2) { - ScanFillEdge *sf_ed; + ScanFillEdge *sf_ed; - sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge)); - BLI_addtail(&sf_ctx->filledgebase, sf_ed); + sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge)); + BLI_addtail(&sf_ctx->filledgebase, sf_ed); - sf_ed->v1 = v1; - sf_ed->v2 = v2; + sf_ed->v1 = v1; + sf_ed->v2 = v2; - /* just zero out the rest */ - sf_ed->poly_nr = sf_ctx->poly_nr; - sf_ed->f = SF_EDGE_NEW; - sf_ed->user_flag = 0; - sf_ed->tmp.c = 0; + /* just zero out the rest */ + sf_ed->poly_nr = sf_ctx->poly_nr; + sf_ed->f = SF_EDGE_NEW; + sf_ed->user_flag = 0; + sf_ed->tmp.c = 0; - return sf_ed; + return sf_ed; } -static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3) +static void addfillface(ScanFillContext *sf_ctx, + ScanFillVert *v1, + ScanFillVert *v2, + ScanFillVert *v3) { - /* does not make edges */ - ScanFillFace *sf_tri; + /* does not make edges */ + ScanFillFace *sf_tri; - sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace)); - BLI_addtail(&sf_ctx->fillfacebase, sf_tri); + sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace)); + BLI_addtail(&sf_ctx->fillfacebase, sf_tri); - sf_tri->v1 = v1; - sf_tri->v2 = v2; - sf_tri->v3 = v3; + sf_tri->v1 = v1; + sf_tri->v2 = v2; + sf_tri->v3 = v3; } static bool boundisect(PolyFill *pf2, PolyFill *pf1) { - /* has pf2 been touched (intersected) by pf1 ? with bounding box */ - /* test first if polys exist */ - - if (pf1->edges == 0 || pf2->edges == 0) { return false; } - - if (pf2->max_xy[0] < pf1->min_xy[0]) { return false; } - if (pf2->max_xy[1] < pf1->min_xy[1]) { return false; } - - if (pf2->min_xy[0] > pf1->max_xy[0]) { return false; } - if (pf2->min_xy[1] > pf1->max_xy[1]) { return false; } - - /* join */ - if (pf2->max_xy[0] < pf1->max_xy[0]) { pf2->max_xy[0] = pf1->max_xy[0]; } - if (pf2->max_xy[1] < pf1->max_xy[1]) { pf2->max_xy[1] = pf1->max_xy[1]; } - - if (pf2->min_xy[0] > pf1->min_xy[0]) { pf2->min_xy[0] = pf1->min_xy[0]; } - if (pf2->min_xy[1] > pf1->min_xy[1]) { pf2->min_xy[1] = pf1->min_xy[1]; } - - return true; + /* has pf2 been touched (intersected) by pf1 ? with bounding box */ + /* test first if polys exist */ + + if (pf1->edges == 0 || pf2->edges == 0) { + return false; + } + + if (pf2->max_xy[0] < pf1->min_xy[0]) { + return false; + } + if (pf2->max_xy[1] < pf1->min_xy[1]) { + return false; + } + + if (pf2->min_xy[0] > pf1->max_xy[0]) { + return false; + } + if (pf2->min_xy[1] > pf1->max_xy[1]) { + return false; + } + + /* join */ + if (pf2->max_xy[0] < pf1->max_xy[0]) { + pf2->max_xy[0] = pf1->max_xy[0]; + } + if (pf2->max_xy[1] < pf1->max_xy[1]) { + pf2->max_xy[1] = pf1->max_xy[1]; + } + + if (pf2->min_xy[0] > pf1->min_xy[0]) { + pf2->min_xy[0] = pf1->min_xy[0]; + } + if (pf2->min_xy[1] > pf1->min_xy[1]) { + pf2->min_xy[1] = pf1->min_xy[1]; + } + + return true; } - /* add pf2 to pf1 */ static void mergepolysSimp(ScanFillContext *sf_ctx, PolyFill *pf1, PolyFill *pf2) { - ScanFillVert *eve; - ScanFillEdge *eed; - - /* replace old poly numbers */ - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (eve->poly_nr == pf2->nr) { - eve->poly_nr = pf1->nr; - } - } - - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - if (eed->poly_nr == pf2->nr) { - eed->poly_nr = pf1->nr; - } - } - - pf1->verts += pf2->verts; - pf1->edges += pf2->edges; - pf2->verts = pf2->edges = 0; - pf1->f = (pf1->f | pf2->f); + ScanFillVert *eve; + ScanFillEdge *eed; + + /* replace old poly numbers */ + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (eve->poly_nr == pf2->nr) { + eve->poly_nr = pf1->nr; + } + } + + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + if (eed->poly_nr == pf2->nr) { + eed->poly_nr = pf1->nr; + } + } + + pf1->verts += pf2->verts; + pf1->edges += pf2->edges; + pf2->verts = pf2->edges = 0; + pf1->f = (pf1->f | pf2->f); } static bool testedgeside(const float v1[2], const float v2[2], const float v3[2]) /* is v3 to the right of v1-v2 ? With exception: v3 == v1 || v3 == v2 */ { - float inp; - - inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + - (v1[1] - v2[1]) * (v1[0] - v3[0]); - - if (inp < 0.0f) { - return false; - } - else if (inp == 0.0f) { - if (v1[0] == v3[0] && v1[1] == v3[1]) { - return false; - } - if (v2[0] == v3[0] && v2[1] == v3[1]) { - return false; - } - } - return true; + float inp; + + inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + (v1[1] - v2[1]) * (v1[0] - v3[0]); + + if (inp < 0.0f) { + return false; + } + else if (inp == 0.0f) { + if (v1[0] == v3[0] && v1[1] == v3[1]) { + return false; + } + if (v2[0] == v3[0] && v2[1] == v3[1]) { + return false; + } + } + return true; } static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed) { - /* find first edge to the right of eed, and insert eed before that */ - ScanFillEdge *ed; - float fac, fac1, x, y; - - if (sc->edge_first == NULL) { - sc->edge_first = sc->edge_last = eed; - eed->prev = eed->next = NULL; - return 1; - } - - x = eed->v1->xy[0]; - y = eed->v1->xy[1]; - - fac1 = eed->v2->xy[1] - y; - if (fac1 == 0.0f) { - fac1 = 1.0e10f * (eed->v2->xy[0] - x); - - } - else { - fac1 = (x - eed->v2->xy[0]) / fac1; - } - - for (ed = sc->edge_first; ed; ed = ed->next) { - - if (ed->v2 == eed->v2) { - return false; - } - - fac = ed->v2->xy[1] - y; - if (fac == 0.0f) { - fac = 1.0e10f * (ed->v2->xy[0] - x); - } - else { - fac = (x - ed->v2->xy[0]) / fac; - } - - if (fac > fac1) { - break; - } - } - if (ed) { - BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed); - } - else { - BLI_addtail((ListBase *)&(sc->edge_first), eed); - } - - return true; + /* find first edge to the right of eed, and insert eed before that */ + ScanFillEdge *ed; + float fac, fac1, x, y; + + if (sc->edge_first == NULL) { + sc->edge_first = sc->edge_last = eed; + eed->prev = eed->next = NULL; + return 1; + } + + x = eed->v1->xy[0]; + y = eed->v1->xy[1]; + + fac1 = eed->v2->xy[1] - y; + if (fac1 == 0.0f) { + fac1 = 1.0e10f * (eed->v2->xy[0] - x); + } + else { + fac1 = (x - eed->v2->xy[0]) / fac1; + } + + for (ed = sc->edge_first; ed; ed = ed->next) { + + if (ed->v2 == eed->v2) { + return false; + } + + fac = ed->v2->xy[1] - y; + if (fac == 0.0f) { + fac = 1.0e10f * (ed->v2->xy[0] - x); + } + else { + fac = (x - ed->v2->xy[0]) / fac; + } + + if (fac > fac1) { + break; + } + } + if (ed) { + BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed); + } + else { + BLI_addtail((ListBase *)&(sc->edge_first), eed); + } + + return true; } - -static ScanFillVertLink *addedgetoscanlist(ScanFillVertLink *scdata, ScanFillEdge *eed, unsigned int len) +static ScanFillVertLink *addedgetoscanlist(ScanFillVertLink *scdata, + ScanFillEdge *eed, + unsigned int len) { - /* inserts edge at correct location in ScanFillVertLink list */ - /* returns sc when edge already exists */ - ScanFillVertLink *sc, scsearch; - ScanFillVert *eve; - - /* which vert is left-top? */ - if (eed->v1->xy[1] == eed->v2->xy[1]) { - if (eed->v1->xy[0] > eed->v2->xy[0]) { - eve = eed->v1; - eed->v1 = eed->v2; - eed->v2 = eve; - } - } - else if (eed->v1->xy[1] < eed->v2->xy[1]) { - eve = eed->v1; - eed->v1 = eed->v2; - eed->v2 = eve; - } - /* find location in list */ - scsearch.vert = eed->v1; - sc = (ScanFillVertLink *)bsearch(&scsearch, scdata, len, - sizeof(ScanFillVertLink), vergscdata); - - if (UNLIKELY(sc == NULL)) { - printf("Error in search edge: %p\n", (void *)eed); - } - else if (addedgetoscanvert(sc, eed) == false) { - return sc; - } - - return NULL; + /* inserts edge at correct location in ScanFillVertLink list */ + /* returns sc when edge already exists */ + ScanFillVertLink *sc, scsearch; + ScanFillVert *eve; + + /* which vert is left-top? */ + if (eed->v1->xy[1] == eed->v2->xy[1]) { + if (eed->v1->xy[0] > eed->v2->xy[0]) { + eve = eed->v1; + eed->v1 = eed->v2; + eed->v2 = eve; + } + } + else if (eed->v1->xy[1] < eed->v2->xy[1]) { + eve = eed->v1; + eed->v1 = eed->v2; + eed->v2 = eve; + } + /* find location in list */ + scsearch.vert = eed->v1; + sc = (ScanFillVertLink *)bsearch(&scsearch, scdata, len, sizeof(ScanFillVertLink), vergscdata); + + if (UNLIKELY(sc == NULL)) { + printf("Error in search edge: %p\n", (void *)eed); + } + else if (addedgetoscanvert(sc, eed) == false) { + return sc; + } + + return NULL; } static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve) /* is eve inside boundbox eed */ { - float minx, maxx, miny, maxy; - - if (eed->v1->xy[0] < eed->v2->xy[0]) { - minx = eed->v1->xy[0]; - maxx = eed->v2->xy[0]; - } - else { - minx = eed->v2->xy[0]; - maxx = eed->v1->xy[0]; - } - if (eve->xy[0] >= minx && eve->xy[0] <= maxx) { - if (eed->v1->xy[1] < eed->v2->xy[1]) { - miny = eed->v1->xy[1]; - maxy = eed->v2->xy[1]; - } - else { - miny = eed->v2->xy[1]; - maxy = eed->v1->xy[1]; - } - if (eve->xy[1] >= miny && eve->xy[1] <= maxy) { - return true; - } - } - return false; + float minx, maxx, miny, maxy; + + if (eed->v1->xy[0] < eed->v2->xy[0]) { + minx = eed->v1->xy[0]; + maxx = eed->v2->xy[0]; + } + else { + minx = eed->v2->xy[0]; + maxx = eed->v1->xy[0]; + } + if (eve->xy[0] >= minx && eve->xy[0] <= maxx) { + if (eed->v1->xy[1] < eed->v2->xy[1]) { + miny = eed->v1->xy[1]; + maxy = eed->v2->xy[1]; + } + else { + miny = eed->v2->xy[1]; + maxy = eed->v1->xy[1]; + } + if (eve->xy[1] >= miny && eve->xy[1] <= maxy) { + return true; + } + } + return false; } - static void testvertexnearedge(ScanFillContext *sf_ctx) { - /* only vertices with (->edge_tot == 1) are being tested for - * being close to an edge, if true insert */ - - ScanFillVert *eve; - ScanFillEdge *eed, *ed1; - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (eve->edge_tot == 1) { - /* find the edge which has vertex eve, - * note: we _know_ this will crash if 'ed1' becomes NULL - * but this will never happen. */ - for (ed1 = sf_ctx->filledgebase.first; - !(ed1->v1 == eve || ed1->v2 == eve); - ed1 = ed1->next) - { - /* do nothing */ - } - - if (ed1->v1 == eve) { - ed1->v1 = ed1->v2; - ed1->v2 = eve; - } - - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) { - if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) { - ed1->v2 = eed->v1; - eed->v1->edge_tot++; - eve->edge_tot = 0; - break; - } - else if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) { - ed1->v2 = eed->v2; - eed->v2->edge_tot++; - eve->edge_tot = 0; - break; - } - else { - if (boundinsideEV(eed, eve)) { - const float dist = dist_squared_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy); - if (dist < SF_EPSILON_SQ) { - /* new edge */ - ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve); - - /* printf("fill: vertex near edge %x\n", eve); */ - ed1->poly_nr = eed->poly_nr; - eed->v1 = eve; - eve->edge_tot = 3; - break; - } - } - } - } - } - } - } + /* only vertices with (->edge_tot == 1) are being tested for + * being close to an edge, if true insert */ + + ScanFillVert *eve; + ScanFillEdge *eed, *ed1; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (eve->edge_tot == 1) { + /* find the edge which has vertex eve, + * note: we _know_ this will crash if 'ed1' becomes NULL + * but this will never happen. */ + for (ed1 = sf_ctx->filledgebase.first; !(ed1->v1 == eve || ed1->v2 == eve); + ed1 = ed1->next) { + /* do nothing */ + } + + if (ed1->v1 == eve) { + ed1->v1 = ed1->v2; + ed1->v2 = eve; + } + + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) { + if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) { + ed1->v2 = eed->v1; + eed->v1->edge_tot++; + eve->edge_tot = 0; + break; + } + else if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) { + ed1->v2 = eed->v2; + eed->v2->edge_tot++; + eve->edge_tot = 0; + break; + } + else { + if (boundinsideEV(eed, eve)) { + const float dist = dist_squared_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy); + if (dist < SF_EPSILON_SQ) { + /* new edge */ + ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve); + + /* printf("fill: vertex near edge %x\n", eve); */ + ed1->poly_nr = eed->poly_nr; + eed->v1 = eve; + eve->edge_tot = 3; + break; + } + } + } + } + } + } + } } -static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, unsigned short nr) +static void splitlist(ScanFillContext *sf_ctx, + ListBase *tempve, + ListBase *temped, + unsigned short nr) { - /* everything is in templist, write only poly nr to fillist */ - ScanFillVert *eve, *eve_next; - ScanFillEdge *eed, *eed_next; - - BLI_movelisttolist(tempve, &sf_ctx->fillvertbase); - BLI_movelisttolist(temped, &sf_ctx->filledgebase); - - - for (eve = tempve->first; eve; eve = eve_next) { - eve_next = eve->next; - if (eve->poly_nr == nr) { - BLI_remlink(tempve, eve); - BLI_addtail(&sf_ctx->fillvertbase, eve); - } - - } - - for (eed = temped->first; eed; eed = eed_next) { - eed_next = eed->next; - if (eed->poly_nr == nr) { - BLI_remlink(temped, eed); - BLI_addtail(&sf_ctx->filledgebase, eed); - } - } + /* everything is in templist, write only poly nr to fillist */ + ScanFillVert *eve, *eve_next; + ScanFillEdge *eed, *eed_next; + + BLI_movelisttolist(tempve, &sf_ctx->fillvertbase); + BLI_movelisttolist(temped, &sf_ctx->filledgebase); + + for (eve = tempve->first; eve; eve = eve_next) { + eve_next = eve->next; + if (eve->poly_nr == nr) { + BLI_remlink(tempve, eve); + BLI_addtail(&sf_ctx->fillvertbase, eve); + } + } + + for (eed = temped->first; eed; eed = eed_next) { + eed_next = eed->next; + if (eed->poly_nr == nr) { + BLI_remlink(temped, eed); + BLI_addtail(&sf_ctx->filledgebase, eed); + } + } } static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) { - ScanFillVertLink *scdata; - ScanFillVertLink *sc = NULL, *sc1; - ScanFillVert *eve, *v1, *v2, *v3; - ScanFillEdge *eed, *eed_next, *ed1, *ed2, *ed3; - unsigned int a, b, verts, maxface, totface; - const unsigned short nr = pf->nr; - bool twoconnected = false; - - /* PRINTS */ + ScanFillVertLink *scdata; + ScanFillVertLink *sc = NULL, *sc1; + ScanFillVert *eve, *v1, *v2, *v3; + ScanFillEdge *eed, *eed_next, *ed1, *ed2, *ed3; + unsigned int a, b, verts, maxface, totface; + const unsigned short nr = pf->nr; + bool twoconnected = false; + + /* PRINTS */ #if 0 - verts = pf->verts; - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]); - } - - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2); - } + verts = pf->verts; + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]); + } + + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2); + } #endif - /* STEP 0: remove zero sized edges */ - if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { - if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { - eed->v1->f = SF_VERT_ZERO_LEN; - eed->v1->tmp.v = eed->v2->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { - eed->v1->tmp.v = eed->v2->tmp.v; - } - else { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1; - } - } - } - } - - /* STEP 1: make using FillVert and FillEdge lists a sorted - * ScanFillVertLink list - */ - sc = scdata = MEM_mallocN(sizeof(*scdata) * pf->verts, "Scanfill1"); - verts = 0; - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (eve->poly_nr == nr) { - if (eve->f != SF_VERT_ZERO_LEN) { - verts++; - eve->f = SF_VERT_NEW; /* flag for connectedges later on */ - sc->vert = eve; - sc->edge_first = sc->edge_last = NULL; - /* Note, debug print only will work for curve polyfill, union is in use for mesh */ - /* if (even->tmp.v == NULL) eve->tmp.u = verts; */ - sc++; - } - } - } - - qsort(scdata, verts, sizeof(ScanFillVertLink), vergscdata); - - if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { - for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { - eed_next = eed->next; - BLI_remlink(&sf_ctx->filledgebase, eed); - /* This code is for handling zero-length edges that get - * collapsed in step 0. It was removed for some time to - * fix trunk bug #4544, so if that comes back, this code - * may need some work, or there will have to be a better - * fix to #4544. - * - * warning, this can hang on un-ordered edges, see: [#33281] - * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons. - */ - if (eed->v1->f == SF_VERT_ZERO_LEN) { - v1 = eed->v1; - while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) { - eed->v1 = eed->v1->tmp.v; - } - } - if (eed->v2->f == SF_VERT_ZERO_LEN) { - v2 = eed->v2; - while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) { - eed->v2 = eed->v2->tmp.v; - } - } - if (eed->v1 != eed->v2) { - addedgetoscanlist(scdata, eed, verts); - } - } - } - else { - for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { - eed_next = eed->next; - BLI_remlink(&sf_ctx->filledgebase, eed); - if (eed->v1 != eed->v2) { - addedgetoscanlist(scdata, eed, verts); - } - } - } + /* STEP 0: remove zero sized edges */ + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { + if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { + eed->v1->f = SF_VERT_ZERO_LEN; + eed->v1->tmp.v = eed->v2->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { + eed->v1->tmp.v = eed->v2->tmp.v; + } + else { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1; + } + } + } + } + + /* STEP 1: make using FillVert and FillEdge lists a sorted + * ScanFillVertLink list + */ + sc = scdata = MEM_mallocN(sizeof(*scdata) * pf->verts, "Scanfill1"); + verts = 0; + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (eve->poly_nr == nr) { + if (eve->f != SF_VERT_ZERO_LEN) { + verts++; + eve->f = SF_VERT_NEW; /* flag for connectedges later on */ + sc->vert = eve; + sc->edge_first = sc->edge_last = NULL; + /* Note, debug print only will work for curve polyfill, union is in use for mesh */ + /* if (even->tmp.v == NULL) eve->tmp.u = verts; */ + sc++; + } + } + } + + qsort(scdata, verts, sizeof(ScanFillVertLink), vergscdata); + + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { + eed_next = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + /* This code is for handling zero-length edges that get + * collapsed in step 0. It was removed for some time to + * fix trunk bug #4544, so if that comes back, this code + * may need some work, or there will have to be a better + * fix to #4544. + * + * warning, this can hang on un-ordered edges, see: [#33281] + * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons. + */ + if (eed->v1->f == SF_VERT_ZERO_LEN) { + v1 = eed->v1; + while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && + (eed->v1 != eed->v1->tmp.v)) { + eed->v1 = eed->v1->tmp.v; + } + } + if (eed->v2->f == SF_VERT_ZERO_LEN) { + v2 = eed->v2; + while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && + (eed->v2 != eed->v2->tmp.v)) { + eed->v2 = eed->v2->tmp.v; + } + } + if (eed->v1 != eed->v2) { + addedgetoscanlist(scdata, eed, verts); + } + } + } + else { + for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { + eed_next = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + if (eed->v1 != eed->v2) { + addedgetoscanlist(scdata, eed, verts); + } + } + } #if 0 - sc = sf_ctx->_scdata; - for (a = 0; a < verts; a++) { - printf("\nscvert: %x\n", sc->vert); - for (eed = sc->edge_first; eed; eed = eed->next) { - printf(" ed %x %x %x\n", eed, eed->v1, eed->v2); - } - sc++; - } + sc = sf_ctx->_scdata; + for (a = 0; a < verts; a++) { + printf("\nscvert: %x\n", sc->vert); + for (eed = sc->edge_first; eed; eed = eed->next) { + printf(" ed %x %x %x\n", eed, eed->v1, eed->v2); + } + sc++; + } #endif - - /* STEP 2: FILL LOOP */ - - if (pf->f == SF_POLY_NEW) { - twoconnected = true; - } - - /* (temporal) security: never much more faces than vertices */ - totface = 0; - if (flag & BLI_SCANFILL_CALC_HOLES) { - maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */ - } - else { - /* when we don't calc any holes, we assume face is a non overlapping loop */ - maxface = verts - 2; - } - - sc = scdata; - for (a = 0; a < verts; a++) { - /* printf("VERTEX %d index %d\n", a, sc->vert->tmp.u); */ - /* set connectflags */ - for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { - eed_next = ed1->next; - if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) { - BLI_remlink((ListBase *)&(sc->edge_first), ed1); - BLI_addtail(&sf_ctx->filledgebase, ed1); - if (ed1->v1->edge_tot > 1) { - ed1->v1->edge_tot--; - } - if (ed1->v2->edge_tot > 1) { - ed1->v2->edge_tot--; - } - } - else { - ed1->v2->f = SF_VERT_AVAILABLE; - } - } - while (sc->edge_first) { /* for as long there are edges */ - ed1 = sc->edge_first; - ed2 = ed1->next; - - /* commented out... the ESC here delivers corrupted memory - * (and doesnt work during grab) */ - /* if (callLocalInterruptCallBack()) break; */ - if (totface >= maxface) { - /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */ - a = verts; - break; - } - if (ed2 == NULL) { - sc->edge_first = sc->edge_last = NULL; - /* printf("just 1 edge to vert\n"); */ - BLI_addtail(&sf_ctx->filledgebase, ed1); - ed1->v2->f = SF_VERT_NEW; - ed1->v1->edge_tot--; - ed1->v2->edge_tot--; - } - else { - /* test rest of vertices */ - ScanFillVertLink *best_sc = NULL; - float angle_best_cos = -1.0f; - float miny; - bool firsttime = false; - - v1 = ed1->v2; - v2 = ed1->v1; - v3 = ed2->v2; - - /* this happens with a serial of overlapping edges */ - if (v1 == v2 || v2 == v3) { - break; - } - - /* printf("test verts %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */ - miny = min_ff(v1->xy[1], v3->xy[1]); - sc1 = sc + 1; - - for (b = a + 1; b < verts; b++, sc1++) { - if (sc1->vert->f == SF_VERT_NEW) { - if (sc1->vert->xy[1] <= miny) { - break; - } - if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) { - if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) { - if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) { - /* point is in triangle */ - - /* Because multiple points can be inside triangle - * (concave holes) we continue searching and pick the - * one with sharpest corner. */ - if (best_sc == NULL) { - /* even without holes we need to keep checking [#35861] */ - best_sc = sc1; - } - else { - /* Prevent angle calc for the simple cases - * only 1 vertex is found. */ - if (firsttime == false) { - angle_best_cos = cos_v2v2v2(v2->xy, v1->xy, best_sc->vert->xy); - firsttime = true; - } - - const float angle_test_cos = cos_v2v2v2(v2->xy, v1->xy, sc1->vert->xy); - if (angle_test_cos > angle_best_cos) { - best_sc = sc1; - angle_best_cos = angle_test_cos; - } - } - } - } - } - } - } - - if (best_sc) { - /* make new edge, and start over */ - /* printf("add new edge %d %d and start again\n", v2->tmp.u, best_sc->vert->tmp.u); */ - - ed3 = BLI_scanfill_edge_add(sf_ctx, v2, best_sc->vert); - BLI_remlink(&sf_ctx->filledgebase, ed3); - BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3); - ed3->v2->f = SF_VERT_AVAILABLE; - ed3->f = SF_EDGE_INTERNAL; - ed3->v1->edge_tot++; - ed3->v2->edge_tot++; - } - else { - /* new triangle */ - /* printf("add face %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */ - addfillface(sf_ctx, v1, v2, v3); - totface++; - BLI_remlink((ListBase *)&(sc->edge_first), ed1); - BLI_addtail(&sf_ctx->filledgebase, ed1); - ed1->v2->f = SF_VERT_NEW; - ed1->v1->edge_tot--; - ed1->v2->edge_tot--; - /* ed2 can be removed when it's a boundary edge */ - if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) { - BLI_remlink((ListBase *)&(sc->edge_first), ed2); - BLI_addtail(&sf_ctx->filledgebase, ed2); - ed2->v2->f = SF_VERT_NEW; - ed2->v1->edge_tot--; - ed2->v2->edge_tot--; - } - - /* new edge */ - ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3); - BLI_remlink(&sf_ctx->filledgebase, ed3); - ed3->f = SF_EDGE_INTERNAL; - ed3->v1->edge_tot++; - ed3->v2->edge_tot++; - - /* printf("add new edge %x %x\n", v1, v3); */ - sc1 = addedgetoscanlist(scdata, ed3, verts); - - if (sc1) { /* ed3 already exists: remove if a boundary */ - /* printf("Edge exists\n"); */ - ed3->v1->edge_tot--; - ed3->v2->edge_tot--; - - for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) { - if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) { - if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) { - BLI_remlink((ListBase *)&(sc1->edge_first), ed3); - BLI_addtail(&sf_ctx->filledgebase, ed3); - ed3->v1->edge_tot--; - ed3->v2->edge_tot--; - } - break; - } - } - } - } - } - - /* test for loose edges */ - for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { - eed_next = ed1->next; - if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) { - BLI_remlink((ListBase *)&(sc->edge_first), ed1); - BLI_addtail(&sf_ctx->filledgebase, ed1); - if (ed1->v1->edge_tot > 1) { - ed1->v1->edge_tot--; - } - if (ed1->v2->edge_tot > 1) { - ed1->v2->edge_tot--; - } - } - } - /* done with loose edges */ - } - - sc++; - } - - MEM_freeN(scdata); - - BLI_assert(totface <= maxface); - - return totface; + /* STEP 2: FILL LOOP */ + + if (pf->f == SF_POLY_NEW) { + twoconnected = true; + } + + /* (temporal) security: never much more faces than vertices */ + totface = 0; + if (flag & BLI_SCANFILL_CALC_HOLES) { + maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */ + } + else { + /* when we don't calc any holes, we assume face is a non overlapping loop */ + maxface = verts - 2; + } + + sc = scdata; + for (a = 0; a < verts; a++) { + /* printf("VERTEX %d index %d\n", a, sc->vert->tmp.u); */ + /* set connectflags */ + for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { + eed_next = ed1->next; + if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) { + BLI_remlink((ListBase *)&(sc->edge_first), ed1); + BLI_addtail(&sf_ctx->filledgebase, ed1); + if (ed1->v1->edge_tot > 1) { + ed1->v1->edge_tot--; + } + if (ed1->v2->edge_tot > 1) { + ed1->v2->edge_tot--; + } + } + else { + ed1->v2->f = SF_VERT_AVAILABLE; + } + } + while (sc->edge_first) { /* for as long there are edges */ + ed1 = sc->edge_first; + ed2 = ed1->next; + + /* commented out... the ESC here delivers corrupted memory + * (and doesnt work during grab) */ + /* if (callLocalInterruptCallBack()) break; */ + if (totface >= maxface) { + /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */ + a = verts; + break; + } + if (ed2 == NULL) { + sc->edge_first = sc->edge_last = NULL; + /* printf("just 1 edge to vert\n"); */ + BLI_addtail(&sf_ctx->filledgebase, ed1); + ed1->v2->f = SF_VERT_NEW; + ed1->v1->edge_tot--; + ed1->v2->edge_tot--; + } + else { + /* test rest of vertices */ + ScanFillVertLink *best_sc = NULL; + float angle_best_cos = -1.0f; + float miny; + bool firsttime = false; + + v1 = ed1->v2; + v2 = ed1->v1; + v3 = ed2->v2; + + /* this happens with a serial of overlapping edges */ + if (v1 == v2 || v2 == v3) { + break; + } + + /* printf("test verts %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */ + miny = min_ff(v1->xy[1], v3->xy[1]); + sc1 = sc + 1; + + for (b = a + 1; b < verts; b++, sc1++) { + if (sc1->vert->f == SF_VERT_NEW) { + if (sc1->vert->xy[1] <= miny) { + break; + } + if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) { + if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) { + if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) { + /* point is in triangle */ + + /* Because multiple points can be inside triangle + * (concave holes) we continue searching and pick the + * one with sharpest corner. */ + if (best_sc == NULL) { + /* even without holes we need to keep checking [#35861] */ + best_sc = sc1; + } + else { + /* Prevent angle calc for the simple cases + * only 1 vertex is found. */ + if (firsttime == false) { + angle_best_cos = cos_v2v2v2(v2->xy, v1->xy, best_sc->vert->xy); + firsttime = true; + } + + const float angle_test_cos = cos_v2v2v2(v2->xy, v1->xy, sc1->vert->xy); + if (angle_test_cos > angle_best_cos) { + best_sc = sc1; + angle_best_cos = angle_test_cos; + } + } + } + } + } + } + } + + if (best_sc) { + /* make new edge, and start over */ + /* printf("add new edge %d %d and start again\n", v2->tmp.u, best_sc->vert->tmp.u); */ + + ed3 = BLI_scanfill_edge_add(sf_ctx, v2, best_sc->vert); + BLI_remlink(&sf_ctx->filledgebase, ed3); + BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3); + ed3->v2->f = SF_VERT_AVAILABLE; + ed3->f = SF_EDGE_INTERNAL; + ed3->v1->edge_tot++; + ed3->v2->edge_tot++; + } + else { + /* new triangle */ + /* printf("add face %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */ + addfillface(sf_ctx, v1, v2, v3); + totface++; + BLI_remlink((ListBase *)&(sc->edge_first), ed1); + BLI_addtail(&sf_ctx->filledgebase, ed1); + ed1->v2->f = SF_VERT_NEW; + ed1->v1->edge_tot--; + ed1->v2->edge_tot--; + /* ed2 can be removed when it's a boundary edge */ + if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) { + BLI_remlink((ListBase *)&(sc->edge_first), ed2); + BLI_addtail(&sf_ctx->filledgebase, ed2); + ed2->v2->f = SF_VERT_NEW; + ed2->v1->edge_tot--; + ed2->v2->edge_tot--; + } + + /* new edge */ + ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3); + BLI_remlink(&sf_ctx->filledgebase, ed3); + ed3->f = SF_EDGE_INTERNAL; + ed3->v1->edge_tot++; + ed3->v2->edge_tot++; + + /* printf("add new edge %x %x\n", v1, v3); */ + sc1 = addedgetoscanlist(scdata, ed3, verts); + + if (sc1) { /* ed3 already exists: remove if a boundary */ + /* printf("Edge exists\n"); */ + ed3->v1->edge_tot--; + ed3->v2->edge_tot--; + + for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) { + if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) { + if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) { + BLI_remlink((ListBase *)&(sc1->edge_first), ed3); + BLI_addtail(&sf_ctx->filledgebase, ed3); + ed3->v1->edge_tot--; + ed3->v2->edge_tot--; + } + break; + } + } + } + } + } + + /* test for loose edges */ + for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { + eed_next = ed1->next; + if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) { + BLI_remlink((ListBase *)&(sc->edge_first), ed1); + BLI_addtail(&sf_ctx->filledgebase, ed1); + if (ed1->v1->edge_tot > 1) { + ed1->v1->edge_tot--; + } + if (ed1->v2->edge_tot > 1) { + ed1->v2->edge_tot--; + } + } + } + /* done with loose edges */ + } + + sc++; + } + + MEM_freeN(scdata); + + BLI_assert(totface <= maxface); + + return totface; } - void BLI_scanfill_begin(ScanFillContext *sf_ctx) { - memset(sf_ctx, 0, sizeof(*sf_ctx)); - sf_ctx->poly_nr = SF_POLY_UNSET; - sf_ctx->arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); + memset(sf_ctx, 0, sizeof(*sf_ctx)); + sf_ctx->poly_nr = SF_POLY_UNSET; + sf_ctx->arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); } void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, MemArena *arena) { - memset(sf_ctx, 0, sizeof(*sf_ctx)); - sf_ctx->poly_nr = SF_POLY_UNSET; - sf_ctx->arena = arena; + memset(sf_ctx, 0, sizeof(*sf_ctx)); + sf_ctx->poly_nr = SF_POLY_UNSET; + sf_ctx->arena = arena; } void BLI_scanfill_end(ScanFillContext *sf_ctx) { - BLI_memarena_free(sf_ctx->arena); - sf_ctx->arena = NULL; + BLI_memarena_free(sf_ctx->arena); + sf_ctx->arena = NULL; - BLI_listbase_clear(&sf_ctx->fillvertbase); - BLI_listbase_clear(&sf_ctx->filledgebase); - BLI_listbase_clear(&sf_ctx->fillfacebase); + BLI_listbase_clear(&sf_ctx->fillvertbase); + BLI_listbase_clear(&sf_ctx->filledgebase); + BLI_listbase_clear(&sf_ctx->fillfacebase); } void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena) { - BLI_memarena_clear(arena); - BLI_assert(sf_ctx->arena == arena); + BLI_memarena_clear(arena); + BLI_assert(sf_ctx->arena == arena); - BLI_listbase_clear(&sf_ctx->fillvertbase); - BLI_listbase_clear(&sf_ctx->filledgebase); - BLI_listbase_clear(&sf_ctx->fillfacebase); + BLI_listbase_clear(&sf_ctx->fillvertbase); + BLI_listbase_clear(&sf_ctx->filledgebase); + BLI_listbase_clear(&sf_ctx->fillfacebase); } unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) { - /* - * - fill works with its own lists, so create that first (no faces!) - * - for vertices, put in ->tmp.v the old pointer - * - struct elements xs en ys are not used here: don't hide stuff in it - * - edge flag ->f becomes 2 when it's a new edge - * - mode: & 1 is check for crossings, then create edges (TO DO ) - * - returns number of triangle faces added. - */ - ListBase tempve, temped; - ScanFillVert *eve; - ScanFillEdge *eed, *eed_next; - PolyFill *pflist, *pf; - float *min_xy_p, *max_xy_p; - unsigned int totfaces = 0; /* total faces added */ - unsigned short a, c, poly = 0; - bool ok; - float mat_2d[3][3]; - - BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON); + /* + * - fill works with its own lists, so create that first (no faces!) + * - for vertices, put in ->tmp.v the old pointer + * - struct elements xs en ys are not used here: don't hide stuff in it + * - edge flag ->f becomes 2 when it's a new edge + * - mode: & 1 is check for crossings, then create edges (TO DO ) + * - returns number of triangle faces added. + */ + ListBase tempve, temped; + ScanFillVert *eve; + ScanFillEdge *eed, *eed_next; + PolyFill *pflist, *pf; + float *min_xy_p, *max_xy_p; + unsigned int totfaces = 0; /* total faces added */ + unsigned short a, c, poly = 0; + bool ok; + float mat_2d[3][3]; + + BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON); #ifdef DEBUG - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - /* these values used to be set, - * however they should always be zero'd so check instead */ - BLI_assert(eve->f == 0); - BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0); - BLI_assert(eve->edge_tot == 0); - } + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + /* these values used to be set, + * however they should always be zero'd so check instead */ + BLI_assert(eve->f == 0); + BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0); + BLI_assert(eve->edge_tot == 0); + } #endif - /* first test vertices if they are in edges */ - /* including resetting of flags */ - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - BLI_assert(sf_ctx->poly_nr != SF_POLY_UNSET || eed->poly_nr == SF_POLY_UNSET); - eed->v1->f = SF_VERT_AVAILABLE; - eed->v2->f = SF_VERT_AVAILABLE; - } - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (eve->f == SF_VERT_AVAILABLE) { - break; - } - } - - if (UNLIKELY(eve == NULL)) { - return 0; - } - else { - float n[3]; - - if (nor_proj) { - copy_v3_v3(n, nor_proj); - } - else { - /* define projection: with 'best' normal */ - /* Newell's Method */ - /* Similar code used elsewhere, but this checks for double ups - * which historically this function supports so better not change */ - - /* warning: this only gives stable direction with single polygons, - * ideally we'd calculate connectivity and each polys normal, see T41047 */ - const float *v_prev; - - zero_v3(n); - eve = sf_ctx->fillvertbase.last; - v_prev = eve->co; - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (LIKELY(!compare_v3v3(v_prev, eve->co, SF_EPSILON))) { - add_newell_cross_v3_v3v3(n, v_prev, eve->co); - v_prev = eve->co; - } - } - } - - if (UNLIKELY(normalize_v3(n) == 0.0f)) { - return 0; - } - - axis_dominant_v3_to_m3(mat_2d, n); - } - - - /* STEP 1: COUNT POLYS */ - if (sf_ctx->poly_nr != SF_POLY_UNSET) { - poly = (unsigned short)(sf_ctx->poly_nr + 1); - sf_ctx->poly_nr = SF_POLY_UNSET; - } - - if (flag & BLI_SCANFILL_CALC_POLYS && (poly == 0)) { - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - mul_v2_m3v3(eve->xy, mat_2d, eve->co); - - /* get first vertex with no poly number */ - if (eve->poly_nr == SF_POLY_UNSET) { - unsigned int toggle = 0; - /* now a sort of select connected */ - ok = true; - eve->poly_nr = poly; - - while (ok) { - - ok = false; - - toggle++; - for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; - eed; - eed = (toggle & 1) ? eed->next : eed->prev) - { - if (eed->v1->poly_nr == SF_POLY_UNSET && eed->v2->poly_nr == poly) { - eed->v1->poly_nr = poly; - eed->poly_nr = poly; - ok = true; - } - else if (eed->v2->poly_nr == SF_POLY_UNSET && eed->v1->poly_nr == poly) { - eed->v2->poly_nr = poly; - eed->poly_nr = poly; - ok = true; - } - else if (eed->poly_nr == SF_POLY_UNSET) { - if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) { - eed->poly_nr = poly; - ok = true; - } - } - } - } - - poly++; - } - } - /* printf("amount of poly's: %d\n", poly); */ - } - else if (poly) { - /* we pre-calculated poly_nr */ - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - mul_v2_m3v3(eve->xy, mat_2d, eve->co); - } - } - else { - poly = 1; - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - mul_v2_m3v3(eve->xy, mat_2d, eve->co); - eve->poly_nr = 0; - } - - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - eed->poly_nr = 0; - } - } - - /* STEP 2: remove loose edges and strings of edges */ - if (flag & BLI_SCANFILL_CALC_LOOSE) { - unsigned int toggle = 0; - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - if (eed->v1->edge_tot++ > 250) { - break; - } - if (eed->v2->edge_tot++ > 250) { - break; - } - } - if (eed) { - /* otherwise it's impossible to be sure you can clear vertices */ + /* first test vertices if they are in edges */ + /* including resetting of flags */ + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + BLI_assert(sf_ctx->poly_nr != SF_POLY_UNSET || eed->poly_nr == SF_POLY_UNSET); + eed->v1->f = SF_VERT_AVAILABLE; + eed->v2->f = SF_VERT_AVAILABLE; + } + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (eve->f == SF_VERT_AVAILABLE) { + break; + } + } + + if (UNLIKELY(eve == NULL)) { + return 0; + } + else { + float n[3]; + + if (nor_proj) { + copy_v3_v3(n, nor_proj); + } + else { + /* define projection: with 'best' normal */ + /* Newell's Method */ + /* Similar code used elsewhere, but this checks for double ups + * which historically this function supports so better not change */ + + /* warning: this only gives stable direction with single polygons, + * ideally we'd calculate connectivity and each polys normal, see T41047 */ + const float *v_prev; + + zero_v3(n); + eve = sf_ctx->fillvertbase.last; + v_prev = eve->co; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (LIKELY(!compare_v3v3(v_prev, eve->co, SF_EPSILON))) { + add_newell_cross_v3_v3v3(n, v_prev, eve->co); + v_prev = eve->co; + } + } + } + + if (UNLIKELY(normalize_v3(n) == 0.0f)) { + return 0; + } + + axis_dominant_v3_to_m3(mat_2d, n); + } + + /* STEP 1: COUNT POLYS */ + if (sf_ctx->poly_nr != SF_POLY_UNSET) { + poly = (unsigned short)(sf_ctx->poly_nr + 1); + sf_ctx->poly_nr = SF_POLY_UNSET; + } + + if (flag & BLI_SCANFILL_CALC_POLYS && (poly == 0)) { + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + mul_v2_m3v3(eve->xy, mat_2d, eve->co); + + /* get first vertex with no poly number */ + if (eve->poly_nr == SF_POLY_UNSET) { + unsigned int toggle = 0; + /* now a sort of select connected */ + ok = true; + eve->poly_nr = poly; + + while (ok) { + + ok = false; + + toggle++; + for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed; + eed = (toggle & 1) ? eed->next : eed->prev) { + if (eed->v1->poly_nr == SF_POLY_UNSET && eed->v2->poly_nr == poly) { + eed->v1->poly_nr = poly; + eed->poly_nr = poly; + ok = true; + } + else if (eed->v2->poly_nr == SF_POLY_UNSET && eed->v1->poly_nr == poly) { + eed->v2->poly_nr = poly; + eed->poly_nr = poly; + ok = true; + } + else if (eed->poly_nr == SF_POLY_UNSET) { + if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) { + eed->poly_nr = poly; + ok = true; + } + } + } + } + + poly++; + } + } + /* printf("amount of poly's: %d\n", poly); */ + } + else if (poly) { + /* we pre-calculated poly_nr */ + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + mul_v2_m3v3(eve->xy, mat_2d, eve->co); + } + } + else { + poly = 1; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + mul_v2_m3v3(eve->xy, mat_2d, eve->co); + eve->poly_nr = 0; + } + + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + eed->poly_nr = 0; + } + } + + /* STEP 2: remove loose edges and strings of edges */ + if (flag & BLI_SCANFILL_CALC_LOOSE) { + unsigned int toggle = 0; + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + if (eed->v1->edge_tot++ > 250) { + break; + } + if (eed->v2->edge_tot++ > 250) { + break; + } + } + if (eed) { + /* otherwise it's impossible to be sure you can clear vertices */ #ifdef DEBUG - printf("No vertices with 250 edges allowed!\n"); + printf("No vertices with 250 edges allowed!\n"); #endif - return 0; - } - - /* does it only for vertices with (->edge_tot == 1) */ - testvertexnearedge(sf_ctx); - - ok = true; - while (ok) { - ok = false; - - toggle++; - for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; - eed; - eed = eed_next) - { - eed_next = (toggle & 1) ? eed->next : eed->prev; - if (eed->v1->edge_tot == 1) { - eed->v2->edge_tot--; - BLI_remlink(&sf_ctx->fillvertbase, eed->v1); - BLI_remlink(&sf_ctx->filledgebase, eed); - ok = true; - } - else if (eed->v2->edge_tot == 1) { - eed->v1->edge_tot--; - BLI_remlink(&sf_ctx->fillvertbase, eed->v2); - BLI_remlink(&sf_ctx->filledgebase, eed); - ok = true; - } - } - } - if (BLI_listbase_is_empty(&sf_ctx->filledgebase)) { - /* printf("All edges removed\n"); */ - return 0; - } - } - else { - /* skip checks for loose edges */ - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - eed->v1->edge_tot++; - eed->v2->edge_tot++; - } + return 0; + } + + /* does it only for vertices with (->edge_tot == 1) */ + testvertexnearedge(sf_ctx); + + ok = true; + while (ok) { + ok = false; + + toggle++; + for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed; + eed = eed_next) { + eed_next = (toggle & 1) ? eed->next : eed->prev; + if (eed->v1->edge_tot == 1) { + eed->v2->edge_tot--; + BLI_remlink(&sf_ctx->fillvertbase, eed->v1); + BLI_remlink(&sf_ctx->filledgebase, eed); + ok = true; + } + else if (eed->v2->edge_tot == 1) { + eed->v1->edge_tot--; + BLI_remlink(&sf_ctx->fillvertbase, eed->v2); + BLI_remlink(&sf_ctx->filledgebase, eed); + ok = true; + } + } + } + if (BLI_listbase_is_empty(&sf_ctx->filledgebase)) { + /* printf("All edges removed\n"); */ + return 0; + } + } + else { + /* skip checks for loose edges */ + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + eed->v1->edge_tot++; + eed->v2->edge_tot++; + } #ifdef DEBUG - /* ensure we're right! */ - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - BLI_assert(eed->v1->edge_tot != 1); - BLI_assert(eed->v2->edge_tot != 1); - } + /* ensure we're right! */ + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + BLI_assert(eed->v1->edge_tot != 1); + BLI_assert(eed->v2->edge_tot != 1); + } #endif - } - - - /* CURRENT STATUS: - * - eve->f :1 = available in edges - * - eve->poly_nr :polynumber - * - eve->edge_tot :amount of edges connected to vertex - * - eve->tmp.v :store! original vertex number - * - * - eed->f :1 = boundary edge (optionally set by caller) - * - eed->poly_nr :poly number - */ - - - /* STEP 3: MAKE POLYFILL STRUCT */ - pflist = MEM_mallocN(sizeof(*pflist) * (size_t)poly, "edgefill"); - pf = pflist; - for (a = 0; a < poly; a++) { - pf->edges = pf->verts = 0; - pf->min_xy[0] = pf->min_xy[1] = 1.0e20f; - pf->max_xy[0] = pf->max_xy[1] = -1.0e20f; - pf->f = SF_POLY_NEW; - pf->nr = a; - pf++; - } - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - pflist[eed->poly_nr].edges++; - } - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - pflist[eve->poly_nr].verts++; - min_xy_p = pflist[eve->poly_nr].min_xy; - max_xy_p = pflist[eve->poly_nr].max_xy; - - min_xy_p[0] = (min_xy_p[0]) < (eve->xy[0]) ? (min_xy_p[0]) : (eve->xy[0]); - min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]); - max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]); - max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]); - if (eve->edge_tot > 2) { - pflist[eve->poly_nr].f = SF_POLY_VALID; - } - } - - /* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM - * ( bounds just to divide it in pieces for optimization, - * the edgefill itself has good auto-hole detection) - * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */ - - if ((flag & BLI_SCANFILL_CALC_HOLES) && (poly > 1)) { - unsigned short *polycache, *pc; - - /* so, sort first */ - qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly); + } + + /* CURRENT STATUS: + * - eve->f :1 = available in edges + * - eve->poly_nr :polynumber + * - eve->edge_tot :amount of edges connected to vertex + * - eve->tmp.v :store! original vertex number + * + * - eed->f :1 = boundary edge (optionally set by caller) + * - eed->poly_nr :poly number + */ + + /* STEP 3: MAKE POLYFILL STRUCT */ + pflist = MEM_mallocN(sizeof(*pflist) * (size_t)poly, "edgefill"); + pf = pflist; + for (a = 0; a < poly; a++) { + pf->edges = pf->verts = 0; + pf->min_xy[0] = pf->min_xy[1] = 1.0e20f; + pf->max_xy[0] = pf->max_xy[1] = -1.0e20f; + pf->f = SF_POLY_NEW; + pf->nr = a; + pf++; + } + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + pflist[eed->poly_nr].edges++; + } + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + pflist[eve->poly_nr].verts++; + min_xy_p = pflist[eve->poly_nr].min_xy; + max_xy_p = pflist[eve->poly_nr].max_xy; + + min_xy_p[0] = (min_xy_p[0]) < (eve->xy[0]) ? (min_xy_p[0]) : (eve->xy[0]); + min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]); + max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]); + max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]); + if (eve->edge_tot > 2) { + pflist[eve->poly_nr].f = SF_POLY_VALID; + } + } + + /* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM + * ( bounds just to divide it in pieces for optimization, + * the edgefill itself has good auto-hole detection) + * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */ + + if ((flag & BLI_SCANFILL_CALC_HOLES) && (poly > 1)) { + unsigned short *polycache, *pc; + + /* so, sort first */ + qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly); #if 0 - pf = pflist; - for (a = 0; a < poly; a++) { - printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f); - PRINT2(f, f, pf->min[0], pf->min[1]); - pf++; - } + pf = pflist; + for (a = 0; a < poly; a++) { + printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f); + PRINT2(f, f, pf->min[0], pf->min[1]); + pf++; + } #endif - polycache = pc = MEM_callocN(sizeof(*polycache) * (size_t)poly, "polycache"); - pf = pflist; - for (a = 0; a < poly; a++, pf++) { - for (c = (unsigned short)(a + 1); c < poly; c++) { - - /* if 'a' inside 'c': join (bbox too) - * Careful: 'a' can also be inside another poly. - */ - if (boundisect(pf, pflist + c)) { - *pc = c; - pc++; - } - /* only for optimize! */ - /* else if (pf->max_xy[0] < (pflist+c)->min[cox]) break; */ - - } - while (pc != polycache) { - pc--; - mergepolysSimp(sf_ctx, pf, pflist + *pc); - } - } - MEM_freeN(polycache); - } + polycache = pc = MEM_callocN(sizeof(*polycache) * (size_t)poly, "polycache"); + pf = pflist; + for (a = 0; a < poly; a++, pf++) { + for (c = (unsigned short)(a + 1); c < poly; c++) { + + /* if 'a' inside 'c': join (bbox too) + * Careful: 'a' can also be inside another poly. + */ + if (boundisect(pf, pflist + c)) { + *pc = c; + pc++; + } + /* only for optimize! */ + /* else if (pf->max_xy[0] < (pflist+c)->min[cox]) break; */ + } + while (pc != polycache) { + pc--; + mergepolysSimp(sf_ctx, pf, pflist + *pc); + } + } + MEM_freeN(polycache); + } #if 0 - printf("after merge\n"); - pf = pflist; - for (a = 0; a < poly; a++) { - printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f); - pf++; - } + printf("after merge\n"); + pf = pflist; + for (a = 0; a < poly; a++) { + printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f); + pf++; + } #endif - /* STEP 5: MAKE TRIANGLES */ + /* STEP 5: MAKE TRIANGLES */ - tempve.first = sf_ctx->fillvertbase.first; - tempve.last = sf_ctx->fillvertbase.last; - temped.first = sf_ctx->filledgebase.first; - temped.last = sf_ctx->filledgebase.last; - BLI_listbase_clear(&sf_ctx->fillvertbase); - BLI_listbase_clear(&sf_ctx->filledgebase); + tempve.first = sf_ctx->fillvertbase.first; + tempve.last = sf_ctx->fillvertbase.last; + temped.first = sf_ctx->filledgebase.first; + temped.last = sf_ctx->filledgebase.last; + BLI_listbase_clear(&sf_ctx->fillvertbase); + BLI_listbase_clear(&sf_ctx->filledgebase); - pf = pflist; - for (a = 0; a < poly; a++) { - if (pf->edges > 1) { - splitlist(sf_ctx, &tempve, &temped, pf->nr); - totfaces += scanfill(sf_ctx, pf, flag); - } - pf++; - } - BLI_movelisttolist(&sf_ctx->fillvertbase, &tempve); - BLI_movelisttolist(&sf_ctx->filledgebase, &temped); + pf = pflist; + for (a = 0; a < poly; a++) { + if (pf->edges > 1) { + splitlist(sf_ctx, &tempve, &temped, pf->nr); + totfaces += scanfill(sf_ctx, pf, flag); + } + pf++; + } + BLI_movelisttolist(&sf_ctx->fillvertbase, &tempve); + BLI_movelisttolist(&sf_ctx->filledgebase, &temped); - /* FREE */ + /* FREE */ - MEM_freeN(pflist); + MEM_freeN(pflist); - return totfaces; + return totfaces; } unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) { - return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); + return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); } diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index f0107908787..0c4151e6575 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -31,348 +31,345 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" -#include "BLI_scanfill.h" /* own include */ +#include "BLI_scanfill.h" /* own include */ #include "BLI_strict_flags.h" typedef struct PolyInfo { - ScanFillEdge *edge_first, *edge_last; - ScanFillVert *vert_outer; + ScanFillEdge *edge_first, *edge_last; + ScanFillVert *vert_outer; } PolyInfo; typedef struct ScanFillIsect { - struct ScanFillIsect *next, *prev; - float co[3]; + struct ScanFillIsect *next, *prev; + float co[3]; - /* newly created vertex */ - ScanFillVert *v; + /* newly created vertex */ + ScanFillVert *v; } ScanFillIsect; - #define V_ISISECT 1 #define E_ISISECT 1 #define E_ISDELETE 2 - -#define EFLAG_SET(eed, val) { CHECK_TYPE(eed, ScanFillEdge *); \ - (eed)->user_flag = (eed)->user_flag | (unsigned int)val; } (void)0 +#define EFLAG_SET(eed, val) \ + { \ + CHECK_TYPE(eed, ScanFillEdge *); \ + (eed)->user_flag = (eed)->user_flag | (unsigned int)val; \ + } \ + (void)0 #if 0 -#define EFLAG_CLEAR(eed, val) { CHECK_TYPE(eed, ScanFillEdge *); \ - (eed)->user_flag = (eed)->user_flag & ~(unsigned int)val; } (void)0 +# define EFLAG_CLEAR(eed, val) \ + { \ + CHECK_TYPE(eed, ScanFillEdge *); \ + (eed)->user_flag = (eed)->user_flag & ~(unsigned int)val; \ + } \ + (void)0 #endif -#define VFLAG_SET(eve, val) { CHECK_TYPE(eve, ScanFillVert *); \ - (eve)->user_flag = (eve)->user_flag | (unsigned int)val; } (void)0 +#define VFLAG_SET(eve, val) \ + { \ + CHECK_TYPE(eve, ScanFillVert *); \ + (eve)->user_flag = (eve)->user_flag | (unsigned int)val; \ + } \ + (void)0 #if 0 -#define VFLAG_CLEAR(eve, val) { CHECK_TYPE(eve, ScanFillVert *); \ - (eve)->user_flags = (eve)->user_flag & ~(unsigned int)val; } (void)0 +# define VFLAG_CLEAR(eve, val) \ + { \ + CHECK_TYPE(eve, ScanFillVert *); \ + (eve)->user_flags = (eve)->user_flag & ~(unsigned int)val; \ + } \ + (void)0 #endif - #if 0 void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx) { - FILE *f = fopen("test.obj", "w"); - unsigned int i = 1; - - ScanFillVert *eve; - ScanFillEdge *eed; - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next, i++) { - fprintf(f, "v %f %f %f\n", UNPACK3(eve->co)); - eve->keyindex = i; - } - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - fprintf(f, "f %d %d\n", eed->v1->keyindex, eed->v2->keyindex); - } - fclose(f); + FILE *f = fopen("test.obj", "w"); + unsigned int i = 1; + + ScanFillVert *eve; + ScanFillEdge *eed; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next, i++) { + fprintf(f, "v %f %f %f\n", UNPACK3(eve->co)); + eve->keyindex = i; + } + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + fprintf(f, "f %d %d\n", eed->v1->keyindex, eed->v2->keyindex); + } + fclose(f); } #endif static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed) { - ListBase *e_ls; - void **val_p; + ListBase *e_ls; + void **val_p; - if (!BLI_ghash_ensure_p(isect_hash, eed, &val_p)) { - *val_p = MEM_callocN(sizeof(ListBase), __func__); - } - e_ls = *val_p; + if (!BLI_ghash_ensure_p(isect_hash, eed, &val_p)) { + *val_p = MEM_callocN(sizeof(ListBase), __func__); + } + e_ls = *val_p; - return e_ls; + return e_ls; } static ListBase *edge_isect_ls_add(GHash *isect_hash, ScanFillEdge *eed, ScanFillIsect *isect) { - ListBase *e_ls; - LinkData *isect_link; - e_ls = edge_isect_ls_ensure(isect_hash, eed); - isect_link = MEM_callocN(sizeof(*isect_link), __func__); - isect_link->data = isect; - EFLAG_SET(eed, E_ISISECT); - BLI_addtail(e_ls, isect_link); - return e_ls; + ListBase *e_ls; + LinkData *isect_link; + e_ls = edge_isect_ls_ensure(isect_hash, eed); + isect_link = MEM_callocN(sizeof(*isect_link), __func__); + isect_link->data = isect; + EFLAG_SET(eed, E_ISISECT); + BLI_addtail(e_ls, isect_link); + return e_ls; } static int edge_isect_ls_sort_cb(void *thunk, const void *def_a_ptr, const void *def_b_ptr) { - const float *co = thunk; - - const ScanFillIsect *i_a = ((const LinkData *)def_a_ptr)->data; - const ScanFillIsect *i_b = ((const LinkData *)def_b_ptr)->data; - const float a = len_squared_v2v2(co, i_a->co); - const float b = len_squared_v2v2(co, i_b->co); - - if (a > b) { - return -1; - } - else { - return (a < b); - } + const float *co = thunk; + + const ScanFillIsect *i_a = ((const LinkData *)def_a_ptr)->data; + const ScanFillIsect *i_b = ((const LinkData *)def_b_ptr)->data; + const float a = len_squared_v2v2(co, i_a->co); + const float b = len_squared_v2v2(co, i_b->co); + + if (a > b) { + return -1; + } + else { + return (a < b); + } } static ScanFillEdge *edge_step(PolyInfo *poly_info, const unsigned short poly_nr, - ScanFillVert *v_prev, ScanFillVert *v_curr, + ScanFillVert *v_prev, + ScanFillVert *v_curr, ScanFillEdge *e_curr) { - ScanFillEdge *eed; - - BLI_assert(ELEM(v_prev, e_curr->v1, e_curr->v2)); - BLI_assert(ELEM(v_curr, e_curr->v1, e_curr->v2)); - - eed = (e_curr->next && e_curr != poly_info[poly_nr].edge_last) ? e_curr->next : poly_info[poly_nr].edge_first; - if ((v_curr == eed->v1 || v_curr == eed->v2) == true && - (v_prev == eed->v1 || v_prev == eed->v2) == false) - { - return eed; - } - - eed = (e_curr->prev && e_curr != poly_info[poly_nr].edge_first) ? e_curr->prev : poly_info[poly_nr].edge_last; - if ((v_curr == eed->v1 || v_curr == eed->v2) == true && - (v_prev == eed->v1 || v_prev == eed->v2) == false) - { - return eed; - } - - BLI_assert(0); - return NULL; + ScanFillEdge *eed; + + BLI_assert(ELEM(v_prev, e_curr->v1, e_curr->v2)); + BLI_assert(ELEM(v_curr, e_curr->v1, e_curr->v2)); + + eed = (e_curr->next && e_curr != poly_info[poly_nr].edge_last) ? e_curr->next : + poly_info[poly_nr].edge_first; + if ((v_curr == eed->v1 || v_curr == eed->v2) == true && + (v_prev == eed->v1 || v_prev == eed->v2) == false) { + return eed; + } + + eed = (e_curr->prev && e_curr != poly_info[poly_nr].edge_first) ? e_curr->prev : + poly_info[poly_nr].edge_last; + if ((v_curr == eed->v1 || v_curr == eed->v2) == true && + (v_prev == eed->v1 || v_prev == eed->v2) == false) { + return eed; + } + + BLI_assert(0); + return NULL; } -static bool scanfill_preprocess_self_isect( - ScanFillContext *sf_ctx, - PolyInfo *poly_info, - const unsigned short poly_nr, - ListBase *filledgebase) +static bool scanfill_preprocess_self_isect(ScanFillContext *sf_ctx, + PolyInfo *poly_info, + const unsigned short poly_nr, + ListBase *filledgebase) { - PolyInfo *pi = &poly_info[poly_nr]; - GHash *isect_hash = NULL; - ListBase isect_lb = {NULL}; - - /* warning, O(n2) check here, should use spatial lookup */ - { - ScanFillEdge *eed; - - for (eed = pi->edge_first; - eed; - eed = (eed == pi->edge_last) ? NULL : eed->next) - { - ScanFillEdge *eed_other; - - for (eed_other = eed->next; - eed_other; - eed_other = (eed_other == pi->edge_last) ? NULL : eed_other->next) - { - if (!ELEM(eed->v1, eed_other->v1, eed_other->v2) && - !ELEM(eed->v2, eed_other->v1, eed_other->v2) && - (eed != eed_other)) - { - /* check isect */ - float pt[2]; - BLI_assert(eed != eed_other); - - if (isect_seg_seg_v2_point(eed->v1->co, eed->v2->co, - eed_other->v1->co, eed_other->v2->co, - pt) == 1) - { - ScanFillIsect *isect; - - if (UNLIKELY(isect_hash == NULL)) { - isect_hash = BLI_ghash_ptr_new(__func__); - } - - isect = MEM_mallocN(sizeof(ScanFillIsect), __func__); - - BLI_addtail(&isect_lb, isect); - - copy_v2_v2(isect->co, pt); - isect->co[2] = eed->v1->co[2]; - isect->v = BLI_scanfill_vert_add(sf_ctx, isect->co); - - /* NOTE: vert may belong to 2 polys now */ - isect->v->poly_nr = eed->v1->poly_nr; - - VFLAG_SET(isect->v, V_ISISECT); - edge_isect_ls_add(isect_hash, eed, isect); - edge_isect_ls_add(isect_hash, eed_other, isect); - } - } - } - } - } - - if (isect_hash == NULL) { - return false; - } - - /* now subdiv the edges */ - { - ScanFillEdge *eed; - - for (eed = pi->edge_first; - eed; - eed = (eed == pi->edge_last) ? NULL : eed->next) - { - if (eed->user_flag & E_ISISECT) { - ListBase *e_ls = BLI_ghash_lookup(isect_hash, eed); - - LinkData *isect_link; - - if (UNLIKELY(e_ls == NULL)) { - /* only happens in very rare cases (entirely overlapping splines). - * in this case we can't do much useful. but at least don't crash */ - continue; - } - - /* maintain coorect terminating edge */ - if (pi->edge_last == eed) { - pi->edge_last = NULL; - } - - if (BLI_listbase_is_single(e_ls) == false) { - BLI_listbase_sort_r(e_ls, edge_isect_ls_sort_cb, eed->v2->co); - } - - /* move original edge to filledgebase and add replacement - * (which gets subdivided next) */ - { - ScanFillEdge *eed_tmp; - eed_tmp = BLI_scanfill_edge_add(sf_ctx, eed->v1, eed->v2); - BLI_remlink(&sf_ctx->filledgebase, eed_tmp); - BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_tmp); - BLI_remlink(&sf_ctx->filledgebase, eed); - BLI_addtail(filledgebase, eed); - if (pi->edge_first == eed) { - pi->edge_first = eed_tmp; - } - eed = eed_tmp; - } - - for (isect_link = e_ls->first; isect_link; isect_link = isect_link->next) { - ScanFillIsect *isect = isect_link->data; - ScanFillEdge *eed_subd; - - eed_subd = BLI_scanfill_edge_add(sf_ctx, isect->v, eed->v2); - eed_subd->poly_nr = poly_nr; - eed->v2 = isect->v; - - BLI_remlink(&sf_ctx->filledgebase, eed_subd); - BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_subd); - - /* step to the next edge and continue dividing */ - eed = eed_subd; - } - - BLI_freelistN(e_ls); - MEM_freeN(e_ls); - - if (pi->edge_last == NULL) { - pi->edge_last = eed; - } - } - } - } - - BLI_freelistN(&isect_lb); - BLI_ghash_free(isect_hash, NULL, NULL); - - { - ScanFillEdge *e_init; - ScanFillEdge *e_curr; - ScanFillEdge *e_next; - - ScanFillVert *v_prev; - ScanFillVert *v_curr; - - bool inside = false; - - /* first vert */ + PolyInfo *pi = &poly_info[poly_nr]; + GHash *isect_hash = NULL; + ListBase isect_lb = {NULL}; + + /* warning, O(n2) check here, should use spatial lookup */ + { + ScanFillEdge *eed; + + for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { + ScanFillEdge *eed_other; + + for (eed_other = eed->next; eed_other; + eed_other = (eed_other == pi->edge_last) ? NULL : eed_other->next) { + if (!ELEM(eed->v1, eed_other->v1, eed_other->v2) && + !ELEM(eed->v2, eed_other->v1, eed_other->v2) && (eed != eed_other)) { + /* check isect */ + float pt[2]; + BLI_assert(eed != eed_other); + + if (isect_seg_seg_v2_point( + eed->v1->co, eed->v2->co, eed_other->v1->co, eed_other->v2->co, pt) == 1) { + ScanFillIsect *isect; + + if (UNLIKELY(isect_hash == NULL)) { + isect_hash = BLI_ghash_ptr_new(__func__); + } + + isect = MEM_mallocN(sizeof(ScanFillIsect), __func__); + + BLI_addtail(&isect_lb, isect); + + copy_v2_v2(isect->co, pt); + isect->co[2] = eed->v1->co[2]; + isect->v = BLI_scanfill_vert_add(sf_ctx, isect->co); + + /* NOTE: vert may belong to 2 polys now */ + isect->v->poly_nr = eed->v1->poly_nr; + + VFLAG_SET(isect->v, V_ISISECT); + edge_isect_ls_add(isect_hash, eed, isect); + edge_isect_ls_add(isect_hash, eed_other, isect); + } + } + } + } + } + + if (isect_hash == NULL) { + return false; + } + + /* now subdiv the edges */ + { + ScanFillEdge *eed; + + for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { + if (eed->user_flag & E_ISISECT) { + ListBase *e_ls = BLI_ghash_lookup(isect_hash, eed); + + LinkData *isect_link; + + if (UNLIKELY(e_ls == NULL)) { + /* only happens in very rare cases (entirely overlapping splines). + * in this case we can't do much useful. but at least don't crash */ + continue; + } + + /* maintain coorect terminating edge */ + if (pi->edge_last == eed) { + pi->edge_last = NULL; + } + + if (BLI_listbase_is_single(e_ls) == false) { + BLI_listbase_sort_r(e_ls, edge_isect_ls_sort_cb, eed->v2->co); + } + + /* move original edge to filledgebase and add replacement + * (which gets subdivided next) */ + { + ScanFillEdge *eed_tmp; + eed_tmp = BLI_scanfill_edge_add(sf_ctx, eed->v1, eed->v2); + BLI_remlink(&sf_ctx->filledgebase, eed_tmp); + BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_tmp); + BLI_remlink(&sf_ctx->filledgebase, eed); + BLI_addtail(filledgebase, eed); + if (pi->edge_first == eed) { + pi->edge_first = eed_tmp; + } + eed = eed_tmp; + } + + for (isect_link = e_ls->first; isect_link; isect_link = isect_link->next) { + ScanFillIsect *isect = isect_link->data; + ScanFillEdge *eed_subd; + + eed_subd = BLI_scanfill_edge_add(sf_ctx, isect->v, eed->v2); + eed_subd->poly_nr = poly_nr; + eed->v2 = isect->v; + + BLI_remlink(&sf_ctx->filledgebase, eed_subd); + BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_subd); + + /* step to the next edge and continue dividing */ + eed = eed_subd; + } + + BLI_freelistN(e_ls); + MEM_freeN(e_ls); + + if (pi->edge_last == NULL) { + pi->edge_last = eed; + } + } + } + } + + BLI_freelistN(&isect_lb); + BLI_ghash_free(isect_hash, NULL, NULL); + + { + ScanFillEdge *e_init; + ScanFillEdge *e_curr; + ScanFillEdge *e_next; + + ScanFillVert *v_prev; + ScanFillVert *v_curr; + + bool inside = false; + + /* first vert */ #if 0 - e_init = pi->edge_last; - e_curr = e_init; - e_next = pi->edge_first; + e_init = pi->edge_last; + e_curr = e_init; + e_next = pi->edge_first; - v_prev = e_curr->v1; - v_curr = e_curr->v2; + v_prev = e_curr->v1; + v_curr = e_curr->v2; #else - /* find outside vertex */ - { - ScanFillEdge *eed; - ScanFillEdge *eed_prev; - float min_x = FLT_MAX; - - e_curr = pi->edge_last; - e_next = pi->edge_first; - - eed_prev = pi->edge_last; - for (eed = pi->edge_first; - eed; - eed = (eed == pi->edge_last) ? NULL : eed->next) - { - if (eed->v2->co[0] < min_x) { - min_x = eed->v2->co[0]; - e_curr = eed_prev; - e_next = eed; - - } - eed_prev = eed; - } - - e_init = e_curr; - v_prev = e_curr->v1; - v_curr = e_curr->v2; - } + /* find outside vertex */ + { + ScanFillEdge *eed; + ScanFillEdge *eed_prev; + float min_x = FLT_MAX; + + e_curr = pi->edge_last; + e_next = pi->edge_first; + + eed_prev = pi->edge_last; + for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { + if (eed->v2->co[0] < min_x) { + min_x = eed->v2->co[0]; + e_curr = eed_prev; + e_next = eed; + } + eed_prev = eed; + } + + e_init = e_curr; + v_prev = e_curr->v1; + v_curr = e_curr->v2; + } #endif - BLI_assert(e_curr->poly_nr == poly_nr); - BLI_assert(pi->edge_last->poly_nr == poly_nr); + BLI_assert(e_curr->poly_nr == poly_nr); + BLI_assert(pi->edge_last->poly_nr == poly_nr); - do { - ScanFillVert *v_next; + do { + ScanFillVert *v_next; - v_next = (e_next->v1 == v_curr) ? e_next->v2 : e_next->v1; - BLI_assert(ELEM(v_curr, e_next->v1, e_next->v2)); + v_next = (e_next->v1 == v_curr) ? e_next->v2 : e_next->v1; + BLI_assert(ELEM(v_curr, e_next->v1, e_next->v2)); - /* track intersections */ - if (inside) { - EFLAG_SET(e_next, E_ISDELETE); - } - if (v_next->user_flag & V_ISISECT) { - inside = !inside; - } - /* now step... */ + /* track intersections */ + if (inside) { + EFLAG_SET(e_next, E_ISDELETE); + } + if (v_next->user_flag & V_ISISECT) { + inside = !inside; + } + /* now step... */ - v_prev = v_curr; - v_curr = v_next; - e_curr = e_next; + v_prev = v_curr; + v_curr = v_next; + e_curr = e_next; - e_next = edge_step(poly_info, poly_nr, v_prev, v_curr, e_curr); + e_next = edge_step(poly_info, poly_nr, v_prev, v_curr, e_curr); - } while (e_curr != e_init); - } + } while (e_curr != e_init); + } - return true; + return true; } /** @@ -380,122 +377,120 @@ static bool scanfill_preprocess_self_isect( * * \return false if no changes were made. */ -bool BLI_scanfill_calc_self_isect( - ScanFillContext *sf_ctx, - ListBase *remvertbase, - ListBase *remedgebase) +bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, + ListBase *remvertbase, + ListBase *remedgebase) { - const unsigned int poly_tot = (unsigned int)sf_ctx->poly_nr + 1; - unsigned int eed_index = 0; - int totvert_new = 0; - bool changed = false; - - PolyInfo *poly_info; - - if (UNLIKELY(sf_ctx->poly_nr == SF_POLY_UNSET)) { - return false; - } - - poly_info = MEM_callocN(sizeof(*poly_info) * poly_tot, __func__); - - /* get the polygon span */ - if (sf_ctx->poly_nr == 0) { - poly_info->edge_first = sf_ctx->filledgebase.first; - poly_info->edge_last = sf_ctx->filledgebase.last; - } - else { - unsigned short poly_nr; - ScanFillEdge *eed; - - poly_nr = 0; - - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next, eed_index++) { - - BLI_assert(eed->poly_nr == eed->v1->poly_nr); - BLI_assert(eed->poly_nr == eed->v2->poly_nr); - - if ((poly_info[poly_nr].edge_last != NULL) && - (poly_info[poly_nr].edge_last->poly_nr != eed->poly_nr)) - { - poly_nr++; - } - - if (poly_info[poly_nr].edge_first == NULL) { - poly_info[poly_nr].edge_first = eed; - poly_info[poly_nr].edge_last = eed; - } - else if (poly_info[poly_nr].edge_last->poly_nr == eed->poly_nr) { - poly_info[poly_nr].edge_last = eed; - } - - BLI_assert(poly_info[poly_nr].edge_first->poly_nr == poly_info[poly_nr].edge_last->poly_nr); - } - } - - /* self-intersect each polygon */ - { - unsigned short poly_nr; - for (poly_nr = 0; poly_nr < poly_tot; poly_nr++) { - changed |= scanfill_preprocess_self_isect(sf_ctx, poly_info, poly_nr, remedgebase); - } - } - - MEM_freeN(poly_info); - - if (changed == false) { - return false; - } - - /* move free edges into own list */ - { - ScanFillEdge *eed; - ScanFillEdge *eed_next; - for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { - eed_next = eed->next; - if (eed->user_flag & E_ISDELETE) { - BLI_remlink(&sf_ctx->filledgebase, eed); - BLI_addtail(remedgebase, eed); - } - } - } - - /* move free vertices into own list */ - { - ScanFillEdge *eed; - ScanFillVert *eve; - ScanFillVert *eve_next; - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - eve->user_flag = 0; - eve->poly_nr = SF_POLY_UNSET; - } - for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { - eed->v1->user_flag = 1; - eed->v2->user_flag = 1; - eed->poly_nr = SF_POLY_UNSET; - } - - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve_next) { - eve_next = eve->next; - if (eve->user_flag != 1) { - BLI_remlink(&sf_ctx->fillvertbase, eve); - BLI_addtail(remvertbase, eve); - totvert_new--; - } - else { - eve->user_flag = 0; - } - } - } - - /* polygon id's are no longer meaningful, - * when removing self intersections we may have created new isolated polys */ - sf_ctx->poly_nr = SF_POLY_UNSET; + const unsigned int poly_tot = (unsigned int)sf_ctx->poly_nr + 1; + unsigned int eed_index = 0; + int totvert_new = 0; + bool changed = false; + + PolyInfo *poly_info; + + if (UNLIKELY(sf_ctx->poly_nr == SF_POLY_UNSET)) { + return false; + } + + poly_info = MEM_callocN(sizeof(*poly_info) * poly_tot, __func__); + + /* get the polygon span */ + if (sf_ctx->poly_nr == 0) { + poly_info->edge_first = sf_ctx->filledgebase.first; + poly_info->edge_last = sf_ctx->filledgebase.last; + } + else { + unsigned short poly_nr; + ScanFillEdge *eed; + + poly_nr = 0; + + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next, eed_index++) { + + BLI_assert(eed->poly_nr == eed->v1->poly_nr); + BLI_assert(eed->poly_nr == eed->v2->poly_nr); + + if ((poly_info[poly_nr].edge_last != NULL) && + (poly_info[poly_nr].edge_last->poly_nr != eed->poly_nr)) { + poly_nr++; + } + + if (poly_info[poly_nr].edge_first == NULL) { + poly_info[poly_nr].edge_first = eed; + poly_info[poly_nr].edge_last = eed; + } + else if (poly_info[poly_nr].edge_last->poly_nr == eed->poly_nr) { + poly_info[poly_nr].edge_last = eed; + } + + BLI_assert(poly_info[poly_nr].edge_first->poly_nr == poly_info[poly_nr].edge_last->poly_nr); + } + } + + /* self-intersect each polygon */ + { + unsigned short poly_nr; + for (poly_nr = 0; poly_nr < poly_tot; poly_nr++) { + changed |= scanfill_preprocess_self_isect(sf_ctx, poly_info, poly_nr, remedgebase); + } + } + + MEM_freeN(poly_info); + + if (changed == false) { + return false; + } + + /* move free edges into own list */ + { + ScanFillEdge *eed; + ScanFillEdge *eed_next; + for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) { + eed_next = eed->next; + if (eed->user_flag & E_ISDELETE) { + BLI_remlink(&sf_ctx->filledgebase, eed); + BLI_addtail(remedgebase, eed); + } + } + } + + /* move free vertices into own list */ + { + ScanFillEdge *eed; + ScanFillVert *eve; + ScanFillVert *eve_next; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + eve->user_flag = 0; + eve->poly_nr = SF_POLY_UNSET; + } + for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { + eed->v1->user_flag = 1; + eed->v2->user_flag = 1; + eed->poly_nr = SF_POLY_UNSET; + } + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve_next) { + eve_next = eve->next; + if (eve->user_flag != 1) { + BLI_remlink(&sf_ctx->fillvertbase, eve); + BLI_addtail(remvertbase, eve); + totvert_new--; + } + else { + eve->user_flag = 0; + } + } + } + + /* polygon id's are no longer meaningful, + * when removing self intersections we may have created new isolated polys */ + sf_ctx->poly_nr = SF_POLY_UNSET; #if 0 - BLI_scanfill_view3d_dump(sf_ctx); - BLI_scanfill_obj_dump(sf_ctx); + BLI_scanfill_view3d_dump(sf_ctx); + BLI_scanfill_obj_dump(sf_ctx); #endif - return changed; + return changed; } diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 7da5ff114be..4060ad15fe3 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -55,17 +55,15 @@ #include "BLI_strict_flags.h" -#define SMHASH_KEY_UNUSED ((uintptr_t)(UINTPTR_MAX - 0)) -#define SMHASH_CELL_FREE ((void *) (UINTPTR_MAX - 1)) -#define SMHASH_CELL_UNUSED ((void *) (UINTPTR_MAX - 2)) +#define SMHASH_KEY_UNUSED ((uintptr_t)(UINTPTR_MAX - 0)) +#define SMHASH_CELL_FREE ((void *)(UINTPTR_MAX - 1)) +#define SMHASH_CELL_UNUSED ((void *)(UINTPTR_MAX - 2)) /* typically this re-assigns 'h' */ -#define SMHASH_NEXT(h, hoff) ( \ - CHECK_TYPE_INLINE(&(h), uint *), \ - CHECK_TYPE_INLINE(&(hoff), uint *), \ - ((h) + (((hoff) = ((hoff) * 2) + 1), (hoff))) \ - ) - +#define SMHASH_NEXT(h, hoff) \ + (CHECK_TYPE_INLINE(&(h), uint *), \ + CHECK_TYPE_INLINE(&(hoff), uint *), \ + ((h) + (((hoff) = ((hoff)*2) + 1), (hoff)))) /* nothing uses BLI_smallhash_remove yet */ // #define USE_REMOVE @@ -73,9 +71,9 @@ BLI_INLINE bool smallhash_val_is_used(const void *val) { #ifdef USE_REMOVE - return !ELEM(val, SMHASH_CELL_FREE, SMHASH_CELL_UNUSED); + return !ELEM(val, SMHASH_CELL_FREE, SMHASH_CELL_UNUSED); #else - return (val != SMHASH_CELL_FREE); + return (val != SMHASH_CELL_FREE); #endif } @@ -84,7 +82,7 @@ extern const uint BLI_ghash_hash_sizes[]; BLI_INLINE uint smallhash_key(const uintptr_t key) { - return (uint)key; + return (uint)key; } /** @@ -92,18 +90,18 @@ BLI_INLINE uint smallhash_key(const uintptr_t key) */ BLI_INLINE bool smallhash_test_expand_buckets(const uint nentries, const uint nbuckets) { - /* (approx * 1.5) */ - return (nentries + (nentries >> 1)) > nbuckets; + /* (approx * 1.5) */ + return (nentries + (nentries >> 1)) > nbuckets; } BLI_INLINE void smallhash_init_empty(SmallHash *sh) { - uint i; + uint i; - for (i = 0; i < sh->nbuckets; i++) { - sh->buckets[i].key = SMHASH_KEY_UNUSED; - sh->buckets[i].val = SMHASH_CELL_FREE; - } + for (i = 0; i < sh->nbuckets; i++) { + sh->buckets[i].key = SMHASH_KEY_UNUSED; + sh->buckets[i].val = SMHASH_CELL_FREE; + } } /** @@ -111,137 +109,132 @@ BLI_INLINE void smallhash_init_empty(SmallHash *sh) */ BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const uint nentries_reserve) { - while (smallhash_test_expand_buckets(nentries_reserve, sh->nbuckets)) { - sh->nbuckets = hashsizes[++sh->cursize]; - } + while (smallhash_test_expand_buckets(nentries_reserve, sh->nbuckets)) { + sh->nbuckets = hashsizes[++sh->cursize]; + } } BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t key) { - SmallHashEntry *e; - uint h = smallhash_key(key); - uint hoff = 1; - - BLI_assert(key != SMHASH_KEY_UNUSED); - - /* note: there are always more buckets than entries, - * so we know there will always be a free bucket if the key isn't found. */ - for (e = &sh->buckets[h % sh->nbuckets]; - e->val != SMHASH_CELL_FREE; - h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) - { - if (e->key == key) { - /* should never happen because unused keys are zero'd */ - BLI_assert(e->val != SMHASH_CELL_UNUSED); - return e; - } - } - - return NULL; + SmallHashEntry *e; + uint h = smallhash_key(key); + uint hoff = 1; + + BLI_assert(key != SMHASH_KEY_UNUSED); + + /* note: there are always more buckets than entries, + * so we know there will always be a free bucket if the key isn't found. */ + for (e = &sh->buckets[h % sh->nbuckets]; e->val != SMHASH_CELL_FREE; + h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) { + if (e->key == key) { + /* should never happen because unused keys are zero'd */ + BLI_assert(e->val != SMHASH_CELL_UNUSED); + return e; + } + } + + return NULL; } BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key) { - SmallHashEntry *e; - uint h = smallhash_key(key); - uint hoff = 1; - - for (e = &sh->buckets[h % sh->nbuckets]; - smallhash_val_is_used(e->val); - h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) - { - /* pass */ - } - - return e; + SmallHashEntry *e; + uint h = smallhash_key(key); + uint hoff = 1; + + for (e = &sh->buckets[h % sh->nbuckets]; smallhash_val_is_used(e->val); + h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) { + /* pass */ + } + + return e; } BLI_INLINE void smallhash_resize_buckets(SmallHash *sh, const uint nbuckets) { - SmallHashEntry *buckets_old = sh->buckets; - const uint nbuckets_old = sh->nbuckets; - const bool was_alloc = (buckets_old != sh->buckets_stack); - uint i = 0; - - BLI_assert(sh->nbuckets != nbuckets); - if (nbuckets <= SMSTACKSIZE) { - const size_t size = sizeof(*buckets_old) * nbuckets_old; - buckets_old = alloca(size); - memcpy(buckets_old, sh->buckets, size); - - sh->buckets = sh->buckets_stack; - } - else { - sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * nbuckets, __func__); - } - - sh->nbuckets = nbuckets; - - smallhash_init_empty(sh); - - for (i = 0; i < nbuckets_old; i++) { - if (smallhash_val_is_used(buckets_old[i].val)) { - SmallHashEntry *e = smallhash_lookup_first_free(sh, buckets_old[i].key); - e->key = buckets_old[i].key; - e->val = buckets_old[i].val; - } - } - - if (was_alloc) { - MEM_freeN(buckets_old); - } + SmallHashEntry *buckets_old = sh->buckets; + const uint nbuckets_old = sh->nbuckets; + const bool was_alloc = (buckets_old != sh->buckets_stack); + uint i = 0; + + BLI_assert(sh->nbuckets != nbuckets); + if (nbuckets <= SMSTACKSIZE) { + const size_t size = sizeof(*buckets_old) * nbuckets_old; + buckets_old = alloca(size); + memcpy(buckets_old, sh->buckets, size); + + sh->buckets = sh->buckets_stack; + } + else { + sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * nbuckets, __func__); + } + + sh->nbuckets = nbuckets; + + smallhash_init_empty(sh); + + for (i = 0; i < nbuckets_old; i++) { + if (smallhash_val_is_used(buckets_old[i].val)) { + SmallHashEntry *e = smallhash_lookup_first_free(sh, buckets_old[i].key); + e->key = buckets_old[i].key; + e->val = buckets_old[i].val; + } + } + + if (was_alloc) { + MEM_freeN(buckets_old); + } } -void BLI_smallhash_init_ex(SmallHash *sh, - const uint nentries_reserve) +void BLI_smallhash_init_ex(SmallHash *sh, const uint nentries_reserve) { - /* assume 'sh' is uninitialized */ + /* assume 'sh' is uninitialized */ - sh->nentries = 0; - sh->cursize = 2; - sh->nbuckets = hashsizes[sh->cursize]; + sh->nentries = 0; + sh->cursize = 2; + sh->nbuckets = hashsizes[sh->cursize]; - sh->buckets = sh->buckets_stack; + sh->buckets = sh->buckets_stack; - if (nentries_reserve) { - smallhash_buckets_reserve(sh, nentries_reserve); + if (nentries_reserve) { + smallhash_buckets_reserve(sh, nentries_reserve); - if (sh->nbuckets > SMSTACKSIZE) { - sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * sh->nbuckets, __func__); - } - } + if (sh->nbuckets > SMSTACKSIZE) { + sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * sh->nbuckets, __func__); + } + } - smallhash_init_empty(sh); + smallhash_init_empty(sh); } void BLI_smallhash_init(SmallHash *sh) { - BLI_smallhash_init_ex(sh, 0); + BLI_smallhash_init_ex(sh, 0); } /* NOTE: does *not* free *sh itself! only the direct data! */ void BLI_smallhash_release(SmallHash *sh) { - if (sh->buckets != sh->buckets_stack) { - MEM_freeN(sh->buckets); - } + if (sh->buckets != sh->buckets_stack) { + MEM_freeN(sh->buckets); + } } void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *val) { - SmallHashEntry *e; + SmallHashEntry *e; - BLI_assert(key != SMHASH_KEY_UNUSED); - BLI_assert(smallhash_val_is_used(val)); - BLI_assert(BLI_smallhash_haskey(sh, key) == false); + BLI_assert(key != SMHASH_KEY_UNUSED); + BLI_assert(smallhash_val_is_used(val)); + BLI_assert(BLI_smallhash_haskey(sh, key) == false); - if (UNLIKELY(smallhash_test_expand_buckets(++sh->nentries, sh->nbuckets))) { - smallhash_resize_buckets(sh, hashsizes[++sh->cursize]); - } + if (UNLIKELY(smallhash_test_expand_buckets(++sh->nentries, sh->nbuckets))) { + smallhash_resize_buckets(sh, hashsizes[++sh->cursize]); + } - e = smallhash_lookup_first_free(sh, key); - e->key = key; - e->val = val; + e = smallhash_lookup_first_free(sh, key); + e->key = key; + e->val = val; } /** @@ -253,109 +246,108 @@ void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *val) */ bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) { - SmallHashEntry *e = smallhash_lookup(sh, key); - if (e) { - e->val = item; - return false; - } - else { - BLI_smallhash_insert(sh, key, item); - return true; - } + SmallHashEntry *e = smallhash_lookup(sh, key); + if (e) { + e->val = item; + return false; + } + else { + BLI_smallhash_insert(sh, key, item); + return true; + } } #ifdef USE_REMOVE bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) { - SmallHashEntry *e = smallhash_lookup(sh, key); - - if (e) { - e->key = SMHASH_KEY_UNUSED; - e->val = SMHASH_CELL_UNUSED; - sh->nentries--; - - return true; - } - else { - return false; - } + SmallHashEntry *e = smallhash_lookup(sh, key); + + if (e) { + e->key = SMHASH_KEY_UNUSED; + e->val = SMHASH_CELL_UNUSED; + sh->nentries--; + + return true; + } + else { + return false; + } } #endif void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key) { - SmallHashEntry *e = smallhash_lookup(sh, key); + SmallHashEntry *e = smallhash_lookup(sh, key); - return e ? e->val : NULL; + return e ? e->val : NULL; } void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key) { - SmallHashEntry *e = smallhash_lookup(sh, key); + SmallHashEntry *e = smallhash_lookup(sh, key); - return e ? &e->val : NULL; + return e ? &e->val : NULL; } bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) { - SmallHashEntry *e = smallhash_lookup(sh, key); + SmallHashEntry *e = smallhash_lookup(sh, key); - return (e != NULL); + return (e != NULL); } int BLI_smallhash_len(const SmallHash *sh) { - return (int)sh->nentries; + return (int)sh->nentries; } BLI_INLINE SmallHashEntry *smallhash_iternext(SmallHashIter *iter, uintptr_t *key) { - while (iter->i < iter->sh->nbuckets) { - if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) { - if (key) { - *key = iter->sh->buckets[iter->i].key; - } + while (iter->i < iter->sh->nbuckets) { + if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) { + if (key) { + *key = iter->sh->buckets[iter->i].key; + } - return &iter->sh->buckets[iter->i++]; - } + return &iter->sh->buckets[iter->i++]; + } - iter->i++; - } + iter->i++; + } - return NULL; + return NULL; } void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) { - SmallHashEntry *e = smallhash_iternext(iter, key); + SmallHashEntry *e = smallhash_iternext(iter, key); - return e ? e->val : NULL; + return e ? e->val : NULL; } void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key) { - SmallHashEntry *e = smallhash_iternext(iter, key); + SmallHashEntry *e = smallhash_iternext(iter, key); - return e ? &e->val : NULL; + return e ? &e->val : NULL; } void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) { - iter->sh = sh; - iter->i = 0; + iter->sh = sh; + iter->i = 0; - return BLI_smallhash_iternext(iter, key); + return BLI_smallhash_iternext(iter, key); } void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key) { - iter->sh = sh; - iter->i = 0; + iter->sh = sh; + iter->i = 0; - return BLI_smallhash_iternext_p(iter, key); + return BLI_smallhash_iternext_p(iter, key); } - /** \name Debugging & Introspection * \{ */ @@ -364,32 +356,32 @@ void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr #if 0 void BLI_smallhash_print(SmallHash *sh) { - uint i, linecol = 79, c = 0; - - printf("{"); - for (i = 0; i < sh->nbuckets; i++) { - if (sh->buckets[i].val == SMHASH_CELL_UNUSED) { - printf("--u-"); - } - else if (sh->buckets[i].val == SMHASH_CELL_FREE) { - printf("--f-"); - } - else { - printf("%2x", (uint)sh->buckets[i].key); - } - - if (i != sh->nbuckets - 1) - printf(", "); - - c += 6; - - if (c >= linecol) { - printf("\n "); - c = 0; - } - } - - fflush(stdout); + uint i, linecol = 79, c = 0; + + printf("{"); + for (i = 0; i < sh->nbuckets; i++) { + if (sh->buckets[i].val == SMHASH_CELL_UNUSED) { + printf("--u-"); + } + else if (sh->buckets[i].val == SMHASH_CELL_FREE) { + printf("--f-"); + } + else { + printf("%2x", (uint)sh->buckets[i].key); + } + + if (i != sh->nbuckets - 1) + printf(", "); + + c += 6; + + if (c >= linecol) { + printf("\n "); + c = 0; + } + } + + fflush(stdout); } #endif @@ -402,31 +394,29 @@ void BLI_smallhash_print(SmallHash *sh) */ double BLI_smallhash_calc_quality(SmallHash *sh) { - uint64_t sum = 0; - uint i; - - if (sh->nentries == 0) { - return -1.0; - } - - for (i = 0; i < sh->nbuckets; i++) { - if (sh->buckets[i].key != SMHASH_KEY_UNUSED) { - uint64_t count = 0; - SmallHashEntry *e, *e_final = &sh->buckets[i]; - uint h = smallhash_key(e_final->key); - uint hoff = 1; - - for (e = &sh->buckets[h % sh->nbuckets]; - e != e_final; - h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) - { - count += 1; - } - - sum += count; - } - } - return ((double)(sh->nentries + sum) / (double)sh->nentries); + uint64_t sum = 0; + uint i; + + if (sh->nentries == 0) { + return -1.0; + } + + for (i = 0; i < sh->nbuckets; i++) { + if (sh->buckets[i].key != SMHASH_KEY_UNUSED) { + uint64_t count = 0; + SmallHashEntry *e, *e_final = &sh->buckets[i]; + uint h = smallhash_key(e_final->key); + uint hoff = 1; + + for (e = &sh->buckets[h % sh->nbuckets]; e != e_final; + h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) { + count += 1; + } + + sum += count; + } + } + return ((double)(sh->nentries + sum) / (double)sh->nentries); } #endif diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c index 07c85e6ba7b..225015db00d 100644 --- a/source/blender/blenlib/intern/sort.c +++ b/source/blender/blenlib/intern/sort.c @@ -27,13 +27,13 @@ /* do nothing! */ #else -#include "BLI_utildefines.h" +# include "BLI_utildefines.h" -#include "BLI_sort.h" +# include "BLI_sort.h" -#ifdef min /* for msvc */ -# undef min -#endif +# ifdef min /* for msvc */ +# undef min +# endif /* Maintained by FreeBSD. */ /* clang-format off */ @@ -45,48 +45,48 @@ * * \note modified to use glibc arg order for callbacks. */ -BLI_INLINE char *med3(char *, char *, char *, BLI_sort_cmp_t, void *); -BLI_INLINE void swapfunc(char *, char *, int, int); - -#define min(a, b) (a) < (b) ? (a) : (b) -#define swapcode(TYPE, parmi, parmj, n) \ -{ \ - long i = (n) / sizeof(TYPE); \ - TYPE *pi = (TYPE *) (parmi); \ - TYPE *pj = (TYPE *) (parmj); \ - do { \ - TYPE t = *pi; \ - *pi++ = *pj; \ - *pj++ = t; \ - } while (--i > 0); \ +BLI_INLINE char *med3(char *, char *, char *, BLI_sort_cmp_t, void *); +BLI_INLINE void swapfunc(char *, char *, int, int); + +#define min(a, b) (a) < (b) ? (a) : (b) +#define swapcode(TYPE, parmi, parmj, n) \ +{ \ + long i = (n) / sizeof(TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ } #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ - es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype) { - if (swaptype <= 1) - swapcode(long, a, b, n) - else - swapcode(char, a, b, n) + if (swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) } -#define swap(a, b) \ - if (swaptype == 0) { \ - long t = *(long *)(a); \ - *(long *)(a) = *(long *)(b);\ - *(long *)(b) = t; \ - } else \ - swapfunc(a, b, es, swaptype) +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b);\ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) -#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) -#define CMP(t, x, y) (cmp((x), (y), (t))) +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) +#define CMP(t, x, y) (cmp((x), (y), (t))) BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk) { - return CMP(thunk, a, b) < 0 ? - (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) : - (CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) : + (CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); } /** @@ -94,92 +94,92 @@ BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk */ void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk) { - char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - int d, r, swaptype, swap_cnt; + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; loop: - SWAPINIT(a, es); - swap_cnt = 0; - if (n < 7) { - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - { - swap(pl, pl - es); - } - } - return; - } - pm = (char *)a + (n / 2) * es; - if (n > 7) { - pl = (char *)a; - pn = (char *)a + (n - 1) * es; - if (n > 40) { - d = (n / 8) * es; - pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); - pm = med3(pm - d, pm, pm + d, cmp, thunk); - pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); - } - pm = med3(pl, pm, pn, cmp, thunk); - } - swap((char *)a, pm); - pa = pb = (char *)a + es; - - pc = pd = (char *)a + (n - 1) * es; - for (;;) { - while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) { - if (r == 0) { - swap_cnt = 1; - swap(pa, pb); - pa += es; - } - pb += es; - } - while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) { - if (r == 0) { - swap_cnt = 1; - swap(pc, pd); - pd -= es; - } - pc -= es; - } - if (pb > pc) { - break; - } - swap(pb, pc); - swap_cnt = 1; - pb += es; - pc -= es; - } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - { - swap(pl, pl - es); - } - } - return; - } - - pn = (char *)a + n * es; - r = min(pa - (char *)a, pb - pa); - vecswap((char *)a, pb - r, r); - r = min(pd - pc, pn - pd - es); - vecswap(pb, pn - r, r); - if ((r = pb - pa) > es) { - BLI_qsort_r(a, r / es, es, cmp, thunk); - } - if ((r = pd - pc) > es) { - /* Iterate rather than recurse to save stack space */ - a = pn - r; - n = r / es; - goto loop; - } + SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = (char *)a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); + } + pm = med3(pl, pm, pn, cmp, thunk); + } + swap((char *)a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) { + break; + } + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap((char *)a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) { + BLI_qsort_r(a, r / es, es, cmp, thunk); + } + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } } /* clang-format on */ -#endif /* __GLIBC__ */ +#endif /* __GLIBC__ */ diff --git a/source/blender/blenlib/intern/sort_utils.c b/source/blender/blenlib/intern/sort_utils.c index 3220f753397..09babd3d424 100644 --- a/source/blender/blenlib/intern/sort_utils.c +++ b/source/blender/blenlib/intern/sort_utils.c @@ -23,70 +23,106 @@ * Utility functions for sorting common types. */ -#include "BLI_sort_utils.h" /* own include */ +#include "BLI_sort_utils.h" /* own include */ struct SortAnyByFloat { - float sort_value; + float sort_value; }; struct SortAnyByInt { - int sort_value; + int sort_value; }; struct SortAnyByPtr { - const void *sort_value; + const void *sort_value; }; int BLI_sortutil_cmp_float(const void *a_, const void *b_) { - const struct SortAnyByFloat *a = a_; - const struct SortAnyByFloat *b = b_; - if (a->sort_value > b->sort_value) { return 1; } - else if (a->sort_value < b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByFloat *a = a_; + const struct SortAnyByFloat *b = b_; + if (a->sort_value > b->sort_value) { + return 1; + } + else if (a->sort_value < b->sort_value) { + return -1; + } + else { + return 0; + } } int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_) { - const struct SortAnyByFloat *a = a_; - const struct SortAnyByFloat *b = b_; - if (a->sort_value < b->sort_value) { return 1; } - else if (a->sort_value > b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByFloat *a = a_; + const struct SortAnyByFloat *b = b_; + if (a->sort_value < b->sort_value) { + return 1; + } + else if (a->sort_value > b->sort_value) { + return -1; + } + else { + return 0; + } } int BLI_sortutil_cmp_int(const void *a_, const void *b_) { - const struct SortAnyByInt *a = a_; - const struct SortAnyByInt *b = b_; - if (a->sort_value > b->sort_value) { return 1; } - else if (a->sort_value < b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByInt *a = a_; + const struct SortAnyByInt *b = b_; + if (a->sort_value > b->sort_value) { + return 1; + } + else if (a->sort_value < b->sort_value) { + return -1; + } + else { + return 0; + } } int BLI_sortutil_cmp_int_reverse(const void *a_, const void *b_) { - const struct SortAnyByInt *a = a_; - const struct SortAnyByInt *b = b_; - if (a->sort_value < b->sort_value) { return 1; } - else if (a->sort_value > b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByInt *a = a_; + const struct SortAnyByInt *b = b_; + if (a->sort_value < b->sort_value) { + return 1; + } + else if (a->sort_value > b->sort_value) { + return -1; + } + else { + return 0; + } } int BLI_sortutil_cmp_ptr(const void *a_, const void *b_) { - const struct SortAnyByPtr *a = a_; - const struct SortAnyByPtr *b = b_; - if (a->sort_value > b->sort_value) { return 1; } - else if (a->sort_value < b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByPtr *a = a_; + const struct SortAnyByPtr *b = b_; + if (a->sort_value > b->sort_value) { + return 1; + } + else if (a->sort_value < b->sort_value) { + return -1; + } + else { + return 0; + } } int BLI_sortutil_cmp_ptr_reverse(const void *a_, const void *b_) { - const struct SortAnyByPtr *a = a_; - const struct SortAnyByPtr *b = b_; - if (a->sort_value < b->sort_value) { return 1; } - else if (a->sort_value > b->sort_value) { return -1; } - else { return 0; } + const struct SortAnyByPtr *a = a_; + const struct SortAnyByPtr *b = b_; + if (a->sort_value < b->sort_value) { + return 1; + } + else if (a->sort_value > b->sort_value) { + return -1; + } + else { + return 0; + } } diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index 4f6f9024fa5..76aef3761ae 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -19,12 +19,12 @@ */ #include <string.h> -#include <stdlib.h> /* abort() */ +#include <stdlib.h> /* abort() */ #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" -#include "BLI_stack.h" /* own include */ +#include "BLI_stack.h" /* own include */ #include "BLI_strict_flags.h" @@ -34,26 +34,25 @@ /* target chunks size: 64kb */ #define CHUNK_SIZE_DEFAULT (1 << 16) /* ensure we get at least this many elems per chunk */ -#define CHUNK_ELEM_MIN 32 +#define CHUNK_ELEM_MIN 32 /* Gets the last element in the stack */ #define CHUNK_LAST_ELEM(_stack) \ - ((void)0, (((char *)(_stack)->chunk_curr->data) + \ - ((_stack)->elem_size * (_stack)->chunk_index))) + ((void)0, (((char *)(_stack)->chunk_curr->data) + ((_stack)->elem_size * (_stack)->chunk_index))) struct StackChunk { - struct StackChunk *next; - char data[0]; + struct StackChunk *next; + char data[0]; }; struct BLI_Stack { - struct StackChunk *chunk_curr; /* currently active chunk */ - struct StackChunk *chunk_free; /* free chunks */ - size_t chunk_index; /* index into 'chunk_curr' */ - size_t chunk_elem_max; /* number of elements per chunk */ - size_t elem_size; + struct StackChunk *chunk_curr; /* currently active chunk */ + struct StackChunk *chunk_free; /* free chunks */ + size_t chunk_index; /* index into 'chunk_curr' */ + size_t chunk_elem_max; /* number of elements per chunk */ + size_t elem_size; #ifdef USE_TOTELEM - size_t totelem; + size_t totelem; #endif }; @@ -62,32 +61,33 @@ struct BLI_Stack { */ static size_t stack_chunk_elem_max_calc(const size_t elem_size, size_t chunk_size) { - /* get at least this number of elems per chunk */ - const size_t elem_size_min = elem_size * CHUNK_ELEM_MIN; + /* get at least this number of elems per chunk */ + const size_t elem_size_min = elem_size * CHUNK_ELEM_MIN; - BLI_assert((elem_size != 0) && (chunk_size != 0)); + BLI_assert((elem_size != 0) && (chunk_size != 0)); - while (UNLIKELY(chunk_size <= elem_size_min)) { - chunk_size <<= 1; - } + while (UNLIKELY(chunk_size <= elem_size_min)) { + chunk_size <<= 1; + } - /* account for slop-space */ - chunk_size -= (sizeof(struct StackChunk) + MEM_SIZE_OVERHEAD); + /* account for slop-space */ + chunk_size -= (sizeof(struct StackChunk) + MEM_SIZE_OVERHEAD); - return chunk_size / elem_size; + return chunk_size / elem_size; } -BLI_Stack *BLI_stack_new_ex(const size_t elem_size, const char *description, +BLI_Stack *BLI_stack_new_ex(const size_t elem_size, + const char *description, const size_t chunk_size) { - BLI_Stack *stack = MEM_callocN(sizeof(*stack), description); + BLI_Stack *stack = MEM_callocN(sizeof(*stack), description); - stack->chunk_elem_max = stack_chunk_elem_max_calc(elem_size, chunk_size); - stack->elem_size = elem_size; - /* force init */ - stack->chunk_index = stack->chunk_elem_max - 1; + stack->chunk_elem_max = stack_chunk_elem_max_calc(elem_size, chunk_size); + stack->elem_size = elem_size; + /* force init */ + stack->chunk_index = stack->chunk_elem_max - 1; - return stack; + return stack; } /** @@ -95,16 +95,16 @@ BLI_Stack *BLI_stack_new_ex(const size_t elem_size, const char *description, */ BLI_Stack *BLI_stack_new(const size_t elem_size, const char *description) { - return BLI_stack_new_ex(elem_size, description, CHUNK_SIZE_DEFAULT); + return BLI_stack_new_ex(elem_size, description, CHUNK_SIZE_DEFAULT); } static void stack_free_chunks(struct StackChunk *data) { - while (data) { - struct StackChunk *data_next = data->next; - MEM_freeN(data); - data = data_next; - } + while (data) { + struct StackChunk *data_next = data->next; + MEM_freeN(data); + data = data_next; + } } /** @@ -112,9 +112,9 @@ static void stack_free_chunks(struct StackChunk *data) */ void BLI_stack_free(BLI_Stack *stack) { - stack_free_chunks(stack->chunk_curr); - stack_free_chunks(stack->chunk_free); - MEM_freeN(stack); + stack_free_chunks(stack->chunk_curr); + stack_free_chunks(stack->chunk_free); + MEM_freeN(stack); } /** @@ -125,32 +125,30 @@ void BLI_stack_free(BLI_Stack *stack) */ void *BLI_stack_push_r(BLI_Stack *stack) { - stack->chunk_index++; - - if (UNLIKELY(stack->chunk_index == stack->chunk_elem_max)) { - struct StackChunk *chunk; - if (stack->chunk_free) { - chunk = stack->chunk_free; - stack->chunk_free = chunk->next; - } - else { - chunk = MEM_mallocN( - sizeof(*chunk) + (stack->elem_size * stack->chunk_elem_max), - __func__); - } - chunk->next = stack->chunk_curr; - stack->chunk_curr = chunk; - stack->chunk_index = 0; - } - - BLI_assert(stack->chunk_index < stack->chunk_elem_max); + stack->chunk_index++; + + if (UNLIKELY(stack->chunk_index == stack->chunk_elem_max)) { + struct StackChunk *chunk; + if (stack->chunk_free) { + chunk = stack->chunk_free; + stack->chunk_free = chunk->next; + } + else { + chunk = MEM_mallocN(sizeof(*chunk) + (stack->elem_size * stack->chunk_elem_max), __func__); + } + chunk->next = stack->chunk_curr; + stack->chunk_curr = chunk; + stack->chunk_index = 0; + } + + BLI_assert(stack->chunk_index < stack->chunk_elem_max); #ifdef USE_TOTELEM - stack->totelem++; + stack->totelem++; #endif - /* Return end of stack */ - return CHUNK_LAST_ELEM(stack); + /* Return end of stack */ + return CHUNK_LAST_ELEM(stack); } /** @@ -163,8 +161,8 @@ void *BLI_stack_push_r(BLI_Stack *stack) */ void BLI_stack_push(BLI_Stack *stack, const void *src) { - void *dst = BLI_stack_push_r(stack); - memcpy(dst, src, stack->elem_size); + void *dst = BLI_stack_push_r(stack); + memcpy(dst, src, stack->elem_size); } /** @@ -175,11 +173,11 @@ void BLI_stack_push(BLI_Stack *stack, const void *src) */ void BLI_stack_pop(BLI_Stack *stack, void *dst) { - BLI_assert(BLI_stack_is_empty(stack) == false); + BLI_assert(BLI_stack_is_empty(stack) == false); - memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size); + memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size); - BLI_stack_discard(stack); + BLI_stack_discard(stack); } /** @@ -193,12 +191,12 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) */ void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) { - BLI_assert(n <= BLI_stack_count(stack)); + BLI_assert(n <= BLI_stack_count(stack)); - while (n--) { - BLI_stack_pop(stack, dst); - dst = (void *)((char *)dst + stack->elem_size); - } + while (n--) { + BLI_stack_pop(stack, dst); + dst = (void *)((char *)dst + stack->elem_size); + } } /** @@ -208,21 +206,21 @@ void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) */ void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n) { - BLI_assert(n <= BLI_stack_count(stack)); + BLI_assert(n <= BLI_stack_count(stack)); - dst = (void *)((char *)dst + (stack->elem_size * n)); + dst = (void *)((char *)dst + (stack->elem_size * n)); - while (n--) { - dst = (void *)((char *)dst - stack->elem_size); - BLI_stack_pop(stack, dst); - } + while (n--) { + dst = (void *)((char *)dst - stack->elem_size); + BLI_stack_pop(stack, dst); + } } void *BLI_stack_peek(BLI_Stack *stack) { - BLI_assert(BLI_stack_is_empty(stack) == false); + BLI_assert(BLI_stack_is_empty(stack) == false); - return CHUNK_LAST_ELEM(stack); + return CHUNK_LAST_ELEM(stack); } /** @@ -230,22 +228,22 @@ void *BLI_stack_peek(BLI_Stack *stack) */ void BLI_stack_discard(BLI_Stack *stack) { - BLI_assert(BLI_stack_is_empty(stack) == false); + BLI_assert(BLI_stack_is_empty(stack) == false); #ifdef USE_TOTELEM - stack->totelem--; + stack->totelem--; #endif - if (UNLIKELY(--stack->chunk_index == CHUNK_EMPTY)) { - struct StackChunk *chunk_free; + if (UNLIKELY(--stack->chunk_index == CHUNK_EMPTY)) { + struct StackChunk *chunk_free; - chunk_free = stack->chunk_curr; - stack->chunk_curr = stack->chunk_curr->next; + chunk_free = stack->chunk_curr; + stack->chunk_curr = stack->chunk_curr->next; - chunk_free->next = stack->chunk_free; - stack->chunk_free = chunk_free; + chunk_free->next = stack->chunk_free; + stack->chunk_free = chunk_free; - stack->chunk_index = stack->chunk_elem_max - 1; - } + stack->chunk_index = stack->chunk_elem_max - 1; + } } /** @@ -254,54 +252,54 @@ void BLI_stack_discard(BLI_Stack *stack) void BLI_stack_clear(BLI_Stack *stack) { #ifdef USE_TOTELEM - if (UNLIKELY(stack->totelem == 0)) { - return; - } - stack->totelem = 0; + if (UNLIKELY(stack->totelem == 0)) { + return; + } + stack->totelem = 0; #else - if (UNLIKELY(stack->chunk_curr == NULL)) { - return; - } + if (UNLIKELY(stack->chunk_curr == NULL)) { + return; + } #endif - stack->chunk_index = stack->chunk_elem_max - 1; - - if (stack->chunk_free) { - if (stack->chunk_curr) { - /* move all used chunks into tail of free list */ - struct StackChunk *chunk_free_last = stack->chunk_free; - while (chunk_free_last->next) { - chunk_free_last = chunk_free_last->next; - } - chunk_free_last->next = stack->chunk_curr; - stack->chunk_curr = NULL; - } - } - else { - stack->chunk_free = stack->chunk_curr; - stack->chunk_curr = NULL; - } + stack->chunk_index = stack->chunk_elem_max - 1; + + if (stack->chunk_free) { + if (stack->chunk_curr) { + /* move all used chunks into tail of free list */ + struct StackChunk *chunk_free_last = stack->chunk_free; + while (chunk_free_last->next) { + chunk_free_last = chunk_free_last->next; + } + chunk_free_last->next = stack->chunk_curr; + stack->chunk_curr = NULL; + } + } + else { + stack->chunk_free = stack->chunk_curr; + stack->chunk_curr = NULL; + } } size_t BLI_stack_count(const BLI_Stack *stack) { #ifdef USE_TOTELEM - return stack->totelem; + return stack->totelem; #else - struct StackChunk *data = stack->chunk_curr; - size_t totelem = stack->chunk_index + 1; - size_t i; - if (totelem != stack->chunk_elem_max) { - data = data->next; - } - else { - totelem = 0; - } - for (i = 0; data; data = data->next) { - i++; - } - totelem += stack->chunk_elem_max * i; - return totelem; + struct StackChunk *data = stack->chunk_curr; + size_t totelem = stack->chunk_index + 1; + size_t i; + if (totelem != stack->chunk_elem_max) { + data = data->next; + } + else { + totelem = 0; + } + for (i = 0; data; data = data->next) { + i++; + } + totelem += stack->chunk_elem_max * i; + return totelem; #endif } @@ -311,7 +309,7 @@ size_t BLI_stack_count(const BLI_Stack *stack) bool BLI_stack_is_empty(const BLI_Stack *stack) { #ifdef USE_TOTELEM - BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0)); + BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0)); #endif - return (stack->chunk_curr == NULL); + return (stack->chunk_curr == NULL); } diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 7b460c77fa8..64b8ff40bcf 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -30,13 +30,14 @@ #include <sys/stat.h> #if defined(__NetBSD__) || defined(__DragonFly__) || defined(__HAIKU__) - /* Other modern unix os's should probably use this also */ +/* Other modern unix os's should probably use this also */ # include <sys/statvfs.h> # define USE_STATFS_STATVFS #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) - /* For statfs */ +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__DragonFly__) +/* For statfs */ # include <sys/param.h> # include <sys/mount.h> #endif @@ -46,7 +47,7 @@ #endif #include <fcntl.h> -#include <string.h> /* strcpy etc.. */ +#include <string.h> /* strcpy etc.. */ #ifdef WIN32 # include <io.h> @@ -76,19 +77,19 @@ */ char *BLI_current_working_dir(char *dir, const size_t maxncpy) { - const char *pwd = BLI_getenv("PWD"); - if (pwd) { - size_t srclen = BLI_strnlen(pwd, maxncpy); - if (srclen != maxncpy) { - memcpy(dir, pwd, srclen + 1); - return dir; - } - else { - return NULL; - } - } - - return getcwd(dir, maxncpy); + const char *pwd = BLI_getenv("PWD"); + if (pwd) { + size_t srclen = BLI_strnlen(pwd, maxncpy); + if (srclen != maxncpy) { + memcpy(dir, pwd, srclen + 1); + return dir; + } + else { + return NULL; + } + } + + return getcwd(dir, maxncpy); } /** @@ -98,81 +99,81 @@ char *BLI_current_working_dir(char *dir, const size_t maxncpy) double BLI_dir_free_space(const char *dir) { #ifdef WIN32 - DWORD sectorspc, bytesps, freec, clusters; - char tmp[4]; - - tmp[0] = '\\'; tmp[1] = 0; /* Just a failsafe */ - if (dir[0] == '/' || dir[0] == '\\') { - tmp[0] = '\\'; - tmp[1] = 0; - } - else if (dir[1] == ':') { - tmp[0] = dir[0]; - tmp[1] = ':'; - tmp[2] = '\\'; - tmp[3] = 0; - } - - GetDiskFreeSpace(tmp, §orspc, &bytesps, &freec, &clusters); - - return (double) (freec * bytesps * sectorspc); + DWORD sectorspc, bytesps, freec, clusters; + char tmp[4]; + + tmp[0] = '\\'; + tmp[1] = 0; /* Just a failsafe */ + if (dir[0] == '/' || dir[0] == '\\') { + tmp[0] = '\\'; + tmp[1] = 0; + } + else if (dir[1] == ':') { + tmp[0] = dir[0]; + tmp[1] = ':'; + tmp[2] = '\\'; + tmp[3] = 0; + } + + GetDiskFreeSpace(tmp, §orspc, &bytesps, &freec, &clusters); + + return (double)(freec * bytesps * sectorspc); #else -#ifdef USE_STATFS_STATVFS - struct statvfs disk; -#else - struct statfs disk; -#endif - - char name[FILE_MAXDIR], *slash; - int len = strlen(dir); - - if (len >= FILE_MAXDIR) { - /* path too long */ - return -1; - } - - strcpy(name, dir); - - if (len) { - slash = strrchr(name, '/'); - if (slash) { - slash[1] = 0; - } - } - else { - strcpy(name, "/"); - } - -#if defined(USE_STATFS_STATVFS) - if (statvfs(name, &disk)) { - return -1; - } -#elif defined(USE_STATFS_4ARGS) - if (statfs(name, &disk, sizeof(struct statfs), 0)) { - return -1; - } -#else - if (statfs(name, &disk)) { - return -1; - } -#endif - - return ( ((double) disk.f_bsize) * ((double) disk.f_bfree)); +# ifdef USE_STATFS_STATVFS + struct statvfs disk; +# else + struct statfs disk; +# endif + + char name[FILE_MAXDIR], *slash; + int len = strlen(dir); + + if (len >= FILE_MAXDIR) { + /* path too long */ + return -1; + } + + strcpy(name, dir); + + if (len) { + slash = strrchr(name, '/'); + if (slash) { + slash[1] = 0; + } + } + else { + strcpy(name, "/"); + } + +# if defined(USE_STATFS_STATVFS) + if (statvfs(name, &disk)) { + return -1; + } +# elif defined(USE_STATFS_4ARGS) + if (statfs(name, &disk, sizeof(struct statfs), 0)) { + return -1; + } +# else + if (statfs(name, &disk)) { + return -1; + } +# endif + + return (((double)disk.f_bsize) * ((double)disk.f_bfree)); #endif } - /** * Returns the file size of an opened file descriptor. */ size_t BLI_file_descriptor_size(int file) { - struct stat st; - if ((file < 0) || (fstat(file, &st) == -1)) { - return -1; - } - return st.st_size; + struct stat st; + if ((file < 0) || (fstat(file, &st) == -1)) { + return -1; + } + return st.st_size; } /** @@ -180,11 +181,11 @@ size_t BLI_file_descriptor_size(int file) */ size_t BLI_file_size(const char *path) { - BLI_stat_t stats; - if (BLI_stat(path, &stats) == -1) { - return -1; - } - return stats.st_size; + BLI_stat_t stats; + if (BLI_stat(path, &stats) == -1) { + return -1; + } + return stats.st_size; } /** @@ -194,78 +195,76 @@ size_t BLI_file_size(const char *path) int BLI_exists(const char *name) { #if defined(WIN32) - BLI_stat_t st; - wchar_t *tmp_16 = alloc_utf16_from_8(name, 1); - int len, res; - unsigned int old_error_mode; - - len = wcslen(tmp_16); - /* in Windows #stat doesn't recognize dir ending on a slash - * so we remove it here */ - if (len > 3 && (tmp_16[len - 1] == L'\\' || tmp_16[len - 1] == L'/')) { - tmp_16[len - 1] = '\0'; - } - /* two special cases where the trailing slash is needed: - * 1. after the share part of a UNC path - * 2. after the C:\ when the path is the volume only - */ - if ((len >= 3) && (tmp_16[0] == L'\\') && (tmp_16[1] == L'\\')) { - BLI_cleanup_unc_16(tmp_16); - } - - if ((tmp_16[1] == L':') && (tmp_16[2] == L'\0')) { - tmp_16[2] = L'\\'; - tmp_16[3] = L'\0'; - } - - - /* change error mode so user does not get a "no disk in drive" popup - * when looking for a file on an empty CD/DVD drive */ - old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); - - res = BLI_wstat(tmp_16, &st); - - SetErrorMode(old_error_mode); - - free(tmp_16); - if (res == -1) { - return(0); - } + BLI_stat_t st; + wchar_t *tmp_16 = alloc_utf16_from_8(name, 1); + int len, res; + unsigned int old_error_mode; + + len = wcslen(tmp_16); + /* in Windows #stat doesn't recognize dir ending on a slash + * so we remove it here */ + if (len > 3 && (tmp_16[len - 1] == L'\\' || tmp_16[len - 1] == L'/')) { + tmp_16[len - 1] = '\0'; + } + /* two special cases where the trailing slash is needed: + * 1. after the share part of a UNC path + * 2. after the C:\ when the path is the volume only + */ + if ((len >= 3) && (tmp_16[0] == L'\\') && (tmp_16[1] == L'\\')) { + BLI_cleanup_unc_16(tmp_16); + } + + if ((tmp_16[1] == L':') && (tmp_16[2] == L'\0')) { + tmp_16[2] = L'\\'; + tmp_16[3] = L'\0'; + } + + /* change error mode so user does not get a "no disk in drive" popup + * when looking for a file on an empty CD/DVD drive */ + old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + + res = BLI_wstat(tmp_16, &st); + + SetErrorMode(old_error_mode); + + free(tmp_16); + if (res == -1) { + return (0); + } #else - struct stat st; - BLI_assert(!BLI_path_is_rel(name)); - if (stat(name, &st)) { - return(0); - } + struct stat st; + BLI_assert(!BLI_path_is_rel(name)); + if (stat(name, &st)) { + return (0); + } #endif - return(st.st_mode); + return (st.st_mode); } - #ifdef WIN32 int BLI_stat(const char *path, BLI_stat_t *buffer) { - int r; - UTF16_ENCODE(path); + int r; + UTF16_ENCODE(path); - r = BLI_wstat(path_16, buffer); + r = BLI_wstat(path_16, buffer); - UTF16_UN_ENCODE(path); - return r; + UTF16_UN_ENCODE(path); + return r; } int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer) { -#if defined(_MSC_VER) - return _wstat64(path, buffer); -#else - return _wstat(path, buffer); -#endif +# if defined(_MSC_VER) + return _wstat64(path, buffer); +# else + return _wstat(path, buffer); +# endif } #else int BLI_stat(const char *path, struct stat *buffer) { - return stat(path, buffer); + return stat(path, buffer); } #endif @@ -275,7 +274,7 @@ int BLI_stat(const char *path, struct stat *buffer) */ bool BLI_is_dir(const char *file) { - return S_ISDIR(BLI_exists(file)); + return S_ISDIR(BLI_exists(file)); } /** @@ -283,83 +282,83 @@ bool BLI_is_dir(const char *file) */ bool BLI_is_file(const char *path) { - const int mode = BLI_exists(path); - return (mode && !S_ISDIR(mode)); + const int mode = BLI_exists(path); + return (mode && !S_ISDIR(mode)); } void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) { - FILE *fp = BLI_fopen(filepath, "r"); - void *mem = NULL; - - if (fp) { - fseek(fp, 0L, SEEK_END); - const long int filelen = ftell(fp); - if (filelen == -1) { - goto finally; - } - fseek(fp, 0L, SEEK_SET); - - mem = MEM_mallocN(filelen + pad_bytes, __func__); - if (mem == NULL) { - goto finally; - } - - const long int filelen_read = fread(mem, 1, filelen, fp); - if ((filelen_read < 0) || ferror(fp)) { - MEM_freeN(mem); - mem = NULL; - goto finally; - } - - if (filelen_read < filelen) { - mem = MEM_reallocN(mem, filelen_read + pad_bytes); - if (mem == NULL) { - goto finally; - } - } - - *r_size = filelen_read; - -finally: - fclose(fp); - } - - return mem; + FILE *fp = BLI_fopen(filepath, "r"); + void *mem = NULL; + + if (fp) { + fseek(fp, 0L, SEEK_END); + const long int filelen = ftell(fp); + if (filelen == -1) { + goto finally; + } + fseek(fp, 0L, SEEK_SET); + + mem = MEM_mallocN(filelen + pad_bytes, __func__); + if (mem == NULL) { + goto finally; + } + + const long int filelen_read = fread(mem, 1, filelen, fp); + if ((filelen_read < 0) || ferror(fp)) { + MEM_freeN(mem); + mem = NULL; + goto finally; + } + + if (filelen_read < filelen) { + mem = MEM_reallocN(mem, filelen_read + pad_bytes); + if (mem == NULL) { + goto finally; + } + } + + *r_size = filelen_read; + + finally: + fclose(fp); + } + + return mem; } void *BLI_file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) { - FILE *fp = BLI_fopen(filepath, "rb"); - void *mem = NULL; - - if (fp) { - fseek(fp, 0L, SEEK_END); - const long int filelen = ftell(fp); - if (filelen == -1) { - goto finally; - } - fseek(fp, 0L, SEEK_SET); - - mem = MEM_mallocN(filelen + pad_bytes, __func__); - if (mem == NULL) { - goto finally; - } - - const long int filelen_read = fread(mem, 1, filelen, fp); - if ((filelen_read != filelen) || ferror(fp)) { - MEM_freeN(mem); - mem = NULL; - goto finally; - } - - *r_size = filelen_read; - -finally: - fclose(fp); - } - - return mem; + FILE *fp = BLI_fopen(filepath, "rb"); + void *mem = NULL; + + if (fp) { + fseek(fp, 0L, SEEK_END); + const long int filelen = ftell(fp); + if (filelen == -1) { + goto finally; + } + fseek(fp, 0L, SEEK_SET); + + mem = MEM_mallocN(filelen + pad_bytes, __func__); + if (mem == NULL) { + goto finally; + } + + const long int filelen_read = fread(mem, 1, filelen, fp); + if ((filelen_read != filelen) || ferror(fp)) { + MEM_freeN(mem); + mem = NULL; + goto finally; + } + + *r_size = filelen_read; + + finally: + fclose(fp); + } + + return mem; } /** @@ -367,48 +366,48 @@ finally: */ LinkNode *BLI_file_read_as_lines(const char *name) { - FILE *fp = BLI_fopen(name, "r"); - LinkNodePair lines = {NULL, NULL}; - char *buf; - size_t size; - - if (!fp) { - return NULL; - } - - fseek(fp, 0, SEEK_END); - size = (size_t)ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (UNLIKELY(size == (size_t)-1)) { - fclose(fp); - return NULL; - } - - buf = MEM_mallocN(size, "file_as_lines"); - if (buf) { - size_t i, last = 0; - - /* - * size = because on win32 reading - * all the bytes in the file will return - * less bytes because of `CRNL` changes. - */ - size = fread(buf, 1, size, fp); - for (i = 0; i <= size; i++) { - if (i == size || buf[i] == '\n') { - char *line = BLI_strdupn(&buf[last], i - last); - BLI_linklist_append(&lines, line); - last = i + 1; - } - } - - MEM_freeN(buf); - } - - fclose(fp); - - return lines.list; + FILE *fp = BLI_fopen(name, "r"); + LinkNodePair lines = {NULL, NULL}; + char *buf; + size_t size; + + if (!fp) { + return NULL; + } + + fseek(fp, 0, SEEK_END); + size = (size_t)ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (UNLIKELY(size == (size_t)-1)) { + fclose(fp); + return NULL; + } + + buf = MEM_mallocN(size, "file_as_lines"); + if (buf) { + size_t i, last = 0; + + /* + * size = because on win32 reading + * all the bytes in the file will return + * less bytes because of `CRNL` changes. + */ + size = fread(buf, 1, size, fp); + for (i = 0; i <= size; i++) { + if (i == size || buf[i] == '\n') { + char *line = BLI_strdupn(&buf[last], i - last); + BLI_linklist_append(&lines, line); + last = i + 1; + } + } + + MEM_freeN(buf); + } + + fclose(fp); + + return lines.list; } /* @@ -416,36 +415,36 @@ LinkNode *BLI_file_read_as_lines(const char *name) */ void BLI_file_free_lines(LinkNode *lines) { - BLI_linklist_freeN(lines); + BLI_linklist_freeN(lines); } /** is file1 older then file2 */ bool BLI_file_older(const char *file1, const char *file2) { #ifdef WIN32 - struct _stat st1, st2; + struct _stat st1, st2; - UTF16_ENCODE(file1); - UTF16_ENCODE(file2); + UTF16_ENCODE(file1); + UTF16_ENCODE(file2); - if (_wstat(file1_16, &st1)) { - return false; - } - if (_wstat(file2_16, &st2)) { - return false; - } + if (_wstat(file1_16, &st1)) { + return false; + } + if (_wstat(file2_16, &st2)) { + return false; + } - UTF16_UN_ENCODE(file2); - UTF16_UN_ENCODE(file1); + UTF16_UN_ENCODE(file2); + UTF16_UN_ENCODE(file1); #else - struct stat st1, st2; - - if (stat(file1, &st1)) { - return false; - } - if (stat(file2, &st2)) { - return false; - } + struct stat st1, st2; + + if (stat(file1, &st1)) { + return false; + } + if (stat(file2, &st2)) { + return false; + } #endif - return (st1.st_mtime < st2.st_mtime); + return (st1.st_mtime < st2.st_mtime); } diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index dfb32e5b76c..01cb635b044 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -21,7 +21,6 @@ * \ingroup bli */ - #include <string.h> #include <stdlib.h> #include <stdarg.h> @@ -52,11 +51,11 @@ */ char *BLI_strdupn(const char *str, const size_t len) { - char *n = MEM_mallocN(len + 1, "strdup"); - memcpy(n, str, len); - n[len] = '\0'; + char *n = MEM_mallocN(len + 1, "strdup"); + memcpy(n, str, len); + n[len] = '\0'; - return n; + return n; } /** @@ -68,7 +67,7 @@ char *BLI_strdupn(const char *str, const size_t len) */ char *BLI_strdup(const char *str) { - return BLI_strdupn(str, strlen(str)); + return BLI_strdupn(str, strlen(str)); } /** @@ -79,18 +78,19 @@ char *BLI_strdup(const char *str) */ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { - /* include the NULL terminator of str2 only */ - const size_t str1_len = strlen(str1); - const size_t str2_len = strlen(str2) + 1; - char *str, *s; + /* include the NULL terminator of str2 only */ + const size_t str1_len = strlen(str1); + const size_t str2_len = strlen(str2) + 1; + char *str, *s; - str = MEM_mallocN(str1_len + str2_len, "strdupcat"); - s = str; + str = MEM_mallocN(str1_len + str2_len, "strdupcat"); + s = str; - memcpy(s, str1, str1_len); s += str1_len; - memcpy(s, str2, str2_len); + memcpy(s, str1, str1_len); + s += str1_len; + memcpy(s, str2, str2_len); - return str; + return str; } /** @@ -105,16 +105,16 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) */ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { - size_t srclen = BLI_strnlen(src, maxncpy - 1); - BLI_assert(maxncpy != 0); + size_t srclen = BLI_strnlen(src, maxncpy - 1); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - memcpy(dst, src, srclen); - dst[srclen] = '\0'; - return dst; + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + return dst; } /** @@ -126,43 +126,46 @@ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t * \param maxncpy: Maximum number of characters to copy (generally the size of dst) * \retval Returns dst */ -char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy) +char *BLI_strncpy_ensure_pad(char *__restrict dst, + const char *__restrict src, + const char pad, + size_t maxncpy) { - BLI_assert(maxncpy != 0); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - if (src[0] == '\0') { - dst[0] = '\0'; - } - else { - /* Add heading/trailing wildcards if needed. */ - size_t idx = 0; - size_t srclen; - - if (src[idx] != pad) { - dst[idx++] = pad; - maxncpy--; - } - maxncpy--; /* trailing '\0' */ - - srclen = BLI_strnlen(src, maxncpy); - if ((src[srclen - 1] != pad) && (srclen == maxncpy)) { - srclen--; - } - - memcpy(&dst[idx], src, srclen); - idx += srclen; - - if (dst[idx - 1] != pad) { - dst[idx++] = pad; - } - dst[idx] = '\0'; - } - - return dst; + if (src[0] == '\0') { + dst[0] = '\0'; + } + else { + /* Add heading/trailing wildcards if needed. */ + size_t idx = 0; + size_t srclen; + + if (src[idx] != pad) { + dst[idx++] = pad; + maxncpy--; + } + maxncpy--; /* trailing '\0' */ + + srclen = BLI_strnlen(src, maxncpy); + if ((src[srclen - 1] != pad) && (srclen == maxncpy)) { + srclen--; + } + + memcpy(&dst[idx], src, srclen); + idx += srclen; + + if (dst[idx - 1] != pad) { + dst[idx++] = pad; + } + dst[idx] = '\0'; + } + + return dst; } /** @@ -180,70 +183,76 @@ char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, c */ size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { - size_t srclen = BLI_strnlen(src, maxncpy - 1); - BLI_assert(maxncpy != 0); + size_t srclen = BLI_strnlen(src, maxncpy - 1); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - memcpy(dst, src, srclen); - dst[srclen] = '\0'; - return srclen; + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + return srclen; } size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) { - size_t srclen = strlen(src); - memcpy(dst, src, srclen + 1); - return srclen; + size_t srclen = strlen(src); + memcpy(dst, src, srclen + 1); + return srclen; } /** * Portable replacement for `vsnprintf`. */ -size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) +size_t BLI_vsnprintf(char *__restrict buffer, + size_t maxncpy, + const char *__restrict format, + va_list arg) { - size_t n; + size_t n; - BLI_assert(buffer != NULL); - BLI_assert(maxncpy > 0); - BLI_assert(format != NULL); + BLI_assert(buffer != NULL); + BLI_assert(maxncpy > 0); + BLI_assert(format != NULL); - n = (size_t)vsnprintf(buffer, maxncpy, format, arg); + n = (size_t)vsnprintf(buffer, maxncpy, format, arg); - if (n != -1 && n < maxncpy) { - buffer[n] = '\0'; - } - else { - buffer[maxncpy - 1] = '\0'; - } + if (n != -1 && n < maxncpy) { + buffer[n] = '\0'; + } + else { + buffer[maxncpy - 1] = '\0'; + } - return n; + return n; } /** * A version of #BLI_vsnprintf that returns ``strlen(buffer)`` */ -size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) +size_t BLI_vsnprintf_rlen(char *__restrict buffer, + size_t maxncpy, + const char *__restrict format, + va_list arg) { - size_t n; + size_t n; - BLI_assert(buffer != NULL); - BLI_assert(maxncpy > 0); - BLI_assert(format != NULL); + BLI_assert(buffer != NULL); + BLI_assert(maxncpy > 0); + BLI_assert(format != NULL); - n = (size_t)vsnprintf(buffer, maxncpy, format, arg); + n = (size_t)vsnprintf(buffer, maxncpy, format, arg); - if (n != -1 && n < maxncpy) { - /* pass */ - } - else { - n = maxncpy - 1; - } - buffer[n] = '\0'; + if (n != -1 && n < maxncpy) { + /* pass */ + } + else { + n = maxncpy - 1; + } + buffer[n] = '\0'; - return n; + return n; } /** @@ -251,18 +260,18 @@ size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *_ */ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) { - size_t n; - va_list arg; + size_t n; + va_list arg; #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - va_start(arg, format); - n = BLI_vsnprintf(dst, maxncpy, format, arg); - va_end(arg); + va_start(arg, format); + n = BLI_vsnprintf(dst, maxncpy, format, arg); + va_end(arg); - return n; + return n; } /** @@ -270,18 +279,18 @@ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict */ size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) { - size_t n; - va_list arg; + size_t n; + va_list arg; #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - va_start(arg, format); - n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg); - va_end(arg); + va_start(arg, format); + n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg); + va_end(arg); - return n; + return n; } /** @@ -290,23 +299,22 @@ size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__res */ char *BLI_sprintfN(const char *__restrict format, ...) { - DynStr *ds; - va_list arg; - char *n; + DynStr *ds; + va_list arg; + char *n; - va_start(arg, format); + va_start(arg, format); - ds = BLI_dynstr_new(); - BLI_dynstr_vappendf(ds, format, arg); - n = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); + ds = BLI_dynstr_new(); + BLI_dynstr_vappendf(ds, format, arg); + n = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); - va_end(arg); + va_end(arg); - return n; + return n; } - /* match pythons string escaping, assume double quotes - (") * TODO: should be used to create RNA animation paths. * TODO: support more fancy string escaping. current code is primitive @@ -314,45 +322,45 @@ char *BLI_sprintfN(const char *__restrict format, ...) * which is a useful reference. */ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { - size_t len = 0; - - BLI_assert(maxncpy != 0); - - while (len < maxncpy) { - switch (*src) { - case '\0': - goto escape_finish; - case '\\': - case '"': - ATTR_FALLTHROUGH; - - /* less common but should also be support */ - case '\t': - case '\n': - case '\r': - if (len + 1 < maxncpy) { - *dst++ = '\\'; - len++; - } - else { - /* not enough space to escape */ - break; - } - ATTR_FALLTHROUGH; - default: - *dst = *src; - break; - } - dst++; - src++; - len++; - } + size_t len = 0; + + BLI_assert(maxncpy != 0); + + while (len < maxncpy) { + switch (*src) { + case '\0': + goto escape_finish; + case '\\': + case '"': + ATTR_FALLTHROUGH; + + /* less common but should also be support */ + case '\t': + case '\n': + case '\r': + if (len + 1 < maxncpy) { + *dst++ = '\\'; + len++; + } + else { + /* not enough space to escape */ + break; + } + ATTR_FALLTHROUGH; + default: + *dst = *src; + break; + } + dst++; + src++; + len++; + } escape_finish: - *dst = '\0'; + *dst = '\0'; - return len; + return len; } /** @@ -369,32 +377,32 @@ escape_finish: */ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { - const char *startMatch, *endMatch; - - /* get the starting point (i.e. where prefix starts, and add prefixLen+1 - * to it to get be after the first " */ - startMatch = strstr(str, prefix); - if (startMatch) { - const size_t prefixLen = strlen(prefix); - startMatch += prefixLen + 1; - /* get the end point (i.e. where the next occurrence of " is after the starting point) */ - - endMatch = startMatch; - while ((endMatch = strchr(endMatch, '"'))) { - if (LIKELY(*(endMatch - 1) != '\\')) { - break; - } - else { - endMatch++; - } - } - - if (endMatch) { - /* return the slice indicated */ - return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); - } - } - return BLI_strdupn("", 0); + const char *startMatch, *endMatch; + + /* get the starting point (i.e. where prefix starts, and add prefixLen+1 + * to it to get be after the first " */ + startMatch = strstr(str, prefix); + if (startMatch) { + const size_t prefixLen = strlen(prefix); + startMatch += prefixLen + 1; + /* get the end point (i.e. where the next occurrence of " is after the starting point) */ + + endMatch = startMatch; + while ((endMatch = strchr(endMatch, '"'))) { + if (LIKELY(*(endMatch - 1) != '\\')) { + break; + } + else { + endMatch++; + } + } + + if (endMatch) { + /* return the slice indicated */ + return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); + } + } + return BLI_strdupn("", 0); } /** @@ -410,63 +418,65 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict * \param substr_new: The text in the string to find and replace * \retval Returns the duplicated string */ -char *BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) +char *BLI_str_replaceN(const char *__restrict str, + const char *__restrict substr_old, + const char *__restrict substr_new) { - DynStr *ds = NULL; - size_t len_old = strlen(substr_old); - const char *match; - - BLI_assert(substr_old[0] != '\0'); - - /* while we can still find a match for the old substring that we're searching for, - * keep dicing and replacing - */ - while ((match = strstr(str, substr_old))) { - /* the assembly buffer only gets created when we actually need to rebuild the string */ - if (ds == NULL) { - ds = BLI_dynstr_new(); - } - - /* if the match position does not match the current position in the string, - * copy the text up to this position and advance the current position in the string - */ - if (str != match) { - /* add the segment of the string from str to match to the buffer, - * then restore the value at match */ - BLI_dynstr_nappend(ds, str, (match - str)); - - /* now our current position should be set on the start of the match */ - str = match; - } - - /* add the replacement text to the accumulation buffer */ - BLI_dynstr_append(ds, substr_new); - - /* advance the current position of the string up to the end of the replaced segment */ - str += len_old; - } - - /* finish off and return a new string that has had all occurrences of */ - if (ds) { - char *str_new; - - /* add what's left of the string to the assembly buffer - * - we've been adjusting str to point at the end of the replaced segments - */ - BLI_dynstr_append(ds, str); - - /* convert to new c-string (MEM_malloc'd), and free the buffer */ - str_new = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return str_new; - } - else { - /* just create a new copy of the entire string - we avoid going through the assembly buffer - * for what should be a bit more efficiency... - */ - return BLI_strdup(str); - } + DynStr *ds = NULL; + size_t len_old = strlen(substr_old); + const char *match; + + BLI_assert(substr_old[0] != '\0'); + + /* while we can still find a match for the old substring that we're searching for, + * keep dicing and replacing + */ + while ((match = strstr(str, substr_old))) { + /* the assembly buffer only gets created when we actually need to rebuild the string */ + if (ds == NULL) { + ds = BLI_dynstr_new(); + } + + /* if the match position does not match the current position in the string, + * copy the text up to this position and advance the current position in the string + */ + if (str != match) { + /* add the segment of the string from str to match to the buffer, + * then restore the value at match */ + BLI_dynstr_nappend(ds, str, (match - str)); + + /* now our current position should be set on the start of the match */ + str = match; + } + + /* add the replacement text to the accumulation buffer */ + BLI_dynstr_append(ds, substr_new); + + /* advance the current position of the string up to the end of the replaced segment */ + str += len_old; + } + + /* finish off and return a new string that has had all occurrences of */ + if (ds) { + char *str_new; + + /* add what's left of the string to the assembly buffer + * - we've been adjusting str to point at the end of the replaced segments + */ + BLI_dynstr_append(ds, str); + + /* convert to new c-string (MEM_malloc'd), and free the buffer */ + str_new = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return str_new; + } + else { + /* just create a new copy of the entire string - we avoid going through the assembly buffer + * for what should be a bit more efficiency... + */ + return BLI_strdup(str); + } } /** @@ -478,12 +488,12 @@ char *BLI_str_replaceN(const char *__restrict str, const char *__restrict substr */ void BLI_str_replace_char(char *str, char src, char dst) { - while (*str) { - if (*str == src) { - *str = dst; - } - str++; - } + while (*str) { + if (*str == src) { + *str = dst; + } + str++; + } } /** @@ -493,7 +503,7 @@ void BLI_str_replace_char(char *str, char src, char dst) */ int BLI_strcaseeq(const char *a, const char *b) { - return (BLI_strcasecmp(a, b) == 0); + return (BLI_strcasecmp(a, b) == 0); } /** @@ -501,23 +511,23 @@ int BLI_strcaseeq(const char *a, const char *b) */ char *BLI_strcasestr(const char *s, const char *find) { - register char c, sc; - register size_t len; - - if ((c = *find++) != 0) { - c = tolower(c); - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) { - return (NULL); - } - sc = tolower(sc); - } while (sc != c); - } while (BLI_strncasecmp(s, find, len) != 0); - s--; - } - return ((char *) s); + register char c, sc; + register size_t len; + + if ((c = *find++) != 0) { + c = tolower(c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) { + return (NULL); + } + sc = tolower(sc); + } while (sc != c); + } while (BLI_strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); } /** @@ -525,195 +535,195 @@ char *BLI_strcasestr(const char *s, const char *find) */ char *BLI_strncasestr(const char *s, const char *find, size_t len) { - register char c, sc; - - if ((c = *find++) != 0) { - c = tolower(c); - if (len > 1) { - do { - do { - if ((sc = *s++) == 0) { - return NULL; - } - sc = tolower(sc); - } while (sc != c); - } while (BLI_strncasecmp(s, find, len - 1) != 0); - } - else { - { - do { - if ((sc = *s++) == 0) { - return NULL; - } - sc = tolower(sc); - } while (sc != c); - } - } - s--; - } - return ((char *)s); + register char c, sc; + + if ((c = *find++) != 0) { + c = tolower(c); + if (len > 1) { + do { + do { + if ((sc = *s++) == 0) { + return NULL; + } + sc = tolower(sc); + } while (sc != c); + } while (BLI_strncasecmp(s, find, len - 1) != 0); + } + else { + { + do { + if ((sc = *s++) == 0) { + return NULL; + } + sc = tolower(sc); + } while (sc != c); + } + } + s--; + } + return ((char *)s); } int BLI_strcasecmp(const char *s1, const char *s2) { - register int i; - register char c1, c2; - - for (i = 0;; i++) { - c1 = tolower(s1[i]); - c2 = tolower(s2[i]); - - if (c1 < c2) { - return -1; - } - else if (c1 > c2) { - return 1; - } - else if (c1 == 0) { - break; - } - } - - return 0; + register int i; + register char c1, c2; + + for (i = 0;; i++) { + c1 = tolower(s1[i]); + c2 = tolower(s2[i]); + + if (c1 < c2) { + return -1; + } + else if (c1 > c2) { + return 1; + } + else if (c1 == 0) { + break; + } + } + + return 0; } int BLI_strncasecmp(const char *s1, const char *s2, size_t len) { - register size_t i; - register char c1, c2; - - for (i = 0; i < len; i++) { - c1 = tolower(s1[i]); - c2 = tolower(s2[i]); - - if (c1 < c2) { - return -1; - } - else if (c1 > c2) { - return 1; - } - else if (c1 == 0) { - break; - } - } - - return 0; + register size_t i; + register char c1, c2; + + for (i = 0; i < len; i++) { + c1 = tolower(s1[i]); + c2 = tolower(s2[i]); + + if (c1 < c2) { + return -1; + } + else if (c1 > c2) { + return 1; + } + else if (c1 == 0) { + break; + } + } + + return 0; } /* compare number on the left size of the string */ static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker) { - const char *p1 = s1, *p2 = s2; - int numdigit, numzero1, numzero2; - - /* count and skip leading zeros */ - for (numzero1 = 0; *p1 == '0'; numzero1++) { - p1++; - } - for (numzero2 = 0; *p2 == '0'; numzero2++) { - p2++; - } - - /* find number of consecutive digits */ - for (numdigit = 0; ; numdigit++) { - if (isdigit(*(p1 + numdigit)) && isdigit(*(p2 + numdigit))) { - continue; - } - else if (isdigit(*(p1 + numdigit))) { - return 1; /* s2 is bigger */ - } - else if (isdigit(*(p2 + numdigit))) { - return -1; /* s1 is bigger */ - } - else { - break; - } - } - - /* same number of digits, compare size of number */ - if (numdigit > 0) { - int compare = (int)strncmp(p1, p2, (size_t)numdigit); - - if (compare != 0) { - return compare; - } - } - - /* use number of leading zeros as tie breaker if still equal */ - if (*tiebreaker == 0) { - if (numzero1 > numzero2) { - *tiebreaker = 1; - } - else if (numzero1 < numzero2) { - *tiebreaker = -1; - } - } - - return 0; + const char *p1 = s1, *p2 = s2; + int numdigit, numzero1, numzero2; + + /* count and skip leading zeros */ + for (numzero1 = 0; *p1 == '0'; numzero1++) { + p1++; + } + for (numzero2 = 0; *p2 == '0'; numzero2++) { + p2++; + } + + /* find number of consecutive digits */ + for (numdigit = 0;; numdigit++) { + if (isdigit(*(p1 + numdigit)) && isdigit(*(p2 + numdigit))) { + continue; + } + else if (isdigit(*(p1 + numdigit))) { + return 1; /* s2 is bigger */ + } + else if (isdigit(*(p2 + numdigit))) { + return -1; /* s1 is bigger */ + } + else { + break; + } + } + + /* same number of digits, compare size of number */ + if (numdigit > 0) { + int compare = (int)strncmp(p1, p2, (size_t)numdigit); + + if (compare != 0) { + return compare; + } + } + + /* use number of leading zeros as tie breaker if still equal */ + if (*tiebreaker == 0) { + if (numzero1 > numzero2) { + *tiebreaker = 1; + } + else if (numzero1 < numzero2) { + *tiebreaker = -1; + } + } + + return 0; } /* natural string compare, keeping numbers in order */ int BLI_natstrcmp(const char *s1, const char *s2) { - register int d1 = 0, d2 = 0; - register char c1, c2; - int tiebreaker = 0; - - /* if both chars are numeric, to a left_number_strcmp(). - * then increase string deltas as long they are - * numeric, else do a tolower and char compare */ - - while (1) { - c1 = tolower(s1[d1]); - c2 = tolower(s2[d2]); - - if (isdigit(c1) && isdigit(c2)) { - int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker); - - if (numcompare != 0) { - return numcompare; - } - - d1++; - while (isdigit(s1[d1])) { - d1++; - } - d2++; - while (isdigit(s2[d2])) { - d2++; - } - - c1 = tolower(s1[d1]); - c2 = tolower(s2[d2]); - } - - /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ - if (c1 == '.' && c2 != '.') { - return -1; - } - if (c1 != '.' && c2 == '.') { - return 1; - } - else if (c1 < c2) { - return -1; - } - else if (c1 > c2) { - return 1; - } - else if (c1 == 0) { - break; - } - d1++; - d2++; - } - - if (tiebreaker) { - return tiebreaker; - } - - /* we might still have a different string because of lower/upper case, in - * that case fall back to regular string comparison */ - return strcmp(s1, s2); + register int d1 = 0, d2 = 0; + register char c1, c2; + int tiebreaker = 0; + + /* if both chars are numeric, to a left_number_strcmp(). + * then increase string deltas as long they are + * numeric, else do a tolower and char compare */ + + while (1) { + c1 = tolower(s1[d1]); + c2 = tolower(s2[d2]); + + if (isdigit(c1) && isdigit(c2)) { + int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker); + + if (numcompare != 0) { + return numcompare; + } + + d1++; + while (isdigit(s1[d1])) { + d1++; + } + d2++; + while (isdigit(s2[d2])) { + d2++; + } + + c1 = tolower(s1[d1]); + c2 = tolower(s2[d2]); + } + + /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ + if (c1 == '.' && c2 != '.') { + return -1; + } + if (c1 != '.' && c2 == '.') { + return 1; + } + else if (c1 < c2) { + return -1; + } + else if (c1 > c2) { + return 1; + } + else if (c1 == 0) { + break; + } + d1++; + d2++; + } + + if (tiebreaker) { + return tiebreaker; + } + + /* we might still have a different string because of lower/upper case, in + * that case fall back to regular string comparison */ + return strcmp(s1, s2); } /** @@ -722,77 +732,77 @@ int BLI_natstrcmp(const char *s1, const char *s2) */ int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) { - size_t str1_len, str2_len; - - while (*str1 == pad) { - str1++; - } - while (*str2 == pad) { - str2++; - } - - str1_len = strlen(str1); - str2_len = strlen(str2); - - while (str1_len && (str1[str1_len - 1] == pad)) { - str1_len--; - } - while (str2_len && (str2[str2_len - 1] == pad)) { - str2_len--; - } - - if (str1_len == str2_len) { - return strncmp(str1, str2, str2_len); - } - else if (str1_len > str2_len) { - int ret = strncmp(str1, str2, str2_len); - if (ret == 0) { - ret = 1; - } - return ret; - } - else { - int ret = strncmp(str1, str2, str1_len); - if (ret == 0) { - ret = -1; - } - return ret; - } + size_t str1_len, str2_len; + + while (*str1 == pad) { + str1++; + } + while (*str2 == pad) { + str2++; + } + + str1_len = strlen(str1); + str2_len = strlen(str2); + + while (str1_len && (str1[str1_len - 1] == pad)) { + str1_len--; + } + while (str2_len && (str2[str2_len - 1] == pad)) { + str2_len--; + } + + if (str1_len == str2_len) { + return strncmp(str1, str2, str2_len); + } + else if (str1_len > str2_len) { + int ret = strncmp(str1, str2, str2_len); + if (ret == 0) { + ret = 1; + } + return ret; + } + else { + int ret = strncmp(str1, str2, str1_len); + if (ret == 0) { + ret = -1; + } + return ret; + } } /* determine the length of a fixed-size string */ size_t BLI_strnlen(const char *s, const size_t maxlen) { - size_t len; - - for (len = 0; len < maxlen; len++, s++) { - if (!*s) { - break; - } - } - return len; + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) { + break; + } + } + return len; } void BLI_str_tolower_ascii(char *str, const size_t len) { - size_t i; + size_t i; - for (i = 0; (i < len) && str[i]; i++) { - if (str[i] >= 'A' && str[i] <= 'Z') { - str[i] += 'a' - 'A'; - } - } + for (i = 0; (i < len) && str[i]; i++) { + if (str[i] >= 'A' && str[i] <= 'Z') { + str[i] += 'a' - 'A'; + } + } } void BLI_str_toupper_ascii(char *str, const size_t len) { - size_t i; + size_t i; - for (i = 0; (i < len) && str[i]; i++) { - if (str[i] >= 'a' && str[i] <= 'z') { - str[i] -= 'a' - 'A'; - } - } + for (i = 0; (i < len) && str[i]; i++) { + if (str[i] >= 'a' && str[i] <= 'z') { + str[i] -= 'a' - 'A'; + } + } } /** @@ -800,14 +810,14 @@ void BLI_str_toupper_ascii(char *str, const size_t len) */ void BLI_str_rstrip(char *str) { - for (int i = (int)strlen(str) - 1; i > 0; i--) { - if (isspace(str[i])) { - str[i] = '\0'; - } - else { - break; - } - } + for (int i = (int)strlen(str) - 1; i > 0; i--) { + if (isspace(str[i])) { + str[i] = '\0'; + } + else { + break; + } + } } /** @@ -821,22 +831,22 @@ void BLI_str_rstrip(char *str) */ int BLI_str_rstrip_float_zero(char *str, const char pad) { - char *p = strchr(str, '.'); - int totstrip = 0; - if (p) { - char *end_p; - p++; /* position at first decimal place */ - end_p = p + (strlen(p) - 1); /* position at last character */ - if (end_p > p) { - while (end_p != p && *end_p == '0') { - *end_p = pad; - end_p--; - totstrip++; - } - } - } - - return totstrip; + char *p = strchr(str, '.'); + int totstrip = 0; + if (p) { + char *end_p; + p++; /* position at first decimal place */ + end_p = p + (strlen(p) - 1); /* position at last character */ + if (end_p > p) { + while (end_p != p && *end_p == '0') { + *end_p = pad; + end_p--; + totstrip++; + } + } + } + + return totstrip; } /** @@ -847,17 +857,19 @@ int BLI_str_rstrip_float_zero(char *str, const char pad) * \param str_array_len: The length of the array, or -1 for a NULL-terminated array. * \return The index of str in str_array or -1. */ -int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len) +int BLI_str_index_in_array_n(const char *__restrict str, + const char **__restrict str_array, + const int str_array_len) { - int index; - const char **str_iter = str_array; - - for (index = 0; index < str_array_len; str_iter++, index++) { - if (STREQ(str, *str_iter)) { - return index; - } - } - return -1; + int index; + const char **str_iter = str_array; + + for (index = 0; index < str_array_len; str_iter++, index++) { + if (STREQ(str, *str_iter)) { + return index; + } + } + return -1; } /** @@ -869,31 +881,31 @@ int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict */ int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array) { - int index; - const char **str_iter = str_array; - - for (index = 0; *str_iter; str_iter++, index++) { - if (STREQ(str, *str_iter)) { - return index; - } - } - return -1; + int index; + const char **str_iter = str_array; + + for (index = 0; *str_iter; str_iter++, index++) { + if (STREQ(str, *str_iter)) { + return index; + } + } + return -1; } bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength) { - size_t elength = strlen(end); - - if (elength < slength) { - const char *iter = &str[slength - elength]; - while (*iter) { - if (*iter++ != *end++) { - return false; - } - } - return true; - } - return false; + size_t elength = strlen(end); + + if (elength < slength) { + const char *iter = &str[slength - elength]; + while (*iter) { + if (*iter++ != *end++) { + return false; + } + } + return true; + } + return false; } /** @@ -903,10 +915,10 @@ bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, s * \param end: The string we look for at the end. * \return If str ends with end. */ -bool BLI_str_endswith(const char *__restrict str, const char * __restrict end) +bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) { - const size_t slength = strlen(str); - return BLI_strn_endswith(str, end, slength); + const size_t slength = strlen(str); + return BLI_strn_endswith(str, end, slength); } /** @@ -920,7 +932,7 @@ bool BLI_str_endswith(const char *__restrict str, const char * __restrict end) */ size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf) { - return BLI_str_partition_ex(str, NULL, delim, sep, suf, false); + return BLI_str_partition_ex(str, NULL, delim, sep, suf, false); } /** @@ -934,7 +946,7 @@ size_t BLI_str_partition(const char *str, const char delim[], const char **sep, */ size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf) { - return BLI_str_partition_ex(str, NULL, delim, sep, suf, true); + return BLI_str_partition_ex(str, NULL, delim, sep, suf, true); } /** @@ -948,74 +960,78 @@ size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, * \param from_right: If %true, search from the right of \a str, else, search from its left. * \return The length of the prefix (i.e. *sep - str). */ -size_t BLI_str_partition_ex( - const char *str, const char *end, const char delim[], const char **sep, const char **suf, const bool from_right) +size_t BLI_str_partition_ex(const char *str, + const char *end, + const char delim[], + const char **sep, + const char **suf, + const bool from_right) { - const char *d; - char *(*func)(const char *str, int c) = from_right ? strrchr : strchr; - - BLI_assert(end == NULL || end > str); - - *sep = *suf = NULL; - - for (d = delim; *d != '\0'; ++d) { - const char *tmp; - - if (end) { - if (from_right) { - for (tmp = end - 1; (tmp >= str) && (*tmp != *d); tmp--) { - /* pass */ - } - if (tmp < str) { - tmp = NULL; - } - } - else { - tmp = func(str, *d); - if (tmp >= end) { - tmp = NULL; - } - } - } - else { - tmp = func(str, *d); - } - - if (tmp && (from_right ? (*sep < tmp) : (!*sep || *sep > tmp))) { - *sep = tmp; - } - } - - if (*sep) { - *suf = *sep + 1; - return (size_t)(*sep - str); - } - - return end ? (size_t)(end - str) : strlen(str); + const char *d; + char *(*func)(const char *str, int c) = from_right ? strrchr : strchr; + + BLI_assert(end == NULL || end > str); + + *sep = *suf = NULL; + + for (d = delim; *d != '\0'; ++d) { + const char *tmp; + + if (end) { + if (from_right) { + for (tmp = end - 1; (tmp >= str) && (*tmp != *d); tmp--) { + /* pass */ + } + if (tmp < str) { + tmp = NULL; + } + } + else { + tmp = func(str, *d); + if (tmp >= end) { + tmp = NULL; + } + } + } + else { + tmp = func(str, *d); + } + + if (tmp && (from_right ? (*sep < tmp) : (!*sep || *sep > tmp))) { + *sep = tmp; + } + } + + if (*sep) { + *suf = *sep + 1; + return (size_t)(*sep - str); + } + + return end ? (size_t)(end - str) : strlen(str); } static size_t BLI_str_format_int_grouped_ex(char src[16], char dst[16], int num_len) { - char *p_src = src; - char *p_dst = dst; - - const char separator = ','; - int commas; - - if (*p_src == '-') { - *p_dst++ = *p_src++; - num_len--; - } - - for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) { - *p_dst++ = *p_src++; - if (commas == 1) { - *p_dst++ = separator; - } - } - *--p_dst = '\0'; - - return (size_t)(p_dst - dst); + char *p_src = src; + char *p_dst = dst; + + const char separator = ','; + int commas; + + if (*p_src == '-') { + *p_dst++ = *p_src++; + num_len--; + } + + for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) { + *p_dst++ = *p_src++; + if (commas == 1) { + *p_dst++ = separator; + } + } + *--p_dst = '\0'; + + return (size_t)(p_dst - dst); } /** @@ -1028,10 +1044,10 @@ static size_t BLI_str_format_int_grouped_ex(char src[16], char dst[16], int num_ */ size_t BLI_str_format_int_grouped(char dst[16], int num) { - char src[16]; - int num_len = sprintf(src, "%d", num); + char src[16]; + int num_len = sprintf(src, "%d", num); - return BLI_str_format_int_grouped_ex(src, dst, num_len); + return BLI_str_format_int_grouped_ex(src, dst, num_len); } /** @@ -1044,12 +1060,12 @@ size_t BLI_str_format_int_grouped(char dst[16], int num) */ size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) { - /* NOTE: Buffer to hold maximum unsigned int64, which is 1.8e+19. but - * we also need space for commas and null-terminator. */ - char src[27]; - int num_len = sprintf(src, "%"PRIu64"", num); + /* NOTE: Buffer to hold maximum unsigned int64, which is 1.8e+19. but + * we also need space for commas and null-terminator. */ + char src[27]; + int num_len = sprintf(src, "%" PRIu64 "", num); - return BLI_str_format_int_grouped_ex(src, dst, num_len); + return BLI_str_format_int_grouped_ex(src, dst, num_len); } /** @@ -1063,28 +1079,28 @@ size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) */ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) { - double bytes_converted = bytes; - int order = 0; - int decimals; - const int base = base_10 ? 1000 : 1024; - const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"}; - const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; - const int tot_units = ARRAY_SIZE(units_base_2); - - BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch"); - - while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) { - bytes_converted /= base; - order++; - } - decimals = MAX2(order - 1, 0); - - /* Format value first, stripping away floating zeroes. */ - const size_t dst_len = 15; - size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted); - len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0'); - dst[len++] = ' '; - BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len); + double bytes_converted = bytes; + int order = 0; + int decimals; + const int base = base_10 ? 1000 : 1024; + const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"}; + const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; + const int tot_units = ARRAY_SIZE(units_base_2); + + BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch"); + + while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) { + bytes_converted /= base; + order++; + } + decimals = MAX2(order - 1, 0); + + /* Format value first, stripping away floating zeroes. */ + const size_t dst_len = 15; + size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted); + len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0'); + dst[len++] = ' '; + BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len); } /** @@ -1098,37 +1114,36 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base * \return The number of words found in \a str */ int BLI_string_find_split_words( - const char *str, const size_t len, - const char delim, int r_words[][2], int words_max) + const char *str, const size_t len, const char delim, int r_words[][2], int words_max) { - int n = 0, i; - bool charsearch = true; - - /* Skip leading spaces */ - for (i = 0; (i < len) && (str[i] != '\0'); i++) { - if (str[i] != delim) { - break; - } - } - - for (; (i < len) && (str[i] != '\0') && (n < words_max); i++) { - if ((str[i] != delim) && (charsearch == true)) { - r_words[n][0] = i; - charsearch = false; - } - else { - if ((str[i] == delim) && (charsearch == false)) { - r_words[n][1] = i - r_words[n][0]; - n++; - charsearch = true; - } - } - } - - if (charsearch == false) { - r_words[n][1] = i - r_words[n][0]; - n++; - } - - return n; + int n = 0, i; + bool charsearch = true; + + /* Skip leading spaces */ + for (i = 0; (i < len) && (str[i] != '\0'); i++) { + if (str[i] != delim) { + break; + } + } + + for (; (i < len) && (str[i] != '\0') && (n < words_max); i++) { + if ((str[i] != delim) && (charsearch == true)) { + r_words[n][0] = i; + charsearch = false; + } + else { + if ((str[i] == delim) && (charsearch == false)) { + r_words[n][1] = i - r_words[n][0]; + n++; + charsearch = true; + } + } + } + + if (charsearch == false) { + r_words[n][1] = i - r_words[n][0]; + n++; + } + + return n; } diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index 8839661dea2..1526a052aad 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -34,182 +34,181 @@ #endif typedef enum eStrCursorDelimType { - STRCUR_DELIM_NONE, - STRCUR_DELIM_ALPHANUMERIC, - STRCUR_DELIM_PUNCT, - STRCUR_DELIM_BRACE, - STRCUR_DELIM_OPERATOR, - STRCUR_DELIM_QUOTE, - STRCUR_DELIM_WHITESPACE, - STRCUR_DELIM_OTHER, + STRCUR_DELIM_NONE, + STRCUR_DELIM_ALPHANUMERIC, + STRCUR_DELIM_PUNCT, + STRCUR_DELIM_BRACE, + STRCUR_DELIM_OPERATOR, + STRCUR_DELIM_QUOTE, + STRCUR_DELIM_WHITESPACE, + STRCUR_DELIM_OTHER, } eStrCursorDelimType; static eStrCursorDelimType cursor_delim_type_unicode(const uint uch) { - switch (uch) { - case ',': - case '.': - return STRCUR_DELIM_PUNCT; + switch (uch) { + case ',': + case '.': + return STRCUR_DELIM_PUNCT; - case '{': - case '}': - case '[': - case ']': - case '(': - case ')': - return STRCUR_DELIM_BRACE; + case '{': + case '}': + case '[': + case ']': + case '(': + case ')': + return STRCUR_DELIM_BRACE; - case '+': - case '-': - case '=': - case '~': - case '%': - case '/': - case '<': - case '>': - case '^': - case '*': - case '&': - case '|': - return STRCUR_DELIM_OPERATOR; + case '+': + case '-': + case '=': + case '~': + case '%': + case '/': + case '<': + case '>': + case '^': + case '*': + case '&': + case '|': + return STRCUR_DELIM_OPERATOR; - case '\'': - case '\"': - return STRCUR_DELIM_QUOTE; + case '\'': + case '\"': + return STRCUR_DELIM_QUOTE; - case ' ': - case '\t': - case '\n': - return STRCUR_DELIM_WHITESPACE; + case ' ': + case '\t': + case '\n': + return STRCUR_DELIM_WHITESPACE; - case '\\': - case '@': - case '#': - case '$': - case ':': - case ';': - case '?': - case '!': - case 0xA3: /* pound */ - case 0x80: /* euro */ - /* case '_': *//* special case, for python */ - return STRCUR_DELIM_OTHER; + case '\\': + case '@': + case '#': + case '$': + case ':': + case ';': + case '?': + case '!': + case 0xA3: /* pound */ + case 0x80: /* euro */ + /* case '_': */ /* special case, for python */ + return STRCUR_DELIM_OTHER; - default: - break; - } - return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */ + default: + break; + } + return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */ } static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8) { - /* for full unicode support we really need to have large lookup tables to figure - * out whats what in every possible char set - and python, glib both have these. */ - uint uch = BLI_str_utf8_as_unicode(ch_utf8); - return cursor_delim_type_unicode(uch); + /* for full unicode support we really need to have large lookup tables to figure + * out whats what in every possible char set - and python, glib both have these. */ + uint uch = BLI_str_utf8_as_unicode(ch_utf8); + return cursor_delim_type_unicode(uch); } bool BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos) { - const char *str_end = str + (maxlen + 1); - const char *str_pos = str + (*pos); - const char *str_next = BLI_str_find_next_char_utf8(str_pos, str_end); - if (str_next) { - (*pos) += (str_next - str_pos); - if ((*pos) > (int)maxlen) { - (*pos) = (int)maxlen; - } - return true; - } + const char *str_end = str + (maxlen + 1); + const char *str_pos = str + (*pos); + const char *str_next = BLI_str_find_next_char_utf8(str_pos, str_end); + if (str_next) { + (*pos) += (str_next - str_pos); + if ((*pos) > (int)maxlen) { + (*pos) = (int)maxlen; + } + return true; + } - return false; + return false; } bool BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *pos) { - if ((*pos) > 0) { - const char *str_pos = str + (*pos); - const char *str_prev = BLI_str_find_prev_char_utf8(str, str_pos); - if (str_prev) { - (*pos) -= (str_pos - str_prev); - return true; - } - } + if ((*pos) > 0) { + const char *str_pos = str + (*pos); + const char *str_prev = BLI_str_find_prev_char_utf8(str, str_pos); + if (str_prev) { + (*pos) -= (str_pos - str_prev); + return true; + } + } - return false; + return false; } -void BLI_str_cursor_step_utf8( - const char *str, size_t maxlen, - int *pos, eStrCursorJumpDirection direction, - eStrCursorJumpType jump, bool use_init_step) +void BLI_str_cursor_step_utf8(const char *str, + size_t maxlen, + int *pos, + eStrCursorJumpDirection direction, + eStrCursorJumpType jump, + bool use_init_step) { - const int pos_orig = *pos; + const int pos_orig = *pos; - if (direction == STRCUR_DIR_NEXT) { - if (use_init_step) { - BLI_str_cursor_step_next_utf8(str, maxlen, pos); - } - else { - BLI_assert(jump == STRCUR_JUMP_DELIM); - } + if (direction == STRCUR_DIR_NEXT) { + if (use_init_step) { + BLI_str_cursor_step_next_utf8(str, maxlen, pos); + } + else { + BLI_assert(jump == STRCUR_JUMP_DELIM); + } - if (jump != STRCUR_JUMP_NONE) { - const eStrCursorDelimType delim_type = - (*pos) < maxlen ? cursor_delim_type_utf8(&str[*pos]) : STRCUR_DELIM_NONE; - /* jump between special characters (/,\,_,-, etc.), - * look at function cursor_delim_type() for complete - * list of special character, ctr -> */ - while ((*pos) < maxlen) { - if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && - (delim_type != cursor_delim_type_utf8(&str[*pos]))) - { - break; - } - } - else { - break; /* unlikely but just in case */ - } - } - } - } - else if (direction == STRCUR_DIR_PREV) { - if (use_init_step) { - BLI_str_cursor_step_prev_utf8(str, maxlen, pos); - } - else { - BLI_assert(jump == STRCUR_JUMP_DELIM); - } + if (jump != STRCUR_JUMP_NONE) { + const eStrCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type_utf8(&str[*pos]) : + STRCUR_DELIM_NONE; + /* jump between special characters (/,\,_,-, etc.), + * look at function cursor_delim_type() for complete + * list of special character, ctr -> */ + while ((*pos) < maxlen) { + if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) { + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) { + break; + } + } + else { + break; /* unlikely but just in case */ + } + } + } + } + else if (direction == STRCUR_DIR_PREV) { + if (use_init_step) { + BLI_str_cursor_step_prev_utf8(str, maxlen, pos); + } + else { + BLI_assert(jump == STRCUR_JUMP_DELIM); + } - if (jump != STRCUR_JUMP_NONE) { - const eStrCursorDelimType delim_type = - (*pos) > 0 ? cursor_delim_type_utf8(&str[(*pos) - 1]) : STRCUR_DELIM_NONE; - /* jump between special characters (/,\,_,-, etc.), - * look at function cursor_delim_type() for complete - * list of special character, ctr -> */ - while ((*pos) > 0) { - const int pos_prev = *pos; - if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && - (delim_type != cursor_delim_type_utf8(&str[*pos]))) - { - /* left only: compensate for index/change in direction */ - if ((pos_orig - (*pos)) >= 1) { - *pos = pos_prev; - } - break; - } - } - else { - break; - } - } - } - } - else { - BLI_assert(0); - } + if (jump != STRCUR_JUMP_NONE) { + const eStrCursorDelimType delim_type = (*pos) > 0 ? + cursor_delim_type_utf8(&str[(*pos) - 1]) : + STRCUR_DELIM_NONE; + /* jump between special characters (/,\,_,-, etc.), + * look at function cursor_delim_type() for complete + * list of special character, ctr -> */ + while ((*pos) > 0) { + const int pos_prev = *pos; + if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) { + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_utf8(&str[*pos]))) { + /* left only: compensate for index/change in direction */ + if ((pos_orig - (*pos)) >= 1) { + *pos = pos_prev; + } + break; + } + } + else { + break; + } + } + } + } + else { + BLI_assert(0); + } } /* wchar_t version of BLI_str_cursor_step_utf8 (keep in sync!) @@ -219,91 +218,93 @@ void BLI_str_cursor_step_utf8( /* helper funcs so we can match BLI_str_cursor_step_utf8 */ static bool wchar_t_step_next(const wchar_t *UNUSED(str), size_t maxlen, int *pos) { - if ((*pos) >= (int)maxlen) { - return false; - } - (*pos)++; - return true; + if ((*pos) >= (int)maxlen) { + return false; + } + (*pos)++; + return true; } static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen), int *pos) { - if ((*pos) <= 0) { - return false; - } - (*pos)--; - return true; + if ((*pos) <= 0) { + return false; + } + (*pos)--; + return true; } -void BLI_str_cursor_step_wchar( - const wchar_t *str, size_t maxlen, - int *pos, eStrCursorJumpDirection direction, - eStrCursorJumpType jump, bool use_init_step) +void BLI_str_cursor_step_wchar(const wchar_t *str, + size_t maxlen, + int *pos, + eStrCursorJumpDirection direction, + eStrCursorJumpType jump, + bool use_init_step) { - const int pos_orig = *pos; + const int pos_orig = *pos; - if (direction == STRCUR_DIR_NEXT) { - if (use_init_step) { - wchar_t_step_next(str, maxlen, pos); - } - else { - BLI_assert(jump == STRCUR_JUMP_DELIM); - } + if (direction == STRCUR_DIR_NEXT) { + if (use_init_step) { + wchar_t_step_next(str, maxlen, pos); + } + else { + BLI_assert(jump == STRCUR_JUMP_DELIM); + } - if (jump != STRCUR_JUMP_NONE) { - const eStrCursorDelimType delim_type = - (*pos) < maxlen ? cursor_delim_type_unicode((uint)str[*pos]) : STRCUR_DELIM_NONE; - /* jump between special characters (/,\,_,-, etc.), - * look at function cursor_delim_type_unicode() for complete - * list of special character, ctr -> */ - while ((*pos) < maxlen) { - if (wchar_t_step_next(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && - (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) - { - break; - } - } - else { - break; /* unlikely but just in case */ - } - } - } - } - else if (direction == STRCUR_DIR_PREV) { - if (use_init_step) { - wchar_t_step_prev(str, maxlen, pos); - } - else { - BLI_assert(jump == STRCUR_JUMP_DELIM); - } + if (jump != STRCUR_JUMP_NONE) { + const eStrCursorDelimType delim_type = (*pos) < maxlen ? + cursor_delim_type_unicode((uint)str[*pos]) : + STRCUR_DELIM_NONE; + /* jump between special characters (/,\,_,-, etc.), + * look at function cursor_delim_type_unicode() for complete + * list of special character, ctr -> */ + while ((*pos) < maxlen) { + if (wchar_t_step_next(str, maxlen, pos)) { + if ((jump != STRCUR_JUMP_ALL) && + (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) { + break; + } + } + else { + break; /* unlikely but just in case */ + } + } + } + } + else if (direction == STRCUR_DIR_PREV) { + if (use_init_step) { + wchar_t_step_prev(str, maxlen, pos); + } + else { + BLI_assert(jump == STRCUR_JUMP_DELIM); + } - if (jump != STRCUR_JUMP_NONE) { - const eStrCursorDelimType delim_type = - (*pos) > 0 ? cursor_delim_type_unicode((uint)str[(*pos) - 1]) : STRCUR_DELIM_NONE; - /* jump between special characters (/,\,_,-, etc.), - * look at function cursor_delim_type() for complete - * list of special character, ctr -> */ - while ((*pos) > 0) { - const int pos_prev = *pos; - if (wchar_t_step_prev(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && - (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) - { - /* left only: compensate for index/change in direction */ - if ((pos_orig - (*pos)) >= 1) { - *pos = pos_prev; - } - break; - } - } - else { - break; - } - } - } - } - else { - BLI_assert(0); - } + if (jump != STRCUR_JUMP_NONE) { + const eStrCursorDelimType delim_type = (*pos) > 0 ? + cursor_delim_type_unicode((uint)str[(*pos) - 1]) : + STRCUR_DELIM_NONE; + /* jump between special characters (/,\,_,-, etc.), + * look at function cursor_delim_type() for complete + * list of special character, ctr -> */ + while ((*pos) > 0) { + const int pos_prev = *pos; + if (wchar_t_step_prev(str, maxlen, pos)) { + if ((jump != STRCUR_JUMP_ALL) && + (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) { + /* left only: compensate for index/change in direction */ + if ((pos_orig - (*pos)) >= 1) { + *pos = pos_prev; + } + break; + } + } + else { + break; + } + } + } + } + else { + BLI_assert(0); + } } diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 0c07d1c361a..01412416854 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -32,7 +32,7 @@ #include "BLI_utildefines.h" -#include "BLI_string_utf8.h" /* own include */ +#include "BLI_string_utf8.h" /* own include */ #ifdef __GNUC__ # pragma GCC diagnostic error "-Wsign-conversion" @@ -44,14 +44,14 @@ /* Note: last two values (0xfe and 0xff) are forbidden in utf-8, * so they are considered 1 byte length too. */ static const size_t utf8_skip_data[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1, }; /* from libswish3, originally called u8_isvalid(), @@ -70,97 +70,127 @@ static const size_t utf8_skip_data[256] = { */ ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length) { - const unsigned char *p, *perr, *pend = (const unsigned char *)str + length; - unsigned char c; - int ab; - - for (p = (const unsigned char *)str; p < pend; p++, length--) { - c = *p; - perr = p; /* Erroneous char is always the first of an invalid utf8 sequence... */ - if (ELEM(c, 0xfe, 0xff, 0x00)) { - /* Those three values are not allowed in utf8 string. */ - goto utf8_error; - } - if (c < 128) { - continue; - } - if ((c & 0xc0) != 0xc0) { - goto utf8_error; - } - - /* Note that since we always increase p (and decrease length) by one byte in main loop, - * we only add/subtract extra utf8 bytes in code below - * (ab number, aka number of bytes remaining in the utf8 sequence after the initial one). */ - ab = (int)utf8_skip_data[c] - 1; - if (length <= ab) { - goto utf8_error; - } - - /* Check top bits in the second byte */ - p++; - length--; - if ((*p & 0xc0) != 0x80) { - goto utf8_error; - } - - /* Check for overlong sequences for each different length */ - switch (ab) { - case 1: - /* Check for xx00 000x */ - if ((c & 0x3e) == 0) { goto utf8_error; } - continue; /* We know there aren't any more bytes to check */ - - case 2: - /* Check for 1110 0000, xx0x xxxx */ - if (c == 0xe0 && (*p & 0x20) == 0) { goto utf8_error; } - /* Some special cases, see section 5 of utf-8 decoder stress-test by Markus Kuhn - * (https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt). */ - /* From section 5.1 (and 5.2) */ - if (c == 0xed) { - if (*p == 0xa0 && *(p + 1) == 0x80) { goto utf8_error; } - if (*p == 0xad && *(p + 1) == 0xbf) { goto utf8_error; } - if (*p == 0xae && *(p + 1) == 0x80) { goto utf8_error; } - if (*p == 0xaf && *(p + 1) == 0xbf) { goto utf8_error; } - if (*p == 0xb0 && *(p + 1) == 0x80) { goto utf8_error; } - if (*p == 0xbe && *(p + 1) == 0x80) { goto utf8_error; } - if (*p == 0xbf && *(p + 1) == 0xbf) { goto utf8_error; } - } - /* From section 5.3 */ - if (c == 0xef) { - if (*p == 0xbf && *(p + 1) == 0xbe) { goto utf8_error; } - if (*p == 0xbf && *(p + 1) == 0xbf) { goto utf8_error; } - } - break; - - case 3: - /* Check for 1111 0000, xx00 xxxx */ - if (c == 0xf0 && (*p & 0x30) == 0) { goto utf8_error; } - break; - - case 4: - /* Check for 1111 1000, xx00 0xxx */ - if (c == 0xf8 && (*p & 0x38) == 0) { goto utf8_error; } - break; - - case 5: - /* Check for 1111 1100, xx00 00xx */ - if (c == 0xfc && (*p & 0x3c) == 0) { goto utf8_error; } - break; - } - - /* Check for valid bytes after the 2nd, if any; all must start 10 */ - while (--ab > 0) { - p++; - length--; - if ((*p & 0xc0) != 0x80) { goto utf8_error; } - } - } - - return -1; + const unsigned char *p, *perr, *pend = (const unsigned char *)str + length; + unsigned char c; + int ab; + + for (p = (const unsigned char *)str; p < pend; p++, length--) { + c = *p; + perr = p; /* Erroneous char is always the first of an invalid utf8 sequence... */ + if (ELEM(c, 0xfe, 0xff, 0x00)) { + /* Those three values are not allowed in utf8 string. */ + goto utf8_error; + } + if (c < 128) { + continue; + } + if ((c & 0xc0) != 0xc0) { + goto utf8_error; + } + + /* Note that since we always increase p (and decrease length) by one byte in main loop, + * we only add/subtract extra utf8 bytes in code below + * (ab number, aka number of bytes remaining in the utf8 sequence after the initial one). */ + ab = (int)utf8_skip_data[c] - 1; + if (length <= ab) { + goto utf8_error; + } + + /* Check top bits in the second byte */ + p++; + length--; + if ((*p & 0xc0) != 0x80) { + goto utf8_error; + } + + /* Check for overlong sequences for each different length */ + switch (ab) { + case 1: + /* Check for xx00 000x */ + if ((c & 0x3e) == 0) { + goto utf8_error; + } + continue; /* We know there aren't any more bytes to check */ + + case 2: + /* Check for 1110 0000, xx0x xxxx */ + if (c == 0xe0 && (*p & 0x20) == 0) { + goto utf8_error; + } + /* Some special cases, see section 5 of utf-8 decoder stress-test by Markus Kuhn + * (https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt). */ + /* From section 5.1 (and 5.2) */ + if (c == 0xed) { + if (*p == 0xa0 && *(p + 1) == 0x80) { + goto utf8_error; + } + if (*p == 0xad && *(p + 1) == 0xbf) { + goto utf8_error; + } + if (*p == 0xae && *(p + 1) == 0x80) { + goto utf8_error; + } + if (*p == 0xaf && *(p + 1) == 0xbf) { + goto utf8_error; + } + if (*p == 0xb0 && *(p + 1) == 0x80) { + goto utf8_error; + } + if (*p == 0xbe && *(p + 1) == 0x80) { + goto utf8_error; + } + if (*p == 0xbf && *(p + 1) == 0xbf) { + goto utf8_error; + } + } + /* From section 5.3 */ + if (c == 0xef) { + if (*p == 0xbf && *(p + 1) == 0xbe) { + goto utf8_error; + } + if (*p == 0xbf && *(p + 1) == 0xbf) { + goto utf8_error; + } + } + break; + + case 3: + /* Check for 1111 0000, xx00 xxxx */ + if (c == 0xf0 && (*p & 0x30) == 0) { + goto utf8_error; + } + break; + + case 4: + /* Check for 1111 1000, xx00 0xxx */ + if (c == 0xf8 && (*p & 0x38) == 0) { + goto utf8_error; + } + break; + + case 5: + /* Check for 1111 1100, xx00 00xx */ + if (c == 0xfc && (*p & 0x3c) == 0) { + goto utf8_error; + } + break; + } + + /* Check for valid bytes after the 2nd, if any; all must start 10 */ + while (--ab > 0) { + p++; + length--; + if ((*p & 0xc0) != 0x80) { + goto utf8_error; + } + } + } + + return -1; utf8_error: - return ((const char *)perr - (const char *)str); + return ((const char *)perr - (const char *)str); } /** @@ -170,97 +200,108 @@ utf8_error: */ int BLI_utf8_invalid_strip(char *str, size_t length) { - ptrdiff_t bad_char; - int tot = 0; - - BLI_assert(str[length] == '\0'); - - while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) { - str += bad_char; - length -= (size_t)(bad_char + 1); - - if (length == 0) { - /* last character bad, strip it */ - *str = '\0'; - tot++; - break; - } - else { - /* strip, keep looking */ - memmove(str, str + 1, length + 1); /* +1 for NULL char! */ - tot++; - } - } - - return tot; + ptrdiff_t bad_char; + int tot = 0; + + BLI_assert(str[length] == '\0'); + + while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) { + str += bad_char; + length -= (size_t)(bad_char + 1); + + if (length == 0) { + /* last character bad, strip it */ + *str = '\0'; + tot++; + break; + } + else { + /* strip, keep looking */ + memmove(str, str + 1, length + 1); /* +1 for NULL char! */ + tot++; + } + } + + return tot; } - /* compatible with BLI_strncpy, but esnure no partial utf8 chars */ -#define BLI_STR_UTF8_CPY(dst, src, maxncpy) \ - { \ - size_t utf8_size; \ - while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) {\ - maxncpy -= utf8_size; \ - switch (utf8_size) { \ - case 6: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ - case 5: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ - case 4: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ - case 3: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ - case 2: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ - case 1: *dst ++ = *src ++; \ - } \ - } \ - *dst = '\0'; \ - } (void)0 +#define BLI_STR_UTF8_CPY(dst, src, maxncpy) \ + { \ + size_t utf8_size; \ + while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) { \ + maxncpy -= utf8_size; \ + switch (utf8_size) { \ + case 6: \ + *dst++ = *src++; \ + ATTR_FALLTHROUGH; \ + case 5: \ + *dst++ = *src++; \ + ATTR_FALLTHROUGH; \ + case 4: \ + *dst++ = *src++; \ + ATTR_FALLTHROUGH; \ + case 3: \ + *dst++ = *src++; \ + ATTR_FALLTHROUGH; \ + case 2: \ + *dst++ = *src++; \ + ATTR_FALLTHROUGH; \ + case 1: \ + *dst++ = *src++; \ + } \ + } \ + *dst = '\0'; \ + } \ + (void)0 char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { - char *r_dst = dst; + char *r_dst = dst; - BLI_assert(maxncpy != 0); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - /* note: currently we don't attempt to deal with invalid utf8 chars */ - BLI_STR_UTF8_CPY(dst, src, maxncpy); + /* note: currently we don't attempt to deal with invalid utf8 chars */ + BLI_STR_UTF8_CPY(dst, src, maxncpy); - return r_dst; + return r_dst; } size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) { - char *r_dst = dst; + char *r_dst = dst; - BLI_assert(maxncpy != 0); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - /* note: currently we don't attempt to deal with invalid utf8 chars */ - BLI_STR_UTF8_CPY(dst, src, maxncpy); + /* note: currently we don't attempt to deal with invalid utf8 chars */ + BLI_STR_UTF8_CPY(dst, src, maxncpy); - return (size_t)(dst - r_dst); + return (size_t)(dst - r_dst); } char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { - while (*dst && maxncpy > 0) { - dst++; - maxncpy--; - } + while (*dst && maxncpy > 0) { + dst++; + maxncpy--; + } #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - BLI_STR_UTF8_CPY(dst, src, maxncpy); + BLI_STR_UTF8_CPY(dst, src, maxncpy); - return dst; + return dst; } #undef BLI_STR_UTF8_CPY @@ -268,89 +309,91 @@ char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t /* --------------------------------------------------------------------------*/ /* wchar_t / utf8 functions */ -size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, + const wchar_t *__restrict src, + const size_t maxncpy) { - const size_t maxlen = maxncpy - 1; - /* 6 is max utf8 length of an unicode char. */ - const int64_t maxlen_secured = (int64_t)maxlen - 6; - size_t len = 0; + const size_t maxlen = maxncpy - 1; + /* 6 is max utf8 length of an unicode char. */ + const int64_t maxlen_secured = (int64_t)maxlen - 6; + size_t len = 0; - BLI_assert(maxncpy != 0); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxncpy); + memset(dst, 0xff, sizeof(*dst) * maxncpy); #endif - while (*src && len <= maxlen_secured) { - len += BLI_str_utf8_from_unicode((uint)*src++, dst + len); - } - - /* We have to be more careful for the last six bytes, - * to avoid buffer overflow in case utf8-encoded char would be too long for our dst buffer. */ - while (*src) { - char t[6]; - size_t l = BLI_str_utf8_from_unicode((uint)*src++, t); - BLI_assert(l <= 6); - if (len + l > maxlen) { - break; - } - memcpy(dst + len, t, l); - len += l; - } - - dst[len] = '\0'; - - return len; + while (*src && len <= maxlen_secured) { + len += BLI_str_utf8_from_unicode((uint)*src++, dst + len); + } + + /* We have to be more careful for the last six bytes, + * to avoid buffer overflow in case utf8-encoded char would be too long for our dst buffer. */ + while (*src) { + char t[6]; + size_t l = BLI_str_utf8_from_unicode((uint)*src++, t); + BLI_assert(l <= 6); + if (len + l > maxlen) { + break; + } + memcpy(dst + len, t, l); + len += l; + } + + dst[len] = '\0'; + + return len; } /* wchar len in utf8 */ size_t BLI_wstrlen_utf8(const wchar_t *src) { - size_t len = 0; + size_t len = 0; - while (*src) { - len += BLI_str_utf8_from_unicode((uint)*src++, NULL); - } + while (*src) { + len += BLI_str_utf8_from_unicode((uint)*src++, NULL); + } - return len; + return len; } size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) { - size_t len; - const char *strc_orig = strc; + size_t len; + const char *strc_orig = strc; - for (len = 0; *strc; len++) { - strc += BLI_str_utf8_size_safe(strc); - } + for (len = 0; *strc; len++) { + strc += BLI_str_utf8_size_safe(strc); + } - *r_len_bytes = (size_t)(strc - strc_orig); - return len; + *r_len_bytes = (size_t)(strc - strc_orig); + return len; } size_t BLI_strlen_utf8(const char *strc) { - size_t len; + size_t len; - for (len = 0; *strc; len++) { - strc += BLI_str_utf8_size_safe(strc); - } + for (len = 0; *strc; len++) { + strc += BLI_str_utf8_size_safe(strc); + } - return len; + return len; } size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) { - size_t len; - const char *strc_orig = strc; - const char *strc_end = strc + maxlen; + size_t len; + const char *strc_orig = strc; + const char *strc_end = strc + maxlen; - for (len = 0; *strc && strc < strc_end; len++) { - strc += BLI_str_utf8_size_safe(strc); - } + for (len = 0; *strc && strc < strc_end; len++) { + strc += BLI_str_utf8_size_safe(strc); + } - *r_len_bytes = (size_t)(strc - strc_orig); - return len; + *r_len_bytes = (size_t)(strc - strc_orig); + return len; } /** @@ -360,45 +403,47 @@ size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_ */ size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) { - size_t len; - const char *strc_end = strc + maxlen; + size_t len; + const char *strc_end = strc + maxlen; - for (len = 0; *strc && strc < strc_end; len++) { - strc += BLI_str_utf8_size_safe(strc); - } + for (len = 0; *strc && strc < strc_end; len++) { + strc += BLI_str_utf8_size_safe(strc); + } - return len; + return len; } -size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, + const char *__restrict src_c, + const size_t maxncpy) { - const size_t maxlen = maxncpy - 1; - size_t len = 0; + const size_t maxlen = maxncpy - 1; + size_t len = 0; - BLI_assert(maxncpy != 0); + BLI_assert(maxncpy != 0); #ifdef DEBUG_STRSIZE - memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy); + memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy); #endif - while (*src_c && len != maxlen) { - size_t step = 0; - uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step); - if (unicode != BLI_UTF8_ERR) { - *dst_w = (wchar_t)unicode; - src_c += step; - } - else { - *dst_w = '?'; - src_c = BLI_str_find_next_char_utf8(src_c, NULL); - } - dst_w++; - len++; - } - - *dst_w = 0; - - return len; + while (*src_c && len != maxlen) { + size_t step = 0; + uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step); + if (unicode != BLI_UTF8_ERR) { + *dst_w = (wchar_t)unicode; + src_c += step; + } + else { + *dst_w = '?'; + src_c = BLI_str_find_next_char_utf8(src_c, NULL); + } + dst_w++; + len++; + } + + *dst_w = 0; + + return len; } /* end wchar_t / utf8 functions */ @@ -408,36 +453,36 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest int BLI_wcwidth(wchar_t ucs) { - return mk_wcwidth(ucs); + return mk_wcwidth(ucs); } int BLI_wcswidth(const wchar_t *pwcs, size_t n) { - return mk_wcswidth(pwcs, n); + return mk_wcswidth(pwcs, n); } int BLI_str_utf8_char_width(const char *p) { - uint unicode = BLI_str_utf8_as_unicode(p); - if (unicode == BLI_UTF8_ERR) { - return -1; - } + uint unicode = BLI_str_utf8_as_unicode(p); + if (unicode == BLI_UTF8_ERR) { + return -1; + } - return BLI_wcwidth((wchar_t)unicode); + return BLI_wcwidth((wchar_t)unicode); } int BLI_str_utf8_char_width_safe(const char *p) { - int columns; + int columns; - uint unicode = BLI_str_utf8_as_unicode(p); - if (unicode == BLI_UTF8_ERR) { - return 1; - } + uint unicode = BLI_str_utf8_as_unicode(p); + if (unicode == BLI_UTF8_ERR) { + return 1; + } - columns = BLI_wcwidth((wchar_t)unicode); + columns = BLI_wcwidth((wchar_t)unicode); - return (columns < 0) ? 1 : columns; + return (columns < 0) ? 1 : columns; } /* --------------------------------------------------------------------------*/ @@ -447,73 +492,74 @@ int BLI_str_utf8_char_width_safe(const char *p) /* note, glib uses uint for unicode, best we do the same, * though we don't typedef it - campbell */ -#define UTF8_COMPUTE(Char, Mask, Len, Err) \ - if (Char < 128) { \ - Len = 1; \ - Mask = 0x7f; \ - } \ - else if ((Char & 0xe0) == 0xc0) { \ - Len = 2; \ - Mask = 0x1f; \ - } \ - else if ((Char & 0xf0) == 0xe0) { \ - Len = 3; \ - Mask = 0x0f; \ - } \ - else if ((Char & 0xf8) == 0xf0) { \ - Len = 4; \ - Mask = 0x07; \ - } \ - else if ((Char & 0xfc) == 0xf8) { \ - Len = 5; \ - Mask = 0x03; \ - } \ - else if ((Char & 0xfe) == 0xfc) { \ - Len = 6; \ - Mask = 0x01; \ - } \ - else { \ - Len = Err; /* -1 is the typical error value or 1 to skip */ \ - } (void)0 +#define UTF8_COMPUTE(Char, Mask, Len, Err) \ + if (Char < 128) { \ + Len = 1; \ + Mask = 0x7f; \ + } \ + else if ((Char & 0xe0) == 0xc0) { \ + Len = 2; \ + Mask = 0x1f; \ + } \ + else if ((Char & 0xf0) == 0xe0) { \ + Len = 3; \ + Mask = 0x0f; \ + } \ + else if ((Char & 0xf8) == 0xf0) { \ + Len = 4; \ + Mask = 0x07; \ + } \ + else if ((Char & 0xfc) == 0xf8) { \ + Len = 5; \ + Mask = 0x03; \ + } \ + else if ((Char & 0xfe) == 0xfc) { \ + Len = 6; \ + Mask = 0x01; \ + } \ + else { \ + Len = Err; /* -1 is the typical error value or 1 to skip */ \ + } \ + (void)0 /* same as glib define but added an 'Err' arg */ -#define UTF8_GET(Result, Chars, Count, Mask, Len, Err) \ - (Result) = (Chars)[0] & (Mask); \ - for ((Count) = 1; (Count) < (Len); ++(Count)) { \ - if (((Chars)[(Count)] & 0xc0) != 0x80) { \ - (Result) = Err; \ - break; \ - } \ - (Result) <<= 6; \ - (Result) |= ((Chars)[(Count)] & 0x3f); \ - } (void)0 - +#define UTF8_GET(Result, Chars, Count, Mask, Len, Err) \ + (Result) = (Chars)[0] & (Mask); \ + for ((Count) = 1; (Count) < (Len); ++(Count)) { \ + if (((Chars)[(Count)] & 0xc0) != 0x80) { \ + (Result) = Err; \ + break; \ + } \ + (Result) <<= 6; \ + (Result) |= ((Chars)[(Count)] & 0x3f); \ + } \ + (void)0 /* uses glib functions but not from glib */ /* gets the size of a single utf8 char */ int BLI_str_utf8_size(const char *p) { - int mask = 0, len; - const unsigned char c = (unsigned char) *p; + int mask = 0, len; + const unsigned char c = (unsigned char)*p; - UTF8_COMPUTE(c, mask, len, -1); + UTF8_COMPUTE(c, mask, len, -1); - (void)mask; /* quiet warning */ + (void)mask; /* quiet warning */ - return len; + return len; } /* use when we want to skip errors */ int BLI_str_utf8_size_safe(const char *p) { - int mask = 0, len; - const unsigned char c = (unsigned char) *p; + int mask = 0, len; + const unsigned char c = (unsigned char)*p; - UTF8_COMPUTE(c, mask, len, 1); + UTF8_COMPUTE(c, mask, len, 1); - (void)mask; /* quiet warning */ + (void)mask; /* quiet warning */ - return len; + return len; } /* was g_utf8_get_char */ @@ -531,98 +577,98 @@ int BLI_str_utf8_size_safe(const char *p) */ uint BLI_str_utf8_as_unicode(const char *p) { - int i, len; - uint mask = 0; - uint result; - const unsigned char c = (unsigned char) *p; - - UTF8_COMPUTE(c, mask, len, -1); - if (UNLIKELY(len == -1)) { - return BLI_UTF8_ERR; - } - UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); - - return result; + int i, len; + uint mask = 0; + uint result; + const unsigned char c = (unsigned char)*p; + + UTF8_COMPUTE(c, mask, len, -1); + if (UNLIKELY(len == -1)) { + return BLI_UTF8_ERR; + } + UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); + + return result; } /* variant that increments the length */ uint BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) { - int i, len; - unsigned mask = 0; - uint result; - const unsigned char c = (unsigned char) *p; - - UTF8_COMPUTE(c, mask, len, -1); - if (UNLIKELY(len == -1)) { - return BLI_UTF8_ERR; - } - UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); - *index += (size_t)len; - return result; + int i, len; + unsigned mask = 0; + uint result; + const unsigned char c = (unsigned char)*p; + + UTF8_COMPUTE(c, mask, len, -1); + if (UNLIKELY(len == -1)) { + return BLI_UTF8_ERR; + } + UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); + *index += (size_t)len; + return result; } uint BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) { - int i, len; - uint mask = 0; - uint result; - const unsigned char c = (unsigned char) *p; - - UTF8_COMPUTE(c, mask, len, -1); - if (UNLIKELY(len == -1)) { - *index += 1; - return c; - } - UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); - *index += (size_t)len; - return result; + int i, len; + uint mask = 0; + uint result; + const unsigned char c = (unsigned char)*p; + + UTF8_COMPUTE(c, mask, len, -1); + if (UNLIKELY(len == -1)) { + *index += 1; + return c; + } + UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); + *index += (size_t)len; + return result; } /* another variant that steps over the index, * note, currently this also falls back to latin1 for text drawing. */ uint BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) { - int i, len; - uint mask = 0; - uint result; - unsigned char c; - - p += *index; - c = (unsigned char) *p; - - UTF8_COMPUTE(c, mask, len, -1); - if (UNLIKELY(len == -1)) { - /* when called with NULL end, result will never be NULL, - * checks for a NULL character */ - const char *p_next = BLI_str_find_next_char_utf8(p, NULL); - /* will never return the same pointer unless '\0', - * eternal loop is prevented */ - *index += (size_t)(p_next - p); - return BLI_UTF8_ERR; - } - - /* this is tricky since there are a few ways we can bail out of bad unicode - * values, 3 possible solutions. */ + int i, len; + uint mask = 0; + uint result; + unsigned char c; + + p += *index; + c = (unsigned char)*p; + + UTF8_COMPUTE(c, mask, len, -1); + if (UNLIKELY(len == -1)) { + /* when called with NULL end, result will never be NULL, + * checks for a NULL character */ + const char *p_next = BLI_str_find_next_char_utf8(p, NULL); + /* will never return the same pointer unless '\0', + * eternal loop is prevented */ + *index += (size_t)(p_next - p); + return BLI_UTF8_ERR; + } + + /* this is tricky since there are a few ways we can bail out of bad unicode + * values, 3 possible solutions. */ #if 0 - UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); + UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); #elif 1 - /* WARNING: this is NOT part of glib, or supported by similar functions. - * this is added for text drawing because some filepaths can have latin1 - * characters */ - UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); - if (result == BLI_UTF8_ERR) { - len = 1; - result = *p; - } - /* end warning! */ + /* WARNING: this is NOT part of glib, or supported by similar functions. + * this is added for text drawing because some filepaths can have latin1 + * characters */ + UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR); + if (result == BLI_UTF8_ERR) { + len = 1; + result = *p; + } + /* end warning! */ #else - /* without a fallback like '?', text drawing will stop on this value */ - UTF8_GET(result, p, i, mask, len, '?'); + /* without a fallback like '?', text drawing will stop on this value */ + UTF8_GET(result, p, i, mask, len, '?'); #endif - *index += (size_t)len; - return result; + *index += (size_t)len; + return result; } /* was g_unichar_to_utf8 */ @@ -639,45 +685,45 @@ uint BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict i */ size_t BLI_str_utf8_from_unicode(uint c, char *outbuf) { - /* If this gets modified, also update the copy in g_string_insert_unichar() */ - uint len = 0; - uint first; - uint i; - - if (c < 0x80) { - first = 0; - len = 1; - } - else if (c < 0x800) { - first = 0xc0; - len = 2; - } - else if (c < 0x10000) { - first = 0xe0; - len = 3; - } - else if (c < 0x200000) { - first = 0xf0; - len = 4; - } - else if (c < 0x4000000) { - first = 0xf8; - len = 5; - } - else { - first = 0xfc; - len = 6; - } - - if (outbuf) { - for (i = len - 1; i > 0; --i) { - outbuf[i] = (c & 0x3f) | 0x80; - c >>= 6; - } - outbuf[0] = c | first; - } - - return len; + /* If this gets modified, also update the copy in g_string_insert_unichar() */ + uint len = 0; + uint first; + uint i; + + if (c < 0x80) { + first = 0; + len = 1; + } + else if (c < 0x800) { + first = 0xc0; + len = 2; + } + else if (c < 0x10000) { + first = 0xe0; + len = 3; + } + else if (c < 0x200000) { + first = 0xf0; + len = 4; + } + else if (c < 0x4000000) { + first = 0xf8; + len = 5; + } + else { + first = 0xfc; + len = 6; + } + + if (outbuf) { + for (i = len - 1; i > 0; --i) { + outbuf[i] = (c & 0x3f) | 0x80; + c >>= 6; + } + outbuf[0] = c | first; + } + + return len; } /* was g_utf8_find_prev_char */ @@ -698,12 +744,12 @@ size_t BLI_str_utf8_from_unicode(uint c, char *outbuf) */ char *BLI_str_find_prev_char_utf8(const char *str, const char *p) { - for (--p; p >= str; --p) { - if ((*p & 0xc0) != 0x80) { - return (char *)p; - } - } - return NULL; + for (--p; p >= str; --p) { + if ((*p & 0xc0) != 0x80) { + return (char *)p; + } + } + return NULL; } /* was g_utf8_find_next_char */ @@ -723,19 +769,19 @@ char *BLI_str_find_prev_char_utf8(const char *str, const char *p) */ char *BLI_str_find_next_char_utf8(const char *p, const char *end) { - if (*p) { - if (end) { - for (++p; p < end && (*p & 0xc0) == 0x80; ++p) { - /* do nothing */ - } - } - else { - for (++p; (*p & 0xc0) == 0x80; ++p) { - /* do nothing */ - } - } - } - return (p == end) ? NULL : (char *)p; + if (*p) { + if (end) { + for (++p; p < end && (*p & 0xc0) == 0x80; ++p) { + /* do nothing */ + } + } + else { + for (++p; (*p & 0xc0) == 0x80; ++p) { + /* do nothing */ + } + } + } + return (p == end) ? NULL : (char *)p; } /* was g_utf8_prev_char */ @@ -754,61 +800,71 @@ char *BLI_str_find_next_char_utf8(const char *p, const char *end) */ char *BLI_str_prev_char_utf8(const char *p) { - while (1) { - p--; - if ((*p & 0xc0) != 0x80) { - return (char *)p; - } - } + while (1) { + p--; + if ((*p & 0xc0) != 0x80) { + return (char *)p; + } + } } /* end glib copy */ -size_t BLI_str_partition_utf8(const char *str, const uint delim[], const char **sep, const char **suf) +size_t BLI_str_partition_utf8(const char *str, + const uint delim[], + const char **sep, + const char **suf) { - return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, false); + return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, false); } -size_t BLI_str_rpartition_utf8(const char *str, const uint delim[], const char **sep, const char **suf) +size_t BLI_str_rpartition_utf8(const char *str, + const uint delim[], + const char **sep, + const char **suf) { - return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, true); + return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, true); } -size_t BLI_str_partition_ex_utf8( - const char *str, const char *end, const uint delim[], const char **sep, const char **suf, const bool from_right) +size_t BLI_str_partition_ex_utf8(const char *str, + const char *end, + const uint delim[], + const char **sep, + const char **suf, + const bool from_right) { - const uint *d; - const size_t str_len = end ? (size_t)(end - str) : strlen(str); - size_t index; - - /* Note that here, we assume end points to a valid utf8 char! */ - BLI_assert(end == NULL || (end >= str && (BLI_str_utf8_as_unicode(end) != BLI_UTF8_ERR))); - - *suf = (char *)(str + str_len); - - for (*sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, str + str_len) : str), index = 0; - *sep >= str && (!end || *sep < end) && **sep != '\0'; - *sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, *sep) : str + index)) - { - const uint c = BLI_str_utf8_as_unicode_and_size(*sep, &index); - - if (c == BLI_UTF8_ERR) { - *suf = *sep = NULL; - break; - } - - for (d = delim; *d != '\0'; ++d) { - if (*d == c) { - /* *suf is already correct in case from_right is true. */ - if (!from_right) { - *suf = (char *)(str + index); - } - return (size_t)(*sep - str); - } - } - - *suf = *sep; /* Useful in 'from_right' case! */ - } - - *suf = *sep = NULL; - return str_len; + const uint *d; + const size_t str_len = end ? (size_t)(end - str) : strlen(str); + size_t index; + + /* Note that here, we assume end points to a valid utf8 char! */ + BLI_assert(end == NULL || (end >= str && (BLI_str_utf8_as_unicode(end) != BLI_UTF8_ERR))); + + *suf = (char *)(str + str_len); + + for (*sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, str + str_len) : str), + index = 0; + *sep >= str && (!end || *sep < end) && **sep != '\0'; + *sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(str, *sep) : str + index)) { + const uint c = BLI_str_utf8_as_unicode_and_size(*sep, &index); + + if (c == BLI_UTF8_ERR) { + *suf = *sep = NULL; + break; + } + + for (d = delim; *d != '\0'; ++d) { + if (*d == c) { + /* *suf is already correct in case from_right is true. */ + if (!from_right) { + *suf = (char *)(str + index); + } + return (size_t)(*sep - str); + } + } + + *suf = *sep; /* Useful in 'from_right' case! */ + } + + *suf = *sep = NULL; + return str_len; } diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c index 46472d8125d..9b6ffd85341 100644 --- a/source/blender/blenlib/intern/string_utils.c +++ b/source/blender/blenlib/intern/string_utils.c @@ -34,7 +34,6 @@ #include "DNA_listBase.h" - #ifdef __GNUC__ # pragma GCC diagnostic error "-Wsign-conversion" #endif @@ -55,37 +54,37 @@ */ size_t BLI_split_name_num(char *left, int *nr, const char *name, const char delim) { - const size_t name_len = strlen(name); - - *nr = 0; - memcpy(left, name, (name_len + 1) * sizeof(char)); - - /* name doesn't end with a delimiter "foo." */ - if ((name_len > 1 && name[name_len - 1] == delim) == 0) { - size_t a = name_len; - while (a--) { - if (name[a] == delim) { - left[a] = '\0'; /* truncate left part here */ - *nr = atol(name + a + 1); - /* casting down to an int, can overflow for large numbers */ - if (*nr < 0) { - *nr = 0; - } - return a; - } - else if (isdigit(name[a]) == 0) { - /* non-numeric suffix - give up */ - break; - } - } - } - - return name_len; + const size_t name_len = strlen(name); + + *nr = 0; + memcpy(left, name, (name_len + 1) * sizeof(char)); + + /* name doesn't end with a delimiter "foo." */ + if ((name_len > 1 && name[name_len - 1] == delim) == 0) { + size_t a = name_len; + while (a--) { + if (name[a] == delim) { + left[a] = '\0'; /* truncate left part here */ + *nr = atol(name + a + 1); + /* casting down to an int, can overflow for large numbers */ + if (*nr < 0) { + *nr = 0; + } + return a; + } + else if (isdigit(name[a]) == 0) { + /* non-numeric suffix - give up */ + break; + } + } + } + + return name_len; } static bool is_char_sep(const char c) { - return ELEM(c, '.', ' ', '-', '_'); + return ELEM(c, '.', ' ', '-', '_'); } /** @@ -94,20 +93,20 @@ static bool is_char_sep(const char c) */ void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len) { - size_t len = BLI_strnlen(string, str_len); - size_t i; + size_t len = BLI_strnlen(string, str_len); + size_t i; - r_body[0] = r_suf[0] = '\0'; + r_body[0] = r_suf[0] = '\0'; - for (i = len; i > 0; i--) { - if (is_char_sep(string[i])) { - BLI_strncpy(r_body, string, i + 1); - BLI_strncpy(r_suf, string + i, (len + 1) - i); - return; - } - } + for (i = len; i > 0; i--) { + if (is_char_sep(string[i])) { + BLI_strncpy(r_body, string, i + 1); + BLI_strncpy(r_suf, string + i, (len + 1) - i); + return; + } + } - memcpy(r_body, string, len + 1); + memcpy(r_body, string, len + 1); } /** @@ -115,21 +114,21 @@ void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, cons */ void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len) { - size_t len = BLI_strnlen(string, str_len); - size_t i; + size_t len = BLI_strnlen(string, str_len); + size_t i; - r_body[0] = r_pre[0] = '\0'; + r_body[0] = r_pre[0] = '\0'; - for (i = 1; i < len; i++) { - if (is_char_sep(string[i])) { - i++; - BLI_strncpy(r_pre, string, i + 1); - BLI_strncpy(r_body, string + i, (len + 1) - i); - return; - } - } + for (i = 1; i < len; i++) { + if (is_char_sep(string[i])) { + i++; + BLI_strncpy(r_pre, string, i + 1); + BLI_strncpy(r_body, string + i, (len + 1) - i); + return; + } + } - BLI_strncpy(r_body, string, len); + BLI_strncpy(r_body, string, len); } /** @@ -139,129 +138,127 @@ void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, cons * \param from_name: original name, assumed to be a pointer to a string of at least \a name_len size. * \param strip_number: If set, remove number extensions. */ -void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len) +void BLI_string_flip_side_name(char *r_name, + const char *from_name, + const bool strip_number, + const size_t name_len) { - size_t len; - char *prefix = alloca(name_len); /* The part before the facing */ - char *suffix = alloca(name_len); /* The part after the facing */ - char *replace = alloca(name_len); /* The replacement string */ - char *number = alloca(name_len); /* The number extension string */ - char *index = NULL; - bool is_set = false; - - *prefix = *suffix = *replace = *number = '\0'; - - /* always copy the name, since this can be called with an uninitialized string */ - BLI_strncpy(r_name, from_name, name_len); - - len = BLI_strnlen(from_name, name_len); - if (len < 3) { - /* we don't do names like .R or .L */ - return; - } - - /* We first check the case with a .### extension, let's find the last period */ - if (isdigit(r_name[len - 1])) { - index = strrchr(r_name, '.'); // last occurrence - if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever! - if (strip_number == false) { - BLI_strncpy(number, index, name_len); - } - *index = 0; - len = BLI_strnlen(r_name, name_len); - } - } - - BLI_strncpy(prefix, r_name, name_len); - - /* first case; separator . - _ with extensions r R l L */ - if ((len > 1) && is_char_sep(r_name[len - 2])) { - is_set = true; - switch (r_name[len - 1]) { - case 'l': - prefix[len - 1] = 0; - strcpy(replace, "r"); - break; - case 'r': - prefix[len - 1] = 0; - strcpy(replace, "l"); - break; - case 'L': - prefix[len - 1] = 0; - strcpy(replace, "R"); - break; - case 'R': - prefix[len - 1] = 0; - strcpy(replace, "L"); - break; - default: - is_set = false; - } - } - - /* case; beginning with r R l L, with separator after it */ - if (!is_set && is_char_sep(r_name[1])) { - is_set = true; - switch (r_name[0]) { - case 'l': - strcpy(replace, "r"); - BLI_strncpy(suffix, r_name + 1, name_len); - prefix[0] = 0; - break; - case 'r': - strcpy(replace, "l"); - BLI_strncpy(suffix, r_name + 1, name_len); - prefix[0] = 0; - break; - case 'L': - strcpy(replace, "R"); - BLI_strncpy(suffix, r_name + 1, name_len); - prefix[0] = 0; - break; - case 'R': - strcpy(replace, "L"); - BLI_strncpy(suffix, r_name + 1, name_len); - prefix[0] = 0; - break; - default: - is_set = false; - } - } - - if (!is_set && len > 5) { - /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ - if (((index = BLI_strcasestr(prefix, "right")) == prefix) || - (index == prefix + len - 5)) - { - is_set = true; - if (index[0] == 'r') { - strcpy(replace, "left"); - } - else { - strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left"); - } - *index = 0; - BLI_strncpy(suffix, index + 5, name_len); - } - else if (((index = BLI_strcasestr(prefix, "left")) == prefix) || - (index == prefix + len - 4)) - { - is_set = true; - if (index[0] == 'l') { - strcpy(replace, "right"); - } - else { - strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right"); - } - *index = 0; - BLI_strncpy(suffix, index + 4, name_len); - } - } - - BLI_snprintf(r_name, name_len, "%s%s%s%s", prefix, replace, suffix, number); + size_t len; + char *prefix = alloca(name_len); /* The part before the facing */ + char *suffix = alloca(name_len); /* The part after the facing */ + char *replace = alloca(name_len); /* The replacement string */ + char *number = alloca(name_len); /* The number extension string */ + char *index = NULL; + bool is_set = false; + + *prefix = *suffix = *replace = *number = '\0'; + + /* always copy the name, since this can be called with an uninitialized string */ + BLI_strncpy(r_name, from_name, name_len); + + len = BLI_strnlen(from_name, name_len); + if (len < 3) { + /* we don't do names like .R or .L */ + return; + } + + /* We first check the case with a .### extension, let's find the last period */ + if (isdigit(r_name[len - 1])) { + index = strrchr(r_name, '.'); // last occurrence + if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever! + if (strip_number == false) { + BLI_strncpy(number, index, name_len); + } + *index = 0; + len = BLI_strnlen(r_name, name_len); + } + } + + BLI_strncpy(prefix, r_name, name_len); + + /* first case; separator . - _ with extensions r R l L */ + if ((len > 1) && is_char_sep(r_name[len - 2])) { + is_set = true; + switch (r_name[len - 1]) { + case 'l': + prefix[len - 1] = 0; + strcpy(replace, "r"); + break; + case 'r': + prefix[len - 1] = 0; + strcpy(replace, "l"); + break; + case 'L': + prefix[len - 1] = 0; + strcpy(replace, "R"); + break; + case 'R': + prefix[len - 1] = 0; + strcpy(replace, "L"); + break; + default: + is_set = false; + } + } + + /* case; beginning with r R l L, with separator after it */ + if (!is_set && is_char_sep(r_name[1])) { + is_set = true; + switch (r_name[0]) { + case 'l': + strcpy(replace, "r"); + BLI_strncpy(suffix, r_name + 1, name_len); + prefix[0] = 0; + break; + case 'r': + strcpy(replace, "l"); + BLI_strncpy(suffix, r_name + 1, name_len); + prefix[0] = 0; + break; + case 'L': + strcpy(replace, "R"); + BLI_strncpy(suffix, r_name + 1, name_len); + prefix[0] = 0; + break; + case 'R': + strcpy(replace, "L"); + BLI_strncpy(suffix, r_name + 1, name_len); + prefix[0] = 0; + break; + default: + is_set = false; + } + } + + if (!is_set && len > 5) { + /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ + if (((index = BLI_strcasestr(prefix, "right")) == prefix) || (index == prefix + len - 5)) { + is_set = true; + if (index[0] == 'r') { + strcpy(replace, "left"); + } + else { + strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left"); + } + *index = 0; + BLI_strncpy(suffix, index + 5, name_len); + } + else if (((index = BLI_strcasestr(prefix, "left")) == prefix) || (index == prefix + len - 4)) { + is_set = true; + if (index[0] == 'l') { + strcpy(replace, "right"); + } + else { + strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right"); + } + *index = 0; + BLI_strncpy(suffix, index + 4, name_len); + } + } + + BLI_snprintf(r_name, name_len, "%s%s%s%s", prefix, replace, suffix, number); } - /* Unique name utils. */ /** @@ -276,47 +273,51 @@ void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool s * \param name_len: Maximum length of name area * \return true if there if the name was changed */ -bool BLI_uniquename_cb( - UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len) +bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, + void *arg, + const char *defname, + char delim, + char *name, + size_t name_len) { - if (name[0] == '\0') { - BLI_strncpy(name, defname, name_len); - } - - if (unique_check(arg, name)) { - char numstr[16]; - char *tempname = alloca(name_len); - char *left = alloca(name_len); - int number; - size_t len = BLI_split_name_num(left, &number, name, delim); - do { - /* add 1 to account for \0 */ - const size_t numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1; - - /* highly unlikely the string only has enough room for the number - * but support anyway */ - if ((len == 0) || (numlen >= name_len)) { - /* number is know not to be utf-8 */ - BLI_strncpy(tempname, numstr, name_len); - } - else { - char *tempname_buf; - tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen); - memcpy(tempname_buf, numstr, numlen); - } - } while (unique_check(arg, tempname)); - - BLI_strncpy(name, tempname, name_len); - - return true; - } - - return false; + if (name[0] == '\0') { + BLI_strncpy(name, defname, name_len); + } + + if (unique_check(arg, name)) { + char numstr[16]; + char *tempname = alloca(name_len); + char *left = alloca(name_len); + int number; + size_t len = BLI_split_name_num(left, &number, name, delim); + do { + /* add 1 to account for \0 */ + const size_t numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1; + + /* highly unlikely the string only has enough room for the number + * but support anyway */ + if ((len == 0) || (numlen >= name_len)) { + /* number is know not to be utf-8 */ + BLI_strncpy(tempname, numstr, name_len); + } + else { + char *tempname_buf; + tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen); + memcpy(tempname_buf, numstr, numlen); + } + } while (unique_check(arg, tempname)); + + BLI_strncpy(name, tempname, name_len); + + return true; + } + + return false; } /* little helper macro for BLI_uniquename */ #ifndef GIVE_STRADDR -# define GIVE_STRADDR(data, offset) ( ((char *)data) + offset) +# define GIVE_STRADDR(data, offset) (((char *)data) + offset) #endif /** @@ -329,23 +330,27 @@ bool BLI_uniquename_cb( */ static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs) { - Link *link; + Link *link; - for (link = list->first; link; link = link->next) { - if (link != vlink) { - if (STREQ(GIVE_STRADDR(link, name_offs), name)) { - return true; - } - } - } + for (link = list->first; link; link = link->next) { + if (link != vlink) { + if (STREQ(GIVE_STRADDR(link, name_offs), name)) { + return true; + } + } + } - return false; + return false; } static bool uniquename_unique_check(void *arg, const char *name) { - struct {ListBase *lb; void *vlink; int name_offs; } *data = arg; - return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs); + struct { + ListBase *lb; + void *vlink; + int name_offs; + } *data = arg; + return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs); } /** @@ -359,21 +364,27 @@ static bool uniquename_unique_check(void *arg, const char *name) * \param name_offs: Offset of name within block structure * \param name_len: Maximum length of name area */ -bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, size_t name_len) +bool BLI_uniquename( + ListBase *list, void *vlink, const char *defname, char delim, int name_offs, size_t name_len) { - struct {ListBase *lb; void *vlink; int name_offs; } data; - data.lb = list; - data.vlink = vlink; - data.name_offs = name_offs; - - BLI_assert(name_len > 1); - - /* See if we are given an empty string */ - if (ELEM(NULL, vlink, defname)) { - return false; - } - - return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len); + struct { + ListBase *lb; + void *vlink; + int name_offs; + } data; + data.lb = list; + data.vlink = vlink; + data.name_offs = name_offs; + + BLI_assert(name_len > 1); + + /* See if we are given an empty string */ + if (ELEM(NULL, vlink, defname)) { + return false; + } + + return BLI_uniquename_cb( + uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len); } /* ------------------------------------------------------------------------- */ @@ -389,77 +400,77 @@ bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim /** * Join an array of strings into a newly allocated, null terminated string. */ -char *BLI_string_join_arrayN( - const char *strings[], uint strings_len) +char *BLI_string_join_arrayN(const char *strings[], uint strings_len) { - uint total_len = 1; - for (uint i = 0; i < strings_len; i++) { - total_len += strlen(strings[i]); - } - char *result = MEM_mallocN(sizeof(char) * total_len, __func__); - char *c = result; - for (uint i = 0; i < strings_len; i++) { - c += BLI_strcpy_rlen(c, strings[i]); - } - return result; + uint total_len = 1; + for (uint i = 0; i < strings_len; i++) { + total_len += strlen(strings[i]); + } + char *result = MEM_mallocN(sizeof(char) * total_len, __func__); + char *c = result; + for (uint i = 0; i < strings_len; i++) { + c += BLI_strcpy_rlen(c, strings[i]); + } + return result; } /** * A version of #BLI_string_joinN that takes a separator which can be any character including '\0'. */ -char *BLI_string_join_array_by_sep_charN( - char sep, const char *strings[], uint strings_len) +char *BLI_string_join_array_by_sep_charN(char sep, const char *strings[], uint strings_len) { - uint total_len = 0; - for (uint i = 0; i < strings_len; i++) { - total_len += strlen(strings[i]) + 1; - } - if (total_len == 0) { - total_len = 1; - } - - char *result = MEM_mallocN(sizeof(char) * total_len, __func__); - char *c = result; - if (strings_len != 0) { - for (uint i = 0; i < strings_len; i++) { - c += BLI_strcpy_rlen(c, strings[i]); - *c = sep; - c++; - } - c--; - } - *c = '\0'; - return result; + uint total_len = 0; + for (uint i = 0; i < strings_len; i++) { + total_len += strlen(strings[i]) + 1; + } + if (total_len == 0) { + total_len = 1; + } + + char *result = MEM_mallocN(sizeof(char) * total_len, __func__); + char *c = result; + if (strings_len != 0) { + for (uint i = 0; i < strings_len; i++) { + c += BLI_strcpy_rlen(c, strings[i]); + *c = sep; + c++; + } + c--; + } + *c = '\0'; + return result; } /** * A version of #BLI_string_join_array_by_sep_charN that takes a table array. * The new location of each string is written into this array. */ -char *BLI_string_join_array_by_sep_char_with_tableN( - char sep, char *table[], const char *strings[], uint strings_len) +char *BLI_string_join_array_by_sep_char_with_tableN(char sep, + char *table[], + const char *strings[], + uint strings_len) { - uint total_len = 0; - for (uint i = 0; i < strings_len; i++) { - total_len += strlen(strings[i]) + 1; - } - if (total_len == 0) { - total_len = 1; - } - - char *result = MEM_mallocN(sizeof(char) * total_len, __func__); - char *c = result; - if (strings_len != 0) { - for (uint i = 0; i < strings_len; i++) { - table[i] = c; /* <-- only difference to BLI_string_join_array_by_sep_charN. */ - c += BLI_strcpy_rlen(c, strings[i]); - *c = sep; - c++; - } - c--; - } - *c = '\0'; - return result; + uint total_len = 0; + for (uint i = 0; i < strings_len; i++) { + total_len += strlen(strings[i]) + 1; + } + if (total_len == 0) { + total_len = 1; + } + + char *result = MEM_mallocN(sizeof(char) * total_len, __func__); + char *c = result; + if (strings_len != 0) { + for (uint i = 0; i < strings_len; i++) { + table[i] = c; /* <-- only difference to BLI_string_join_array_by_sep_charN. */ + c += BLI_strcpy_rlen(c, strings[i]); + *c = sep; + c++; + } + c--; + } + *c = '\0'; + return result; } /** \} */ diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 2b0dfd045ca..d23b45a3937 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -40,32 +40,32 @@ int BLI_cpu_support_sse2(void) { #if defined(__x86_64__) || defined(_M_X64) - /* x86_64 always has SSE2 instructions */ - return 1; + /* x86_64 always has SSE2 instructions */ + return 1; #elif defined(__GNUC__) && defined(i386) - /* for GCC x86 we check cpuid */ - unsigned int d; - __asm__( - "pushl %%ebx\n\t" - "cpuid\n\t" - "popl %%ebx\n\t" - : "=d" (d) - : "a" (1)); - return (d & 0x04000000) != 0; + /* for GCC x86 we check cpuid */ + unsigned int d; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=d"(d) + : "a"(1)); + return (d & 0x04000000) != 0; #elif (defined(_MSC_VER) && defined(_M_IX86)) - /* also check cpuid for MSVC x86 */ - unsigned int d; - __asm { - xor eax, eax - inc eax - push ebx - cpuid - pop ebx - mov d, edx - } - return (d & 0x04000000) != 0; + /* also check cpuid for MSVC x86 */ + unsigned int d; + __asm { + xor eax, eax + inc eax + push ebx + cpuid + pop ebx + mov d, edx + } + return (d & 0x04000000) != 0; #else - return 0; + return 0; #endif } @@ -74,67 +74,66 @@ int BLI_cpu_support_sse2(void) */ void BLI_system_backtrace(FILE *fp) { - /* ------------- */ - /* Linux / Apple */ + /* ------------- */ + /* Linux / Apple */ #if defined(__linux__) || defined(__APPLE__) -#define SIZE 100 - void *buffer[SIZE]; - int nptrs; - char **strings; - int i; - - /* include a backtrace for good measure */ - nptrs = backtrace(buffer, SIZE); - strings = backtrace_symbols(buffer, nptrs); - for (i = 0; i < nptrs; i++) { - fputs(strings[i], fp); - fputc('\n', fp); - } - - free(strings); -#undef SIZE - - /* -------- */ - /* Windows */ +# define SIZE 100 + void *buffer[SIZE]; + int nptrs; + char **strings; + int i; + + /* include a backtrace for good measure */ + nptrs = backtrace(buffer, SIZE); + strings = backtrace_symbols(buffer, nptrs); + for (i = 0; i < nptrs; i++) { + fputs(strings[i], fp); + fputc('\n', fp); + } + + free(strings); +# undef SIZE + + /* -------- */ + /* Windows */ #elif defined(_MSC_VER) -#ifndef NDEBUG -#define MAXSYMBOL 256 -#define SIZE 100 - unsigned short i; - void *stack[SIZE]; - unsigned short nframes; - SYMBOL_INFO *symbolinfo; - HANDLE process; - - process = GetCurrentProcess(); - - SymInitialize(process, NULL, TRUE); - - nframes = CaptureStackBackTrace(0, SIZE, stack, NULL); - symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table"); - symbolinfo->MaxNameLen = MAXSYMBOL - 1; - symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); - - for (i = 0; i < nframes; i++) { - SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); - - fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); - } - - MEM_freeN(symbolinfo); -#undef MAXSYMBOL -#undef SIZE -#else - fprintf(fp, "Crash backtrace not supported on release builds\n"); -#endif /* NDEBUG */ -#else /* _MSC_VER */ - /* ------------------ */ - /* non msvc/osx/linux */ - (void)fp; +# ifndef NDEBUG +# define MAXSYMBOL 256 +# define SIZE 100 + unsigned short i; + void *stack[SIZE]; + unsigned short nframes; + SYMBOL_INFO *symbolinfo; + HANDLE process; + + process = GetCurrentProcess(); + + SymInitialize(process, NULL, TRUE); + + nframes = CaptureStackBackTrace(0, SIZE, stack, NULL); + symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table"); + symbolinfo->MaxNameLen = MAXSYMBOL - 1; + symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); + + for (i = 0; i < nframes; i++) { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); + + fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); + } + + MEM_freeN(symbolinfo); +# undef MAXSYMBOL +# undef SIZE +# else + fprintf(fp, "Crash backtrace not supported on release builds\n"); +# endif /* NDEBUG */ +#else /* _MSC_VER */ + /* ------------------ */ + /* non msvc/osx/linux */ + (void)fp; #endif - } /* end BLI_system_backtrace */ @@ -143,50 +142,50 @@ void BLI_system_backtrace(FILE *fp) #if !defined(_WIN32) || defined(FREE_WINDOWS) static void __cpuid(int data[4], int selector) { -#if defined(__x86_64__) - asm("cpuid" : "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector)); -#elif defined(__i386__) - asm("pushl %%ebx \n\t" - "cpuid \n\t" - "movl %%ebx, %1 \n\t" - "popl %%ebx \n\t" - : "=a" (data[0]), "=r" (data[1]), "=c" (data[2]), "=d" (data[3]) - : "a"(selector) - : "ebx"); -#else - data[0] = data[1] = data[2] = data[3] = 0; -#endif +# if defined(__x86_64__) + asm("cpuid" : "=a"(data[0]), "=b"(data[1]), "=c"(data[2]), "=d"(data[3]) : "a"(selector)); +# elif defined(__i386__) + asm("pushl %%ebx \n\t" + "cpuid \n\t" + "movl %%ebx, %1 \n\t" + "popl %%ebx \n\t" + : "=a"(data[0]), "=r"(data[1]), "=c"(data[2]), "=d"(data[3]) + : "a"(selector) + : "ebx"); +# else + data[0] = data[1] = data[2] = data[3] = 0; +# endif } #endif char *BLI_cpu_brand_string(void) { - char buf[48] = { 0 }; - int result[4] = { 0 }; - __cpuid(result, 0x80000000); - if (result[0] >= (int)0x80000004) { - __cpuid((int *)(buf + 0), 0x80000002); - __cpuid((int *)(buf + 16), 0x80000003); - __cpuid((int *)(buf + 32), 0x80000004); - char *brand = BLI_strdup(buf); - /* TODO(sergey): Make it a bit more presentable by removing trademark. */ - return brand; - } - return NULL; + char buf[48] = {0}; + int result[4] = {0}; + __cpuid(result, 0x80000000); + if (result[0] >= (int)0x80000004) { + __cpuid((int *)(buf + 0), 0x80000002); + __cpuid((int *)(buf + 16), 0x80000003); + __cpuid((int *)(buf + 32), 0x80000004); + char *brand = BLI_strdup(buf); + /* TODO(sergey): Make it a bit more presentable by removing trademark. */ + return brand; + } + return NULL; } void BLI_hostname_get(char *buffer, size_t bufsize) { #ifndef WIN32 - if (gethostname(buffer, bufsize - 1) < 0) { - BLI_strncpy(buffer, "-unknown-", bufsize); - } - /* When gethostname() truncates, it doesn't guarantee the trailing \0. */ - buffer[bufsize - 1] = '\0'; + if (gethostname(buffer, bufsize - 1) < 0) { + BLI_strncpy(buffer, "-unknown-", bufsize); + } + /* When gethostname() truncates, it doesn't guarantee the trailing \0. */ + buffer[bufsize - 1] = '\0'; #else - DWORD bufsize_inout = bufsize; - if (!GetComputerName(buffer, &bufsize_inout)) { - strncpy(buffer, "-unknown-", bufsize); - } + DWORD bufsize_inout = bufsize; + if (!GetComputerName(buffer, &bufsize_inout)) { + strncpy(buffer, "-unknown-", bufsize); + } #endif } diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index 3a6613b2612..57ce4f16b1a 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -59,33 +59,33 @@ #define DELAYED_QUEUE_SIZE 4096 #ifndef NDEBUG -# define ASSERT_THREAD_ID(scheduler, thread_id) \ - do { \ - if (!BLI_thread_is_main()) { \ - TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); \ - if (thread == NULL) { \ - BLI_assert(thread_id == 0); \ - } \ - else { \ - BLI_assert(thread_id == thread->id); \ - } \ - } \ - else { \ - BLI_assert(thread_id == 0); \ - } \ - } while (false) +# define ASSERT_THREAD_ID(scheduler, thread_id) \ + do { \ + if (!BLI_thread_is_main()) { \ + TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); \ + if (thread == NULL) { \ + BLI_assert(thread_id == 0); \ + } \ + else { \ + BLI_assert(thread_id == thread->id); \ + } \ + } \ + else { \ + BLI_assert(thread_id == 0); \ + } \ + } while (false) #else # define ASSERT_THREAD_ID(scheduler, thread_id) #endif typedef struct Task { - struct Task *next, *prev; + struct Task *next, *prev; - TaskRunFunction run; - void *taskdata; - bool free_taskdata; - TaskFreeFunction freedata; - TaskPool *pool; + TaskRunFunction run; + void *taskdata; + bool free_taskdata; + TaskFreeFunction freedata; + TaskPool *pool; } Task; /* This is a per-thread storage of pre-allocated tasks. @@ -115,471 +115,467 @@ typedef struct Task { * pool which corresponds to a thread which handled the task. */ typedef struct TaskMemPool { - /* Number of pre-allocated tasks in the pool. */ - int num_tasks; - /* Pre-allocated task memory pointers. */ - Task *tasks[MEMPOOL_SIZE]; + /* Number of pre-allocated tasks in the pool. */ + int num_tasks; + /* Pre-allocated task memory pointers. */ + Task *tasks[MEMPOOL_SIZE]; } TaskMemPool; #ifdef DEBUG_STATS typedef struct TaskMemPoolStats { - /* Number of allocations. */ - int num_alloc; - /* Number of avoided allocations (pointer was re-used from the pool). */ - int num_reuse; - /* Number of discarded memory due to pool saturation, */ - int num_discard; + /* Number of allocations. */ + int num_alloc; + /* Number of avoided allocations (pointer was re-used from the pool). */ + int num_reuse; + /* Number of discarded memory due to pool saturation, */ + int num_discard; } TaskMemPoolStats; #endif typedef struct TaskThreadLocalStorage { - /* Memory pool for faster task allocation. - * The idea is to re-use memory of finished/discarded tasks by this thread. - */ - TaskMemPool task_mempool; - - /* Local queue keeps thread alive by keeping small amount of tasks ready - * to be picked up without causing global thread locks for synchronization. - */ - int num_local_queue; - Task *local_queue[LOCAL_QUEUE_SIZE]; - - /* Thread can be marked for delayed tasks push. This is helpful when it's - * know that lots of subsequent task pushed will happen from the same thread - * without "interrupting" for task execution. - * - * We try to accumulate as much tasks as possible in a local queue without - * any locks first, and then we push all of them into a scheduler's queue - * from within a single mutex lock. - */ - bool do_delayed_push; - int num_delayed_queue; - Task *delayed_queue[DELAYED_QUEUE_SIZE]; + /* Memory pool for faster task allocation. + * The idea is to re-use memory of finished/discarded tasks by this thread. + */ + TaskMemPool task_mempool; + + /* Local queue keeps thread alive by keeping small amount of tasks ready + * to be picked up without causing global thread locks for synchronization. + */ + int num_local_queue; + Task *local_queue[LOCAL_QUEUE_SIZE]; + + /* Thread can be marked for delayed tasks push. This is helpful when it's + * know that lots of subsequent task pushed will happen from the same thread + * without "interrupting" for task execution. + * + * We try to accumulate as much tasks as possible in a local queue without + * any locks first, and then we push all of them into a scheduler's queue + * from within a single mutex lock. + */ + bool do_delayed_push; + int num_delayed_queue; + Task *delayed_queue[DELAYED_QUEUE_SIZE]; } TaskThreadLocalStorage; struct TaskPool { - TaskScheduler *scheduler; - - volatile size_t num; - ThreadMutex num_mutex; - ThreadCondition num_cond; - - void *userdata; - ThreadMutex user_mutex; - - volatile bool do_cancel; - volatile bool do_work; - - volatile bool is_suspended; - bool start_suspended; - ListBase suspended_queue; - size_t num_suspended; - - /* If set, this pool may never be work_and_wait'ed, which means TaskScheduler - * has to use its special background fallback thread in case we are in - * single-threaded situation. - */ - bool run_in_background; - - /* This is a task scheduler's ID of a thread at which pool was constructed. - * It will be used to access task TLS. - */ - int thread_id; - - /* For the pools which are created from non-main thread which is not a - * scheduler worker thread we can't re-use any of scheduler's threads TLS - * and have to use our own one. - */ - bool use_local_tls; - TaskThreadLocalStorage local_tls; + TaskScheduler *scheduler; + + volatile size_t num; + ThreadMutex num_mutex; + ThreadCondition num_cond; + + void *userdata; + ThreadMutex user_mutex; + + volatile bool do_cancel; + volatile bool do_work; + + volatile bool is_suspended; + bool start_suspended; + ListBase suspended_queue; + size_t num_suspended; + + /* If set, this pool may never be work_and_wait'ed, which means TaskScheduler + * has to use its special background fallback thread in case we are in + * single-threaded situation. + */ + bool run_in_background; + + /* This is a task scheduler's ID of a thread at which pool was constructed. + * It will be used to access task TLS. + */ + int thread_id; + + /* For the pools which are created from non-main thread which is not a + * scheduler worker thread we can't re-use any of scheduler's threads TLS + * and have to use our own one. + */ + bool use_local_tls; + TaskThreadLocalStorage local_tls; #ifndef NDEBUG - pthread_t creator_thread_id; + pthread_t creator_thread_id; #endif #ifdef DEBUG_STATS - TaskMemPoolStats *mempool_stats; + TaskMemPoolStats *mempool_stats; #endif }; struct TaskScheduler { - pthread_t *threads; - struct TaskThread *task_threads; - int num_threads; - bool background_thread_only; + pthread_t *threads; + struct TaskThread *task_threads; + int num_threads; + bool background_thread_only; - ListBase queue; - ThreadMutex queue_mutex; - ThreadCondition queue_cond; + ListBase queue; + ThreadMutex queue_mutex; + ThreadCondition queue_cond; - volatile bool do_exit; + volatile bool do_exit; - /* NOTE: In pthread's TLS we store the whole TaskThread structure. */ - pthread_key_t tls_id_key; + /* NOTE: In pthread's TLS we store the whole TaskThread structure. */ + pthread_key_t tls_id_key; }; typedef struct TaskThread { - TaskScheduler *scheduler; - int id; - TaskThreadLocalStorage tls; + TaskScheduler *scheduler; + int id; + TaskThreadLocalStorage tls; } TaskThread; /* Helper */ BLI_INLINE void task_data_free(Task *task, const int thread_id) { - if (task->free_taskdata) { - if (task->freedata) { - task->freedata(task->pool, task->taskdata, thread_id); - } - else { - MEM_freeN(task->taskdata); - } - } + if (task->free_taskdata) { + if (task->freedata) { + task->freedata(task->pool, task->taskdata, thread_id); + } + else { + MEM_freeN(task->taskdata); + } + } } BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls) { - memset(tls, 0, sizeof(TaskThreadLocalStorage)); + memset(tls, 0, sizeof(TaskThreadLocalStorage)); } -BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, - const int thread_id) +BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, const int thread_id) { - TaskScheduler *scheduler = pool->scheduler; - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= scheduler->num_threads); - if (pool->use_local_tls && thread_id == 0) { - BLI_assert(pool->thread_id == 0); - BLI_assert(!BLI_thread_is_main()); - BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id)); - return &pool->local_tls; - } - if (thread_id == 0) { - BLI_assert(BLI_thread_is_main()); - return &scheduler->task_threads[pool->thread_id].tls; - } - return &scheduler->task_threads[thread_id].tls; + TaskScheduler *scheduler = pool->scheduler; + BLI_assert(thread_id >= 0); + BLI_assert(thread_id <= scheduler->num_threads); + if (pool->use_local_tls && thread_id == 0) { + BLI_assert(pool->thread_id == 0); + BLI_assert(!BLI_thread_is_main()); + BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id)); + return &pool->local_tls; + } + if (thread_id == 0) { + BLI_assert(BLI_thread_is_main()); + return &scheduler->task_threads[pool->thread_id].tls; + } + return &scheduler->task_threads[thread_id].tls; } BLI_INLINE void free_task_tls(TaskThreadLocalStorage *tls) { - TaskMemPool *task_mempool = &tls->task_mempool; - for (int i = 0; i < task_mempool->num_tasks; ++i) { - MEM_freeN(task_mempool->tasks[i]); - } + TaskMemPool *task_mempool = &tls->task_mempool; + for (int i = 0; i < task_mempool->num_tasks; ++i) { + MEM_freeN(task_mempool->tasks[i]); + } } static Task *task_alloc(TaskPool *pool, const int thread_id) { - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id != -1) { - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - /* Try to re-use task memory from a thread local storage. */ - if (task_mempool->num_tasks > 0) { - --task_mempool->num_tasks; - /* Success! We've just avoided task allocation. */ + BLI_assert(thread_id <= pool->scheduler->num_threads); + if (thread_id != -1) { + BLI_assert(thread_id >= 0); + BLI_assert(thread_id <= pool->scheduler->num_threads); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + TaskMemPool *task_mempool = &tls->task_mempool; + /* Try to re-use task memory from a thread local storage. */ + if (task_mempool->num_tasks > 0) { + --task_mempool->num_tasks; + /* Success! We've just avoided task allocation. */ #ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_reuse++; + pool->mempool_stats[thread_id].num_reuse++; #endif - return task_mempool->tasks[task_mempool->num_tasks]; - } - /* We are doomed to allocate new task data. */ + return task_mempool->tasks[task_mempool->num_tasks]; + } + /* We are doomed to allocate new task data. */ #ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_alloc++; + pool->mempool_stats[thread_id].num_alloc++; #endif - } - return MEM_mallocN(sizeof(Task), "New task"); + } + return MEM_mallocN(sizeof(Task), "New task"); } static void task_free(TaskPool *pool, Task *task, const int thread_id) { - task_data_free(task, thread_id); - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id == 0) { - BLI_assert(pool->use_local_tls || BLI_thread_is_main()); - } - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) { - /* Successfully allowed the task to be re-used later. */ - task_mempool->tasks[task_mempool->num_tasks] = task; - ++task_mempool->num_tasks; - } - else { - /* Local storage saturated, no other way than just discard - * the memory. - * - * TODO(sergey): We can perhaps store such pointer in a global - * scheduler pool, maybe it'll be faster than discarding and - * allocating again. - */ - MEM_freeN(task); + task_data_free(task, thread_id); + BLI_assert(thread_id >= 0); + BLI_assert(thread_id <= pool->scheduler->num_threads); + if (thread_id == 0) { + BLI_assert(pool->use_local_tls || BLI_thread_is_main()); + } + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + TaskMemPool *task_mempool = &tls->task_mempool; + if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) { + /* Successfully allowed the task to be re-used later. */ + task_mempool->tasks[task_mempool->num_tasks] = task; + ++task_mempool->num_tasks; + } + else { + /* Local storage saturated, no other way than just discard + * the memory. + * + * TODO(sergey): We can perhaps store such pointer in a global + * scheduler pool, maybe it'll be faster than discarding and + * allocating again. + */ + MEM_freeN(task); #ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_discard++; + pool->mempool_stats[thread_id].num_discard++; #endif - } + } } /* Task Scheduler */ static void task_pool_num_decrease(TaskPool *pool, size_t done) { - BLI_mutex_lock(&pool->num_mutex); + BLI_mutex_lock(&pool->num_mutex); - BLI_assert(pool->num >= done); + BLI_assert(pool->num >= done); - pool->num -= done; + pool->num -= done; - if (pool->num == 0) { - BLI_condition_notify_all(&pool->num_cond); - } + if (pool->num == 0) { + BLI_condition_notify_all(&pool->num_cond); + } - BLI_mutex_unlock(&pool->num_mutex); + BLI_mutex_unlock(&pool->num_mutex); } static void task_pool_num_increase(TaskPool *pool, size_t new) { - BLI_mutex_lock(&pool->num_mutex); + BLI_mutex_lock(&pool->num_mutex); - pool->num += new; - BLI_condition_notify_all(&pool->num_cond); + pool->num += new; + BLI_condition_notify_all(&pool->num_cond); - BLI_mutex_unlock(&pool->num_mutex); + BLI_mutex_unlock(&pool->num_mutex); } static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task) { - bool found_task = false; - BLI_mutex_lock(&scheduler->queue_mutex); - - while (!scheduler->queue.first && !scheduler->do_exit) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); - } - - do { - Task *current_task; - - /* Assuming we can only have a void queue in 'exit' case here seems logical - * (we should only be here after our worker thread has been woken up from a - * condition_wait(), which only happens after a new task was added to the queue), - * but it is wrong. - * Waiting on condition may wake up the thread even if condition is not signaled - * (spurious wake-ups), and some race condition may also empty the queue **after** - * condition has been signaled, but **before** awoken thread reaches this point... - * See http://stackoverflow.com/questions/8594591 - * - * So we only abort here if do_exit is set. - */ - if (scheduler->do_exit) { - BLI_mutex_unlock(&scheduler->queue_mutex); - return false; - } - - for (current_task = scheduler->queue.first; - current_task != NULL; - current_task = current_task->next) - { - TaskPool *pool = current_task->pool; - - if (scheduler->background_thread_only && !pool->run_in_background) { - continue; - } - - *task = current_task; - found_task = true; - BLI_remlink(&scheduler->queue, *task); - break; - } - if (!found_task) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); - } - } while (!found_task); - - BLI_mutex_unlock(&scheduler->queue_mutex); - - return true; + bool found_task = false; + BLI_mutex_lock(&scheduler->queue_mutex); + + while (!scheduler->queue.first && !scheduler->do_exit) { + BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); + } + + do { + Task *current_task; + + /* Assuming we can only have a void queue in 'exit' case here seems logical + * (we should only be here after our worker thread has been woken up from a + * condition_wait(), which only happens after a new task was added to the queue), + * but it is wrong. + * Waiting on condition may wake up the thread even if condition is not signaled + * (spurious wake-ups), and some race condition may also empty the queue **after** + * condition has been signaled, but **before** awoken thread reaches this point... + * See http://stackoverflow.com/questions/8594591 + * + * So we only abort here if do_exit is set. + */ + if (scheduler->do_exit) { + BLI_mutex_unlock(&scheduler->queue_mutex); + return false; + } + + for (current_task = scheduler->queue.first; current_task != NULL; + current_task = current_task->next) { + TaskPool *pool = current_task->pool; + + if (scheduler->background_thread_only && !pool->run_in_background) { + continue; + } + + *task = current_task; + found_task = true; + BLI_remlink(&scheduler->queue, *task); + break; + } + if (!found_task) { + BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); + } + } while (!found_task); + + BLI_mutex_unlock(&scheduler->queue_mutex); + + return true; } -BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, - const int thread_id) +BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id) { - BLI_assert(!tls->do_delayed_push); - while (tls->num_local_queue > 0) { - /* We pop task from queue before handling it so handler of the task can - * push next job to the local queue. - */ - tls->num_local_queue--; - Task *local_task = tls->local_queue[tls->num_local_queue]; - /* TODO(sergey): Double-check work_and_wait() doesn't handle other's - * pool tasks. - */ - TaskPool *local_pool = local_task->pool; - local_task->run(local_pool, local_task->taskdata, thread_id); - task_free(local_pool, local_task, thread_id); - } - BLI_assert(!tls->do_delayed_push); + BLI_assert(!tls->do_delayed_push); + while (tls->num_local_queue > 0) { + /* We pop task from queue before handling it so handler of the task can + * push next job to the local queue. + */ + tls->num_local_queue--; + Task *local_task = tls->local_queue[tls->num_local_queue]; + /* TODO(sergey): Double-check work_and_wait() doesn't handle other's + * pool tasks. + */ + TaskPool *local_pool = local_task->pool; + local_task->run(local_pool, local_task->taskdata, thread_id); + task_free(local_pool, local_task, thread_id); + } + BLI_assert(!tls->do_delayed_push); } static void *task_scheduler_thread_run(void *thread_p) { - TaskThread *thread = (TaskThread *) thread_p; - TaskThreadLocalStorage *tls = &thread->tls; - TaskScheduler *scheduler = thread->scheduler; - int thread_id = thread->id; - Task *task; + TaskThread *thread = (TaskThread *)thread_p; + TaskThreadLocalStorage *tls = &thread->tls; + TaskScheduler *scheduler = thread->scheduler; + int thread_id = thread->id; + Task *task; - pthread_setspecific(scheduler->tls_id_key, thread); + pthread_setspecific(scheduler->tls_id_key, thread); - /* keep popping off tasks */ - while (task_scheduler_thread_wait_pop(scheduler, &task)) { - TaskPool *pool = task->pool; + /* keep popping off tasks */ + while (task_scheduler_thread_wait_pop(scheduler, &task)) { + TaskPool *pool = task->pool; - /* run task */ - BLI_assert(!tls->do_delayed_push); - task->run(pool, task->taskdata, thread_id); - BLI_assert(!tls->do_delayed_push); + /* run task */ + BLI_assert(!tls->do_delayed_push); + task->run(pool, task->taskdata, thread_id); + BLI_assert(!tls->do_delayed_push); - /* delete task */ - task_free(pool, task, thread_id); + /* delete task */ + task_free(pool, task, thread_id); - /* Handle all tasks from local queue. */ - handle_local_queue(tls, thread_id); + /* Handle all tasks from local queue. */ + handle_local_queue(tls, thread_id); - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); - } + /* notify pool task was done */ + task_pool_num_decrease(pool, 1); + } - return NULL; + return NULL; } TaskScheduler *BLI_task_scheduler_create(int num_threads) { - TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); + TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); - /* multiple places can use this task scheduler, sharing the same - * threads, so we keep track of the number of users. */ - scheduler->do_exit = false; + /* multiple places can use this task scheduler, sharing the same + * threads, so we keep track of the number of users. */ + scheduler->do_exit = false; - BLI_listbase_clear(&scheduler->queue); - BLI_mutex_init(&scheduler->queue_mutex); - BLI_condition_init(&scheduler->queue_cond); + BLI_listbase_clear(&scheduler->queue); + BLI_mutex_init(&scheduler->queue_mutex); + BLI_condition_init(&scheduler->queue_cond); - if (num_threads == 0) { - /* automatic number of threads will be main thread + num cores */ - num_threads = BLI_system_thread_count(); - } + if (num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ + num_threads = BLI_system_thread_count(); + } - /* main thread will also work, so we count it too */ - num_threads -= 1; + /* main thread will also work, so we count it too */ + num_threads -= 1; - /* Add background-only thread if needed. */ - if (num_threads == 0) { - scheduler->background_thread_only = true; - num_threads = 1; - } + /* Add background-only thread if needed. */ + if (num_threads == 0) { + scheduler->background_thread_only = true; + num_threads = 1; + } - scheduler->task_threads = MEM_mallocN(sizeof(TaskThread) * (num_threads + 1), - "TaskScheduler task threads"); + scheduler->task_threads = MEM_mallocN(sizeof(TaskThread) * (num_threads + 1), + "TaskScheduler task threads"); - /* Initialize TLS for main thread. */ - initialize_task_tls(&scheduler->task_threads[0].tls); + /* Initialize TLS for main thread. */ + initialize_task_tls(&scheduler->task_threads[0].tls); - pthread_key_create(&scheduler->tls_id_key, NULL); + pthread_key_create(&scheduler->tls_id_key, NULL); - /* launch threads that will be waiting for work */ - if (num_threads > 0) { - int i; + /* launch threads that will be waiting for work */ + if (num_threads > 0) { + int i; - scheduler->num_threads = num_threads; - scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads"); + scheduler->num_threads = num_threads; + scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads"); - for (i = 0; i < num_threads; i++) { - TaskThread *thread = &scheduler->task_threads[i + 1]; - thread->scheduler = scheduler; - thread->id = i + 1; - initialize_task_tls(&thread->tls); + for (i = 0; i < num_threads; i++) { + TaskThread *thread = &scheduler->task_threads[i + 1]; + thread->scheduler = scheduler; + thread->id = i + 1; + initialize_task_tls(&thread->tls); - if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { - fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); - } - } - } + if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { + fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); + } + } + } - return scheduler; + return scheduler; } void BLI_task_scheduler_free(TaskScheduler *scheduler) { - Task *task; - - /* stop all waiting threads */ - BLI_mutex_lock(&scheduler->queue_mutex); - scheduler->do_exit = true; - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); - - pthread_key_delete(scheduler->tls_id_key); - - /* delete threads */ - if (scheduler->threads) { - int i; - - for (i = 0; i < scheduler->num_threads; i++) { - if (pthread_join(scheduler->threads[i], NULL) != 0) { - fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads); - } - } - - MEM_freeN(scheduler->threads); - } - - /* Delete task thread data */ - if (scheduler->task_threads) { - for (int i = 0; i < scheduler->num_threads + 1; ++i) { - TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls; - free_task_tls(tls); - } - - MEM_freeN(scheduler->task_threads); - } - - /* delete leftover tasks */ - for (task = scheduler->queue.first; task; task = task->next) { - task_data_free(task, 0); - } - BLI_freelistN(&scheduler->queue); - - /* delete mutex/condition */ - BLI_mutex_end(&scheduler->queue_mutex); - BLI_condition_end(&scheduler->queue_cond); - - MEM_freeN(scheduler); + Task *task; + + /* stop all waiting threads */ + BLI_mutex_lock(&scheduler->queue_mutex); + scheduler->do_exit = true; + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); + + pthread_key_delete(scheduler->tls_id_key); + + /* delete threads */ + if (scheduler->threads) { + int i; + + for (i = 0; i < scheduler->num_threads; i++) { + if (pthread_join(scheduler->threads[i], NULL) != 0) { + fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads); + } + } + + MEM_freeN(scheduler->threads); + } + + /* Delete task thread data */ + if (scheduler->task_threads) { + for (int i = 0; i < scheduler->num_threads + 1; ++i) { + TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls; + free_task_tls(tls); + } + + MEM_freeN(scheduler->task_threads); + } + + /* delete leftover tasks */ + for (task = scheduler->queue.first; task; task = task->next) { + task_data_free(task, 0); + } + BLI_freelistN(&scheduler->queue); + + /* delete mutex/condition */ + BLI_mutex_end(&scheduler->queue_mutex); + BLI_condition_end(&scheduler->queue_cond); + + MEM_freeN(scheduler); } int BLI_task_scheduler_num_threads(TaskScheduler *scheduler) { - return scheduler->num_threads + 1; + return scheduler->num_threads + 1; } static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority) { - task_pool_num_increase(task->pool, 1); + task_pool_num_increase(task->pool, 1); - /* add task to queue */ - BLI_mutex_lock(&scheduler->queue_mutex); + /* add task to queue */ + BLI_mutex_lock(&scheduler->queue_mutex); - if (priority == TASK_PRIORITY_HIGH) { - BLI_addhead(&scheduler->queue, task); - } - else { - BLI_addtail(&scheduler->queue, task); - } + if (priority == TASK_PRIORITY_HIGH) { + BLI_addhead(&scheduler->queue, task); + } + else { + BLI_addtail(&scheduler->queue, task); + } - BLI_condition_notify_one(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_condition_notify_one(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); } static void task_scheduler_push_all(TaskScheduler *scheduler, @@ -587,45 +583,45 @@ static void task_scheduler_push_all(TaskScheduler *scheduler, Task **tasks, int num_tasks) { - if (num_tasks == 0) { - return; - } + if (num_tasks == 0) { + return; + } - task_pool_num_increase(pool, num_tasks); + task_pool_num_increase(pool, num_tasks); - BLI_mutex_lock(&scheduler->queue_mutex); + BLI_mutex_lock(&scheduler->queue_mutex); - for (int i = 0; i < num_tasks; i++) { - BLI_addhead(&scheduler->queue, tasks[i]); - } + for (int i = 0; i < num_tasks; i++) { + BLI_addhead(&scheduler->queue, tasks[i]); + } - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); } static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) { - Task *task, *nexttask; - size_t done = 0; + Task *task, *nexttask; + size_t done = 0; - BLI_mutex_lock(&scheduler->queue_mutex); + BLI_mutex_lock(&scheduler->queue_mutex); - /* free all tasks from this pool from the queue */ - for (task = scheduler->queue.first; task; task = nexttask) { - nexttask = task->next; + /* free all tasks from this pool from the queue */ + for (task = scheduler->queue.first; task; task = nexttask) { + nexttask = task->next; - if (task->pool == pool) { - task_data_free(task, pool->thread_id); - BLI_freelinkN(&scheduler->queue, task); + if (task->pool == pool) { + task_data_free(task, pool->thread_id); + BLI_freelinkN(&scheduler->queue, task); - done++; - } - } + done++; + } + } - BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_mutex_unlock(&scheduler->queue_mutex); - /* notify done */ - task_pool_num_decrease(pool, done); + /* notify done */ + task_pool_num_decrease(pool, done); } /* Task Pool */ @@ -635,76 +631,75 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, const bool is_background, const bool is_suspended) { - TaskPool *pool = MEM_mallocN(sizeof(TaskPool), "TaskPool"); + TaskPool *pool = MEM_mallocN(sizeof(TaskPool), "TaskPool"); #ifndef NDEBUG - /* Assert we do not try to create a background pool from some parent task - - * those only work OK from main thread. */ - if (is_background) { - const pthread_t thread_id = pthread_self(); - int i = scheduler->num_threads; - - while (i--) { - BLI_assert(!pthread_equal(scheduler->threads[i], thread_id)); - } - } + /* Assert we do not try to create a background pool from some parent task - + * those only work OK from main thread. */ + if (is_background) { + const pthread_t thread_id = pthread_self(); + int i = scheduler->num_threads; + + while (i--) { + BLI_assert(!pthread_equal(scheduler->threads[i], thread_id)); + } + } #endif - pool->scheduler = scheduler; - pool->num = 0; - pool->do_cancel = false; - pool->do_work = false; - pool->is_suspended = is_suspended; - pool->start_suspended = is_suspended; - pool->num_suspended = 0; - pool->suspended_queue.first = pool->suspended_queue.last = NULL; - pool->run_in_background = is_background; - pool->use_local_tls = false; - - BLI_mutex_init(&pool->num_mutex); - BLI_condition_init(&pool->num_cond); - - pool->userdata = userdata; - BLI_mutex_init(&pool->user_mutex); - - if (BLI_thread_is_main()) { - pool->thread_id = 0; - } - else { - TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); - if (thread == NULL) { - /* NOTE: Task pool is created from non-main thread which is not - * managed by the task scheduler. We identify ourselves as thread ID - * 0 but we do not use scheduler's TLS storage and use our own - * instead to avoid any possible threading conflicts. - */ - pool->thread_id = 0; - pool->use_local_tls = true; + pool->scheduler = scheduler; + pool->num = 0; + pool->do_cancel = false; + pool->do_work = false; + pool->is_suspended = is_suspended; + pool->start_suspended = is_suspended; + pool->num_suspended = 0; + pool->suspended_queue.first = pool->suspended_queue.last = NULL; + pool->run_in_background = is_background; + pool->use_local_tls = false; + + BLI_mutex_init(&pool->num_mutex); + BLI_condition_init(&pool->num_cond); + + pool->userdata = userdata; + BLI_mutex_init(&pool->user_mutex); + + if (BLI_thread_is_main()) { + pool->thread_id = 0; + } + else { + TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); + if (thread == NULL) { + /* NOTE: Task pool is created from non-main thread which is not + * managed by the task scheduler. We identify ourselves as thread ID + * 0 but we do not use scheduler's TLS storage and use our own + * instead to avoid any possible threading conflicts. + */ + pool->thread_id = 0; + pool->use_local_tls = true; #ifndef NDEBUG - pool->creator_thread_id = pthread_self(); + pool->creator_thread_id = pthread_self(); #endif - initialize_task_tls(&pool->local_tls); - } - else { - pool->thread_id = thread->id; - } - } + initialize_task_tls(&pool->local_tls); + } + else { + pool->thread_id = thread->id; + } + } #ifdef DEBUG_STATS - pool->mempool_stats = - MEM_callocN(sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1), - "per-taskpool mempool stats"); + pool->mempool_stats = MEM_callocN(sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1), + "per-taskpool mempool stats"); #endif - /* Ensure malloc will go fine from threads, - * - * This is needed because we could be in main thread here - * and malloc could be non-thread safe at this point because - * no other jobs are running. - */ - BLI_threaded_malloc_begin(); + /* Ensure malloc will go fine from threads, + * + * This is needed because we could be in main thread here + * and malloc could be non-thread safe at this point because + * no other jobs are running. + */ + BLI_threaded_malloc_begin(); - return pool; + return pool; } /** @@ -714,7 +709,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, */ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata) { - return task_pool_create_ex(scheduler, userdata, false, false); + return task_pool_create_ex(scheduler, userdata, false, false); } /** @@ -729,7 +724,7 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata) */ TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userdata) { - return task_pool_create_ex(scheduler, userdata, true, false); + return task_pool_create_ex(scheduler, userdata, true, false); } /** @@ -739,256 +734,263 @@ TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userda */ TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, void *userdata) { - return task_pool_create_ex(scheduler, userdata, false, true); + return task_pool_create_ex(scheduler, userdata, false, true); } void BLI_task_pool_free(TaskPool *pool) { - BLI_task_pool_cancel(pool); + BLI_task_pool_cancel(pool); - BLI_mutex_end(&pool->num_mutex); - BLI_condition_end(&pool->num_cond); + BLI_mutex_end(&pool->num_mutex); + BLI_condition_end(&pool->num_cond); - BLI_mutex_end(&pool->user_mutex); + BLI_mutex_end(&pool->user_mutex); #ifdef DEBUG_STATS - printf("Thread ID Allocated Reused Discarded\n"); - for (int i = 0; i < pool->scheduler->num_threads + 1; ++i) { - printf("%02d %05d %05d %05d\n", - i, - pool->mempool_stats[i].num_alloc, - pool->mempool_stats[i].num_reuse, - pool->mempool_stats[i].num_discard); - } - MEM_freeN(pool->mempool_stats); + printf("Thread ID Allocated Reused Discarded\n"); + for (int i = 0; i < pool->scheduler->num_threads + 1; ++i) { + printf("%02d %05d %05d %05d\n", + i, + pool->mempool_stats[i].num_alloc, + pool->mempool_stats[i].num_reuse, + pool->mempool_stats[i].num_discard); + } + MEM_freeN(pool->mempool_stats); #endif - if (pool->use_local_tls) { - free_task_tls(&pool->local_tls); - } + if (pool->use_local_tls) { + free_task_tls(&pool->local_tls); + } - MEM_freeN(pool); + MEM_freeN(pool); - BLI_threaded_malloc_end(); + BLI_threaded_malloc_end(); } BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id) { - return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); + return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); } -static void task_pool_push( - TaskPool *pool, TaskRunFunction run, void *taskdata, - bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority, - int thread_id) +static void task_pool_push(TaskPool *pool, + TaskRunFunction run, + void *taskdata, + bool free_taskdata, + TaskFreeFunction freedata, + TaskPriority priority, + int thread_id) { - /* Allocate task and fill it's properties. */ - Task *task = task_alloc(pool, thread_id); - task->run = run; - task->taskdata = taskdata; - task->free_taskdata = free_taskdata; - task->freedata = freedata; - task->pool = pool; - /* For suspended pools we put everything yo a global queue first - * and exit as soon as possible. - * - * This tasks will be moved to actual execution when pool is - * activated by work_and_wait(). - */ - if (pool->is_suspended) { - BLI_addhead(&pool->suspended_queue, task); - atomic_fetch_and_add_z(&pool->num_suspended, 1); - return; - } - /* Populate to any local queue first, this is cheapest push ever. */ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - /* Try to push to a local execution queue. - * These tasks will be picked up next. - */ - if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { - tls->local_queue[tls->num_local_queue] = task; - tls->num_local_queue++; - return; - } - /* If we are in the delayed tasks push mode, we push tasks to a - * temporary local queue first without any locks, and then move them - * to global execution queue with a single lock. - */ - if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { - tls->delayed_queue[tls->num_delayed_queue] = task; - tls->num_delayed_queue++; - return; - } - } - /* Do push to a global execution pool, slowest possible method, - * causes quite reasonable amount of threading overhead. - */ - task_scheduler_push(pool->scheduler, task, priority); + /* Allocate task and fill it's properties. */ + Task *task = task_alloc(pool, thread_id); + task->run = run; + task->taskdata = taskdata; + task->free_taskdata = free_taskdata; + task->freedata = freedata; + task->pool = pool; + /* For suspended pools we put everything yo a global queue first + * and exit as soon as possible. + * + * This tasks will be moved to actual execution when pool is + * activated by work_and_wait(). + */ + if (pool->is_suspended) { + BLI_addhead(&pool->suspended_queue, task); + atomic_fetch_and_add_z(&pool->num_suspended, 1); + return; + } + /* Populate to any local queue first, this is cheapest push ever. */ + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + /* Try to push to a local execution queue. + * These tasks will be picked up next. + */ + if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { + tls->local_queue[tls->num_local_queue] = task; + tls->num_local_queue++; + return; + } + /* If we are in the delayed tasks push mode, we push tasks to a + * temporary local queue first without any locks, and then move them + * to global execution queue with a single lock. + */ + if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { + tls->delayed_queue[tls->num_delayed_queue] = task; + tls->num_delayed_queue++; + return; + } + } + /* Do push to a global execution pool, slowest possible method, + * causes quite reasonable amount of threading overhead. + */ + task_scheduler_push(pool->scheduler, task, priority); } -void BLI_task_pool_push_ex( - TaskPool *pool, TaskRunFunction run, void *taskdata, - bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority) +void BLI_task_pool_push_ex(TaskPool *pool, + TaskRunFunction run, + void *taskdata, + bool free_taskdata, + TaskFreeFunction freedata, + TaskPriority priority) { - task_pool_push(pool, run, taskdata, free_taskdata, freedata, priority, -1); + task_pool_push(pool, run, taskdata, free_taskdata, freedata, priority, -1); } void BLI_task_pool_push( - TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskPriority priority) + TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskPriority priority) { - BLI_task_pool_push_ex(pool, run, taskdata, free_taskdata, NULL, priority); + BLI_task_pool_push_ex(pool, run, taskdata, free_taskdata, NULL, priority); } -void BLI_task_pool_push_from_thread(TaskPool *pool, TaskRunFunction run, - void *taskdata, bool free_taskdata, TaskPriority priority, int thread_id) +void BLI_task_pool_push_from_thread(TaskPool *pool, + TaskRunFunction run, + void *taskdata, + bool free_taskdata, + TaskPriority priority, + int thread_id) { - task_pool_push(pool, run, taskdata, free_taskdata, NULL, priority, thread_id); + task_pool_push(pool, run, taskdata, free_taskdata, NULL, priority, thread_id); } void BLI_task_pool_work_and_wait(TaskPool *pool) { - TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id); - TaskScheduler *scheduler = pool->scheduler; + TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id); + TaskScheduler *scheduler = pool->scheduler; - if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) { - if (pool->num_suspended) { - task_pool_num_increase(pool, pool->num_suspended); - BLI_mutex_lock(&scheduler->queue_mutex); + if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) { + if (pool->num_suspended) { + task_pool_num_increase(pool, pool->num_suspended); + BLI_mutex_lock(&scheduler->queue_mutex); - BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue); + BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue); - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); - pool->num_suspended = 0; - } - } + pool->num_suspended = 0; + } + } - pool->do_work = true; + pool->do_work = true; - ASSERT_THREAD_ID(pool->scheduler, pool->thread_id); + ASSERT_THREAD_ID(pool->scheduler, pool->thread_id); - handle_local_queue(tls, pool->thread_id); + handle_local_queue(tls, pool->thread_id); - BLI_mutex_lock(&pool->num_mutex); + BLI_mutex_lock(&pool->num_mutex); - while (pool->num != 0) { - Task *task, *work_task = NULL; - bool found_task = false; + while (pool->num != 0) { + Task *task, *work_task = NULL; + bool found_task = false; - BLI_mutex_unlock(&pool->num_mutex); + BLI_mutex_unlock(&pool->num_mutex); - BLI_mutex_lock(&scheduler->queue_mutex); + BLI_mutex_lock(&scheduler->queue_mutex); - /* find task from this pool. if we get a task from another pool, - * we can get into deadlock */ + /* find task from this pool. if we get a task from another pool, + * we can get into deadlock */ - for (task = scheduler->queue.first; task; task = task->next) { - if (task->pool == pool) { - work_task = task; - found_task = true; - BLI_remlink(&scheduler->queue, task); - break; - } - } + for (task = scheduler->queue.first; task; task = task->next) { + if (task->pool == pool) { + work_task = task; + found_task = true; + BLI_remlink(&scheduler->queue, task); + break; + } + } - BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_mutex_unlock(&scheduler->queue_mutex); - /* if found task, do it, otherwise wait until other tasks are done */ - if (found_task) { - /* run task */ - BLI_assert(!tls->do_delayed_push); - work_task->run(pool, work_task->taskdata, pool->thread_id); - BLI_assert(!tls->do_delayed_push); + /* if found task, do it, otherwise wait until other tasks are done */ + if (found_task) { + /* run task */ + BLI_assert(!tls->do_delayed_push); + work_task->run(pool, work_task->taskdata, pool->thread_id); + BLI_assert(!tls->do_delayed_push); - /* delete task */ - task_free(pool, task, pool->thread_id); + /* delete task */ + task_free(pool, task, pool->thread_id); - /* Handle all tasks from local queue. */ - handle_local_queue(tls, pool->thread_id); + /* Handle all tasks from local queue. */ + handle_local_queue(tls, pool->thread_id); - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); - } + /* notify pool task was done */ + task_pool_num_decrease(pool, 1); + } - BLI_mutex_lock(&pool->num_mutex); - if (pool->num == 0) { - break; - } + BLI_mutex_lock(&pool->num_mutex); + if (pool->num == 0) { + break; + } - if (!found_task) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); - } - } + if (!found_task) { + BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + } + } - BLI_mutex_unlock(&pool->num_mutex); + BLI_mutex_unlock(&pool->num_mutex); - BLI_assert(tls->num_local_queue == 0); + BLI_assert(tls->num_local_queue == 0); } void BLI_task_pool_work_wait_and_reset(TaskPool *pool) { - BLI_task_pool_work_and_wait(pool); + BLI_task_pool_work_and_wait(pool); - pool->do_work = false; - pool->is_suspended = pool->start_suspended; + pool->do_work = false; + pool->is_suspended = pool->start_suspended; } void BLI_task_pool_cancel(TaskPool *pool) { - pool->do_cancel = true; + pool->do_cancel = true; - task_scheduler_clear(pool->scheduler, pool); + task_scheduler_clear(pool->scheduler, pool); - /* wait until all entries are cleared */ - BLI_mutex_lock(&pool->num_mutex); - while (pool->num) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); - } - BLI_mutex_unlock(&pool->num_mutex); + /* wait until all entries are cleared */ + BLI_mutex_lock(&pool->num_mutex); + while (pool->num) { + BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + } + BLI_mutex_unlock(&pool->num_mutex); - pool->do_cancel = false; + pool->do_cancel = false; } bool BLI_task_pool_canceled(TaskPool *pool) { - return pool->do_cancel; + return pool->do_cancel; } void *BLI_task_pool_userdata(TaskPool *pool) { - return pool->userdata; + return pool->userdata; } ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) { - return &pool->user_mutex; + return &pool->user_mutex; } void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id) { - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - tls->do_delayed_push = true; - } + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + tls->do_delayed_push = true; + } } void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) { - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - BLI_assert(tls->do_delayed_push); - task_scheduler_push_all(pool->scheduler, - pool, - tls->delayed_queue, - tls->num_delayed_queue); - tls->do_delayed_push = false; - tls->num_delayed_queue = 0; - } + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + BLI_assert(tls->do_delayed_push); + task_scheduler_push_all(pool->scheduler, pool, tls->delayed_queue, tls->num_delayed_queue); + tls->do_delayed_push = false; + tls->num_delayed_queue = 0; + } } /* Parallel range routines */ @@ -1007,72 +1009,72 @@ void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) /* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */ #define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__) -#define MALLOCA_FREE(_mem, _size) if (((_mem) != NULL) && ((_size) > 8192)) MEM_freeN((_mem)) +#define MALLOCA_FREE(_mem, _size) \ + if (((_mem) != NULL) && ((_size) > 8192)) \ + MEM_freeN((_mem)) typedef struct ParallelRangeState { - int start, stop; - void *userdata; + int start, stop; + void *userdata; - TaskParallelRangeFunc func; + TaskParallelRangeFunc func; - int iter; - int chunk_size; + int iter; + int chunk_size; } ParallelRangeState; -BLI_INLINE bool parallel_range_next_iter_get( - ParallelRangeState * __restrict state, - int * __restrict iter, int * __restrict count) +BLI_INLINE bool parallel_range_next_iter_get(ParallelRangeState *__restrict state, + int *__restrict iter, + int *__restrict count) { - int previter = atomic_fetch_and_add_int32(&state->iter, state->chunk_size); + int previter = atomic_fetch_and_add_int32(&state->iter, state->chunk_size); - *iter = previter; - *count = max_ii(0, min_ii(state->chunk_size, state->stop - previter)); + *iter = previter; + *count = max_ii(0, min_ii(state->chunk_size, state->stop - previter)); - return (previter < state->stop); + return (previter < state->stop); } -static void parallel_range_func( - TaskPool * __restrict pool, - void *userdata_chunk, - int thread_id) +static void parallel_range_func(TaskPool *__restrict pool, void *userdata_chunk, int thread_id) { - ParallelRangeState * __restrict state = BLI_task_pool_userdata(pool); - ParallelRangeTLS tls = { - .thread_id = thread_id, - .userdata_chunk = userdata_chunk, - }; - int iter, count; - while (parallel_range_next_iter_get(state, &iter, &count)) { - for (int i = 0; i < count; ++i) { - state->func(state->userdata, iter + i, &tls); - } - } + ParallelRangeState *__restrict state = BLI_task_pool_userdata(pool); + ParallelRangeTLS tls = { + .thread_id = thread_id, + .userdata_chunk = userdata_chunk, + }; + int iter, count; + while (parallel_range_next_iter_get(state, &iter, &count)) { + for (int i = 0; i < count; ++i) { + state->func(state->userdata, iter + i, &tls); + } + } } -static void parallel_range_single_thread(const int start, int const stop, +static void parallel_range_single_thread(const int start, + int const stop, void *userdata, TaskParallelRangeFunc func, const ParallelRangeSettings *settings) { - void *userdata_chunk = settings->userdata_chunk; - const size_t userdata_chunk_size = settings->userdata_chunk_size; - void *userdata_chunk_local = NULL; - const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); - if (use_userdata_chunk) { - userdata_chunk_local = MALLOCA(userdata_chunk_size); - memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); - } - ParallelRangeTLS tls = { - .thread_id = 0, - .userdata_chunk = userdata_chunk_local, - }; - for (int i = start; i < stop; ++i) { - func(userdata, i, &tls); - } - if (settings->func_finalize != NULL) { - settings->func_finalize(userdata, userdata_chunk_local); - } - MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size); + void *userdata_chunk = settings->userdata_chunk; + const size_t userdata_chunk_size = settings->userdata_chunk_size; + void *userdata_chunk_local = NULL; + const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); + if (use_userdata_chunk) { + userdata_chunk_local = MALLOCA(userdata_chunk_size); + memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + } + ParallelRangeTLS tls = { + .thread_id = 0, + .userdata_chunk = userdata_chunk_local, + }; + for (int i = start; i < stop; ++i) { + func(userdata, i, &tls); + } + if (settings->func_finalize != NULL) { + settings->func_finalize(userdata, userdata_chunk_local); + } + MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size); } /** @@ -1080,176 +1082,166 @@ static void parallel_range_single_thread(const int start, int const stop, * * See public API doc of ParallelRangeSettings for description of all settings. */ -void BLI_task_parallel_range(const int start, const int stop, +void BLI_task_parallel_range(const int start, + const int stop, void *userdata, TaskParallelRangeFunc func, const ParallelRangeSettings *settings) { - TaskScheduler *task_scheduler; - TaskPool *task_pool; - ParallelRangeState state; - int i, num_threads, num_tasks; - - void *userdata_chunk = settings->userdata_chunk; - const size_t userdata_chunk_size = settings->userdata_chunk_size; - void *userdata_chunk_local = NULL; - void *userdata_chunk_array = NULL; - const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); - - if (start == stop) { - return; - } - - BLI_assert(start < stop); - if (userdata_chunk_size != 0) { - BLI_assert(userdata_chunk != NULL); - } - - /* If it's not enough data to be crunched, don't bother with tasks at all, - * do everything from the main thread. - */ - if (!settings->use_threading) { - parallel_range_single_thread(start, stop, - userdata, - func, - settings); - return; - } - - task_scheduler = BLI_task_scheduler_get(); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* The idea here is to prevent creating task for each of the loop iterations - * and instead have tasks which are evenly distributed across CPU cores and - * pull next iter to be crunched using the queue. - */ - num_tasks = num_threads + 2; - - state.start = start; - state.stop = stop; - state.userdata = userdata; - state.func = func; - state.iter = start; - switch (settings->scheduling_mode) { - case TASK_SCHEDULING_STATIC: - state.chunk_size = max_ii( - settings->min_iter_per_thread, - (stop - start) / (num_tasks)); - break; - case TASK_SCHEDULING_DYNAMIC: - /* TODO(sergey): Make it configurable from min_iter_per_thread. */ - state.chunk_size = 32; - break; - } - - num_tasks = min_ii(num_tasks, - max_ii(1, (stop - start) / state.chunk_size)); - - if (num_tasks == 1) { - parallel_range_single_thread(start, stop, - userdata, - func, - settings); - return; - } - - task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); - - /* NOTE: This way we are adding a memory barrier and ensure all worker - * threads can read and modify the value, without any locks. */ - atomic_fetch_and_add_int32(&state.iter, 0); - - if (use_userdata_chunk) { - userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); - } - - for (i = 0; i < num_tasks; i++) { - if (use_userdata_chunk) { - userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); - memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); - } - /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread(task_pool, - parallel_range_func, - userdata_chunk_local, false, - TASK_PRIORITY_HIGH, - task_pool->thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - for (i = 0; i < num_tasks; i++) { - userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); - settings->func_finalize(userdata, userdata_chunk_local); - } - } - MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); - } + TaskScheduler *task_scheduler; + TaskPool *task_pool; + ParallelRangeState state; + int i, num_threads, num_tasks; + + void *userdata_chunk = settings->userdata_chunk; + const size_t userdata_chunk_size = settings->userdata_chunk_size; + void *userdata_chunk_local = NULL; + void *userdata_chunk_array = NULL; + const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); + + if (start == stop) { + return; + } + + BLI_assert(start < stop); + if (userdata_chunk_size != 0) { + BLI_assert(userdata_chunk != NULL); + } + + /* If it's not enough data to be crunched, don't bother with tasks at all, + * do everything from the main thread. + */ + if (!settings->use_threading) { + parallel_range_single_thread(start, stop, userdata, func, settings); + return; + } + + task_scheduler = BLI_task_scheduler_get(); + num_threads = BLI_task_scheduler_num_threads(task_scheduler); + + /* The idea here is to prevent creating task for each of the loop iterations + * and instead have tasks which are evenly distributed across CPU cores and + * pull next iter to be crunched using the queue. + */ + num_tasks = num_threads + 2; + + state.start = start; + state.stop = stop; + state.userdata = userdata; + state.func = func; + state.iter = start; + switch (settings->scheduling_mode) { + case TASK_SCHEDULING_STATIC: + state.chunk_size = max_ii(settings->min_iter_per_thread, (stop - start) / (num_tasks)); + break; + case TASK_SCHEDULING_DYNAMIC: + /* TODO(sergey): Make it configurable from min_iter_per_thread. */ + state.chunk_size = 32; + break; + } + + num_tasks = min_ii(num_tasks, max_ii(1, (stop - start) / state.chunk_size)); + + if (num_tasks == 1) { + parallel_range_single_thread(start, stop, userdata, func, settings); + return; + } + + task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); + + /* NOTE: This way we are adding a memory barrier and ensure all worker + * threads can read and modify the value, without any locks. */ + atomic_fetch_and_add_int32(&state.iter, 0); + + if (use_userdata_chunk) { + userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); + } + + for (i = 0; i < num_tasks; i++) { + if (use_userdata_chunk) { + userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); + memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + } + /* Use this pool's pre-allocated tasks. */ + BLI_task_pool_push_from_thread(task_pool, + parallel_range_func, + userdata_chunk_local, + false, + TASK_PRIORITY_HIGH, + task_pool->thread_id); + } + + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + + if (use_userdata_chunk) { + if (settings->func_finalize != NULL) { + for (i = 0; i < num_tasks; i++) { + userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); + settings->func_finalize(userdata, userdata_chunk_local); + } + } + MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); + } } #undef MALLOCA #undef MALLOCA_FREE typedef struct ParallelListbaseState { - void *userdata; - TaskParallelListbaseFunc func; + void *userdata; + TaskParallelListbaseFunc func; - int chunk_size; - int index; - Link *link; - SpinLock lock; + int chunk_size; + int index; + Link *link; + SpinLock lock; } ParallelListState; -BLI_INLINE Link *parallel_listbase_next_iter_get( - ParallelListState * __restrict state, - int * __restrict index, - int * __restrict count) +BLI_INLINE Link *parallel_listbase_next_iter_get(ParallelListState *__restrict state, + int *__restrict index, + int *__restrict count) { - int task_count = 0; - BLI_spin_lock(&state->lock); - Link *result = state->link; - if (LIKELY(result != NULL)) { - *index = state->index; - while (state->link != NULL && task_count < state->chunk_size) { - ++task_count; - state->link = state->link->next; - } - state->index += task_count; - } - BLI_spin_unlock(&state->lock); - *count = task_count; - return result; + int task_count = 0; + BLI_spin_lock(&state->lock); + Link *result = state->link; + if (LIKELY(result != NULL)) { + *index = state->index; + while (state->link != NULL && task_count < state->chunk_size) { + ++task_count; + state->link = state->link->next; + } + state->index += task_count; + } + BLI_spin_unlock(&state->lock); + *count = task_count; + return result; } -static void parallel_listbase_func( - TaskPool * __restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void parallel_listbase_func(TaskPool *__restrict pool, + void *UNUSED(taskdata), + int UNUSED(threadid)) { - ParallelListState * __restrict state = BLI_task_pool_userdata(pool); - Link *link; - int index, count; - - while ((link = parallel_listbase_next_iter_get(state, &index, &count)) != NULL) { - for (int i = 0; i < count; ++i) { - state->func(state->userdata, link, index + i); - link = link->next; - } - } + ParallelListState *__restrict state = BLI_task_pool_userdata(pool); + Link *link; + int index, count; + + while ((link = parallel_listbase_next_iter_get(state, &index, &count)) != NULL) { + for (int i = 0; i < count; ++i) { + state->func(state->userdata, link, index + i); + link = link->next; + } + } } -static void task_parallel_listbase_no_threads( - struct ListBase *listbase, - void *userdata, - TaskParallelListbaseFunc func) +static void task_parallel_listbase_no_threads(struct ListBase *listbase, + void *userdata, + TaskParallelListbaseFunc func) { - int i = 0; - for (Link *link = listbase->first; link != NULL; link = link->next, ++i) { - func(userdata, link, i); - } + int i = 0; + for (Link *link = listbase->first; link != NULL; link = link->next, ++i) { + func(userdata, link, i); + } } /* NOTE: The idea here is to compensate for rather measurable threading @@ -1257,13 +1249,13 @@ static void task_parallel_listbase_no_threads( * to spend too much time in those overheads. */ BLI_INLINE int task_parallel_listbasecalc_chunk_size(const int num_threads) { - if (num_threads > 32) { - return 128; - } - else if (num_threads > 16) { - return 64; - } - return 32; + if (num_threads > 32) { + return 128; + } + else if (num_threads > 16) { + return 64; + } + return 32; } /** @@ -1277,75 +1269,65 @@ BLI_INLINE int task_parallel_listbasecalc_chunk_size(const int num_threads) * * \note There is no static scheduling here, since it would need another full loop over items to count them... */ -void BLI_task_parallel_listbase( - struct ListBase *listbase, - void *userdata, - TaskParallelListbaseFunc func, - const bool use_threading) +void BLI_task_parallel_listbase(struct ListBase *listbase, + void *userdata, + TaskParallelListbaseFunc func, + const bool use_threading) { - if (BLI_listbase_is_empty(listbase)) { - return; - } - if (!use_threading) { - task_parallel_listbase_no_threads(listbase, userdata, func); - return; - } - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); - /* TODO(sergey): Consider making chunk size configurable. */ - const int chunk_size = task_parallel_listbasecalc_chunk_size(num_threads); - const int num_tasks = min_ii( - num_threads, - BLI_listbase_count(listbase) / chunk_size); - if (num_tasks <= 1) { - task_parallel_listbase_no_threads(listbase, userdata, func); - return; - } - - ParallelListState state; - TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); - - state.index = 0; - state.link = listbase->first; - state.userdata = userdata; - state.func = func; - state.chunk_size = chunk_size; - BLI_spin_init(&state.lock); - - BLI_assert(num_tasks > 0); - for (int i = 0; i < num_tasks; i++) { - /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread(task_pool, - parallel_listbase_func, - NULL, false, - TASK_PRIORITY_HIGH, - task_pool->thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - BLI_spin_end(&state.lock); + if (BLI_listbase_is_empty(listbase)) { + return; + } + if (!use_threading) { + task_parallel_listbase_no_threads(listbase, userdata, func); + return; + } + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); + /* TODO(sergey): Consider making chunk size configurable. */ + const int chunk_size = task_parallel_listbasecalc_chunk_size(num_threads); + const int num_tasks = min_ii(num_threads, BLI_listbase_count(listbase) / chunk_size); + if (num_tasks <= 1) { + task_parallel_listbase_no_threads(listbase, userdata, func); + return; + } + + ParallelListState state; + TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); + + state.index = 0; + state.link = listbase->first; + state.userdata = userdata; + state.func = func; + state.chunk_size = chunk_size; + BLI_spin_init(&state.lock); + + BLI_assert(num_tasks > 0); + for (int i = 0; i < num_tasks; i++) { + /* Use this pool's pre-allocated tasks. */ + BLI_task_pool_push_from_thread( + task_pool, parallel_listbase_func, NULL, false, TASK_PRIORITY_HIGH, task_pool->thread_id); + } + + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + + BLI_spin_end(&state.lock); } - typedef struct ParallelMempoolState { - void *userdata; - TaskParallelMempoolFunc func; + void *userdata; + TaskParallelMempoolFunc func; } ParallelMempoolState; -static void parallel_mempool_func( - TaskPool * __restrict pool, - void *taskdata, - int UNUSED(threadid)) +static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) { - ParallelMempoolState * __restrict state = BLI_task_pool_userdata(pool); - BLI_mempool_iter *iter = taskdata; - MempoolIterData *item; + ParallelMempoolState *__restrict state = BLI_task_pool_userdata(pool); + BLI_mempool_iter *iter = taskdata; + MempoolIterData *item; - while ((item = BLI_mempool_iterstep(iter)) != NULL) { - state->func(state->userdata, item); - } + while ((item = BLI_mempool_iterstep(iter)) != NULL) { + state->func(state->userdata, item); + } } /** @@ -1359,57 +1341,59 @@ static void parallel_mempool_func( * * \note There is no static scheduling here. */ -void BLI_task_parallel_mempool( - BLI_mempool *mempool, - void *userdata, - TaskParallelMempoolFunc func, - const bool use_threading) +void BLI_task_parallel_mempool(BLI_mempool *mempool, + void *userdata, + TaskParallelMempoolFunc func, + const bool use_threading) { - TaskScheduler *task_scheduler; - TaskPool *task_pool; - ParallelMempoolState state; - int i, num_threads, num_tasks; - - if (BLI_mempool_len(mempool) == 0) { - return; - } - - if (!use_threading) { - BLI_mempool_iter iter; - BLI_mempool_iternew(mempool, &iter); - - for (void *item = BLI_mempool_iterstep(&iter); item != NULL; item = BLI_mempool_iterstep(&iter)) { - func(userdata, item); - } - return; - } - - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* The idea here is to prevent creating task for each of the loop iterations - * and instead have tasks which are evenly distributed across CPU cores and - * pull next item to be crunched using the threaded-aware BLI_mempool_iter. - */ - num_tasks = num_threads + 2; - - state.userdata = userdata; - state.func = func; - - BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, (size_t)num_tasks); - - for (i = 0; i < num_tasks; i++) { - /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread(task_pool, - parallel_mempool_func, - &mempool_iterators[i], false, - TASK_PRIORITY_HIGH, - task_pool->thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - BLI_mempool_iter_threadsafe_free(mempool_iterators); + TaskScheduler *task_scheduler; + TaskPool *task_pool; + ParallelMempoolState state; + int i, num_threads, num_tasks; + + if (BLI_mempool_len(mempool) == 0) { + return; + } + + if (!use_threading) { + BLI_mempool_iter iter; + BLI_mempool_iternew(mempool, &iter); + + for (void *item = BLI_mempool_iterstep(&iter); item != NULL; + item = BLI_mempool_iterstep(&iter)) { + func(userdata, item); + } + return; + } + + task_scheduler = BLI_task_scheduler_get(); + task_pool = BLI_task_pool_create_suspended(task_scheduler, &state); + num_threads = BLI_task_scheduler_num_threads(task_scheduler); + + /* The idea here is to prevent creating task for each of the loop iterations + * and instead have tasks which are evenly distributed across CPU cores and + * pull next item to be crunched using the threaded-aware BLI_mempool_iter. + */ + num_tasks = num_threads + 2; + + state.userdata = userdata; + state.func = func; + + BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, + (size_t)num_tasks); + + for (i = 0; i < num_tasks; i++) { + /* Use this pool's pre-allocated tasks. */ + BLI_task_pool_push_from_thread(task_pool, + parallel_mempool_func, + &mempool_iterators[i], + false, + TASK_PRIORITY_HIGH, + task_pool->thread_id); + } + + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + + BLI_mempool_iter_threadsafe_free(mempool_iterators); } diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 0758af03193..abd59dac891 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -50,7 +50,8 @@ #include "atomic_ops.h" #include "numaapi.h" -#if defined(__APPLE__) && defined(_OPENMP) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) && !defined(__clang__) +#if defined(__APPLE__) && defined(_OPENMP) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) && \ + !defined(__clang__) # define USE_APPLE_OMP_FIX #endif @@ -122,60 +123,60 @@ static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; static bool is_numa_available = false; -static unsigned int thread_levels = 0; /* threads can be invoked inside threads */ +static unsigned int thread_levels = 0; /* threads can be invoked inside threads */ static int num_threads_override = 0; /* just a max for security reasons */ #define RE_MAX_THREAD BLENDER_MAX_THREADS typedef struct ThreadSlot { - struct ThreadSlot *next, *prev; - void *(*do_thread)(void *); - void *callerdata; - pthread_t pthread; - int avail; + struct ThreadSlot *next, *prev; + void *(*do_thread)(void *); + void *callerdata; + pthread_t pthread; + int avail; } ThreadSlot; static void BLI_lock_malloc_thread(void) { - BLI_spin_lock(&_malloc_lock); + BLI_spin_lock(&_malloc_lock); } static void BLI_unlock_malloc_thread(void) { - BLI_spin_unlock(&_malloc_lock); + BLI_spin_unlock(&_malloc_lock); } void BLI_threadapi_init(void) { - mainid = pthread_self(); + mainid = pthread_self(); - BLI_spin_init(&_malloc_lock); - if (numaAPI_Initialize() == NUMAAPI_SUCCESS) { - is_numa_available = true; - } + BLI_spin_init(&_malloc_lock); + if (numaAPI_Initialize() == NUMAAPI_SUCCESS) { + is_numa_available = true; + } } void BLI_threadapi_exit(void) { - if (task_scheduler) { - BLI_task_scheduler_free(task_scheduler); - } - BLI_spin_end(&_malloc_lock); + if (task_scheduler) { + BLI_task_scheduler_free(task_scheduler); + } + BLI_spin_end(&_malloc_lock); } TaskScheduler *BLI_task_scheduler_get(void) { - if (task_scheduler == NULL) { - int tot_thread = BLI_system_thread_count(); + if (task_scheduler == NULL) { + int tot_thread = BLI_system_thread_count(); - /* Do a lazy initialization, so it happens after - * command line arguments parsing - */ - task_scheduler = BLI_task_scheduler_create(tot_thread); - } + /* Do a lazy initialization, so it happens after + * command line arguments parsing + */ + task_scheduler = BLI_task_scheduler_create(tot_thread); + } - return task_scheduler; + return task_scheduler; } /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) @@ -184,161 +185,161 @@ TaskScheduler *BLI_task_scheduler_get(void) void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int tot) { - int a; + int a; - if (threadbase != NULL && tot > 0) { - BLI_listbase_clear(threadbase); + if (threadbase != NULL && tot > 0) { + BLI_listbase_clear(threadbase); - if (tot > RE_MAX_THREAD) { - tot = RE_MAX_THREAD; - } - else if (tot < 1) { - tot = 1; - } + if (tot > RE_MAX_THREAD) { + tot = RE_MAX_THREAD; + } + else if (tot < 1) { + tot = 1; + } - for (a = 0; a < tot; a++) { - ThreadSlot *tslot = MEM_callocN(sizeof(ThreadSlot), "threadslot"); - BLI_addtail(threadbase, tslot); - tslot->do_thread = do_thread; - tslot->avail = 1; - } - } + for (a = 0; a < tot; a++) { + ThreadSlot *tslot = MEM_callocN(sizeof(ThreadSlot), "threadslot"); + BLI_addtail(threadbase, tslot); + tslot->do_thread = do_thread; + tslot->avail = 1; + } + } - unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); + if (level == 0) { + MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); #ifdef USE_APPLE_OMP_FIX - /* workaround for Apple gcc 4.2.1 omp vs background thread bug, - * we copy gomp thread local storage pointer to setting it again - * inside the thread that we start */ - thread_tls_data = pthread_getspecific(gomp_tls_key); + /* workaround for Apple gcc 4.2.1 omp vs background thread bug, + * we copy gomp thread local storage pointer to setting it again + * inside the thread that we start */ + thread_tls_data = pthread_getspecific(gomp_tls_key); #endif - } + } } /* amount of available threads */ int BLI_available_threads(ListBase *threadbase) { - ThreadSlot *tslot; - int counter = 0; + ThreadSlot *tslot; + int counter = 0; - for (tslot = threadbase->first; tslot; tslot = tslot->next) { - if (tslot->avail) { - counter++; - } - } - return counter; + for (tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->avail) { + counter++; + } + } + return counter; } /* returns thread number, for sample patterns or threadsafe tables */ int BLI_threadpool_available_thread_index(ListBase *threadbase) { - ThreadSlot *tslot; - int counter = 0; + ThreadSlot *tslot; + int counter = 0; - for (tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { - if (tslot->avail) { - return counter; - } - } - return 0; + for (tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { + if (tslot->avail) { + return counter; + } + } + return 0; } static void *tslot_thread_start(void *tslot_p) { - ThreadSlot *tslot = (ThreadSlot *)tslot_p; + ThreadSlot *tslot = (ThreadSlot *)tslot_p; #ifdef USE_APPLE_OMP_FIX - /* workaround for Apple gcc 4.2.1 omp vs background thread bug, - * set gomp thread local storage pointer which was copied beforehand */ - pthread_setspecific(gomp_tls_key, thread_tls_data); + /* workaround for Apple gcc 4.2.1 omp vs background thread bug, + * set gomp thread local storage pointer which was copied beforehand */ + pthread_setspecific(gomp_tls_key, thread_tls_data); #endif - return tslot->do_thread(tslot->callerdata); + return tslot->do_thread(tslot->callerdata); } int BLI_thread_is_main(void) { - return pthread_equal(pthread_self(), mainid); + return pthread_equal(pthread_self(), mainid); } void BLI_threadpool_insert(ListBase *threadbase, void *callerdata) { - ThreadSlot *tslot; + ThreadSlot *tslot; - for (tslot = threadbase->first; tslot; tslot = tslot->next) { - if (tslot->avail) { - tslot->avail = 0; - tslot->callerdata = callerdata; - pthread_create(&tslot->pthread, NULL, tslot_thread_start, tslot); - return; - } - } - printf("ERROR: could not insert thread slot\n"); + for (tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->avail) { + tslot->avail = 0; + tslot->callerdata = callerdata; + pthread_create(&tslot->pthread, NULL, tslot_thread_start, tslot); + return; + } + } + printf("ERROR: could not insert thread slot\n"); } void BLI_threadpool_remove(ListBase *threadbase, void *callerdata) { - ThreadSlot *tslot; + ThreadSlot *tslot; - for (tslot = threadbase->first; tslot; tslot = tslot->next) { - if (tslot->callerdata == callerdata) { - pthread_join(tslot->pthread, NULL); - tslot->callerdata = NULL; - tslot->avail = 1; - } - } + for (tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->callerdata == callerdata) { + pthread_join(tslot->pthread, NULL); + tslot->callerdata = NULL; + tslot->avail = 1; + } + } } void BLI_threadpool_remove_index(ListBase *threadbase, int index) { - ThreadSlot *tslot; - int counter = 0; + ThreadSlot *tslot; + int counter = 0; - for (tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { - if (counter == index && tslot->avail == 0) { - pthread_join(tslot->pthread, NULL); - tslot->callerdata = NULL; - tslot->avail = 1; - break; - } - } + for (tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { + if (counter == index && tslot->avail == 0) { + pthread_join(tslot->pthread, NULL); + tslot->callerdata = NULL; + tslot->avail = 1; + break; + } + } } void BLI_threadpool_clear(ListBase *threadbase) { - ThreadSlot *tslot; + ThreadSlot *tslot; - for (tslot = threadbase->first; tslot; tslot = tslot->next) { - if (tslot->avail == 0) { - pthread_join(tslot->pthread, NULL); - tslot->callerdata = NULL; - tslot->avail = 1; - } - } + for (tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->avail == 0) { + pthread_join(tslot->pthread, NULL); + tslot->callerdata = NULL; + tslot->avail = 1; + } + } } void BLI_threadpool_end(ListBase *threadbase) { - ThreadSlot *tslot; + ThreadSlot *tslot; - /* only needed if there's actually some stuff to end - * this way we don't end up decrementing thread_levels on an empty threadbase - * */ - if (threadbase && (BLI_listbase_is_empty(threadbase) == false)) { - for (tslot = threadbase->first; tslot; tslot = tslot->next) { - if (tslot->avail == 0) { - pthread_join(tslot->pthread, NULL); - } - } - BLI_freelistN(threadbase); - } + /* only needed if there's actually some stuff to end + * this way we don't end up decrementing thread_levels on an empty threadbase + * */ + if (threadbase && (BLI_listbase_is_empty(threadbase) == false)) { + for (tslot = threadbase->first; tslot; tslot = tslot->next) { + if (tslot->avail == 0) { + pthread_join(tslot->pthread, NULL); + } + } + BLI_freelistN(threadbase); + } - unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(NULL, NULL); - } + unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); + if (level == 0) { + MEM_set_lock_callback(NULL, NULL); + } } /* System Information */ @@ -346,131 +347,131 @@ void BLI_threadpool_end(ListBase *threadbase) /* how many threads are native on this system? */ int BLI_system_thread_count(void) { - static int t = -1; + static int t = -1; - if (num_threads_override != 0) { - return num_threads_override; - } - else if (LIKELY(t != -1)) { - return t; - } + if (num_threads_override != 0) { + return num_threads_override; + } + else if (LIKELY(t != -1)) { + return t; + } - { + { #ifdef WIN32 - SYSTEM_INFO info; - GetSystemInfo(&info); - t = (int) info.dwNumberOfProcessors; + SYSTEM_INFO info; + GetSystemInfo(&info); + t = (int)info.dwNumberOfProcessors; #else -# ifdef __APPLE__ - int mib[2]; - size_t len; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(t); - sysctl(mib, 2, &t, &len, NULL, 0); -# else - t = (int)sysconf(_SC_NPROCESSORS_ONLN); -# endif +# ifdef __APPLE__ + int mib[2]; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(t); + sysctl(mib, 2, &t, &len, NULL, 0); +# else + t = (int)sysconf(_SC_NPROCESSORS_ONLN); +# endif #endif - } + } - CLAMP(t, 1, RE_MAX_THREAD); + CLAMP(t, 1, RE_MAX_THREAD); - return t; + return t; } void BLI_system_num_threads_override_set(int num) { - num_threads_override = num; + num_threads_override = num; } int BLI_system_num_threads_override_get(void) { - return num_threads_override; + return num_threads_override; } /* Global Mutex Locks */ static ThreadMutex *global_mutex_from_type(const int type) { - switch (type) { - case LOCK_IMAGE: - return &_image_lock; - case LOCK_DRAW_IMAGE: - return &_image_draw_lock; - case LOCK_VIEWER: - return &_viewer_lock; - case LOCK_CUSTOM1: - return &_custom1_lock; - case LOCK_RCACHE: - return &_rcache_lock; - case LOCK_OPENGL: - return &_opengl_lock; - case LOCK_NODES: - return &_nodes_lock; - case LOCK_MOVIECLIP: - return &_movieclip_lock; - case LOCK_COLORMANAGE: - return &_colormanage_lock; - case LOCK_FFTW: - return &_fftw_lock; - case LOCK_VIEW3D: - return &_view3d_lock; - default: - BLI_assert(0); - return NULL; - } + switch (type) { + case LOCK_IMAGE: + return &_image_lock; + case LOCK_DRAW_IMAGE: + return &_image_draw_lock; + case LOCK_VIEWER: + return &_viewer_lock; + case LOCK_CUSTOM1: + return &_custom1_lock; + case LOCK_RCACHE: + return &_rcache_lock; + case LOCK_OPENGL: + return &_opengl_lock; + case LOCK_NODES: + return &_nodes_lock; + case LOCK_MOVIECLIP: + return &_movieclip_lock; + case LOCK_COLORMANAGE: + return &_colormanage_lock; + case LOCK_FFTW: + return &_fftw_lock; + case LOCK_VIEW3D: + return &_view3d_lock; + default: + BLI_assert(0); + return NULL; + } } void BLI_thread_lock(int type) { - pthread_mutex_lock(global_mutex_from_type(type)); + pthread_mutex_lock(global_mutex_from_type(type)); } void BLI_thread_unlock(int type) { - pthread_mutex_unlock(global_mutex_from_type(type)); + pthread_mutex_unlock(global_mutex_from_type(type)); } /* Mutex Locks */ void BLI_mutex_init(ThreadMutex *mutex) { - pthread_mutex_init(mutex, NULL); + pthread_mutex_init(mutex, NULL); } void BLI_mutex_lock(ThreadMutex *mutex) { - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } void BLI_mutex_unlock(ThreadMutex *mutex) { - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } bool BLI_mutex_trylock(ThreadMutex *mutex) { - return (pthread_mutex_trylock(mutex) == 0); + return (pthread_mutex_trylock(mutex) == 0); } void BLI_mutex_end(ThreadMutex *mutex) { - pthread_mutex_destroy(mutex); + pthread_mutex_destroy(mutex); } ThreadMutex *BLI_mutex_alloc(void) { - ThreadMutex *mutex = MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"); - BLI_mutex_init(mutex); - return mutex; + ThreadMutex *mutex = MEM_callocN(sizeof(ThreadMutex), "ThreadMutex"); + BLI_mutex_init(mutex); + return mutex; } void BLI_mutex_free(ThreadMutex *mutex) { - BLI_mutex_end(mutex); - MEM_freeN(mutex); + BLI_mutex_end(mutex); + MEM_freeN(mutex); } /* Spin Locks */ @@ -478,39 +479,39 @@ void BLI_mutex_free(ThreadMutex *mutex) void BLI_spin_init(SpinLock *spin) { #if defined(__APPLE__) - *spin = OS_SPINLOCK_INIT; + *spin = OS_SPINLOCK_INIT; #elif defined(_MSC_VER) - *spin = 0; + *spin = 0; #else - pthread_spin_init(spin, 0); + pthread_spin_init(spin, 0); #endif } void BLI_spin_lock(SpinLock *spin) { #if defined(__APPLE__) - OSSpinLockLock(spin); + OSSpinLockLock(spin); #elif defined(_MSC_VER) - while (InterlockedExchangeAcquire(spin, 1)) { - while (*spin) { - /* Spinlock hint for processors with hyperthreading. */ - YieldProcessor(); - } - } + while (InterlockedExchangeAcquire(spin, 1)) { + while (*spin) { + /* Spinlock hint for processors with hyperthreading. */ + YieldProcessor(); + } + } #else - pthread_spin_lock(spin); + pthread_spin_lock(spin); #endif } void BLI_spin_unlock(SpinLock *spin) { #if defined(__APPLE__) - OSSpinLockUnlock(spin); + OSSpinLockUnlock(spin); #elif defined(_MSC_VER) - _ReadWriteBarrier(); - *spin = 0; + _ReadWriteBarrier(); + *spin = 0; #else - pthread_spin_unlock(spin); + pthread_spin_unlock(spin); #endif } @@ -521,7 +522,7 @@ void BLI_spin_end(SpinLock *UNUSED(spin)) #else void BLI_spin_end(SpinLock *spin) { - pthread_spin_destroy(spin); + pthread_spin_destroy(spin); } #endif @@ -529,87 +530,87 @@ void BLI_spin_end(SpinLock *spin) void BLI_rw_mutex_init(ThreadRWMutex *mutex) { - pthread_rwlock_init(mutex, NULL); + pthread_rwlock_init(mutex, NULL); } void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode) { - if (mode == THREAD_LOCK_READ) { - pthread_rwlock_rdlock(mutex); - } - else { - pthread_rwlock_wrlock(mutex); - } + if (mode == THREAD_LOCK_READ) { + pthread_rwlock_rdlock(mutex); + } + else { + pthread_rwlock_wrlock(mutex); + } } void BLI_rw_mutex_unlock(ThreadRWMutex *mutex) { - pthread_rwlock_unlock(mutex); + pthread_rwlock_unlock(mutex); } void BLI_rw_mutex_end(ThreadRWMutex *mutex) { - pthread_rwlock_destroy(mutex); + pthread_rwlock_destroy(mutex); } ThreadRWMutex *BLI_rw_mutex_alloc(void) { - ThreadRWMutex *mutex = MEM_callocN(sizeof(ThreadRWMutex), "ThreadRWMutex"); - BLI_rw_mutex_init(mutex); - return mutex; + ThreadRWMutex *mutex = MEM_callocN(sizeof(ThreadRWMutex), "ThreadRWMutex"); + BLI_rw_mutex_init(mutex); + return mutex; } void BLI_rw_mutex_free(ThreadRWMutex *mutex) { - BLI_rw_mutex_end(mutex); - MEM_freeN(mutex); + BLI_rw_mutex_end(mutex); + MEM_freeN(mutex); } /* Ticket Mutex Lock */ struct TicketMutex { - pthread_cond_t cond; - pthread_mutex_t mutex; - unsigned int queue_head, queue_tail; + pthread_cond_t cond; + pthread_mutex_t mutex; + unsigned int queue_head, queue_tail; }; TicketMutex *BLI_ticket_mutex_alloc(void) { - TicketMutex *ticket = MEM_callocN(sizeof(TicketMutex), "TicketMutex"); + TicketMutex *ticket = MEM_callocN(sizeof(TicketMutex), "TicketMutex"); - pthread_cond_init(&ticket->cond, NULL); - pthread_mutex_init(&ticket->mutex, NULL); + pthread_cond_init(&ticket->cond, NULL); + pthread_mutex_init(&ticket->mutex, NULL); - return ticket; + return ticket; } void BLI_ticket_mutex_free(TicketMutex *ticket) { - pthread_mutex_destroy(&ticket->mutex); - pthread_cond_destroy(&ticket->cond); - MEM_freeN(ticket); + pthread_mutex_destroy(&ticket->mutex); + pthread_cond_destroy(&ticket->cond); + MEM_freeN(ticket); } void BLI_ticket_mutex_lock(TicketMutex *ticket) { - unsigned int queue_me; + unsigned int queue_me; - pthread_mutex_lock(&ticket->mutex); - queue_me = ticket->queue_tail++; + pthread_mutex_lock(&ticket->mutex); + queue_me = ticket->queue_tail++; - while (queue_me != ticket->queue_head) { - pthread_cond_wait(&ticket->cond, &ticket->mutex); - } + while (queue_me != ticket->queue_head) { + pthread_cond_wait(&ticket->cond, &ticket->mutex); + } - pthread_mutex_unlock(&ticket->mutex); + pthread_mutex_unlock(&ticket->mutex); } void BLI_ticket_mutex_unlock(TicketMutex *ticket) { - pthread_mutex_lock(&ticket->mutex); - ticket->queue_head++; - pthread_cond_broadcast(&ticket->cond); - pthread_mutex_unlock(&ticket->mutex); + pthread_mutex_lock(&ticket->mutex); + ticket->queue_head++; + pthread_cond_broadcast(&ticket->cond); + pthread_mutex_unlock(&ticket->mutex); } /* ************************************************ */ @@ -618,241 +619,241 @@ void BLI_ticket_mutex_unlock(TicketMutex *ticket) void BLI_condition_init(ThreadCondition *cond) { - pthread_cond_init(cond, NULL); + pthread_cond_init(cond, NULL); } void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex) { - pthread_cond_wait(cond, mutex); + pthread_cond_wait(cond, mutex); } void BLI_condition_wait_global_mutex(ThreadCondition *cond, const int type) { - pthread_cond_wait(cond, global_mutex_from_type(type)); + pthread_cond_wait(cond, global_mutex_from_type(type)); } void BLI_condition_notify_one(ThreadCondition *cond) { - pthread_cond_signal(cond); + pthread_cond_signal(cond); } void BLI_condition_notify_all(ThreadCondition *cond) { - pthread_cond_broadcast(cond); + pthread_cond_broadcast(cond); } void BLI_condition_end(ThreadCondition *cond) { - pthread_cond_destroy(cond); + pthread_cond_destroy(cond); } /* ************************************************ */ struct ThreadQueue { - GSQueue *queue; - pthread_mutex_t mutex; - pthread_cond_t push_cond; - pthread_cond_t finish_cond; - volatile int nowait; - volatile int canceled; + GSQueue *queue; + pthread_mutex_t mutex; + pthread_cond_t push_cond; + pthread_cond_t finish_cond; + volatile int nowait; + volatile int canceled; }; ThreadQueue *BLI_thread_queue_init(void) { - ThreadQueue *queue; + ThreadQueue *queue; - queue = MEM_callocN(sizeof(ThreadQueue), "ThreadQueue"); - queue->queue = BLI_gsqueue_new(sizeof(void *)); + queue = MEM_callocN(sizeof(ThreadQueue), "ThreadQueue"); + queue->queue = BLI_gsqueue_new(sizeof(void *)); - pthread_mutex_init(&queue->mutex, NULL); - pthread_cond_init(&queue->push_cond, NULL); - pthread_cond_init(&queue->finish_cond, NULL); + pthread_mutex_init(&queue->mutex, NULL); + pthread_cond_init(&queue->push_cond, NULL); + pthread_cond_init(&queue->finish_cond, NULL); - return queue; + return queue; } void BLI_thread_queue_free(ThreadQueue *queue) { - /* destroy everything, assumes no one is using queue anymore */ - pthread_cond_destroy(&queue->finish_cond); - pthread_cond_destroy(&queue->push_cond); - pthread_mutex_destroy(&queue->mutex); + /* destroy everything, assumes no one is using queue anymore */ + pthread_cond_destroy(&queue->finish_cond); + pthread_cond_destroy(&queue->push_cond); + pthread_mutex_destroy(&queue->mutex); - BLI_gsqueue_free(queue->queue); + BLI_gsqueue_free(queue->queue); - MEM_freeN(queue); + MEM_freeN(queue); } void BLI_thread_queue_push(ThreadQueue *queue, void *work) { - pthread_mutex_lock(&queue->mutex); + pthread_mutex_lock(&queue->mutex); - BLI_gsqueue_push(queue->queue, &work); + BLI_gsqueue_push(queue->queue, &work); - /* signal threads waiting to pop */ - pthread_cond_signal(&queue->push_cond); - pthread_mutex_unlock(&queue->mutex); + /* signal threads waiting to pop */ + pthread_cond_signal(&queue->push_cond); + pthread_mutex_unlock(&queue->mutex); } void *BLI_thread_queue_pop(ThreadQueue *queue) { - void *work = NULL; + void *work = NULL; - /* wait until there is work */ - pthread_mutex_lock(&queue->mutex); - while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) { - pthread_cond_wait(&queue->push_cond, &queue->mutex); - } + /* wait until there is work */ + pthread_mutex_lock(&queue->mutex); + while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) { + pthread_cond_wait(&queue->push_cond, &queue->mutex); + } - /* if we have something, pop it */ - if (!BLI_gsqueue_is_empty(queue->queue)) { - BLI_gsqueue_pop(queue->queue, &work); + /* if we have something, pop it */ + if (!BLI_gsqueue_is_empty(queue->queue)) { + BLI_gsqueue_pop(queue->queue, &work); - if (BLI_gsqueue_is_empty(queue->queue)) { - pthread_cond_broadcast(&queue->finish_cond); - } - } + if (BLI_gsqueue_is_empty(queue->queue)) { + pthread_cond_broadcast(&queue->finish_cond); + } + } - pthread_mutex_unlock(&queue->mutex); + pthread_mutex_unlock(&queue->mutex); - return work; + return work; } static void wait_timeout(struct timespec *timeout, int ms) { - ldiv_t div_result; - long sec, usec, x; + ldiv_t div_result; + long sec, usec, x; #ifdef WIN32 - { - struct _timeb now; - _ftime(&now); - sec = now.time; - usec = now.millitm * 1000; /* microsecond precision would be better */ - } + { + struct _timeb now; + _ftime(&now); + sec = now.time; + usec = now.millitm * 1000; /* microsecond precision would be better */ + } #else - { - struct timeval now; - gettimeofday(&now, NULL); - sec = now.tv_sec; - usec = now.tv_usec; - } + { + struct timeval now; + gettimeofday(&now, NULL); + sec = now.tv_sec; + usec = now.tv_usec; + } #endif - /* add current time + millisecond offset */ - div_result = ldiv(ms, 1000); - timeout->tv_sec = sec + div_result.quot; + /* add current time + millisecond offset */ + div_result = ldiv(ms, 1000); + timeout->tv_sec = sec + div_result.quot; - x = usec + (div_result.rem * 1000); + x = usec + (div_result.rem * 1000); - if (x >= 1000000) { - timeout->tv_sec++; - x -= 1000000; - } + if (x >= 1000000) { + timeout->tv_sec++; + x -= 1000000; + } - timeout->tv_nsec = x * 1000; + timeout->tv_nsec = x * 1000; } void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms) { - double t; - void *work = NULL; - struct timespec timeout; + double t; + void *work = NULL; + struct timespec timeout; - t = PIL_check_seconds_timer(); - wait_timeout(&timeout, ms); + t = PIL_check_seconds_timer(); + wait_timeout(&timeout, ms); - /* wait until there is work */ - pthread_mutex_lock(&queue->mutex); - while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) { - if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) { - break; - } - else if (PIL_check_seconds_timer() - t >= ms * 0.001) { - break; - } - } + /* wait until there is work */ + pthread_mutex_lock(&queue->mutex); + while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) { + if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) { + break; + } + else if (PIL_check_seconds_timer() - t >= ms * 0.001) { + break; + } + } - /* if we have something, pop it */ - if (!BLI_gsqueue_is_empty(queue->queue)) { - BLI_gsqueue_pop(queue->queue, &work); + /* if we have something, pop it */ + if (!BLI_gsqueue_is_empty(queue->queue)) { + BLI_gsqueue_pop(queue->queue, &work); - if (BLI_gsqueue_is_empty(queue->queue)) { - pthread_cond_broadcast(&queue->finish_cond); - } - } + if (BLI_gsqueue_is_empty(queue->queue)) { + pthread_cond_broadcast(&queue->finish_cond); + } + } - pthread_mutex_unlock(&queue->mutex); + pthread_mutex_unlock(&queue->mutex); - return work; + return work; } int BLI_thread_queue_len(ThreadQueue *queue) { - int size; + int size; - pthread_mutex_lock(&queue->mutex); - size = BLI_gsqueue_len(queue->queue); - pthread_mutex_unlock(&queue->mutex); + pthread_mutex_lock(&queue->mutex); + size = BLI_gsqueue_len(queue->queue); + pthread_mutex_unlock(&queue->mutex); - return size; + return size; } bool BLI_thread_queue_is_empty(ThreadQueue *queue) { - bool is_empty; + bool is_empty; - pthread_mutex_lock(&queue->mutex); - is_empty = BLI_gsqueue_is_empty(queue->queue); - pthread_mutex_unlock(&queue->mutex); + pthread_mutex_lock(&queue->mutex); + is_empty = BLI_gsqueue_is_empty(queue->queue); + pthread_mutex_unlock(&queue->mutex); - return is_empty; + return is_empty; } void BLI_thread_queue_nowait(ThreadQueue *queue) { - pthread_mutex_lock(&queue->mutex); + pthread_mutex_lock(&queue->mutex); - queue->nowait = 1; + queue->nowait = 1; - /* signal threads waiting to pop */ - pthread_cond_broadcast(&queue->push_cond); - pthread_mutex_unlock(&queue->mutex); + /* signal threads waiting to pop */ + pthread_cond_broadcast(&queue->push_cond); + pthread_mutex_unlock(&queue->mutex); } void BLI_thread_queue_wait_finish(ThreadQueue *queue) { - /* wait for finish condition */ - pthread_mutex_lock(&queue->mutex); + /* wait for finish condition */ + pthread_mutex_lock(&queue->mutex); - while (!BLI_gsqueue_is_empty(queue->queue)) { - pthread_cond_wait(&queue->finish_cond, &queue->mutex); - } + while (!BLI_gsqueue_is_empty(queue->queue)) { + pthread_cond_wait(&queue->finish_cond, &queue->mutex); + } - pthread_mutex_unlock(&queue->mutex); + pthread_mutex_unlock(&queue->mutex); } /* ************************************************ */ void BLI_threaded_malloc_begin(void) { - unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - /* There is a little chance that two threads will need to access to a - * scheduler which was not yet created from main thread. which could - * cause scheduler created multiple times. - */ - BLI_task_scheduler_get(); - } + unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); + if (level == 0) { + MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + /* There is a little chance that two threads will need to access to a + * scheduler which was not yet created from main thread. which could + * cause scheduler created multiple times. + */ + BLI_task_scheduler_get(); + } } void BLI_threaded_malloc_end(void) { - unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(NULL, NULL); - } + unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); + if (level == 0) { + MEM_set_lock_callback(NULL, NULL); + } } /* **** Special functions to help performance on crazy NUMA setups. **** */ @@ -860,107 +861,107 @@ void BLI_threaded_malloc_end(void) #if 0 /* UNUSED */ static bool check_is_threadripper2_alike_topology(void) { - /* NOTE: We hope operating system does not support CPU hotswap to - * a different brand. And that SMP of different types is also not - * encouraged by the system. */ - static bool is_initialized = false; - static bool is_threadripper2 = false; - if (is_initialized) { - return is_threadripper2; - } - is_initialized = true; - char *cpu_brand = BLI_cpu_brand_string(); - if (cpu_brand == NULL) { - return false; - } - if (strstr(cpu_brand, "Threadripper")) { - /* NOTE: We consider all Thread-rippers having similar topology to - * the second one. This is because we are trying to utilize NUMA node - * 0 as much as possible. This node does exist on earlier versions of - * thread-ripper and setting affinity to it should not have negative - * effect. - * This allows us to avoid per-model check, making the code more - * reliable for the CPUs which are not yet released. - */ - if (strstr(cpu_brand, "2990WX") || strstr(cpu_brand, "2950X")) { - is_threadripper2 = true; - } - } - /* NOTE: While all dies of EPYC has memory controller, only two f them - * has access to a lower-indexed DDR slots. Those dies are same as on - * Threadripper2 with the memory controller. - * Now, it is rather likely that reasonable amount of users don't max - * up their DR slots, making it only two dies connected to a DDR slot - * with actual memory in it. */ - if (strstr(cpu_brand, "EPYC")) { - /* NOTE: Similarly to Thread-ripper we do not do model check. */ - is_threadripper2 = true; - } - MEM_freeN(cpu_brand); - return is_threadripper2; + /* NOTE: We hope operating system does not support CPU hotswap to + * a different brand. And that SMP of different types is also not + * encouraged by the system. */ + static bool is_initialized = false; + static bool is_threadripper2 = false; + if (is_initialized) { + return is_threadripper2; + } + is_initialized = true; + char *cpu_brand = BLI_cpu_brand_string(); + if (cpu_brand == NULL) { + return false; + } + if (strstr(cpu_brand, "Threadripper")) { + /* NOTE: We consider all Thread-rippers having similar topology to + * the second one. This is because we are trying to utilize NUMA node + * 0 as much as possible. This node does exist on earlier versions of + * thread-ripper and setting affinity to it should not have negative + * effect. + * This allows us to avoid per-model check, making the code more + * reliable for the CPUs which are not yet released. + */ + if (strstr(cpu_brand, "2990WX") || strstr(cpu_brand, "2950X")) { + is_threadripper2 = true; + } + } + /* NOTE: While all dies of EPYC has memory controller, only two f them + * has access to a lower-indexed DDR slots. Those dies are same as on + * Threadripper2 with the memory controller. + * Now, it is rather likely that reasonable amount of users don't max + * up their DR slots, making it only two dies connected to a DDR slot + * with actual memory in it. */ + if (strstr(cpu_brand, "EPYC")) { + /* NOTE: Similarly to Thread-ripper we do not do model check. */ + is_threadripper2 = true; + } + MEM_freeN(cpu_brand); + return is_threadripper2; } static void threadripper_put_process_on_fast_node(void) { - if (!is_numa_available) { - return; - } - /* NOTE: Technically, we can use NUMA nodes 0 and 2 and using both of - * them in the affinity mask will allow OS to schedule threads more - * flexible,possibly increasing overall performance when multiple apps - * are crunching numbers. - * - * However, if scene fits into memory adjacent to a single die we don't - * want OS to re-schedule the process to another die since that will make - * it further away from memory allocated for .blend file. */ - /* NOTE: Even if NUMA is available in the API but is disabled in BIOS on - * this workstation we still process here. If NUMA is disabled it will be a - * single node, so our action is no-visible-changes, but allows to keep - * things simple and unified. */ - numaAPI_RunProcessOnNode(0); + if (!is_numa_available) { + return; + } + /* NOTE: Technically, we can use NUMA nodes 0 and 2 and using both of + * them in the affinity mask will allow OS to schedule threads more + * flexible,possibly increasing overall performance when multiple apps + * are crunching numbers. + * + * However, if scene fits into memory adjacent to a single die we don't + * want OS to re-schedule the process to another die since that will make + * it further away from memory allocated for .blend file. */ + /* NOTE: Even if NUMA is available in the API but is disabled in BIOS on + * this workstation we still process here. If NUMA is disabled it will be a + * single node, so our action is no-visible-changes, but allows to keep + * things simple and unified. */ + numaAPI_RunProcessOnNode(0); } static void threadripper_put_thread_on_fast_node(void) { - if (!is_numa_available) { - return; - } - /* NOTE: This is where things becomes more interesting. On the one hand - * we can use nodes 0 and 2 and allow operating system to do balancing - * of processes/threads for the maximum performance when multiple apps - * are running. - * On another hand, however, we probably want to use same node as the - * main thread since that's where the memory of .blend file is likely - * to be allocated. - * Since the main thread is currently on node 0, we also put thread on - * same node. */ - /* See additional note about NUMA disabled in BIOS above. */ - numaAPI_RunThreadOnNode(0); -} -#endif /* UNUSED */ + if (!is_numa_available) { + return; + } + /* NOTE: This is where things becomes more interesting. On the one hand + * we can use nodes 0 and 2 and allow operating system to do balancing + * of processes/threads for the maximum performance when multiple apps + * are running. + * On another hand, however, we probably want to use same node as the + * main thread since that's where the memory of .blend file is likely + * to be allocated. + * Since the main thread is currently on node 0, we also put thread on + * same node. */ + /* See additional note about NUMA disabled in BIOS above. */ + numaAPI_RunThreadOnNode(0); +} +#endif /* UNUSED */ void BLI_thread_put_process_on_fast_node(void) { - /* Disabled for now since this causes only 16 threads to be used on a - * thread-ripper for computations like sculpting and fluid sim. The problem - * is that all threads created as children from this thread will inherit - * the NUMA node and so will end up on the same node. This can be fixed - * case-by-case by assigning the NUMA node for every child thread, however - * this is difficult for external libraries and OpenMP, and out of our - * control for plugins like external renderers. */ + /* Disabled for now since this causes only 16 threads to be used on a + * thread-ripper for computations like sculpting and fluid sim. The problem + * is that all threads created as children from this thread will inherit + * the NUMA node and so will end up on the same node. This can be fixed + * case-by-case by assigning the NUMA node for every child thread, however + * this is difficult for external libraries and OpenMP, and out of our + * control for plugins like external renderers. */ #if 0 - if (check_is_threadripper2_alike_topology()) { - threadripper_put_process_on_fast_node(); - } + if (check_is_threadripper2_alike_topology()) { + threadripper_put_process_on_fast_node(); + } #endif } void BLI_thread_put_thread_on_fast_node(void) { - /* Disabled for now, see comment above. */ + /* Disabled for now, see comment above. */ #if 0 - if (check_is_threadripper2_alike_topology()) { - threadripper_put_thread_on_fast_node(); - } + if (check_is_threadripper2_alike_topology()) { + threadripper_put_thread_on_fast_node(); + } #endif } diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c index ee90e74ea52..f7bcf303b4b 100644 --- a/source/blender/blenlib/intern/time.c +++ b/source/blender/blenlib/intern/time.c @@ -21,94 +21,93 @@ * \ingroup bli */ - #include "PIL_time.h" #ifdef WIN32 -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x501 /* Windows XP or newer */ -#endif -#define WIN32_LEAN_AND_MEAN -#include <windows.h> +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x501 /* Windows XP or newer */ +# endif +# define WIN32_LEAN_AND_MEAN +# include <windows.h> double PIL_check_seconds_timer(void) { - static int hasperfcounter = -1; /* (-1 == unknown) */ - static double perffreq; - - if (hasperfcounter == -1) { - __int64 ifreq; - hasperfcounter = QueryPerformanceFrequency((LARGE_INTEGER *) &ifreq); - perffreq = (double) ifreq; - } - - if (hasperfcounter) { - __int64 count; - - QueryPerformanceCounter((LARGE_INTEGER *) &count); - - return count / perffreq; - } - else { - static double accum = 0.0; - static int ltick = 0; - int ntick = GetTickCount(); - - if (ntick < ltick) { - accum += (0xFFFFFFFF - ltick + ntick) / 1000.0; - } - else { - accum += (ntick - ltick) / 1000.0; - } - - ltick = ntick; - return accum; - } + static int hasperfcounter = -1; /* (-1 == unknown) */ + static double perffreq; + + if (hasperfcounter == -1) { + __int64 ifreq; + hasperfcounter = QueryPerformanceFrequency((LARGE_INTEGER *)&ifreq); + perffreq = (double)ifreq; + } + + if (hasperfcounter) { + __int64 count; + + QueryPerformanceCounter((LARGE_INTEGER *)&count); + + return count / perffreq; + } + else { + static double accum = 0.0; + static int ltick = 0; + int ntick = GetTickCount(); + + if (ntick < ltick) { + accum += (0xFFFFFFFF - ltick + ntick) / 1000.0; + } + else { + accum += (ntick - ltick) / 1000.0; + } + + ltick = ntick; + return accum; + } } long int PIL_check_seconds_timer_i(void) { - return (long int)PIL_check_seconds_timer(); + return (long int)PIL_check_seconds_timer(); } void PIL_sleep_ms(int ms) { - Sleep(ms); + Sleep(ms); } #else -#include <unistd.h> -#include <sys/time.h> +# include <unistd.h> +# include <sys/time.h> double PIL_check_seconds_timer(void) { - struct timeval tv; - struct timezone tz; + struct timeval tv; + struct timezone tz; - gettimeofday(&tv, &tz); + gettimeofday(&tv, &tz); - return ((double) tv.tv_sec + tv.tv_usec / 1000000.0); + return ((double)tv.tv_sec + tv.tv_usec / 1000000.0); } long int PIL_check_seconds_timer_i(void) { - struct timeval tv; - struct timezone tz; + struct timeval tv; + struct timezone tz; - gettimeofday(&tv, &tz); + gettimeofday(&tv, &tz); - return tv.tv_sec; + return tv.tv_sec; } void PIL_sleep_ms(int ms) { - if (ms >= 1000) { - sleep(ms / 1000); - ms = (ms % 1000); - } + if (ms >= 1000) { + sleep(ms / 1000); + ms = (ms % 1000); + } - usleep(ms * 1000); + usleep(ms * 1000); } #endif diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c index 53d0347d088..9b6ed00c704 100644 --- a/source/blender/blenlib/intern/timecode.c +++ b/source/blender/blenlib/intern/timecode.c @@ -25,14 +25,13 @@ #include <stdio.h> - #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_math.h" -#include "BLI_timecode.h" /* own include */ +#include "BLI_timecode.h" /* own include */ -#include "DNA_userdef_types.h" /* for eTimecodeStyles only */ +#include "DNA_userdef_types.h" /* for eTimecodeStyles only */ #include "BLI_strict_flags.h" @@ -49,149 +48,151 @@ * \return length of \a str */ -size_t BLI_timecode_string_from_time( - char *str, const size_t maxncpy, const int brevity_level, const float time_seconds, - const double fps, const short timecode_style) +size_t BLI_timecode_string_from_time(char *str, + const size_t maxncpy, + const int brevity_level, + const float time_seconds, + const double fps, + const short timecode_style) { - int hours = 0, minutes = 0, seconds = 0, frames = 0; - float time = time_seconds; - char neg[2] = {'\0'}; - size_t rlen; - - /* get cframes */ - if (time < 0) { - /* correction for negative cfraues */ - neg[0] = '-'; - time = -time; - } - - if (time >= 3600.0f) { - /* hours */ - /* XXX should we only display a single digit for hours since clips are - * VERY UNLIKELY to be more than 1-2 hours max? However, that would - * go against conventions... - */ - hours = (int)time / 3600; - time = fmodf(time, 3600); - } - - if (time >= 60.0f) { - /* minutes */ - minutes = (int)time / 60; - time = fmodf(time, 60); - } - - if (brevity_level <= 0) { - /* seconds + frames - * Frames are derived from 'fraction' of second. We need to perform some additional rounding - * to cope with 'half' frames, etc., which should be fine in most cases - */ - seconds = (int)time; - frames = round_fl_to_int((float)(((double)time - (double)seconds) * fps)); - } - else { - /* seconds (with pixel offset rounding) */ - seconds = round_fl_to_int(time); - } - - switch (timecode_style) { - case USER_TIMECODE_MINIMAL: - { - /* - In general, minutes and seconds should be shown, as most clips will be - * within this length. Hours will only be included if relevant. - * - Only show frames when zoomed in enough for them to be relevant - * (using separator of '+' for frames). - * When showing frames, use slightly different display to avoid confusion with mm:ss format - */ - if (brevity_level <= 0) { - /* include "frames" in display */ - if (hours) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); - } - else if (minutes) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames); - } - } - else { - /* don't include 'frames' in display */ - if (hours) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); - } - } - break; - } - case USER_TIMECODE_SMPTE_MSF: - { - /* reduced SMPTE format that always shows minutes, seconds, frames. - * Hours only shown as needed. */ - if (hours) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); - } - break; - } - case USER_TIMECODE_MILLISECONDS: - { - /* reduced SMPTE. Instead of frames, milliseconds are shown */ - - /* precision of decimal part */ - const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1; - - /* to get 2 digit whole-number part for seconds display - * (i.e. 3 is for 2 digits + radix, on top of full length) */ - const int s_pad = ms_dp + 3; - - if (hours) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); - } - break; - } - case USER_TIMECODE_SUBRIP: - { - /* SubRip, like SMPTE milliseconds but seconds and milliseconds - * are separated by a comma, not a dot... */ - - /* precision of decimal part */ - const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1; - const int ms = round_fl_to_int((time - (float)seconds) * 1000.0f); - - rlen = BLI_snprintf_rlen( - str, maxncpy, "%s%02d:%02d:%02d,%0*d", neg, hours, minutes, seconds, ms_dp, ms); - break; - } - case USER_TIMECODE_SECONDS_ONLY: - { - /* only show the original seconds display */ - /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */ - if (brevity_level <= 0) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds)); - } - break; - } - case USER_TIMECODE_SMPTE_FULL: - default: - { - /* full SMPTE format */ - rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); - break; - } - } - - return rlen; + int hours = 0, minutes = 0, seconds = 0, frames = 0; + float time = time_seconds; + char neg[2] = {'\0'}; + size_t rlen; + + /* get cframes */ + if (time < 0) { + /* correction for negative cfraues */ + neg[0] = '-'; + time = -time; + } + + if (time >= 3600.0f) { + /* hours */ + /* XXX should we only display a single digit for hours since clips are + * VERY UNLIKELY to be more than 1-2 hours max? However, that would + * go against conventions... + */ + hours = (int)time / 3600; + time = fmodf(time, 3600); + } + + if (time >= 60.0f) { + /* minutes */ + minutes = (int)time / 60; + time = fmodf(time, 60); + } + + if (brevity_level <= 0) { + /* seconds + frames + * Frames are derived from 'fraction' of second. We need to perform some additional rounding + * to cope with 'half' frames, etc., which should be fine in most cases + */ + seconds = (int)time; + frames = round_fl_to_int((float)(((double)time - (double)seconds) * fps)); + } + else { + /* seconds (with pixel offset rounding) */ + seconds = round_fl_to_int(time); + } + + switch (timecode_style) { + case USER_TIMECODE_MINIMAL: { + /* - In general, minutes and seconds should be shown, as most clips will be + * within this length. Hours will only be included if relevant. + * - Only show frames when zoomed in enough for them to be relevant + * (using separator of '+' for frames). + * When showing frames, use slightly different display to avoid confusion with mm:ss format + */ + if (brevity_level <= 0) { + /* include "frames" in display */ + if (hours) { + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); + } + else if (minutes) { + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames); + } + } + else { + /* don't include 'frames' in display */ + if (hours) { + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); + } + } + break; + } + case USER_TIMECODE_SMPTE_MSF: { + /* reduced SMPTE format that always shows minutes, seconds, frames. + * Hours only shown as needed. */ + if (hours) { + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); + } + break; + } + case USER_TIMECODE_MILLISECONDS: { + /* reduced SMPTE. Instead of frames, milliseconds are shown */ + + /* precision of decimal part */ + const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1; + + /* to get 2 digit whole-number part for seconds display + * (i.e. 3 is for 2 digits + radix, on top of full length) */ + const int s_pad = ms_dp + 3; + + if (hours) { + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); + } + break; + } + case USER_TIMECODE_SUBRIP: { + /* SubRip, like SMPTE milliseconds but seconds and milliseconds + * are separated by a comma, not a dot... */ + + /* precision of decimal part */ + const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1; + const int ms = round_fl_to_int((time - (float)seconds) * 1000.0f); + + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d:%02d,%0*d", neg, hours, minutes, seconds, ms_dp, ms); + break; + } + case USER_TIMECODE_SECONDS_ONLY: { + /* only show the original seconds display */ + /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */ + if (brevity_level <= 0) { + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds)); + } + break; + } + case USER_TIMECODE_SMPTE_FULL: + default: { + /* full SMPTE format */ + rlen = BLI_snprintf_rlen( + str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + break; + } + } + + return rlen; } /** @@ -202,25 +203,26 @@ size_t BLI_timecode_string_from_time( * \param time_seconds: time total time in seconds * \return length of \a str */ -size_t BLI_timecode_string_from_time_simple( - char *str, const size_t maxncpy, const double time_seconds) +size_t BLI_timecode_string_from_time_simple(char *str, + const size_t maxncpy, + const double time_seconds) { - size_t rlen; - - /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */ - const int hr = ( (int) time_seconds) / (60 * 60); - const int min = (((int) time_seconds) / 60 ) % 60; - const int sec = ( (int) time_seconds) % 60; - const int hun = ( (int) (time_seconds * 100.0)) % 100; - - if (hr) { - rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun); - } - else { - rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d.%.2d", min, sec, hun); - } - - return rlen; + size_t rlen; + + /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */ + const int hr = ((int)time_seconds) / (60 * 60); + const int min = (((int)time_seconds) / 60) % 60; + const int sec = ((int)time_seconds) % 60; + const int hun = ((int)(time_seconds * 100.0)) % 100; + + if (hr) { + rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun); + } + else { + rlen = BLI_snprintf(str, maxncpy, "%.2d:%.2d.%.2d", min, sec, hun); + } + + return rlen; } /** @@ -235,18 +237,20 @@ size_t BLI_timecode_string_from_time_simple( * * \note in some cases this is used to print non-seconds values. */ -size_t BLI_timecode_string_from_time_seconds( - char *str, const size_t maxncpy, const int brevity_level, const float time_seconds) +size_t BLI_timecode_string_from_time_seconds(char *str, + const size_t maxncpy, + const int brevity_level, + const float time_seconds) { - size_t rlen; + size_t rlen; - /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */ - if (brevity_level <= 0) { - rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds); - } - else { - rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds)); - } + /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */ + if (brevity_level <= 0) { + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds); + } + else { + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds)); + } - return rlen; + return rlen; } diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c index c08f0d5e32b..a34c551767a 100644 --- a/source/blender/blenlib/intern/uvproject.c +++ b/source/blender/blenlib/intern/uvproject.c @@ -29,168 +29,173 @@ #include "BLI_uvproject.h" typedef struct ProjCameraInfo { - float camangle; - float camsize; - float xasp, yasp; - float shiftx, shifty; - float rotmat[4][4]; - float caminv[4][4]; - bool do_persp, do_pano, do_rotmat; + float camangle; + float camsize; + float xasp, yasp; + float shiftx, shifty; + float rotmat[4][4]; + float caminv[4][4]; + bool do_persp, do_pano, do_rotmat; } ProjCameraInfo; void BLI_uvproject_from_camera(float target[2], float source[3], ProjCameraInfo *uci) { - float pv4[4]; - - copy_v3_v3(pv4, source); - pv4[3] = 1.0; - - /* rotmat is the object matrix in this case */ - if (uci->do_rotmat) { - mul_m4_v4(uci->rotmat, pv4); - } - - /* caminv is the inverse camera matrix */ - mul_m4_v4(uci->caminv, pv4); - - if (uci->do_pano) { - float angle = atan2f(pv4[0], -pv4[2]) / ((float)M_PI * 2.0f); /* angle around the camera */ - if (uci->do_persp == false) { - target[0] = angle; /* no correct method here, just map to 0-1 */ - target[1] = pv4[1] / uci->camsize; - } - else { - float vec2d[2]; /* 2D position from the camera */ - vec2d[0] = pv4[0]; - vec2d[1] = pv4[2]; - target[0] = angle * ((float)M_PI / uci->camangle); - target[1] = pv4[1] / (len_v2(vec2d) * (uci->camsize * 2.0f)); - } - } - else { - if (pv4[2] == 0.0f) { - pv4[2] = 0.00001f; /* don't allow div by 0 */ - } - - if (uci->do_persp == false) { - target[0] = (pv4[0] / uci->camsize); - target[1] = (pv4[1] / uci->camsize); - } - else { - target[0] = (-pv4[0] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f; - target[1] = (-pv4[1] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f; - } - } - - target[0] *= uci->xasp; - target[1] *= uci->yasp; - - /* adds camera shift + 0.5 */ - target[0] += uci->shiftx; - target[1] += uci->shifty; + float pv4[4]; + + copy_v3_v3(pv4, source); + pv4[3] = 1.0; + + /* rotmat is the object matrix in this case */ + if (uci->do_rotmat) { + mul_m4_v4(uci->rotmat, pv4); + } + + /* caminv is the inverse camera matrix */ + mul_m4_v4(uci->caminv, pv4); + + if (uci->do_pano) { + float angle = atan2f(pv4[0], -pv4[2]) / ((float)M_PI * 2.0f); /* angle around the camera */ + if (uci->do_persp == false) { + target[0] = angle; /* no correct method here, just map to 0-1 */ + target[1] = pv4[1] / uci->camsize; + } + else { + float vec2d[2]; /* 2D position from the camera */ + vec2d[0] = pv4[0]; + vec2d[1] = pv4[2]; + target[0] = angle * ((float)M_PI / uci->camangle); + target[1] = pv4[1] / (len_v2(vec2d) * (uci->camsize * 2.0f)); + } + } + else { + if (pv4[2] == 0.0f) { + pv4[2] = 0.00001f; /* don't allow div by 0 */ + } + + if (uci->do_persp == false) { + target[0] = (pv4[0] / uci->camsize); + target[1] = (pv4[1] / uci->camsize); + } + else { + target[0] = (-pv4[0] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f; + target[1] = (-pv4[1] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f; + } + } + + target[0] *= uci->xasp; + target[1] *= uci->yasp; + + /* adds camera shift + 0.5 */ + target[0] += uci->shiftx; + target[1] += uci->shifty; } /* could rv3d->persmat */ -void BLI_uvproject_from_view(float target[2], float source[3], float persmat[4][4], float rotmat[4][4], float winx, float winy) +void BLI_uvproject_from_view(float target[2], + float source[3], + float persmat[4][4], + float rotmat[4][4], + float winx, + float winy) { - float pv4[4], x = 0.0, y = 0.0; - - copy_v3_v3(pv4, source); - pv4[3] = 1.0; - - /* rotmat is the object matrix in this case */ - mul_m4_v4(rotmat, pv4); - - /* almost ED_view3d_project_short */ - mul_m4_v4(persmat, pv4); - if (fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */ - target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0] / pv4[3]; - target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1] / pv4[3]; - } - else { - /* scaling is lost but give a valid result */ - target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0]; - target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1]; - } - - /* v3d->persmat seems to do this funky scaling */ - if (winx > winy) { - y = (winx - winy) / 2.0f; - winy = winx; - } - else { - x = (winy - winx) / 2.0f; - winx = winy; - } - - target[0] = (x + target[0]) / winx; - target[1] = (y + target[1]) / winy; + float pv4[4], x = 0.0, y = 0.0; + + copy_v3_v3(pv4, source); + pv4[3] = 1.0; + + /* rotmat is the object matrix in this case */ + mul_m4_v4(rotmat, pv4); + + /* almost ED_view3d_project_short */ + mul_m4_v4(persmat, pv4); + if (fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */ + target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0] / pv4[3]; + target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1] / pv4[3]; + } + else { + /* scaling is lost but give a valid result */ + target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0]; + target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1]; + } + + /* v3d->persmat seems to do this funky scaling */ + if (winx > winy) { + y = (winx - winy) / 2.0f; + winy = winx; + } + else { + x = (winy - winx) / 2.0f; + winx = winy; + } + + target[0] = (x + target[0]) / winx; + target[1] = (y + target[1]) / winy; } /* 'rotmat' can be obedit->obmat when uv project is used. * 'winx' and 'winy' can be from scene->r.xsch/ysch */ -ProjCameraInfo *BLI_uvproject_camera_info(Object *ob, float(*rotmat)[4], float winx, float winy) +ProjCameraInfo *BLI_uvproject_camera_info(Object *ob, float (*rotmat)[4], float winx, float winy) { - ProjCameraInfo uci; - Camera *camera = ob->data; - - uci.do_pano = (camera->type == CAM_PANO); - uci.do_persp = (camera->type == CAM_PERSP); - - uci.camangle = focallength_to_fov(camera->lens, camera->sensor_x) / 2.0f; - uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; - - /* account for scaled cameras */ - copy_m4_m4(uci.caminv, ob->obmat); - normalize_m4(uci.caminv); - - if (invert_m4(uci.caminv)) { - ProjCameraInfo *uci_pt; - - /* normal projection */ - if (rotmat) { - copy_m4_m4(uci.rotmat, rotmat); - uci.do_rotmat = true; - } - else { - uci.do_rotmat = false; - } - - /* also make aspect ratio adjustment factors */ - if (winx > winy) { - uci.xasp = 1.0f; - uci.yasp = winx / winy; - } - else { - uci.xasp = winy / winx; - uci.yasp = 1.0f; - } - - /* include 0.5f here to move the UVs into the center */ - uci.shiftx = 0.5f - (camera->shiftx * uci.xasp); - uci.shifty = 0.5f - (camera->shifty * uci.yasp); - - uci_pt = MEM_mallocN(sizeof(ProjCameraInfo), "ProjCameraInfo"); - *uci_pt = uci; - return uci_pt; - } - - return NULL; + ProjCameraInfo uci; + Camera *camera = ob->data; + + uci.do_pano = (camera->type == CAM_PANO); + uci.do_persp = (camera->type == CAM_PERSP); + + uci.camangle = focallength_to_fov(camera->lens, camera->sensor_x) / 2.0f; + uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; + + /* account for scaled cameras */ + copy_m4_m4(uci.caminv, ob->obmat); + normalize_m4(uci.caminv); + + if (invert_m4(uci.caminv)) { + ProjCameraInfo *uci_pt; + + /* normal projection */ + if (rotmat) { + copy_m4_m4(uci.rotmat, rotmat); + uci.do_rotmat = true; + } + else { + uci.do_rotmat = false; + } + + /* also make aspect ratio adjustment factors */ + if (winx > winy) { + uci.xasp = 1.0f; + uci.yasp = winx / winy; + } + else { + uci.xasp = winy / winx; + uci.yasp = 1.0f; + } + + /* include 0.5f here to move the UVs into the center */ + uci.shiftx = 0.5f - (camera->shiftx * uci.xasp); + uci.shifty = 0.5f - (camera->shifty * uci.yasp); + + uci_pt = MEM_mallocN(sizeof(ProjCameraInfo), "ProjCameraInfo"); + *uci_pt = uci; + return uci_pt; + } + + return NULL; } void BLI_uvproject_from_view_ortho(float target[2], float source[3], float rotmat[4][4]) { - float pv[3]; + float pv[3]; - mul_v3_m4v3(pv, rotmat, source); + mul_v3_m4v3(pv, rotmat, source); - /* ortho projection */ - target[0] = -pv[0]; - target[1] = pv[2]; + /* ortho projection */ + target[0] = -pv[0]; + target[1] = pv[2]; } void BLI_uvproject_camera_info_scale(ProjCameraInfo *uci, float scale_x, float scale_y) { - uci->xasp *= scale_x; - uci->yasp *= scale_y; + uci->xasp *= scale_x; + uci->yasp *= scale_y; } diff --git a/source/blender/blenlib/intern/voronoi_2d.c b/source/blender/blenlib/intern/voronoi_2d.c index 248e07eae35..29beb93159a 100644 --- a/source/blender/blenlib/intern/voronoi_2d.c +++ b/source/blender/blenlib/intern/voronoi_2d.c @@ -34,823 +34,829 @@ #define VORONOI_EPS 1e-2f enum { - voronoiEventType_Site = 0, - voronoiEventType_Circle = 1, + voronoiEventType_Site = 0, + voronoiEventType_Circle = 1, }; typedef struct VoronoiEvent { - struct VoronoiEvent *next, *prev; + struct VoronoiEvent *next, *prev; - int type; /* type of event (site or circle) */ - float site[2]; /* site for which event was generated */ + int type; /* type of event (site or circle) */ + float site[2]; /* site for which event was generated */ - struct VoronoiParabola *parabola; /* parabola for which event was generated */ + struct VoronoiParabola *parabola; /* parabola for which event was generated */ } VoronoiEvent; typedef struct VoronoiParabola { - struct VoronoiParabola *left, *right, *parent; - VoronoiEvent *event; - VoronoiEdge *edge; - float site[2]; - bool is_leaf; + struct VoronoiParabola *left, *right, *parent; + VoronoiEvent *event; + VoronoiEdge *edge; + float site[2]; + bool is_leaf; } VoronoiParabola; typedef struct VoronoiProcess { - ListBase queue, edges; - VoronoiParabola *root; - int width, height; - float current_y; + ListBase queue, edges; + VoronoiParabola *root; + int width, height; + float current_y; } VoronoiProcess; /* event */ static void voronoi_insertEvent(VoronoiProcess *process, VoronoiEvent *event) { - VoronoiEvent *current_event = process->queue.first; + VoronoiEvent *current_event = process->queue.first; - while (current_event) { - if (current_event->site[1] < event->site[1]) { - break; - } - if (current_event->site[1] == event->site[1]) { - event->site[1] -= VORONOI_EPS; - } + while (current_event) { + if (current_event->site[1] < event->site[1]) { + break; + } + if (current_event->site[1] == event->site[1]) { + event->site[1] -= VORONOI_EPS; + } - current_event = current_event->next; - } + current_event = current_event->next; + } - BLI_insertlinkbefore(&process->queue, current_event, event); + BLI_insertlinkbefore(&process->queue, current_event, event); } /* edge */ static VoronoiEdge *voronoiEdge_new(float start[2], float left[2], float right[2]) { - VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "voronoi edge"); + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "voronoi edge"); - copy_v2_v2(edge->start, start); - copy_v2_v2(edge->left, left); - copy_v2_v2(edge->right, right); + copy_v2_v2(edge->start, start); + copy_v2_v2(edge->left, left); + copy_v2_v2(edge->right, right); - edge->neighbor = NULL; - edge->end[0] = 0; - edge->end[1] = 0; + edge->neighbor = NULL; + edge->end[0] = 0; + edge->end[1] = 0; - edge->f = (right[0] - left[0]) / (left[1] - right[1]); - edge->g = start[1] - edge->f * start[0]; + edge->f = (right[0] - left[0]) / (left[1] - right[1]); + edge->g = start[1] - edge->f * start[0]; - edge->direction[0] = right[1] - left[1]; - edge->direction[1] = -(right[0] - left[0]); + edge->direction[0] = right[1] - left[1]; + edge->direction[1] = -(right[0] - left[0]); - return edge; + return edge; } /* parabola */ static VoronoiParabola *voronoiParabola_new(void) { - VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola"); + VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola"); - parabola->is_leaf = false; - parabola->event = NULL; - parabola->edge = NULL; - parabola->parent = NULL; + parabola->is_leaf = false; + parabola->event = NULL; + parabola->edge = NULL; + parabola->parent = NULL; - return parabola; + return parabola; } static VoronoiParabola *voronoiParabola_newSite(float site[2]) { - VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola site"); + VoronoiParabola *parabola = MEM_callocN(sizeof(VoronoiParabola), "voronoi parabola site"); - copy_v2_v2(parabola->site, site); - parabola->is_leaf = true; - parabola->event = NULL; - parabola->edge = NULL; - parabola->parent = NULL; + copy_v2_v2(parabola->site, site); + parabola->is_leaf = true; + parabola->event = NULL; + parabola->edge = NULL; + parabola->parent = NULL; - return parabola; + return parabola; } /* returns the closest leave which is on the left of current node */ static VoronoiParabola *voronoiParabola_getLeftChild(VoronoiParabola *parabola) { - VoronoiParabola *current_parabola; + VoronoiParabola *current_parabola; - if (!parabola) { - return NULL; - } + if (!parabola) { + return NULL; + } - current_parabola = parabola->left; - while (!current_parabola->is_leaf) { - current_parabola = current_parabola->right; - } + current_parabola = parabola->left; + while (!current_parabola->is_leaf) { + current_parabola = current_parabola->right; + } - return current_parabola; + return current_parabola; } /* returns the closest leave which is on the right of current node */ static VoronoiParabola *voronoiParabola_getRightChild(VoronoiParabola *parabola) { - VoronoiParabola *current_parabola; + VoronoiParabola *current_parabola; - if (!parabola) { - return NULL; - } + if (!parabola) { + return NULL; + } - current_parabola = parabola->right; - while (!current_parabola->is_leaf) { - current_parabola = current_parabola->left; - } + current_parabola = parabola->right; + while (!current_parabola->is_leaf) { + current_parabola = current_parabola->left; + } - return current_parabola; + return current_parabola; } /* returns the closest parent which is on the left */ static VoronoiParabola *voronoiParabola_getLeftParent(VoronoiParabola *parabola) { - VoronoiParabola *current_par = parabola->parent; - VoronoiParabola *last_parabola = parabola; + VoronoiParabola *current_par = parabola->parent; + VoronoiParabola *last_parabola = parabola; - while (current_par->left == last_parabola) { - if (!current_par->parent) { - return NULL; - } + while (current_par->left == last_parabola) { + if (!current_par->parent) { + return NULL; + } - last_parabola = current_par; - current_par = current_par->parent; - } + last_parabola = current_par; + current_par = current_par->parent; + } - return current_par; + return current_par; } /* returns the closest parent which is on the right */ static VoronoiParabola *voronoiParabola_getRightParent(VoronoiParabola *parabola) { - VoronoiParabola *current_parabola = parabola->parent; - VoronoiParabola *last_parabola = parabola; + VoronoiParabola *current_parabola = parabola->parent; + VoronoiParabola *last_parabola = parabola; - while (current_parabola->right == last_parabola) { - if (!current_parabola->parent) { - return NULL; - } + while (current_parabola->right == last_parabola) { + if (!current_parabola->parent) { + return NULL; + } - last_parabola = current_parabola; - current_parabola = current_parabola->parent; - } + last_parabola = current_parabola; + current_parabola = current_parabola->parent; + } - return current_parabola; + return current_parabola; } static void voronoiParabola_setLeft(VoronoiParabola *parabola, VoronoiParabola *left) { - parabola->left = left; - left->parent = parabola; + parabola->left = left; + left->parent = parabola; } static void voronoiParabola_setRight(VoronoiParabola *parabola, VoronoiParabola *right) { - parabola->right = right; - right->parent = parabola; + parabola->right = right; + right->parent = parabola; } static float voronoi_getY(VoronoiProcess *process, float p[2], float x) { - float ly = process->current_y; + float ly = process->current_y; - float dp = 2 * (p[1] - ly); - float a1 = 1 / dp; - float b1 = -2 * p[0] / dp; - float c1 = ly + dp / 4 + p[0] * p[0] / dp; + float dp = 2 * (p[1] - ly); + float a1 = 1 / dp; + float b1 = -2 * p[0] / dp; + float c1 = ly + dp / 4 + p[0] * p[0] / dp; - return a1 * x * x + b1 * x + c1; + return a1 * x * x + b1 * x + c1; } static float voronoi_getXOfEdge(VoronoiProcess *process, VoronoiParabola *par, float y) { - VoronoiParabola *left = voronoiParabola_getLeftChild(par); - VoronoiParabola *right = voronoiParabola_getRightChild(par); - float p[2], r[2]; - float dp, a1, b1, c1, a2, b2, c2, a, b, c, disc, ry, x1, x2; - float ly = process->current_y; - - copy_v2_v2(p, left->site); - copy_v2_v2(r, right->site); - - dp = 2.0f * (p[1] - y); - a1 = 1.0f / dp; - b1 = -2.0f * p[0] / dp; - c1 = y + dp / 4 + p[0] * p[0] / dp; - - dp = 2.0f * (r[1] - y); - a2 = 1.0f / dp; - b2 = -2.0f * r[0] / dp; - c2 = ly + dp / 4 + r[0] * r[0] / dp; - - a = a1 - a2; - b = b1 - b2; - c = c1 - c2; - - disc = b * b - 4 * a * c; - x1 = (-b + sqrtf(disc)) / (2 * a); - x2 = (-b - sqrtf(disc)) / (2 * a); - - if (p[1] < r[1]) { - ry = max_ff(x1, x2); - } - else { - ry = min_ff(x1, x2); - } - - return ry; + VoronoiParabola *left = voronoiParabola_getLeftChild(par); + VoronoiParabola *right = voronoiParabola_getRightChild(par); + float p[2], r[2]; + float dp, a1, b1, c1, a2, b2, c2, a, b, c, disc, ry, x1, x2; + float ly = process->current_y; + + copy_v2_v2(p, left->site); + copy_v2_v2(r, right->site); + + dp = 2.0f * (p[1] - y); + a1 = 1.0f / dp; + b1 = -2.0f * p[0] / dp; + c1 = y + dp / 4 + p[0] * p[0] / dp; + + dp = 2.0f * (r[1] - y); + a2 = 1.0f / dp; + b2 = -2.0f * r[0] / dp; + c2 = ly + dp / 4 + r[0] * r[0] / dp; + + a = a1 - a2; + b = b1 - b2; + c = c1 - c2; + + disc = b * b - 4 * a * c; + x1 = (-b + sqrtf(disc)) / (2 * a); + x2 = (-b - sqrtf(disc)) / (2 * a); + + if (p[1] < r[1]) { + ry = max_ff(x1, x2); + } + else { + ry = min_ff(x1, x2); + } + + return ry; } static VoronoiParabola *voronoi_getParabolaByX(VoronoiProcess *process, float xx) { - VoronoiParabola *par = process->root; - float x = 0.0f; - float ly = process->current_y; - - while (!par->is_leaf) { - x = voronoi_getXOfEdge(process, par, ly); - - if (x > xx) { - par = par->left; - } - else { - par = par->right; - } - } - - return par; + VoronoiParabola *par = process->root; + float x = 0.0f; + float ly = process->current_y; + + while (!par->is_leaf) { + x = voronoi_getXOfEdge(process, par, ly); + + if (x > xx) { + par = par->left; + } + else { + par = par->right; + } + } + + return par; } static int voronoi_getEdgeIntersection(VoronoiEdge *a, VoronoiEdge *b, float p[2]) { - float x = (b->g - a->g) / (a->f - b->f); - float y = a->f * x + a->g; + float x = (b->g - a->g) / (a->f - b->f); + float y = a->f * x + a->g; - if ((x - a->start[0]) / a->direction[0] < 0) { - return 0; - } + if ((x - a->start[0]) / a->direction[0] < 0) { + return 0; + } - if ((y - a->start[1]) / a->direction[1] < 0) { - return 0; - } + if ((y - a->start[1]) / a->direction[1] < 0) { + return 0; + } - if ((x - b->start[0]) / b->direction[0] < 0) { - return 0; - } + if ((x - b->start[0]) / b->direction[0] < 0) { + return 0; + } - if ((y - b->start[1]) / b->direction[1] < 0) { - return 0; - } + if ((y - b->start[1]) / b->direction[1] < 0) { + return 0; + } - p[0] = x; - p[1] = y; + p[0] = x; + p[1] = y; - return 1; + return 1; } static void voronoi_checkCircle(VoronoiProcess *process, VoronoiParabola *b) { - VoronoiParabola *lp = voronoiParabola_getLeftParent(b); - VoronoiParabola *rp = voronoiParabola_getRightParent(b); + VoronoiParabola *lp = voronoiParabola_getLeftParent(b); + VoronoiParabola *rp = voronoiParabola_getRightParent(b); - VoronoiParabola *a = voronoiParabola_getLeftChild(lp); - VoronoiParabola *c = voronoiParabola_getRightChild(rp); + VoronoiParabola *a = voronoiParabola_getLeftChild(lp); + VoronoiParabola *c = voronoiParabola_getRightChild(rp); - VoronoiEvent *event; + VoronoiEvent *event; - float ly = process->current_y; - float s[2], dx, dy, d; + float ly = process->current_y; + float s[2], dx, dy, d; - if (!a || !c || len_squared_v2v2(a->site, c->site) < VORONOI_EPS) { - return; - } + if (!a || !c || len_squared_v2v2(a->site, c->site) < VORONOI_EPS) { + return; + } - if (!voronoi_getEdgeIntersection(lp->edge, rp->edge, s)) { - return; - } + if (!voronoi_getEdgeIntersection(lp->edge, rp->edge, s)) { + return; + } - dx = a->site[0] - s[0]; - dy = a->site[1] - s[1]; + dx = a->site[0] - s[0]; + dy = a->site[1] - s[1]; - d = sqrtf((dx * dx) + (dy * dy)); + d = sqrtf((dx * dx) + (dy * dy)); - if (s[1] - d >= ly) { - return; - } + if (s[1] - d >= ly) { + return; + } - event = MEM_callocN(sizeof(VoronoiEvent), "voronoi circle event"); + event = MEM_callocN(sizeof(VoronoiEvent), "voronoi circle event"); - event->type = voronoiEventType_Circle; + event->type = voronoiEventType_Circle; - event->site[0] = s[0]; - event->site[1] = s[1] - d; + event->site[0] = s[0]; + event->site[1] = s[1] - d; - b->event = event; - event->parabola = b; + b->event = event; + event->parabola = b; - voronoi_insertEvent(process, event); + voronoi_insertEvent(process, event); } static void voronoi_addParabola(VoronoiProcess *process, float site[2]) { - VoronoiParabola *root = process->root; - VoronoiParabola *par, *p0, *p1, *p2; - VoronoiEdge *el, *er; - float start[2]; + VoronoiParabola *root = process->root; + VoronoiParabola *par, *p0, *p1, *p2; + VoronoiEdge *el, *er; + float start[2]; - if (!process->root) { - process->root = voronoiParabola_newSite(site); + if (!process->root) { + process->root = voronoiParabola_newSite(site); - return; - } + return; + } - if (root->is_leaf && root->site[1] - site[1] < 0) { - float *fp = root->site; - float s[2]; + if (root->is_leaf && root->site[1] - site[1] < 0) { + float *fp = root->site; + float s[2]; - root->is_leaf = false; - voronoiParabola_setLeft(root, voronoiParabola_newSite(fp)); - voronoiParabola_setRight(root, voronoiParabola_newSite(site)); + root->is_leaf = false; + voronoiParabola_setLeft(root, voronoiParabola_newSite(fp)); + voronoiParabola_setRight(root, voronoiParabola_newSite(site)); - s[0] = (site[0] + fp[0]) / 2.0f; - s[1] = process->height; + s[0] = (site[0] + fp[0]) / 2.0f; + s[1] = process->height; - if (site[0] > fp[0]) { - root->edge = voronoiEdge_new(s, fp, site); - } - else { - root->edge = voronoiEdge_new(s, site, fp); - } + if (site[0] > fp[0]) { + root->edge = voronoiEdge_new(s, fp, site); + } + else { + root->edge = voronoiEdge_new(s, site, fp); + } - BLI_addtail(&process->edges, root->edge); + BLI_addtail(&process->edges, root->edge); - return; - } + return; + } - par = voronoi_getParabolaByX(process, site[0]); + par = voronoi_getParabolaByX(process, site[0]); - if (par->event) { - BLI_freelinkN(&process->queue, par->event); + if (par->event) { + BLI_freelinkN(&process->queue, par->event); - par->event = NULL; - } + par->event = NULL; + } - start[0] = site[0]; - start[1] = voronoi_getY(process, par->site, site[0]); + start[0] = site[0]; + start[1] = voronoi_getY(process, par->site, site[0]); - el = voronoiEdge_new(start, par->site, site); - er = voronoiEdge_new(start, site, par->site); + el = voronoiEdge_new(start, par->site, site); + er = voronoiEdge_new(start, site, par->site); - el->neighbor = er; - BLI_addtail(&process->edges, el); + el->neighbor = er; + BLI_addtail(&process->edges, el); - par->edge = er; - par->is_leaf = false; + par->edge = er; + par->is_leaf = false; - p0 = voronoiParabola_newSite(par->site); - p1 = voronoiParabola_newSite(site); - p2 = voronoiParabola_newSite(par->site); + p0 = voronoiParabola_newSite(par->site); + p1 = voronoiParabola_newSite(site); + p2 = voronoiParabola_newSite(par->site); - voronoiParabola_setRight(par, p2); - voronoiParabola_setLeft(par, voronoiParabola_new()); - par->left->edge = el; + voronoiParabola_setRight(par, p2); + voronoiParabola_setLeft(par, voronoiParabola_new()); + par->left->edge = el; - voronoiParabola_setLeft(par->left, p0); - voronoiParabola_setRight(par->left, p1); + voronoiParabola_setLeft(par->left, p0); + voronoiParabola_setRight(par->left, p1); - voronoi_checkCircle(process, p0); - voronoi_checkCircle(process, p2); + voronoi_checkCircle(process, p0); + voronoi_checkCircle(process, p2); } static void voronoi_removeParabola(VoronoiProcess *process, VoronoiEvent *event) { - VoronoiParabola *p1 = event->parabola; - - VoronoiParabola *xl = voronoiParabola_getLeftParent(p1); - VoronoiParabola *xr = voronoiParabola_getRightParent(p1); - - VoronoiParabola *p0 = voronoiParabola_getLeftChild(xl); - VoronoiParabola *p2 = voronoiParabola_getRightChild(xr); - - VoronoiParabola *higher = NULL, *par, *gparent; - - float p[2]; - - if (p0->event) { - BLI_freelinkN(&process->queue, p0->event); - p0->event = NULL; - } - - if (p2->event) { - BLI_freelinkN(&process->queue, p2->event); - p2->event = NULL; - } - - p[0] = event->site[0]; - p[1] = voronoi_getY(process, p1->site, event->site[0]); - - copy_v2_v2(xl->edge->end, p); - copy_v2_v2(xr->edge->end, p); - - par = p1; - while (par != process->root) { - par = par->parent; - - if (par == xl) { - higher = xl; - } - if (par == xr) { - higher = xr; - } - } - - higher->edge = voronoiEdge_new(p, p0->site, p2->site); - BLI_addtail(&process->edges, higher->edge); - - gparent = p1->parent->parent; - if (p1->parent->left == p1) { - if (gparent->left == p1->parent) { - voronoiParabola_setLeft(gparent, p1->parent->right); - } - if (gparent->right == p1->parent) { - voronoiParabola_setRight(gparent, p1->parent->right); - } - } - else { - if (gparent->left == p1->parent) { - voronoiParabola_setLeft(gparent, p1->parent->left); - } - if (gparent->right == p1->parent) { - voronoiParabola_setRight(gparent, p1->parent->left); - } - } - - MEM_freeN(p1->parent); - MEM_freeN(p1); - - voronoi_checkCircle(process, p0); - voronoi_checkCircle(process, p2); + VoronoiParabola *p1 = event->parabola; + + VoronoiParabola *xl = voronoiParabola_getLeftParent(p1); + VoronoiParabola *xr = voronoiParabola_getRightParent(p1); + + VoronoiParabola *p0 = voronoiParabola_getLeftChild(xl); + VoronoiParabola *p2 = voronoiParabola_getRightChild(xr); + + VoronoiParabola *higher = NULL, *par, *gparent; + + float p[2]; + + if (p0->event) { + BLI_freelinkN(&process->queue, p0->event); + p0->event = NULL; + } + + if (p2->event) { + BLI_freelinkN(&process->queue, p2->event); + p2->event = NULL; + } + + p[0] = event->site[0]; + p[1] = voronoi_getY(process, p1->site, event->site[0]); + + copy_v2_v2(xl->edge->end, p); + copy_v2_v2(xr->edge->end, p); + + par = p1; + while (par != process->root) { + par = par->parent; + + if (par == xl) { + higher = xl; + } + if (par == xr) { + higher = xr; + } + } + + higher->edge = voronoiEdge_new(p, p0->site, p2->site); + BLI_addtail(&process->edges, higher->edge); + + gparent = p1->parent->parent; + if (p1->parent->left == p1) { + if (gparent->left == p1->parent) { + voronoiParabola_setLeft(gparent, p1->parent->right); + } + if (gparent->right == p1->parent) { + voronoiParabola_setRight(gparent, p1->parent->right); + } + } + else { + if (gparent->left == p1->parent) { + voronoiParabola_setLeft(gparent, p1->parent->left); + } + if (gparent->right == p1->parent) { + voronoiParabola_setRight(gparent, p1->parent->left); + } + } + + MEM_freeN(p1->parent); + MEM_freeN(p1); + + voronoi_checkCircle(process, p0); + voronoi_checkCircle(process, p2); } static void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) { - float mx; + float mx; - if (parabola->is_leaf) { - MEM_freeN(parabola); - return; - } + if (parabola->is_leaf) { + MEM_freeN(parabola); + return; + } - if (parabola->edge->direction[0] > 0.0f) { - mx = max_ff(process->width, parabola->edge->start[0] + 10); - } - else { - mx = min_ff(0.0f, parabola->edge->start[0] - 10.0f); - } + if (parabola->edge->direction[0] > 0.0f) { + mx = max_ff(process->width, parabola->edge->start[0] + 10); + } + else { + mx = min_ff(0.0f, parabola->edge->start[0] - 10.0f); + } - parabola->edge->end[0] = mx; - parabola->edge->end[1] = mx * parabola->edge->f + parabola->edge->g; + parabola->edge->end[0] = mx; + parabola->edge->end[1] = mx * parabola->edge->f + parabola->edge->g; - voronoi_finishEdge(process, parabola->left); - voronoi_finishEdge(process, parabola->right); + voronoi_finishEdge(process, parabola->left); + voronoi_finishEdge(process, parabola->right); - MEM_freeN(parabola); + MEM_freeN(parabola); } static void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) { - const float corners[4][2] = {{0.0f, 0.0f}, - {width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}}; - int i; - - if (IN_RANGE_INCL(coord[0], 0, width - 1) && IN_RANGE_INCL(coord[1], 0, height - 1)) { - return; - } - - for (i = 0; i < 4; i++) { - float v1[2], v2[2]; - float p[2]; - - copy_v2_v2(v1, corners[i]); - - if (i == 3) { - copy_v2_v2(v2, corners[0]); - } - else { - copy_v2_v2(v2, corners[i + 1]); - } - - if (isect_seg_seg_v2_point(v1, v2, coord, other_coord, p) == 1) { - if (i == 0 && coord[1] > p[1]) { - continue; - } - if (i == 1 && coord[0] < p[0]) { - continue; - } - if (i == 2 && coord[1] < p[1]) { - continue; - } - if (i == 3 && coord[0] > p[0]) { - continue; - } - - copy_v2_v2(coord, p); - } - } + const float corners[4][2] = { + {0.0f, 0.0f}, {width - 1, 0.0f}, {width - 1, height - 1}, {0.0f, height - 1}}; + int i; + + if (IN_RANGE_INCL(coord[0], 0, width - 1) && IN_RANGE_INCL(coord[1], 0, height - 1)) { + return; + } + + for (i = 0; i < 4; i++) { + float v1[2], v2[2]; + float p[2]; + + copy_v2_v2(v1, corners[i]); + + if (i == 3) { + copy_v2_v2(v2, corners[0]); + } + else { + copy_v2_v2(v2, corners[i + 1]); + } + + if (isect_seg_seg_v2_point(v1, v2, coord, other_coord, p) == 1) { + if (i == 0 && coord[1] > p[1]) { + continue; + } + if (i == 1 && coord[0] < p[0]) { + continue; + } + if (i == 2 && coord[1] < p[1]) { + continue; + } + if (i == 3 && coord[0] > p[0]) { + continue; + } + + copy_v2_v2(coord, p); + } + } } static void voronoi_clampEdges(ListBase *edges, int width, int height, ListBase *clamped_edges) { - VoronoiEdge *edge; + VoronoiEdge *edge; - edge = edges->first; - while (edge) { - VoronoiEdge *new_edge = MEM_callocN(sizeof(VoronoiEdge), "clamped edge"); + edge = edges->first; + while (edge) { + VoronoiEdge *new_edge = MEM_callocN(sizeof(VoronoiEdge), "clamped edge"); - *new_edge = *edge; - BLI_addtail(clamped_edges, new_edge); + *new_edge = *edge; + BLI_addtail(clamped_edges, new_edge); - voronoi_clampEdgeVertex(width, height, new_edge->start, new_edge->end); - voronoi_clampEdgeVertex(width, height, new_edge->end, new_edge->start); + voronoi_clampEdgeVertex(width, height, new_edge->start, new_edge->end); + voronoi_clampEdgeVertex(width, height, new_edge->end, new_edge->start); - edge = edge->next; - } + edge = edge->next; + } } -static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, int dir, float next_coord[2]) +static int voronoi_getNextSideCoord( + ListBase *edges, float coord[2], int dim, int dir, float next_coord[2]) { - VoronoiEdge *edge = edges->first; - float distance = FLT_MAX; - int other_dim = dim ? 0 : 1; - - while (edge) { - bool ok = false; - float co[2], cur_distance; - - if (fabsf(edge->start[other_dim] - coord[other_dim]) < VORONOI_EPS && - len_squared_v2v2(coord, edge->start) > VORONOI_EPS) - { - copy_v2_v2(co, edge->start); - ok = true; - } - - if (fabsf(edge->end[other_dim] - coord[other_dim]) < VORONOI_EPS && - len_squared_v2v2(coord, edge->end) > VORONOI_EPS) - { - copy_v2_v2(co, edge->end); - ok = true; - } - - if (ok) { - if (dir > 0 && coord[dim] > co[dim]) { - ok = false; - } - else if (dir < 0 && coord[dim] < co[dim]) { - ok = false; - } - } - - if (ok) { - cur_distance = len_squared_v2v2(coord, co); - if (cur_distance < distance) { - copy_v2_v2(next_coord, co); - distance = cur_distance; - } - } - - edge = edge->next; - } - - return distance < FLT_MAX; + VoronoiEdge *edge = edges->first; + float distance = FLT_MAX; + int other_dim = dim ? 0 : 1; + + while (edge) { + bool ok = false; + float co[2], cur_distance; + + if (fabsf(edge->start[other_dim] - coord[other_dim]) < VORONOI_EPS && + len_squared_v2v2(coord, edge->start) > VORONOI_EPS) { + copy_v2_v2(co, edge->start); + ok = true; + } + + if (fabsf(edge->end[other_dim] - coord[other_dim]) < VORONOI_EPS && + len_squared_v2v2(coord, edge->end) > VORONOI_EPS) { + copy_v2_v2(co, edge->end); + ok = true; + } + + if (ok) { + if (dir > 0 && coord[dim] > co[dim]) { + ok = false; + } + else if (dir < 0 && coord[dim] < co[dim]) { + ok = false; + } + } + + if (ok) { + cur_distance = len_squared_v2v2(coord, co); + if (cur_distance < distance) { + copy_v2_v2(next_coord, co); + distance = cur_distance; + } + } + + edge = edge->next; + } + + return distance < FLT_MAX; } static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height) { - const float corners[4][2] = {{width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}, - {0.0f, 0.0f}}; - int i, dim = 0, dir = 1; - - float coord[2] = {0.0f, 0.0f}; - float next_coord[2] = {0.0f, 0.0f}; - - for (i = 0; i < 4; i++) { - while (voronoi_getNextSideCoord(edges, coord, dim, dir, next_coord)) { - VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); - - copy_v2_v2(edge->start, coord); - copy_v2_v2(edge->end, next_coord); - BLI_addtail(edges, edge); - - copy_v2_v2(coord, next_coord); - } - - if (len_squared_v2v2(coord, corners[i]) > VORONOI_EPS) { - VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); - - copy_v2_v2(edge->start, coord); - copy_v2_v2(edge->end, corners[i]); - BLI_addtail(edges, edge); - copy_v2_v2(coord, corners[i]); - } - - dim = dim ? 0 : 1; - if (i == 1) { - dir = -1; - } - } + const float corners[4][2] = { + {width - 1, 0.0f}, {width - 1, height - 1}, {0.0f, height - 1}, {0.0f, 0.0f}}; + int i, dim = 0, dir = 1; + + float coord[2] = {0.0f, 0.0f}; + float next_coord[2] = {0.0f, 0.0f}; + + for (i = 0; i < 4; i++) { + while (voronoi_getNextSideCoord(edges, coord, dim, dir, next_coord)) { + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); + + copy_v2_v2(edge->start, coord); + copy_v2_v2(edge->end, next_coord); + BLI_addtail(edges, edge); + + copy_v2_v2(coord, next_coord); + } + + if (len_squared_v2v2(coord, corners[i]) > VORONOI_EPS) { + VoronoiEdge *edge = MEM_callocN(sizeof(VoronoiEdge), "boundary edge"); + + copy_v2_v2(edge->start, coord); + copy_v2_v2(edge->end, corners[i]); + BLI_addtail(edges, edge); + copy_v2_v2(coord, corners[i]); + } + + dim = dim ? 0 : 1; + if (i == 1) { + dir = -1; + } + } } -void BLI_voronoi_compute(const VoronoiSite *sites, int sites_total, int width, int height, ListBase *edges) +void BLI_voronoi_compute( + const VoronoiSite *sites, int sites_total, int width, int height, ListBase *edges) { - VoronoiProcess process; - VoronoiEdge *edge; - int i; + VoronoiProcess process; + VoronoiEdge *edge; + int i; - memset(&process, 0, sizeof(VoronoiProcess)); + memset(&process, 0, sizeof(VoronoiProcess)); - process.width = width; - process.height = height; + process.width = width; + process.height = height; - for (i = 0; i < sites_total; i++) { - VoronoiEvent *event = MEM_callocN(sizeof(VoronoiEvent), "voronoi site event"); + for (i = 0; i < sites_total; i++) { + VoronoiEvent *event = MEM_callocN(sizeof(VoronoiEvent), "voronoi site event"); - event->type = voronoiEventType_Site; - copy_v2_v2(event->site, sites[i].co); + event->type = voronoiEventType_Site; + copy_v2_v2(event->site, sites[i].co); - voronoi_insertEvent(&process, event); - } + voronoi_insertEvent(&process, event); + } - while (process.queue.first) { - VoronoiEvent *event = process.queue.first; + while (process.queue.first) { + VoronoiEvent *event = process.queue.first; - process.current_y = event->site[1]; + process.current_y = event->site[1]; - if (event->type == voronoiEventType_Site) { - voronoi_addParabola(&process, event->site); - } - else { - voronoi_removeParabola(&process, event); - } + if (event->type == voronoiEventType_Site) { + voronoi_addParabola(&process, event->site); + } + else { + voronoi_removeParabola(&process, event); + } - BLI_freelinkN(&process.queue, event); - } + BLI_freelinkN(&process.queue, event); + } - voronoi_finishEdge(&process, process.root); + voronoi_finishEdge(&process, process.root); - edge = process.edges.first; - while (edge) { - if (edge->neighbor) { - copy_v2_v2(edge->start, edge->neighbor->end); - MEM_freeN(edge->neighbor); - } + edge = process.edges.first; + while (edge) { + if (edge->neighbor) { + copy_v2_v2(edge->start, edge->neighbor->end); + MEM_freeN(edge->neighbor); + } - edge = edge->next; - } + edge = edge->next; + } - BLI_movelisttolist(edges, &process.edges); + BLI_movelisttolist(edges, &process.edges); } static bool testVoronoiEdge(const float site[2], const float point[2], const VoronoiEdge *edge) { - float p[2]; + float p[2]; - if (isect_seg_seg_v2_point(site, point, edge->start, edge->end, p) == 1) { - if (len_squared_v2v2(p, edge->start) > VORONOI_EPS && - len_squared_v2v2(p, edge->end) > VORONOI_EPS) - { - return false; - } - } + if (isect_seg_seg_v2_point(site, point, edge->start, edge->end, p) == 1) { + if (len_squared_v2v2(p, edge->start) > VORONOI_EPS && + len_squared_v2v2(p, edge->end) > VORONOI_EPS) { + return false; + } + } - return true; + return true; } -static int voronoi_addTriangulationPoint(const float coord[2], const float color[3], +static int voronoi_addTriangulationPoint(const float coord[2], + const float color[3], VoronoiTriangulationPoint **triangulated_points, int *triangulated_points_total) { - VoronoiTriangulationPoint *triangulation_point; - int i; + VoronoiTriangulationPoint *triangulation_point; + int i; - for (i = 0; i < *triangulated_points_total; i++) { - if (equals_v2v2(coord, (*triangulated_points)[i].co)) { - triangulation_point = &(*triangulated_points)[i]; + for (i = 0; i < *triangulated_points_total; i++) { + if (equals_v2v2(coord, (*triangulated_points)[i].co)) { + triangulation_point = &(*triangulated_points)[i]; - add_v3_v3(triangulation_point->color, color); - triangulation_point->power++; + add_v3_v3(triangulation_point->color, color); + triangulation_point->power++; - return i; - } - } + return i; + } + } - if (*triangulated_points) { - *triangulated_points = MEM_reallocN(*triangulated_points, - sizeof(VoronoiTriangulationPoint) * (*triangulated_points_total + 1)); - } - else { - *triangulated_points = MEM_callocN(sizeof(VoronoiTriangulationPoint), "triangulation points"); - } + if (*triangulated_points) { + *triangulated_points = MEM_reallocN(*triangulated_points, + sizeof(VoronoiTriangulationPoint) * + (*triangulated_points_total + 1)); + } + else { + *triangulated_points = MEM_callocN(sizeof(VoronoiTriangulationPoint), "triangulation points"); + } - triangulation_point = &(*triangulated_points)[(*triangulated_points_total)]; - copy_v2_v2(triangulation_point->co, coord); - copy_v3_v3(triangulation_point->color, color); + triangulation_point = &(*triangulated_points)[(*triangulated_points_total)]; + copy_v2_v2(triangulation_point->co, coord); + copy_v3_v3(triangulation_point->color, color); - triangulation_point->power = 1; + triangulation_point->power = 1; - (*triangulated_points_total)++; + (*triangulated_points_total)++; - return (*triangulated_points_total) - 1; + return (*triangulated_points_total) - 1; } static void voronoi_addTriangle(int v1, int v2, int v3, int (**triangles)[3], int *triangles_total) { - int *triangle; + int *triangle; - if (*triangles) { - *triangles = MEM_reallocN(*triangles, sizeof(int[3]) * (*triangles_total + 1)); - } - else { - *triangles = MEM_callocN(sizeof(int[3]), "trianglulation triangles"); - } + if (*triangles) { + *triangles = MEM_reallocN(*triangles, sizeof(int[3]) * (*triangles_total + 1)); + } + else { + *triangles = MEM_callocN(sizeof(int[3]), "trianglulation triangles"); + } - triangle = (int *)&(*triangles)[(*triangles_total)]; + triangle = (int *)&(*triangles)[(*triangles_total)]; - triangle[0] = v1; - triangle[1] = v2; - triangle[2] = v3; + triangle[0] = v1; + triangle[1] = v2; + triangle[2] = v3; - (*triangles_total)++; + (*triangles_total)++; } -void BLI_voronoi_triangulate(const VoronoiSite *sites, int sites_total, ListBase *edges, int width, int height, - VoronoiTriangulationPoint **triangulated_points_r, int *triangulated_points_total_r, - int (**triangles_r)[3], int *triangles_total_r) +void BLI_voronoi_triangulate(const VoronoiSite *sites, + int sites_total, + ListBase *edges, + int width, + int height, + VoronoiTriangulationPoint **triangulated_points_r, + int *triangulated_points_total_r, + int (**triangles_r)[3], + int *triangles_total_r) { - VoronoiTriangulationPoint *triangulated_points = NULL; - int (*triangles)[3] = NULL; - int triangulated_points_total = 0, triangles_total = 0; - int i; - ListBase boundary_edges = {NULL, NULL}; + VoronoiTriangulationPoint *triangulated_points = NULL; + int(*triangles)[3] = NULL; + int triangulated_points_total = 0, triangles_total = 0; + int i; + ListBase boundary_edges = {NULL, NULL}; - voronoi_clampEdges(edges, width, height, &boundary_edges); - voronoi_createBoundaryEdges(&boundary_edges, width, height); + voronoi_clampEdges(edges, width, height, &boundary_edges); + voronoi_createBoundaryEdges(&boundary_edges, width, height); - for (i = 0; i < sites_total; i++) { - VoronoiEdge *edge; - int v1; + for (i = 0; i < sites_total; i++) { + VoronoiEdge *edge; + int v1; - v1 = voronoi_addTriangulationPoint(sites[i].co, sites[i].color, &triangulated_points, &triangulated_points_total); + v1 = voronoi_addTriangulationPoint( + sites[i].co, sites[i].color, &triangulated_points, &triangulated_points_total); - edge = boundary_edges.first; - while (edge) { - VoronoiEdge *test_edge = boundary_edges.first; - bool ok_start = true, ok_end = true; + edge = boundary_edges.first; + while (edge) { + VoronoiEdge *test_edge = boundary_edges.first; + bool ok_start = true, ok_end = true; - while (test_edge) { - if (ok_start && !testVoronoiEdge(sites[i].co, edge->start, test_edge)) { - ok_start = false; - break; - } + while (test_edge) { + if (ok_start && !testVoronoiEdge(sites[i].co, edge->start, test_edge)) { + ok_start = false; + break; + } - if (ok_end && !testVoronoiEdge(sites[i].co, edge->end, test_edge)) { - ok_end = false; - break; - } + if (ok_end && !testVoronoiEdge(sites[i].co, edge->end, test_edge)) { + ok_end = false; + break; + } - test_edge = test_edge->next; - } + test_edge = test_edge->next; + } - if (ok_start && ok_end) { - int v2, v3; + if (ok_start && ok_end) { + int v2, v3; - v2 = voronoi_addTriangulationPoint(edge->start, sites[i].color, &triangulated_points, &triangulated_points_total); - v3 = voronoi_addTriangulationPoint(edge->end, sites[i].color, &triangulated_points, &triangulated_points_total); + v2 = voronoi_addTriangulationPoint( + edge->start, sites[i].color, &triangulated_points, &triangulated_points_total); + v3 = voronoi_addTriangulationPoint( + edge->end, sites[i].color, &triangulated_points, &triangulated_points_total); - voronoi_addTriangle(v1, v2, v3, &triangles, &triangles_total); - } + voronoi_addTriangle(v1, v2, v3, &triangles, &triangles_total); + } - edge = edge->next; - } - } + edge = edge->next; + } + } - for (i = 0; i < triangulated_points_total; i++) { - VoronoiTriangulationPoint *triangulation_point = &triangulated_points[i]; + for (i = 0; i < triangulated_points_total; i++) { + VoronoiTriangulationPoint *triangulation_point = &triangulated_points[i]; - mul_v3_fl(triangulation_point->color, 1.0f / triangulation_point->power); - } + mul_v3_fl(triangulation_point->color, 1.0f / triangulation_point->power); + } - *triangulated_points_r = triangulated_points; - *triangulated_points_total_r = triangulated_points_total; + *triangulated_points_r = triangulated_points; + *triangulated_points_total_r = triangulated_points_total; - *triangles_r = triangles; - *triangles_total_r = triangles_total; + *triangles_r = triangles; + *triangles_total_r = triangles_total; - BLI_freelistN(&boundary_edges); + BLI_freelistN(&boundary_edges); } diff --git a/source/blender/blenlib/intern/voxel.c b/source/blender/blenlib/intern/voxel.c index fbd6fb74ab5..c7c794957c2 100644 --- a/source/blender/blenlib/intern/voxel.c +++ b/source/blender/blenlib/intern/voxel.c @@ -26,33 +26,32 @@ #include "BLI_strict_flags.h" - BLI_INLINE float D(float *data, const int res[3], int x, int y, int z) { - CLAMP(x, 0, res[0] - 1); - CLAMP(y, 0, res[1] - 1); - CLAMP(z, 0, res[2] - 1); - return data[BLI_VOXEL_INDEX(x, y, z, res)]; + CLAMP(x, 0, res[0] - 1); + CLAMP(y, 0, res[1] - 1); + CLAMP(z, 0, res[2] - 1); + return data[BLI_VOXEL_INDEX(x, y, z, res)]; } /* *** nearest neighbor *** */ /* input coordinates must be in bounding box 0.0 - 1.0 */ float BLI_voxel_sample_nearest(float *data, const int res[3], const float co[3]) { - int xi, yi, zi; + int xi, yi, zi; - xi = (int)(co[0] * (float)res[0]); - yi = (int)(co[1] * (float)res[1]); - zi = (int)(co[2] * (float)res[2]); + xi = (int)(co[0] * (float)res[0]); + yi = (int)(co[1] * (float)res[1]); + zi = (int)(co[2] * (float)res[2]); - return D(data, res, xi, yi, zi); + return D(data, res, xi, yi, zi); } /* returns highest integer <= x as integer (slightly faster than floor()) */ BLI_INLINE int FLOORI(float x) { - const int r = (int)x; - return ((x >= 0.f) || (float)r == x) ? r : (r - 1); + const int r = (int)x; + return ((x >= 0.f) || (float)r == x) ? r : (r - 1); } /* clamp function, cannot use the CLAMPIS macro, @@ -63,169 +62,200 @@ BLI_INLINE int FLOORI(float x) * x + 2 should wrap around to -2147483647 so the test < 0 should return true, which it doesn't) */ BLI_INLINE int64_t _clamp(int a, int b, int c) { - return (a < b) ? b : ((a > c) ? c : a); + return (a < b) ? b : ((a > c) ? c : a); } float BLI_voxel_sample_trilinear(float *data, const int res[3], const float co[3]) { - if (data) { - - const float xf = co[0] * (float)res[0] - 0.5f; - const float yf = co[1] * (float)res[1] - 0.5f; - const float zf = co[2] * (float)res[2] - 0.5f; - - const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); - - const int64_t xc[2] = { - _clamp(x, 0, res[0] - 1), - _clamp(x + 1, 0, res[0] - 1), - }; - const int64_t yc[2] = { - _clamp(y, 0, res[1] - 1) * res[0], - _clamp(y + 1, 0, res[1] - 1) * res[0], - }; - const int64_t zc[2] = { - _clamp(z, 0, res[2] - 1) * res[0] * res[1], - _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], - }; - - const float dx = xf - (float)x; - const float dy = yf - (float)y; - const float dz = zf - (float)z; - - const float u[2] = {1.f - dx, dx}; - const float v[2] = {1.f - dy, dy}; - const float w[2] = {1.f - dz, dz}; - - return w[0] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] ) ) - + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] ) ); - - } - return 0.f; + if (data) { + + const float xf = co[0] * (float)res[0] - 0.5f; + const float yf = co[1] * (float)res[1] - 0.5f; + const float zf = co[2] * (float)res[2] - 0.5f; + + const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); + + const int64_t xc[2] = { + _clamp(x, 0, res[0] - 1), + _clamp(x + 1, 0, res[0] - 1), + }; + const int64_t yc[2] = { + _clamp(y, 0, res[1] - 1) * res[0], + _clamp(y + 1, 0, res[1] - 1) * res[0], + }; + const int64_t zc[2] = { + _clamp(z, 0, res[2] - 1) * res[0] * res[1], + _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], + }; + + const float dx = xf - (float)x; + const float dy = yf - (float)y; + const float dz = zf - (float)z; + + const float u[2] = {1.f - dx, dx}; + const float v[2] = {1.f - dy, dy}; + const float w[2] = {1.f - dz, dz}; + + return w[0] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]])) + + w[1] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]])); + } + return 0.f; } float BLI_voxel_sample_triquadratic(float *data, const int res[3], const float co[3]) { - if (data) { - - const float xf = co[0] * (float)res[0]; - const float yf = co[1] * (float)res[1]; - const float zf = co[2] * (float)res[2]; - const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); - - const int64_t xc[3] = { - _clamp(x - 1, 0, res[0] - 1), - _clamp(x, 0, res[0] - 1), - _clamp(x + 1, 0, res[0] - 1), - }; - const int64_t yc[3] = { - _clamp(y - 1, 0, res[1] - 1) * res[0], - _clamp(y, 0, res[1] - 1) * res[0], - _clamp(y + 1, 0, res[1] - 1) * res[0], - }; - const int64_t zc[3] = { - _clamp(z - 1, 0, res[2] - 1) * res[0] * res[1], - _clamp(z, 0, res[2] - 1) * res[0] * res[1], - _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], - }; - - const float dx = xf - (float)x, dy = yf - (float)y, dz = zf - (float)z; - const float u[3] = {dx * (0.5f * dx - 1.f) + 0.5f, dx * (1.0f - dx) + 0.5f, 0.5f * dx * dx}; - const float v[3] = {dy * (0.5f * dy - 1.f) + 0.5f, dy * (1.0f - dy) + 0.5f, 0.5f * dy * dy}; - const float w[3] = {dz * (0.5f * dz - 1.f) + 0.5f, dz * (1.0f - dz) + 0.5f, 0.5f * dz * dz}; - - return w[0] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + u[2] * data[xc[2] + yc[0] + zc[0]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] ) ) - + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] ) ) - + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] ) ); - - } - return 0.f; + if (data) { + + const float xf = co[0] * (float)res[0]; + const float yf = co[1] * (float)res[1]; + const float zf = co[2] * (float)res[2]; + const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); + + const int64_t xc[3] = { + _clamp(x - 1, 0, res[0] - 1), + _clamp(x, 0, res[0] - 1), + _clamp(x + 1, 0, res[0] - 1), + }; + const int64_t yc[3] = { + _clamp(y - 1, 0, res[1] - 1) * res[0], + _clamp(y, 0, res[1] - 1) * res[0], + _clamp(y + 1, 0, res[1] - 1) * res[0], + }; + const int64_t zc[3] = { + _clamp(z - 1, 0, res[2] - 1) * res[0] * res[1], + _clamp(z, 0, res[2] - 1) * res[0] * res[1], + _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], + }; + + const float dx = xf - (float)x, dy = yf - (float)y, dz = zf - (float)z; + const float u[3] = {dx * (0.5f * dx - 1.f) + 0.5f, dx * (1.0f - dx) + 0.5f, 0.5f * dx * dx}; + const float v[3] = {dy * (0.5f * dy - 1.f) + 0.5f, dy * (1.0f - dy) + 0.5f, 0.5f * dy * dy}; + const float w[3] = {dz * (0.5f * dz - 1.f) + 0.5f, dz * (1.0f - dz) + 0.5f, 0.5f * dz * dz}; + + return w[0] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + + u[2] * data[xc[2] + yc[0] + zc[0]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + + u[2] * data[xc[2] + yc[1] + zc[0]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + + u[2] * data[xc[2] + yc[2] + zc[0]])) + + w[1] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + + u[2] * data[xc[2] + yc[0] + zc[1]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + + u[2] * data[xc[2] + yc[1] + zc[1]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + + u[2] * data[xc[2] + yc[2] + zc[1]])) + + w[2] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + + u[2] * data[xc[2] + yc[0] + zc[2]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + + u[2] * data[xc[2] + yc[1] + zc[2]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + + u[2] * data[xc[2] + yc[2] + zc[2]])); + } + return 0.f; } float BLI_voxel_sample_tricubic(float *data, const int res[3], const float co[3], int bspline) { - if (data) { - - const float xf = co[0] * (float)res[0] - 0.5f; - const float yf = co[1] * (float)res[1] - 0.5f; - const float zf = co[2] * (float)res[2] - 0.5f; - const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); - - const int64_t xc[4] = { - _clamp(x - 1, 0, res[0] - 1), - _clamp(x, 0, res[0] - 1), - _clamp(x + 1, 0, res[0] - 1), - _clamp(x + 2, 0, res[0] - 1), - }; - const int64_t yc[4] = { - _clamp(y - 1, 0, res[1] - 1) * res[0], - _clamp(y, 0, res[1] - 1) * res[0], - _clamp(y + 1, 0, res[1] - 1) * res[0], - _clamp(y + 2, 0, res[1] - 1) * res[0], - }; - const int64_t zc[4] = { - _clamp(z - 1, 0, res[2] - 1) * res[0] * res[1], - _clamp(z, 0, res[2] - 1) * res[0] * res[1], - _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], - _clamp(z + 2, 0, res[2] - 1) * res[0] * res[1], - }; - const float dx = xf - (float)x, dy = yf - (float)y, dz = zf - (float)z; - - float u[4], v[4], w[4]; - if (bspline) { // B-Spline - u[0] = (((-1.f/6.f)*dx + 0.5f)*dx - 0.5f)*dx + (1.f/6.f); - u[1] = (( 0.5f*dx - 1.f )*dx )*dx + (2.f/3.f); - u[2] = (( -0.5f*dx + 0.5f)*dx + 0.5f)*dx + (1.f/6.f); - u[3] = ( 1.f/6.f)*dx*dx*dx; - v[0] = (((-1.f/6.f)*dy + 0.5f)*dy - 0.5f)*dy + (1.f/6.f); - v[1] = (( 0.5f*dy - 1.f )*dy )*dy + (2.f/3.f); - v[2] = (( -0.5f*dy + 0.5f)*dy + 0.5f)*dy + (1.f/6.f); - v[3] = ( 1.f/6.f)*dy*dy*dy; - w[0] = (((-1.f/6.f)*dz + 0.5f)*dz - 0.5f)*dz + (1.f/6.f); - w[1] = (( 0.5f*dz - 1.f )*dz )*dz + (2.f/3.f); - w[2] = (( -0.5f*dz + 0.5f)*dz + 0.5f)*dz + (1.f/6.f); - w[3] = ( 1.f/6.f)*dz*dz*dz; - } - else { // Catmull-Rom - u[0] = ((-0.5f*dx + 1.0f)*dx - 0.5f)*dx; - u[1] = (( 1.5f*dx - 2.5f)*dx )*dx + 1.0f; - u[2] = ((-1.5f*dx + 2.0f)*dx + 0.5f)*dx; - u[3] = (( 0.5f*dx - 0.5f)*dx )*dx; - v[0] = ((-0.5f*dy + 1.0f)*dy - 0.5f)*dy; - v[1] = (( 1.5f*dy - 2.5f)*dy )*dy + 1.0f; - v[2] = ((-1.5f*dy + 2.0f)*dy + 0.5f)*dy; - v[3] = (( 0.5f*dy - 0.5f)*dy )*dy; - w[0] = ((-0.5f*dz + 1.0f)*dz - 0.5f)*dz; - w[1] = (( 1.5f*dz - 2.5f)*dz )*dz + 1.0f; - w[2] = ((-1.5f*dz + 2.0f)*dz + 0.5f)*dz; - w[3] = (( 0.5f*dz - 0.5f)*dz )*dz; - } - - return w[0] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + u[2] * data[xc[2] + yc[0] + zc[0]] + u[3] * data[xc[3] + yc[0] + zc[0]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] + u[3] * data[xc[3] + yc[1] + zc[0]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] + u[3] * data[xc[3] + yc[2] + zc[0]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[0]] + u[1] * data[xc[1] + yc[3] + zc[0]] + u[2] * data[xc[2] + yc[3] + zc[0]] + u[3] * data[xc[3] + yc[3] + zc[0]] ) ) - + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] + u[3] * data[xc[3] + yc[0] + zc[1]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] + u[3] * data[xc[3] + yc[1] + zc[1]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] + u[3] * data[xc[3] + yc[2] + zc[1]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[1]] + u[1] * data[xc[1] + yc[3] + zc[1]] + u[2] * data[xc[2] + yc[3] + zc[1]] + u[3] * data[xc[3] + yc[3] + zc[1]] ) ) - + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] + u[3] * data[xc[3] + yc[0] + zc[2]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] + u[3] * data[xc[3] + yc[1] + zc[2]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] + u[3] * data[xc[3] + yc[2] + zc[2]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[2]] + u[1] * data[xc[1] + yc[3] + zc[2]] + u[2] * data[xc[2] + yc[3] + zc[2]] + u[3] * data[xc[3] + yc[3] + zc[2]] ) ) - + w[3] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[3]] + u[1] * data[xc[1] + yc[0] + zc[3]] + u[2] * data[xc[2] + yc[0] + zc[3]] + u[3] * data[xc[3] + yc[0] + zc[3]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[3]] + u[1] * data[xc[1] + yc[1] + zc[3]] + u[2] * data[xc[2] + yc[1] + zc[3]] + u[3] * data[xc[3] + yc[1] + zc[3]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[3]] + u[1] * data[xc[1] + yc[2] + zc[3]] + u[2] * data[xc[2] + yc[2] + zc[3]] + u[3] * data[xc[3] + yc[2] + zc[3]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[3]] + u[1] * data[xc[1] + yc[3] + zc[3]] + u[2] * data[xc[2] + yc[3] + zc[3]] + u[3] * data[xc[3] + yc[3] + zc[3]] ) ); - - } - return 0.f; + if (data) { + + const float xf = co[0] * (float)res[0] - 0.5f; + const float yf = co[1] * (float)res[1] - 0.5f; + const float zf = co[2] * (float)res[2] - 0.5f; + const int x = FLOORI(xf), y = FLOORI(yf), z = FLOORI(zf); + + const int64_t xc[4] = { + _clamp(x - 1, 0, res[0] - 1), + _clamp(x, 0, res[0] - 1), + _clamp(x + 1, 0, res[0] - 1), + _clamp(x + 2, 0, res[0] - 1), + }; + const int64_t yc[4] = { + _clamp(y - 1, 0, res[1] - 1) * res[0], + _clamp(y, 0, res[1] - 1) * res[0], + _clamp(y + 1, 0, res[1] - 1) * res[0], + _clamp(y + 2, 0, res[1] - 1) * res[0], + }; + const int64_t zc[4] = { + _clamp(z - 1, 0, res[2] - 1) * res[0] * res[1], + _clamp(z, 0, res[2] - 1) * res[0] * res[1], + _clamp(z + 1, 0, res[2] - 1) * res[0] * res[1], + _clamp(z + 2, 0, res[2] - 1) * res[0] * res[1], + }; + const float dx = xf - (float)x, dy = yf - (float)y, dz = zf - (float)z; + + float u[4], v[4], w[4]; + if (bspline) { // B-Spline + u[0] = (((-1.f / 6.f) * dx + 0.5f) * dx - 0.5f) * dx + (1.f / 6.f); + u[1] = ((0.5f * dx - 1.f) * dx) * dx + (2.f / 3.f); + u[2] = ((-0.5f * dx + 0.5f) * dx + 0.5f) * dx + (1.f / 6.f); + u[3] = (1.f / 6.f) * dx * dx * dx; + v[0] = (((-1.f / 6.f) * dy + 0.5f) * dy - 0.5f) * dy + (1.f / 6.f); + v[1] = ((0.5f * dy - 1.f) * dy) * dy + (2.f / 3.f); + v[2] = ((-0.5f * dy + 0.5f) * dy + 0.5f) * dy + (1.f / 6.f); + v[3] = (1.f / 6.f) * dy * dy * dy; + w[0] = (((-1.f / 6.f) * dz + 0.5f) * dz - 0.5f) * dz + (1.f / 6.f); + w[1] = ((0.5f * dz - 1.f) * dz) * dz + (2.f / 3.f); + w[2] = ((-0.5f * dz + 0.5f) * dz + 0.5f) * dz + (1.f / 6.f); + w[3] = (1.f / 6.f) * dz * dz * dz; + } + else { // Catmull-Rom + u[0] = ((-0.5f * dx + 1.0f) * dx - 0.5f) * dx; + u[1] = ((1.5f * dx - 2.5f) * dx) * dx + 1.0f; + u[2] = ((-1.5f * dx + 2.0f) * dx + 0.5f) * dx; + u[3] = ((0.5f * dx - 0.5f) * dx) * dx; + v[0] = ((-0.5f * dy + 1.0f) * dy - 0.5f) * dy; + v[1] = ((1.5f * dy - 2.5f) * dy) * dy + 1.0f; + v[2] = ((-1.5f * dy + 2.0f) * dy + 0.5f) * dy; + v[3] = ((0.5f * dy - 0.5f) * dy) * dy; + w[0] = ((-0.5f * dz + 1.0f) * dz - 0.5f) * dz; + w[1] = ((1.5f * dz - 2.5f) * dz) * dz + 1.0f; + w[2] = ((-1.5f * dz + 2.0f) * dz + 0.5f) * dz; + w[3] = ((0.5f * dz - 0.5f) * dz) * dz; + } + + return w[0] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + + u[2] * data[xc[2] + yc[0] + zc[0]] + u[3] * data[xc[3] + yc[0] + zc[0]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + + u[2] * data[xc[2] + yc[1] + zc[0]] + u[3] * data[xc[3] + yc[1] + zc[0]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + + u[2] * data[xc[2] + yc[2] + zc[0]] + u[3] * data[xc[3] + yc[2] + zc[0]]) + + v[3] * (u[0] * data[xc[0] + yc[3] + zc[0]] + u[1] * data[xc[1] + yc[3] + zc[0]] + + u[2] * data[xc[2] + yc[3] + zc[0]] + u[3] * data[xc[3] + yc[3] + zc[0]])) + + w[1] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + + u[2] * data[xc[2] + yc[0] + zc[1]] + u[3] * data[xc[3] + yc[0] + zc[1]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + + u[2] * data[xc[2] + yc[1] + zc[1]] + u[3] * data[xc[3] + yc[1] + zc[1]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + + u[2] * data[xc[2] + yc[2] + zc[1]] + u[3] * data[xc[3] + yc[2] + zc[1]]) + + v[3] * (u[0] * data[xc[0] + yc[3] + zc[1]] + u[1] * data[xc[1] + yc[3] + zc[1]] + + u[2] * data[xc[2] + yc[3] + zc[1]] + u[3] * data[xc[3] + yc[3] + zc[1]])) + + w[2] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + + u[2] * data[xc[2] + yc[0] + zc[2]] + u[3] * data[xc[3] + yc[0] + zc[2]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + + u[2] * data[xc[2] + yc[1] + zc[2]] + u[3] * data[xc[3] + yc[1] + zc[2]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + + u[2] * data[xc[2] + yc[2] + zc[2]] + u[3] * data[xc[3] + yc[2] + zc[2]]) + + v[3] * (u[0] * data[xc[0] + yc[3] + zc[2]] + u[1] * data[xc[1] + yc[3] + zc[2]] + + u[2] * data[xc[2] + yc[3] + zc[2]] + u[3] * data[xc[3] + yc[3] + zc[2]])) + + w[3] * + (v[0] * (u[0] * data[xc[0] + yc[0] + zc[3]] + u[1] * data[xc[1] + yc[0] + zc[3]] + + u[2] * data[xc[2] + yc[0] + zc[3]] + u[3] * data[xc[3] + yc[0] + zc[3]]) + + v[1] * (u[0] * data[xc[0] + yc[1] + zc[3]] + u[1] * data[xc[1] + yc[1] + zc[3]] + + u[2] * data[xc[2] + yc[1] + zc[3]] + u[3] * data[xc[3] + yc[1] + zc[3]]) + + v[2] * (u[0] * data[xc[0] + yc[2] + zc[3]] + u[1] * data[xc[1] + yc[2] + zc[3]] + + u[2] * data[xc[2] + yc[2] + zc[3]] + u[3] * data[xc[3] + yc[2] + zc[3]]) + + v[3] * (u[0] * data[xc[0] + yc[3] + zc[3]] + u[1] * data[xc[1] + yc[3] + zc[3]] + + u[2] * data[xc[2] + yc[3] + zc[3]] + u[3] * data[xc[3] + yc[3] + zc[3]])); + } + return 0.f; } diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 483351801f4..9e6ea0bb6ee 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -22,244 +22,263 @@ * \ingroup bli */ - #ifdef WIN32 -#include <stdlib.h> -#include <stdio.h> -#include <conio.h> +# include <stdlib.h> +# include <stdio.h> +# include <conio.h> -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" -#define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY -#include "BLI_winstuff.h" -#include "BLI_utildefines.h" -#include "BLI_path_util.h" -#include "BLI_string.h" +# define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY +# include "BLI_winstuff.h" +# include "BLI_utildefines.h" +# include "BLI_path_util.h" +# include "BLI_string.h" -#include "../blenkernel/BKE_global.h" /* G.background, bad level include (no function calls) */ +# include "../blenkernel/BKE_global.h" /* G.background, bad level include (no function calls) */ -#include "utf_winfunc.h" -#include "utfconv.h" +# include "utf_winfunc.h" +# include "utfconv.h" /* FILE_MAXDIR + FILE_MAXFILE */ int BLI_getInstallationDir(char *str) { - char dir[FILE_MAXDIR]; - int a; - /*change to utf support*/ - GetModuleFileName(NULL, str, FILE_MAX); - BLI_split_dir_part(str, dir, sizeof(dir)); /* shouldn't be relative */ - a = strlen(dir); - if (dir[a - 1] == '\\') { - dir[a - 1] = 0; - } + char dir[FILE_MAXDIR]; + int a; + /*change to utf support*/ + GetModuleFileName(NULL, str, FILE_MAX); + BLI_split_dir_part(str, dir, sizeof(dir)); /* shouldn't be relative */ + a = strlen(dir); + if (dir[a - 1] == '\\') { + dir[a - 1] = 0; + } - strcpy(str, dir); + strcpy(str, dir); - return 1; + return 1; } static void RegisterBlendExtension_Fail(HKEY root) { - printf("failed\n"); - if (root) { - RegCloseKey(root); - } - if (!G.background) { - MessageBox(0, "Could not register file extension.", "Blender error", MB_OK | MB_ICONERROR); - } - TerminateProcess(GetCurrentProcess(), 1); + printf("failed\n"); + if (root) { + RegCloseKey(root); + } + if (!G.background) { + MessageBox(0, "Could not register file extension.", "Blender error", MB_OK | MB_ICONERROR); + } + TerminateProcess(GetCurrentProcess(), 1); } void RegisterBlendExtension(void) { - LONG lresult; - HKEY hkey = 0; - HKEY root = 0; - BOOL usr_mode = false; - DWORD dwd = 0; - char buffer[256]; + LONG lresult; + HKEY hkey = 0; + HKEY root = 0; + BOOL usr_mode = false; + DWORD dwd = 0; + char buffer[256]; - char BlPath[MAX_PATH]; - char InstallDir[FILE_MAXDIR]; - char SysDir[FILE_MAXDIR]; - const char *ThumbHandlerDLL; - char RegCmd[MAX_PATH * 2]; - char MBox[256]; - char *blender_app; -#ifndef _WIN64 - BOOL IsWOW64; -#endif + char BlPath[MAX_PATH]; + char InstallDir[FILE_MAXDIR]; + char SysDir[FILE_MAXDIR]; + const char *ThumbHandlerDLL; + char RegCmd[MAX_PATH * 2]; + char MBox[256]; + char *blender_app; +# ifndef _WIN64 + BOOL IsWOW64; +# endif - printf("Registering file extension..."); - GetModuleFileName(0, BlPath, MAX_PATH); + printf("Registering file extension..."); + GetModuleFileName(0, BlPath, MAX_PATH); - /* Replace the actual app name with the wrapper. */ - blender_app = strstr(BlPath, "blender-app.exe"); - if (blender_app != NULL) { - strcpy(blender_app, "blender.exe"); - } + /* Replace the actual app name with the wrapper. */ + blender_app = strstr(BlPath, "blender-app.exe"); + if (blender_app != NULL) { + strcpy(blender_app, "blender.exe"); + } - /* root is HKLM by default */ - lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root); - if (lresult != ERROR_SUCCESS) { - /* try HKCU on failure */ - usr_mode = true; - lresult = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &root); - if (lresult != ERROR_SUCCESS) { - RegisterBlendExtension_Fail(0); - } - } + /* root is HKLM by default */ + lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root); + if (lresult != ERROR_SUCCESS) { + /* try HKCU on failure */ + usr_mode = true; + lresult = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &root); + if (lresult != ERROR_SUCCESS) { + RegisterBlendExtension_Fail(0); + } + } - lresult = RegCreateKeyEx(root, "blendfile", 0, - NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); - if (lresult == ERROR_SUCCESS) { - strcpy(buffer, "Blender File"); - lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); - RegCloseKey(hkey); - } - if (lresult != ERROR_SUCCESS) { - RegisterBlendExtension_Fail(root); - } + lresult = RegCreateKeyEx( + root, "blendfile", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); + if (lresult == ERROR_SUCCESS) { + strcpy(buffer, "Blender File"); + lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); + RegCloseKey(hkey); + } + if (lresult != ERROR_SUCCESS) { + RegisterBlendExtension_Fail(root); + } - lresult = RegCreateKeyEx(root, "blendfile\\shell\\open\\command", 0, - NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); - if (lresult == ERROR_SUCCESS) { - sprintf(buffer, "\"%s\" \"%%1\"", BlPath); - lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); - RegCloseKey(hkey); - } - if (lresult != ERROR_SUCCESS) { - RegisterBlendExtension_Fail(root); - } + lresult = RegCreateKeyEx(root, + "blendfile\\shell\\open\\command", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hkey, + &dwd); + if (lresult == ERROR_SUCCESS) { + sprintf(buffer, "\"%s\" \"%%1\"", BlPath); + lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); + RegCloseKey(hkey); + } + if (lresult != ERROR_SUCCESS) { + RegisterBlendExtension_Fail(root); + } - lresult = RegCreateKeyEx(root, "blendfile\\DefaultIcon", 0, - NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); - if (lresult == ERROR_SUCCESS) { - sprintf(buffer, "\"%s\", 1", BlPath); - lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); - RegCloseKey(hkey); - } - if (lresult != ERROR_SUCCESS) { - RegisterBlendExtension_Fail(root); - } + lresult = RegCreateKeyEx(root, + "blendfile\\DefaultIcon", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hkey, + &dwd); + if (lresult == ERROR_SUCCESS) { + sprintf(buffer, "\"%s\", 1", BlPath); + lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); + RegCloseKey(hkey); + } + if (lresult != ERROR_SUCCESS) { + RegisterBlendExtension_Fail(root); + } - lresult = RegCreateKeyEx(root, ".blend", 0, - NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); - if (lresult == ERROR_SUCCESS) { - strcpy(buffer, "blendfile"); - lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); - RegCloseKey(hkey); - } - if (lresult != ERROR_SUCCESS) { - RegisterBlendExtension_Fail(root); - } + lresult = RegCreateKeyEx( + root, ".blend", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); + if (lresult == ERROR_SUCCESS) { + strcpy(buffer, "blendfile"); + lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); + RegCloseKey(hkey); + } + if (lresult != ERROR_SUCCESS) { + RegisterBlendExtension_Fail(root); + } - BLI_getInstallationDir(InstallDir); - GetSystemDirectory(SysDir, FILE_MAXDIR); -#ifdef _WIN64 - ThumbHandlerDLL = "BlendThumb64.dll"; -#else - IsWow64Process(GetCurrentProcess(), &IsWOW64); - if (IsWOW64 == true) { - ThumbHandlerDLL = "BlendThumb64.dll"; - } - else { - ThumbHandlerDLL = "BlendThumb.dll"; - } -#endif - snprintf(RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL); - system(RegCmd); + BLI_getInstallationDir(InstallDir); + GetSystemDirectory(SysDir, FILE_MAXDIR); +# ifdef _WIN64 + ThumbHandlerDLL = "BlendThumb64.dll"; +# else + IsWow64Process(GetCurrentProcess(), &IsWOW64); + if (IsWOW64 == true) { + ThumbHandlerDLL = "BlendThumb64.dll"; + } + else { + ThumbHandlerDLL = "BlendThumb.dll"; + } +# endif + snprintf( + RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL); + system(RegCmd); - RegCloseKey(root); - printf("success (%s)\n", usr_mode ? "user" : "system"); - if (!G.background) { - sprintf(MBox, "File extension registered for %s.", usr_mode ? "the current user. To register for all users, run as an administrator" : "all users"); - MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION); - } - TerminateProcess(GetCurrentProcess(), 0); + RegCloseKey(root); + printf("success (%s)\n", usr_mode ? "user" : "system"); + if (!G.background) { + sprintf(MBox, + "File extension registered for %s.", + usr_mode ? "the current user. To register for all users, run as an administrator" : + "all users"); + MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION); + } + TerminateProcess(GetCurrentProcess(), 0); } void get_default_root(char *root) { - char str[MAX_PATH + 1]; + char str[MAX_PATH + 1]; - /* the default drive to resolve a directory without a specified drive - * should be the Windows installation drive, since this was what the OS - * assumes. */ - if (GetWindowsDirectory(str, MAX_PATH + 1)) { - root[0] = str[0]; - root[1] = ':'; - root[2] = '\\'; - root[3] = '\0'; - } - else { - /* if GetWindowsDirectory fails, something has probably gone wrong, - * we are trying the blender install dir though */ - if (GetModuleFileName(NULL, str, MAX_PATH + 1)) { - printf("Error! Could not get the Windows Directory - " - "Defaulting to Blender installation Dir!\n"); - root[0] = str[0]; - root[1] = ':'; - root[2] = '\\'; - root[3] = '\0'; - } - else { - DWORD tmp; - int i; - int rc = 0; - /* now something has gone really wrong - still trying our best guess */ - printf("Error! Could not get the Windows Directory - " - "Defaulting to first valid drive! Path might be invalid!\n"); - tmp = GetLogicalDrives(); - for (i = 2; i < 26; i++) { - if ((tmp >> i) & 1) { - root[0] = 'a' + i; - root[1] = ':'; - root[2] = '\\'; - root[3] = '\0'; - if (GetFileAttributes(root) != 0xFFFFFFFF) { - rc = i; - break; - } - } - } - if (0 == rc) { - printf("ERROR in 'get_default_root': can't find a valid drive!\n"); - root[0] = 'C'; - root[1] = ':'; - root[2] = '\\'; - root[3] = '\0'; - } - } - } + /* the default drive to resolve a directory without a specified drive + * should be the Windows installation drive, since this was what the OS + * assumes. */ + if (GetWindowsDirectory(str, MAX_PATH + 1)) { + root[0] = str[0]; + root[1] = ':'; + root[2] = '\\'; + root[3] = '\0'; + } + else { + /* if GetWindowsDirectory fails, something has probably gone wrong, + * we are trying the blender install dir though */ + if (GetModuleFileName(NULL, str, MAX_PATH + 1)) { + printf( + "Error! Could not get the Windows Directory - " + "Defaulting to Blender installation Dir!\n"); + root[0] = str[0]; + root[1] = ':'; + root[2] = '\\'; + root[3] = '\0'; + } + else { + DWORD tmp; + int i; + int rc = 0; + /* now something has gone really wrong - still trying our best guess */ + printf( + "Error! Could not get the Windows Directory - " + "Defaulting to first valid drive! Path might be invalid!\n"); + tmp = GetLogicalDrives(); + for (i = 2; i < 26; i++) { + if ((tmp >> i) & 1) { + root[0] = 'a' + i; + root[1] = ':'; + root[2] = '\\'; + root[3] = '\0'; + if (GetFileAttributes(root) != 0xFFFFFFFF) { + rc = i; + break; + } + } + } + if (0 == rc) { + printf("ERROR in 'get_default_root': can't find a valid drive!\n"); + root[0] = 'C'; + root[1] = ':'; + root[2] = '\\'; + root[3] = '\0'; + } + } + } } /* UNUSED */ -#if 0 +# if 0 int check_file_chars(char *filename) { - char *p = filename; - while (*p) { - switch (*p) { - case ':': - case '?': - case '*': - case '|': - case '\\': - case '/': - case '\"': - return 0; - break; - } + char *p = filename; + while (*p) { + switch (*p) { + case ':': + case '?': + case '*': + case '|': + case '\\': + case '/': + case '\"': + return 0; + break; + } - p++; - } - return 1; + p++; + } + return 1; } -#endif +# endif #else diff --git a/source/blender/blenlib/intern/winstuff_dir.c b/source/blender/blenlib/intern/winstuff_dir.c index 9c1a51f9be7..1e5a0db678e 100644 --- a/source/blender/blenlib/intern/winstuff_dir.c +++ b/source/blender/blenlib/intern/winstuff_dir.c @@ -33,25 +33,25 @@ # include "MEM_guardedalloc.h" # endif -#define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY -#include "BLI_winstuff.h" -#include "BLI_utildefines.h" -#include "utfconv.h" +# define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY +# include "BLI_winstuff.h" +# include "BLI_utildefines.h" +# include "utfconv.h" -#define PATH_SUFFIX "\\*" -#define PATH_SUFFIX_LEN 2 +# define PATH_SUFFIX "\\*" +# define PATH_SUFFIX_LEN 2 /* keep local to this file */ struct __dirstream { - HANDLE handle; - WIN32_FIND_DATAW data; - char path[MAX_PATH + PATH_SUFFIX_LEN]; - long dd_loc; - long dd_size; - char dd_buf[4096]; - void *dd_direct; - - struct dirent direntry; + HANDLE handle; + WIN32_FIND_DATAW data; + char path[MAX_PATH + PATH_SUFFIX_LEN]; + long dd_loc; + long dd_size; + char dd_buf[4096]; + void *dd_direct; + + struct dirent direntry; }; /** @@ -64,95 +64,92 @@ struct __dirstream { DIR *opendir(const char *path) { - wchar_t *path_16 = alloc_utf16_from_8(path, 0); - int path_len; - DIR *newd = NULL; - - if ((GetFileAttributesW(path_16) & FILE_ATTRIBUTE_DIRECTORY) && - ((path_len = strlen(path)) < (sizeof(newd->path) - PATH_SUFFIX_LEN))) - { - newd = MEM_mallocN(sizeof(DIR), "opendir"); - newd->handle = INVALID_HANDLE_VALUE; - memcpy(newd->path, path, path_len); - memcpy(newd->path + path_len, PATH_SUFFIX, PATH_SUFFIX_LEN + 1); - - newd->direntry.d_ino = 0; - newd->direntry.d_off = 0; - newd->direntry.d_reclen = 0; - newd->direntry.d_name = NULL; - } - - free(path_16); - return newd; + wchar_t *path_16 = alloc_utf16_from_8(path, 0); + int path_len; + DIR *newd = NULL; + + if ((GetFileAttributesW(path_16) & FILE_ATTRIBUTE_DIRECTORY) && + ((path_len = strlen(path)) < (sizeof(newd->path) - PATH_SUFFIX_LEN))) { + newd = MEM_mallocN(sizeof(DIR), "opendir"); + newd->handle = INVALID_HANDLE_VALUE; + memcpy(newd->path, path, path_len); + memcpy(newd->path + path_len, PATH_SUFFIX, PATH_SUFFIX_LEN + 1); + + newd->direntry.d_ino = 0; + newd->direntry.d_off = 0; + newd->direntry.d_reclen = 0; + newd->direntry.d_name = NULL; + } + + free(path_16); + return newd; } static char *BLI_alloc_utf_8_from_16(wchar_t *in16, size_t add) { - size_t bsize = count_utf_8_from_16(in16); - char *out8 = NULL; - if (!bsize) { - return NULL; - } - out8 = (char *)MEM_mallocN(sizeof(char) * (bsize + add), "UTF-8 String"); - conv_utf_16_to_8(in16, out8, bsize); - return out8; + size_t bsize = count_utf_8_from_16(in16); + char *out8 = NULL; + if (!bsize) { + return NULL; + } + out8 = (char *)MEM_mallocN(sizeof(char) * (bsize + add), "UTF-8 String"); + conv_utf_16_to_8(in16, out8, bsize); + return out8; } -static wchar_t *UNUSED_FUNCTION(BLI_alloc_utf16_from_8) (char *in8, size_t add) +static wchar_t *UNUSED_FUNCTION(BLI_alloc_utf16_from_8)(char *in8, size_t add) { - size_t bsize = count_utf_16_from_8(in8); - wchar_t *out16 = NULL; - if (!bsize) { - return NULL; - } - out16 = (wchar_t *) MEM_mallocN(sizeof(wchar_t) * (bsize + add), "UTF-16 String"); - conv_utf_8_to_16(in8, out16, bsize); - return out16; + size_t bsize = count_utf_16_from_8(in8); + wchar_t *out16 = NULL; + if (!bsize) { + return NULL; + } + out16 = (wchar_t *)MEM_mallocN(sizeof(wchar_t) * (bsize + add), "UTF-16 String"); + conv_utf_8_to_16(in8, out16, bsize); + return out16; } - - struct dirent *readdir(DIR *dp) { - if (dp->direntry.d_name) { - MEM_freeN(dp->direntry.d_name); - dp->direntry.d_name = NULL; - } - - if (dp->handle == INVALID_HANDLE_VALUE) { - wchar_t *path_16 = alloc_utf16_from_8(dp->path, 0); - dp->handle = FindFirstFileW(path_16, &(dp->data)); - free(path_16); - if (dp->handle == INVALID_HANDLE_VALUE) { - return NULL; - } - - dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0); - - return &dp->direntry; - } - else if (FindNextFileW(dp->handle, &(dp->data))) { - dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0); - - return &dp->direntry; - } - else { - return NULL; - } + if (dp->direntry.d_name) { + MEM_freeN(dp->direntry.d_name); + dp->direntry.d_name = NULL; + } + + if (dp->handle == INVALID_HANDLE_VALUE) { + wchar_t *path_16 = alloc_utf16_from_8(dp->path, 0); + dp->handle = FindFirstFileW(path_16, &(dp->data)); + free(path_16); + if (dp->handle == INVALID_HANDLE_VALUE) { + return NULL; + } + + dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0); + + return &dp->direntry; + } + else if (FindNextFileW(dp->handle, &(dp->data))) { + dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0); + + return &dp->direntry; + } + else { + return NULL; + } } int closedir(DIR *dp) { - if (dp->direntry.d_name) { - MEM_freeN(dp->direntry.d_name); - } - if (dp->handle != INVALID_HANDLE_VALUE) { - FindClose(dp->handle); - } + if (dp->direntry.d_name) { + MEM_freeN(dp->direntry.d_name); + } + if (dp->handle != INVALID_HANDLE_VALUE) { + FindClose(dp->handle); + } - MEM_freeN(dp); + MEM_freeN(dp); - return 0; + return 0; } /* End of copied part */ |