diff options
author | Joseph Eagar <joeedh@gmail.com> | 2010-07-19 08:44:37 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2010-07-19 08:44:37 +0400 |
commit | c11c196efadf5ef52293d782638497f86a209722 (patch) | |
tree | 43abcd60b2400d28db8686f4dbea68f17475ef58 /source/blender/blenlib/intern | |
parent | f54aa7811029c90b6071ccc9e27e57a758e5884d (diff) | |
parent | 7f083c45bee15f7540e2a35a725efe28fc962239 (diff) |
part 1 of merge from trunk at r30358; it compiles, but doesn't link quite yet :)
Diffstat (limited to 'source/blender/blenlib/intern')
44 files changed, 2979 insertions, 1570 deletions
diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index cd876023830..8d72311f80b 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -1,7 +1,7 @@ /** * A general argument parsing module * - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -33,10 +33,22 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_args.h" #include "BLI_ghash.h" +char NO_DOCS[] = "NO DOCUMENTATION SPECIFIED"; + +struct bArgDoc; +typedef struct bArgDoc { + struct bArgDoc *next, *prev; + char *short_arg; + char *long_arg; + char *documentation; + int done; +} bArgDoc; + typedef struct bAKey { char *arg; uintptr_t pass; /* cast easier */ @@ -47,9 +59,11 @@ typedef struct bArgument { bAKey *key; BA_ArgCallback func; void *data; + bArgDoc *doc; } bArgument; struct bArgs { + ListBase docs; GHash *items; int argc; char **argv; @@ -70,7 +84,7 @@ static unsigned int case_strhash(void *ptr) { static unsigned int keyhash(void *ptr) { bAKey *k = ptr; - return case_strhash(k->arg) ^ BLI_ghashutil_inthash((void*)k->pass); + return case_strhash(k->arg); // ^ BLI_ghashutil_inthash((void*)k->pass); } static int keycmp(void *a, void *b) @@ -102,7 +116,8 @@ bArgs *BLI_argsInit(int argc, 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); + ba->items = BLI_ghash_new(keyhash, keycmp, "bArgs passes gh"); + ba->docs.first = ba->docs.last = NULL; ba->argc = argc; ba->argv = argv; @@ -118,6 +133,7 @@ void BLI_argsFree(struct bArgs *ba) { BLI_ghash_free(ba->items, freeItem, freeItem); MEM_freeN(ba->passes); + BLI_freelistN(&ba->docs); MEM_freeN(ba); } @@ -134,7 +150,25 @@ char **BLI_argsArgv(struct bArgs *ba) return ba->argv; } -static void internalAdd(struct bArgs *ba, char *arg, int pass, int case_str, BA_ArgCallback cb, void *data) +static bArgDoc *internalDocs(struct bArgs *ba, char *short_arg, char *long_arg, char *doc) +{ + bArgDoc *d; + + d = MEM_callocN(sizeof(bArgDoc), "bArgDoc"); + + if (doc == NULL) + doc = NO_DOCS; + + d->short_arg = short_arg; + d->long_arg = long_arg; + d->documentation = doc; + + BLI_addtail(&ba->docs, d); + + return d; +} + +static void internalAdd(struct bArgs *ba, char *arg, int pass, int case_str, BA_ArgCallback cb, void *data, bArgDoc *d) { bArgument *a; bAKey *key; @@ -157,20 +191,67 @@ static void internalAdd(struct bArgs *ba, char *arg, int pass, int case_str, BA_ a->key = key; a->func = cb; a->data = data; + a->doc = d; BLI_ghash_insert(ba->items, key, a); } -void BLI_argsAdd(struct bArgs *ba, char *arg, int pass, BA_ArgCallback cb, void *data) +void BLI_argsAddCase(struct bArgs *ba, int pass, char *short_arg, int short_case, char *long_arg, int long_case, char *doc, BA_ArgCallback cb, void *data) { - internalAdd(ba, arg, pass, 0, cb, data); + bArgDoc *d = internalDocs(ba, short_arg, long_arg, doc); + + 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); + + } -void BLI_argsAddCase(struct bArgs *ba, char *arg, int pass, BA_ArgCallback cb, void *data) +void BLI_argsAdd(struct bArgs *ba, int pass, char *short_arg, char *long_arg, char *doc, BA_ArgCallback cb, void *data) { - internalAdd(ba, arg, pass, 1, 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); +} + +void BLI_argsPrintArgDoc(struct bArgs *ba, char *arg) +{ + bArgument *a = lookUp(ba, arg, -1, -1); + + if (a) + { + bArgDoc *d = a->doc; + + internalDocPrint(d); + + d->done = 1; + } +} + +void BLI_argsPrintOtherDoc(struct bArgs *ba) +{ + bArgDoc *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) { @@ -203,7 +284,8 @@ void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void * } i += retval; } else if (retval == -1){ - ba->passes[i] = pass; + if (a->key->pass != -1) + ba->passes[i] = pass; break; } } diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c index 3306283ad3f..b9ac6875b20 100644 --- a/source/blender/blenlib/intern/BLI_bfile.c +++ b/source/blender/blenlib/intern/BLI_bfile.c @@ -1,4 +1,5 @@ -/* +/* -*- indent-tabs-mode:t; tab-width:4; -*- + * * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,6 +34,7 @@ #else #include <io.h> #include "BLI_winstuff.h" + static char* find_in_pathlist(char* filename, char* pathlist); #endif #include <sys/types.h> #include <sys/stat.h> @@ -46,8 +48,6 @@ #include "BLI_storage.h" #include "BLI_bfile.h" -#include "GHOST_C-api.h" - /* Internal bfile classification flags */ #define BCF_OPEN (0) #define BCF_FOPEN (1<<0) @@ -62,17 +62,14 @@ /* Declaration of internal functions */ -void chomp(char* line); -void expand_envvars(char* src, char* dst); -void fill_paths(BFILE *bfile, const char *path); -char* find_in_pathlist(char* filename, char* pathlist); -void init_vars_from_file(const char* path); -void setup_temp(); +static void fill_paths(BFILE *bfile, const char *path, const char *relpath); +static void free_paths(BFILE* bfile); + /*** Exported functions ***/ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, - BEnvVarFam envvars) + const char *relpath) { BFILE *bfile; @@ -88,50 +85,85 @@ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, a BCF_AT_END | BCF_WRITE a+ BCF_AT_END | BCF_WRITE | BCF_READ */ - if(strchr(mode, 'r')) + if (strchr(mode, 'r')) bfile->classf |= BCF_READ; - if(strchr(mode, 'w')) + if (strchr(mode, 'w')) bfile->classf |= (BCF_DISCARD | BCF_WRITE); - if(strchr(mode, 'a')) + if (strchr(mode, 'a')) bfile->classf |= (BCF_AT_END | BCF_WRITE); - if(strchr(mode, '+')) + if (strchr(mode, '+')) bfile->classf |= (BCF_READ | BCF_WRITE); - fill_paths(bfile, path); + fill_paths(bfile, path, relpath); bfile->stream = fopen(bfile->tpath, mode); - // detect failed fopen + if (!(bfile->stream)) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + bfile->fd = fileno(bfile->stream); + return bfile; } BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags, - BEnvVarFam envvars) + const char *relpath) { BFILE *bfile; + char fopen_mode[3]; bfile = MEM_mallocN(sizeof(BFILE), "bfile-open"); bfile->classf = BCF_OPEN; bfile->uflags = bflags; /* Easy mapping for open() */ - if(flags & O_RDONLY) + if (flags & O_RDONLY) bfile->classf |= BCF_READ; - if(flags & O_WRONLY) + if (flags & O_WRONLY) bfile->classf |= BCF_WRITE; - if(flags & O_RDWR) + if (flags & O_RDWR) bfile->classf |= (BCF_READ | BCF_WRITE); - if(flags & O_APPEND) + if (flags & O_APPEND) bfile->classf |= BCF_AT_END; - if(flags & O_TRUNC) + if (flags & O_TRUNC) bfile->classf |= BCF_DISCARD; - fill_paths(bfile, pathname); + fill_paths(bfile, pathname, relpath); bfile->fd = open(bfile->tpath, flags); - // detect failed open -// bfile->stream = fdopen(bfile->fd, XXX); /* MSWindows _fdopen? */ + if (bfile->fd == -1) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + + fopen_mode[0] = 'r'; + fopen_mode[1] = '\0'; + fopen_mode[2] = '\0'; + if (bfile->classf & BCF_DISCARD) { + fopen_mode[0] = 'w'; + if (bfile->classf & BCF_READ) { + fopen_mode[1] = '+'; + } + } else if (bfile->classf & BCF_AT_END) { + fopen_mode[0] = 'a'; + if (bfile->classf & BCF_READ) { + fopen_mode[1] = '+'; + } + } else if (bfile->classf & BCF_WRITE) { + fopen_mode[1] = '+'; + } + + bfile->stream = fdopen(bfile->fd, fopen_mode); /* MSWindows _fdopen? */ + if (!(bfile->stream)) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + return bfile; } @@ -175,8 +207,11 @@ size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, { size_t ret; + if (f == NULL) + return 0; + ret = fwrite(ptr, size, nmemb, f->stream); - if (ret < 0) { + if (ret <= 0) { f->error = 1; } @@ -187,8 +222,11 @@ size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) { size_t ret; + if (f == NULL) + return 0; + ret = fread(ptr, size, nmemb, f->stream); - if ((ret < 0) && ferror(f->stream)) { + if ((ret <= 0) && ferror(f->stream)) { f->error = 1; } @@ -197,21 +235,23 @@ size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) { void BLI_bfile_close(BFILE *bfile) { - if((bfile->classf | BCF_WRITE) && - !(bfile->uflags | BFILE_RAW)) { + if ((bfile->classf | BCF_WRITE) && + !(bfile->uflags | BFILE_RAW)) { + int error; /* Make sure data is on disk */ + error = fsync(bfile->fd); + /* fsync the directory too? */ /* Move to final name if no errors */ + if (!(bfile->error) && !error) { + rename(bfile->tpath, bfile->fpath); + } } /* Normal close */ /* Cleanup */ - if(bfile->fpath) { - MEM_freeN(bfile->fpath); - } - if(bfile->tpath) { - MEM_freeN(bfile->tpath); - } + free_paths(bfile); + MEM_freeN(bfile); } @@ -228,197 +268,9 @@ void BLI_bfile_set_error(BFILE *bfile, int error) { } -void BLI_bfile_init_vars() { - char file[MAXPATHLEN]; - char temp[MAXPATHLEN]; - extern char bprogname[]; - FILE* fp; - - /* This one is unconditional */ - sprintf(temp, "%d", BLENDER_VERSION); - BLI_setenv("BLENDER_VERSION", temp); - - /* Is this unpack&run? */ - sprintf(temp, "%s/%d/environment", dirname(bprogname), BLENDER_VERSION); - if(BLI_exist(temp)) { - BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname)); - } else { - BLI_setenv_if_new("BLENDER_SHARE", (const char*)GHOST_getSystemDir()); - } - - strcpy(file, (const char*)GHOST_getUserDir()); - BLI_add_slash(file); - strcat(file, LAST_SESSION_FILE); - fp = fopen(file, "r"); - /* 1st line, read previous version */ - if (fp && (fscanf(fp, "%3c\n", temp) == 1)) { - temp[3] = '\0'; - BLI_setenv("BLENDER_VERSION_PREV", temp); - /* 2nd line, read previous session path if needed */ - if(!getenv("BLENDER_TEMP")) { - if ((fgets(temp, MAXPATHLEN, fp) != NULL)) { - /* Clean any \n */ - chomp(temp); - /* Check the dir is still there or generate new one */ - if(!BLI_exist(temp)) { - setup_temp(); - } - } else { - /* We have to generate it for sure */ - setup_temp(); - } - } - } else { - /* Probably new user, or only <=249 before */ - BLI_setenv("BLENDER_VERSION_PREV", "0"); - setup_temp(); - } - - if(fp) { - fclose(fp); - } - - /* Load vars from user and system files */ - strcpy(file, (const char *)GHOST_getUserDir()); - BLI_add_slash(file); - strcat(file, ENVIRONMENT_FILE); - init_vars_from_file(file); - sprintf(temp, "/%d/environment", BLENDER_VERSION); - BLI_make_file_string("/", file, getenv("BLENDER_SHARE"), temp); - init_vars_from_file(file); -} - - /*** Internal functions ***/ /** - Eliminate trailing EOL by writing a \0 over it. - Name taken from Perl. - */ -void chomp(char* line) { - int len = strlen(line); -#ifndef WIN32 - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } -#else - if ((line[len - 2] == '\r' ) && ((line[len - 1] == '\n'))) { - line[len - 2] = '\0'; - } -#endif /* WIN32 */ -} - - -/** - Parse a file with lines like FOO=bar (comment lines have # as first - character) assigning to envvar FOO the value bar if FOO does not - exist yet. - Any white space before FOO, around the = or trailing will be used, - so beware. - */ -#define MAX_LINE 4096 -#define ENV_VAR 256 -#define VAR_LEN 8192 -void init_vars_from_file(const char* path) { - char line[MAX_LINE]; - char name[ENV_VAR]; - FILE *fp; - char* separator; - char expanded[VAR_LEN]; - - fp = fopen(path, "r"); - if (!fp) return; - - while (fgets(line, MAX_LINE, fp) != NULL) { - /* Ignore comment lines */ - if (line[0] == '#') - continue; - - /* Split into envvar name and contents */ - separator = strchr(line, '='); - if(separator && ((separator - line) < ENV_VAR)) { - /* First remove EOL */ - chomp(line); - strncpy(name, line, separator - line); - name[separator - line] = '\0'; - expand_envvars(separator + 1, expanded); - BLI_setenv_if_new(name, expanded); - } - } - fclose(fp); -} - - -/** - Look for ${} (or %%) env vars in src and expand if the var - exists (even if empty value). If not exist, the name is left as is. - The process is done all over src, and nested ${${}} is not supported. - src must be \0 terminated, and dst must be big enough. -*/ -#ifndef WIN32 - #define ENVVAR_PREFFIX "${" - #define ENVVAR_P_SIZE 2 - #define ENVVAR_SUFFIX "}" - #define ENVVAR_S_SIZE 1 -#else - #define ENVVAR_PREFFIX "%" - #define ENVVAR_P_SIZE 1 - #define ENVVAR_SUFFIX "%" - #define ENVVAR_S_SIZE 1 -#endif /* WIN32 */ -void expand_envvars(char* src, char* dst) { - char* hit1; - char* hit2; - char name[ENV_VAR]; - char* value; - int prevlen; - int done = 0; - char* source = src; - - dst[0] = '\0'; - while (!done) { - hit1 = strstr(source, ENVVAR_PREFFIX); - if (hit1) { - hit2 = strstr(hit1 + ENVVAR_P_SIZE, ENVVAR_SUFFIX); - if (hit2) { - /* "Copy" the leading part, if any */ - if (hit1 != source) { - prevlen = strlen(dst); - strncat(dst, source, hit1 - source); - dst[prevlen + (hit1 - source)] = '\0'; - } - /* Figure the name of the env var we just found */ - strncpy(name, hit1 + ENVVAR_P_SIZE, - hit2 - (hit1 + ENVVAR_P_SIZE)); - name[hit2 - (hit1 + ENVVAR_P_SIZE)] = '\0'; - /* See if we can get something with that name */ - value = getenv(name); - if (value) { - /* Push the var value */ - strcat(dst, value); - } else { - /* Leave the var name, so it is clear that it failed */ - strcat(dst, ENVVAR_PREFFIX); - strcat(dst, name); - strcat(dst, ENVVAR_SUFFIX); - } - /* Continue after closing mark, like a new string */ - source = hit2 + ENVVAR_S_SIZE; - } else { - /* Non terminated var so "copy as is" and finish */ - strcat(dst, source); - done = 1; - } - } else { - /* "Copy" whatever is left */ - strcat(dst, source); - done = 1; - } - } -} - - -/** Return a full path if the filename exists when combined with any item from pathlist. Or NULL otherwise. */ @@ -427,7 +279,9 @@ void expand_envvars(char* src, char* dst) { #else #define SEPARATOR ':' #endif -char* find_in_pathlist(char* filename, char* pathlist) { + +#ifdef WIN32 +static char* find_in_pathlist(char* filename, char* pathlist) { char first[FILE_MAX + 10]; char* rest = NULL; @@ -445,51 +299,58 @@ char* find_in_pathlist(char* filename, char* pathlist) { /* Check if combination exists */ BLI_add_slash(first); strcat(first, filename); - if(BLI_exist(first)) { + if (BLI_exist(first)) { return strdup(first); } /* First path failed, try with rest of paths if possible */ - if(rest) { + if (rest) { return find_in_pathlist(filename, rest); } else { return NULL; } } - +#endif /** Setup fpath and tpath based in the needs of the bfile. */ -void fill_paths(BFILE *bfile, const char *path) { +static void fill_paths(BFILE *bfile, const char *path, const char *relpath) { char* source_path = NULL; char* temp_path = NULL; int bflags = bfile->uflags; - if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) { + if (bflags & BFILE_NORMAL || bflags & BFILE_RAW) { // bfile->fpath is path with // replaced } - if(bflags & BFILE_TEMP) { + if (bflags & BFILE_TEMP) { temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-1"); snprintf(temp_path, MAXPATHLEN, "%s/%s", getenv("BLENDER_TEMP"), path); bfile->fpath = temp_path; } - if(bflags & BFILE_CONFIG) { + if (bflags & (BFILE_CONFIG_BASE | BFILE_CONFIG_DATAFILES | + BFILE_CONFIG_PYTHON | BFILE_CONFIG_PLUGINS)) { +// evars // bfile->fpath is userdir+version+path // source_path is first hit in (if using fallback to older versions) // userdir+curversion+path (... userdir+limitversion+path) sysdir+path // (limitversion is based in path, using some kind of regex or "tables") } - if(bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) { - /* Generate temp path */ + if (bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) { + /* Generate random named path */ temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-2"); snprintf(temp_path, MAXPATHLEN, "%s.XXXXXX", path); - bfile->tpath = mkdtemp(temp_path); - if(!(bfile->classf & BCF_DISCARD)) { - /* Copy data to tpath */ - if(source_path) { - // copy it from older version or sys version + bfile->fd = mkstemp(temp_path); + bfile->tpath = temp_path; + /* It will be reopened in upper levels, later */ + close(bfile->fd); + if (!(bfile->classf & BCF_DISCARD)) { + /* Copy original data into temp location */ + if (source_path) { + BLI_copy_fileops(source_path, bfile->tpath); + } else { + BLI_copy_fileops(bfile->fpath, bfile->tpath); } } } else { @@ -499,19 +360,13 @@ void fill_paths(BFILE *bfile, const char *path) { /** - Create a temp directory in safe and multiuser way. + Free memory used for path strings. */ -void setup_temp() { - char template[MAXPATHLEN]; - char* tempdir; - - if(getenv("TMPDIR")) { - sprintf(template, "%s/blender-XXXXXX", getenv("TMPDIR")); - } else { - sprintf(template, "/tmp/blender-XXXXXX"); -// MacOSX NSTemporaryDirectory and WIN32 ??? +static void free_paths(BFILE* bfile) { + if (bfile->fpath) { + MEM_freeN(bfile->fpath); + } + if (bfile->tpath) { + MEM_freeN(bfile->tpath); } - tempdir = mkdtemp(template); - BLI_setenv("BLENDER_TEMP", tempdir); } - diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c index 4b7b61e64d9..5b61a86305b 100644 --- a/source/blender/blenlib/intern/BLI_dynstr.c +++ b/source/blender/blenlib/intern/BLI_dynstr.c @@ -29,8 +29,6 @@ */ #include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 6ef8d9e5f19..456872d6612 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -28,21 +28,10 @@ * A general (pointer -> pointer) hash table ADT */ -#include <stdlib.h> -#include <string.h> -#include "MEM_guardedalloc.h" #include "BLI_ghash.h" -#include "BLI_mempool.h" - #include "BLO_sys_types.h" // for intptr_t support -#include "BKE_utildefines.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - /***/ unsigned int hashsizes[]= { @@ -56,8 +45,8 @@ unsigned int hashsizes[]= { /***/ -GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) { - GHash *gh= MEM_mallocN(sizeof(*gh), "GHash"); +GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) { + GHash *gh= MEM_mallocN(sizeof(*gh), info); gh->hashfp= hashfp; gh->cmpfp= cmpfp; gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, 1, 0); @@ -145,7 +134,7 @@ void *BLI_ghashIterator_getValue(GHashIterator *ghi) { void BLI_ghashIterator_step(GHashIterator *ghi) { if (ghi->curEntry) { - ghi->curEntry= ghi->curEntry->next; + ghi->curEntry= ghi->curEntry->next; while (!ghi->curEntry) { ghi->curBucket++; if (ghi->curBucket==ghi->gh->nbuckets) @@ -180,7 +169,7 @@ unsigned int BLI_ghashutil_inthash(void *ptr) { key += ~(key << 9); key ^= (key >> 17); - return (unsigned int)(key & 0xffffffff); + return (unsigned int)(key & 0xffffffff); } int BLI_ghashutil_intcmp(void *a, void *b) { diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 196c9ed284c..f6616ecb06b 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -28,7 +28,6 @@ * A heap / priority queue ADT. */ -#include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" @@ -70,7 +69,7 @@ Heap *BLI_heap_new() Heap *heap = (Heap*)MEM_callocN(sizeof(Heap), "BLIHeap"); heap->bufsize = 1; heap->tree = (HeapNode**)MEM_mallocN(sizeof(HeapNode*), "BLIHeapTree"); - heap->arena = BLI_memarena_new(1<<16); + heap->arena = BLI_memarena_new(1<<16, "heap arena"); return heap; } diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7118b804cad..4d64f4a50ff 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "math.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include <assert.h> #include "MEM_guardedalloc.h" @@ -1494,7 +1490,7 @@ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *nod dist = t1x; if (t1y > dist) dist = t1y; - if (t1z > dist) dist = t1z; + if (t1z > dist) dist = t1z; return dist; } @@ -1617,7 +1613,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float { dfs_raycast(&data, root); // iterative_raycast(&data, root); - } + } if(hit) diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index 38b4d7a54d2..cf94a0c9ffe 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -28,9 +28,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include <stdlib.h> -#include <string.h> -#include <math.h> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index 4631d9e6bf2..c903e66057e 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -29,14 +29,9 @@ */ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_memarena.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - int BLI_linklist_length(LinkNode *list) { if (0) { return list?(1+BLI_linklist_length(list->next)):0; @@ -50,18 +45,28 @@ int BLI_linklist_length(LinkNode *list) { } } -int BLI_linklist_index(struct LinkNode *list, void *ptr) +int BLI_linklist_index(LinkNode *list, void *ptr) { int index; - for (index = 0; list; list= list->next, index++) { + for (index = 0; list; list= list->next, index++) if (list->link == ptr) return index; - } return -1; } +LinkNode *BLI_linklist_find(LinkNode *list, int index) +{ + int i; + + for (i = 0; list; list= list->next, i++) + if (i == index) + return list; + + return NULL; +} + void BLI_linklist_reverse(LinkNode **listp) { LinkNode *rhead= NULL, *cur= *listp; @@ -93,13 +98,13 @@ void BLI_linklist_append(LinkNode **listp, void *ptr) { nlink->next = NULL; if(node == NULL){ - *listp = nlink; - } else { - while(node->next != NULL){ - node = node->next; - } - node->next = nlink; - } + *listp = nlink; + } else { + while(node->next != NULL){ + node = node->next; + } + node->next = nlink; + } } void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) { @@ -110,6 +115,22 @@ void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) { *listp= nlink; } +void BLI_linklist_insert_after(LinkNode **listp, void *ptr) { + LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink"); + 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; diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 6c87f0914f9..de2a73e065f 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -28,21 +28,16 @@ * Efficient memory allocation for lots of similar small chunks. */ -#include <stdlib.h> #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_memarena.h" #include "BLI_linklist.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - struct MemArena { unsigned char *curbuf; int bufsize, cursize; + const char *name; int use_calloc; int align; @@ -50,10 +45,11 @@ struct MemArena { LinkNode *bufs; }; -MemArena *BLI_memarena_new(int bufsize) { +MemArena *BLI_memarena_new(int bufsize, const char *name) { MemArena *ma= MEM_callocN(sizeof(*ma), "memarena"); ma->bufsize= bufsize; ma->align = 8; + ma->name= name; return ma; } @@ -96,9 +92,9 @@ void *BLI_memarena_alloc(MemArena *ma, int size) { else ma->cursize = ma->bufsize; if(ma->use_calloc) - ma->curbuf= MEM_callocN(ma->cursize, "memarena calloc"); + ma->curbuf= MEM_callocN(ma->cursize, ma->name); else - ma->curbuf= MEM_mallocN(ma->cursize, "memarena malloc"); + ma->curbuf= MEM_mallocN(ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index eebffd6bd6e..1c910dbb519 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -240,17 +240,17 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) if (vert->free & quad_flags[j]) { switch (j) { case BL: - SET_BOXRIGHT(box, vert->x); - SET_BOXTOP(box, vert->y); - break; + SET_BOXRIGHT(box, vert->x); + SET_BOXTOP(box, vert->y); + break; case TR: - SET_BOXLEFT(box, vert->x); - SET_BOXBOTTOM(box, vert->y); - break; + SET_BOXLEFT(box, vert->x); + SET_BOXBOTTOM(box, vert->y); + break; case TL: - SET_BOXRIGHT(box, vert->x); - SET_BOXBOTTOM(box, vert->y); - break; + SET_BOXRIGHT(box, vert->x); + SET_BOXBOTTOM(box, vert->y); + break; case BR: SET_BOXLEFT(box, vert->x); SET_BOXTOP(box, vert->y); @@ -302,11 +302,11 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) case TR: box->v[BL]= vert; vert->trb = box; - break; + break; case TL: box->v[BR]= vert; vert->tlb = box; - break; + break; case BR: box->v[TL]= vert; vert->brb = box; @@ -314,7 +314,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) case BL: box->v[TR]= vert; vert->blb = box; - break; + break; } /* Mask free flags for verts that are diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 8d3d807ba1b..fbe71019379 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -27,12 +27,7 @@ */ #include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> #include <string.h> /* path/file handeling stuff */ @@ -46,13 +41,9 @@ #include "MEM_guardedalloc.h" -#include "DNA_ID.h" /* Library */ -#include "DNA_customdata_types.h" -#include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" /* to get the current frame */ #include "DNA_sequence_types.h" -#include "DNA_sound_types.h" #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" @@ -71,9 +62,6 @@ /* for sequence */ //XXX #include "BSE_sequence.h" //XXX define below from BSE_sequence.h - otherwise potentially odd behaviour -#define SEQ_HAS_PATH(seq) (seq->type==SEQ_MOVIE || seq->type==SEQ_IMAGE) - - #define FILE_MAX 240 @@ -86,7 +74,7 @@ enum BPathTypes { BPATH_SEQ, BPATH_CDATA, - BPATH_DONE + BPATH_DONE }; void BLI_bpathIterator_init( struct BPathIterator *bpi, char *base_path ) { @@ -137,10 +125,11 @@ void BLI_bpathIterator_getPathExpanded( struct BPathIterator *bpi, char *path_ex libpath = BLI_bpathIterator_getLib(bpi); if (libpath) { /* check the files location relative to its library path */ - BLI_convertstringcode(path_expanded, libpath); + BLI_path_abs(path_expanded, libpath); } else { /* local data, use the blend files path */ - BLI_convertstringcode(path_expanded, bpi->base_path); + BLI_path_abs(path_expanded, bpi->base_path); } + BLI_cleanup_file(NULL, path_expanded); } char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) { return bpi->lib; @@ -270,7 +259,7 @@ static void seq_getpath(struct BPathIterator *bpi, char *path) { path[0] = '\0'; /* incase we cant get the path */ if (seq==NULL) return; if (SEQ_HAS_PATH(seq)) { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { + if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) { BLI_strncpy(path, seq->strip->dir, FILE_MAX); BLI_add_slash(path); /* incase its missing */ if (seq->strip->stripdata) { /* should always be true! */ @@ -289,8 +278,8 @@ static void seq_setpath(struct BPathIterator *bpi, char *path) { if (seq==NULL) return; if (SEQ_HAS_PATH(seq)) { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { - BLI_split_dirfile_basic(path, seq->strip->dir, seq->strip->stripdata->name); + if (ELEM3(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SOUND)) { + BLI_split_dirfile(path, seq->strip->dir, seq->strip->stripdata->name); } else { /* simple case */ BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir)); @@ -343,7 +332,7 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { /* get the path info from this datatype */ Image *ima = (Image *)bpi->data; - bpi->lib = ima->id.lib ? ima->id.lib->filename : NULL; + bpi->lib = ima->id.lib ? ima->id.lib->filepath : NULL; bpi->path = ima->name; bpi->name = ima->id.name+2; bpi->len = sizeof(ima->name); @@ -364,7 +353,7 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { /* get the path info from this datatype */ bSound *snd = (bSound *)bpi->data; - bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL; + bpi->lib = snd->id.lib ? snd->id.lib->filepath : NULL; bpi->path = snd->name; bpi->name = snd->id.name+2; bpi->len = sizeof(snd->name); @@ -385,7 +374,7 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { /* get the path info from this datatype */ VFont *vf = (VFont *)bpi->data; - bpi->lib = vf->id.lib ? vf->id.lib->filename : NULL; + bpi->lib = vf->id.lib ? vf->id.lib->filepath : NULL; bpi->path = vf->name; bpi->name = vf->id.name+2; bpi->len = sizeof(vf->name); @@ -432,7 +421,7 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { if (bpi->data) { Mesh *me = (Mesh *)bpi->data; - bpi->lib = me->id.lib ? me->id.lib->filename : NULL; + bpi->lib = me->id.lib ? me->id.lib->filepath : NULL; bpi->path = me->fdata.external->filename; bpi->name = me->id.name+2; bpi->len = sizeof(me->fdata.external->filename); @@ -533,7 +522,7 @@ void makeFilesRelative(char *basepath, ReportList *reports) { /* Important BLI_cleanup_dir runs before the path is made relative * because it wont work for paths that start with "//../" */ BLI_cleanup_file(bpi.base_path, filepath_relative); /* fix any /foo/../foo/ */ - BLI_makestringcode(bpi.base_path, filepath_relative); + BLI_path_rel(filepath_relative, bpi.base_path); /* be safe and check the length */ if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) { bpath_as_report(&bpi, "couldn't make path relative (too long)", reports); @@ -631,7 +620,7 @@ static int findFileRecursive(char *filename_new, const char *dirname, const char while ((de = readdir(dir)) != NULL) { - if (strncmp(".", de->d_name, 2)==0 || strncmp("..", de->d_name, 3)==0) + if (strcmp(".", de->d_name)==0 || strcmp("..", de->d_name)==0) continue; BLI_join_dirfile(path, dirname, de->d_name); @@ -669,11 +658,11 @@ void findMissingFiles(char *basepath, char *str) { char filepath[FILE_MAX], *libpath; int filesize, recur_depth; - char dirname[FILE_MAX], filename[FILE_MAX], filename_new[FILE_MAX]; + char dirname[FILE_MAX], filename_new[FILE_MAX]; //XXX waitcursor( 1 ); - BLI_split_dirfile_basic(str, dirname, NULL); + BLI_split_dirfile(str, dirname, NULL); BLI_bpathIterator_init(&bpi, basepath); @@ -694,9 +683,8 @@ void findMissingFiles(char *basepath, char *str) { /* can the dir be opened? */ filesize = -1; recur_depth = 0; - BLI_split_dirfile_basic(filepath, NULL, filename); /* the file to find */ - findFileRecursive(filename_new, dirname, filename, &filesize, &recur_depth); + findFileRecursive(filename_new, dirname, BLI_path_basename(filepath), &filesize, &recur_depth); if (filesize == -1) { /* could not open dir */ printf("Could not open dir \"%s\"\n", dirname); return; @@ -709,7 +697,7 @@ void findMissingFiles(char *basepath, char *str) { } else { /* copy the found path into the old one */ if (G.relbase_valid) - BLI_makestringcode(bpi.base_path, filename_new); + BLI_path_rel(filename_new, bpi.base_path); BLI_bpathIterator_setPath( &bpi, filename_new ); } diff --git a/source/blender/blenlib/intern/cpu.c b/source/blender/blenlib/intern/cpu.c new file mode 100644 index 00000000000..65e6b34488c --- /dev/null +++ b/source/blender/blenlib/intern/cpu.c @@ -0,0 +1,57 @@ +/** + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "BLI_cpu.h" + +int BLI_cpu_support_sse2(void) +{ +#if defined(__x86_64__) || defined(_M_X64) + /* 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; +#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; +#endif + + return 0; +} + diff --git a/source/blender/blenlib/intern/dynamiclist.c b/source/blender/blenlib/intern/dynamiclist.c deleted file mode 100644 index 4bcccab4b18..00000000000 --- a/source/blender/blenlib/intern/dynamiclist.c +++ /dev/null @@ -1,265 +0,0 @@ -/* util.c - * - * various string, file, list operations. - * - * - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" - -#include "BLI_listbase.h" -#include "BLI_dynamiclist.h" - -#define PAGE_SIZE 4 - -/*=====================================================================================*/ -/* Methods for access array (realloc) */ -/*=====================================================================================*/ - -/* remove item with index */ -static void rem_array_item(struct DynamicArray *da, unsigned int index) -{ - da->items[index]=NULL; - da->count--; - if(index==da->last_item_index){ - while((!da->items[da->last_item_index]) && (da->last_item_index>0)){ - da->last_item_index--; - } - } -} - -/* add array (if needed, then realloc) */ -static void add_array_item(struct DynamicArray *da, void *item, unsigned int index) -{ - /* realloc of access array */ - if(da->max_item_index < index){ - unsigned int i, max = da->max_item_index; - void **nitems; - - do { - da->max_item_index += PAGE_SIZE; /* OS can allocate only PAGE_SIZE Bytes */ - } while(da->max_item_index<=index); - - nitems = (void**)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array"); - for(i=0;i<=max;i++) - nitems[i] = da->items[i]; - - /* set rest pointers to the NULL */ - for(i=max+1; i<=da->max_item_index; i++) - nitems[i]=NULL; - - MEM_freeN(da->items); /* free old access array */ - da->items = nitems; - } - - da->items[index] = item; - da->count++; - if(index > da->last_item_index) da->last_item_index = index; -} - -/* free access array */ -static void destroy_array(DynamicArray *da) -{ - da->count=0; - da->last_item_index=0; - da->max_item_index=0; - MEM_freeN(da->items); - da->items = NULL; -} - -/* initialize dynamic array */ -static void init_array(DynamicArray *da) -{ - unsigned int i; - - da->count=0; - da->last_item_index=0; - da->max_item_index = PAGE_SIZE-1; - da->items = (void*)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array"); - for(i=0; i<=da->max_item_index; i++) da->items[i]=NULL; -} - -/* reinitialize dynamic array */ -static void reinit_array(DynamicArray *da) -{ - destroy_array(da); - init_array(da); -} - -/*=====================================================================================*/ -/* Methods for two way dynamic list with access array */ -/*=====================================================================================*/ - -/* create new two way dynamic list with access array from two way dynamic list - * it doesn't copy any items to new array or something like this It is strongly - * recomended to use BLI_dlist_ methods for adding/removing items from dynamic list - * unless you can end with inconsistence system !!! */ -DynamicList *BLI_dlist_from_listbase(ListBase *lb) -{ - DynamicList *dlist; - Link *item; - int i=0, count; - - if(!lb) return NULL; - - count = BLI_countlist(lb); - - dlist = MEM_mallocN(sizeof(DynamicList), "temp dynamic list"); - /* ListBase stuff */ - dlist->lb.first = lb->first; - dlist->lb.last = lb->last; - /* access array stuff */ - dlist->da.count=count; - dlist->da.max_item_index = count-1; - dlist->da.last_item_index = count -1; - dlist->da.items = (void*)MEM_mallocN(sizeof(void*)*count, "temp dlist access array"); - - item = (Link*)lb->first; - while(item){ - dlist->da.items[i] = (void*)item; - item = item->next; - i++; - } - - /* to prevent you of using original ListBase :-) */ - lb->first = lb->last = NULL; - - return dlist; -} - -/* take out ListBase from DynamicList and destroy all temporary structures of DynamicList */ -ListBase *BLI_listbase_from_dlist(DynamicList *dlist, ListBase *lb) -{ - if(!dlist) return NULL; - - if(!lb) lb = (ListBase*)MEM_mallocN(sizeof(ListBase), "ListBase"); - - lb->first = dlist->lb.first; - lb->last = dlist->lb.last; - - /* free all items of access array */ - MEM_freeN(dlist->da.items); - /* free DynamicList*/ - MEM_freeN(dlist); - - return lb; -} - -/* return pointer at item from th dynamic list with access array */ -void *BLI_dlist_find_link(DynamicList *dlist, unsigned int index) -{ - if(!dlist || !dlist->da.items) return NULL; - - if((index <= dlist->da.last_item_index) && (index >= 0) && (dlist->da.count>0)){ - return dlist->da.items[index]; - } - else { - return NULL; - } -} - -/* return count of items in the dynamic list with access array */ -unsigned int BLI_count_items(DynamicList *dlist) -{ - if(!dlist) return 0; - - return dlist->da.count; -} - -/* free item from the dynamic list with access array */ -void BLI_dlist_free_item(DynamicList *dlist, unsigned int index) -{ - if(!dlist || !dlist->da.items) return; - - if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){ - BLI_freelinkN(&(dlist->lb), dlist->da.items[index]); - rem_array_item(&(dlist->da), index); - } -} - -/* remove item from the dynamic list with access array */ -void BLI_dlist_rem_item(DynamicList *dlist, unsigned int index) -{ - if(!dlist || !dlist->da.items) return; - - if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){ - BLI_remlink(&(dlist->lb), dlist->da.items[index]); - rem_array_item(&(dlist->da), index); - } -} - -/* add item to the dynamic list with access array (index) */ -void* BLI_dlist_add_item_index(DynamicList *dlist, void *item, unsigned int index) -{ - if(!dlist || !dlist->da.items) return NULL; - - if((index <= dlist->da.max_item_index) && (dlist->da.items[index])) { - /* you can't place item at used index */ - return NULL; - } - else { - add_array_item(&(dlist->da), item, index); - BLI_addtail(&(dlist->lb), item); - return item; - } -} - -/* destroy dynamic list with access array */ -void BLI_dlist_destroy(DynamicList *dlist) -{ - if(!dlist) return; - - BLI_freelistN(&(dlist->lb)); - destroy_array(&(dlist->da)); -} - -/* initialize dynamic list with access array */ -void BLI_dlist_init(DynamicList *dlist) -{ - if(!dlist) return; - - dlist->lb.first = NULL; - dlist->lb.last = NULL; - - init_array(&(dlist->da)); -} - -/* reinitialize dynamic list with acces array */ -void BLI_dlist_reinit(DynamicList *dlist) -{ - if(!dlist) return; - - BLI_freelistN(&(dlist->lb)); - reinit_array(&(dlist->da)); -} - -/*=====================================================================================*/ diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c index eb41916c619..f42b342e326 100644 --- a/source/blender/blenlib/intern/dynlib.c +++ b/source/blender/blenlib/intern/dynlib.c @@ -28,15 +28,9 @@ */ #include <stdlib.h> -#include <string.h> -#include <stdio.h> #include "../PIL_dynlib.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #if !defined(CHAR_MAX) #define CHAR_MAX 255 #endif @@ -47,6 +41,8 @@ */ #ifdef WIN32 +#include <string.h> +#include <stdio.h> #include <windows.h> diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 1f70a34329f..44abd13c3fd 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -125,7 +125,7 @@ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) { void BLI_edgehashIterator_step(EdgeHashIterator *ehi) { if (ehi->curEntry) { - ehi->curEntry= ehi->curEntry->next; + ehi->curEntry= ehi->curEntry->next; while (!ehi->curEntry) { ehi->curBucket++; if (ehi->curBucket==ehi->eh->nbuckets) diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 3503164ea56..7a24d9b36b1 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -29,7 +29,6 @@ #include <string.h> #include <stdio.h> -#include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> @@ -49,9 +48,6 @@ #include "BLI_blenlib.h" -#include "BLI_storage.h" -#include "BLI_fileops.h" -#include "BLI_callbacks.h" #include "BKE_utildefines.h" @@ -84,31 +80,6 @@ char *BLI_last_slash(const char *string) { else return lfslash; } -static const char *last_slash_len(const char *string, int len) { - int a; - - for(a=len-1; a>=0; a--) - if(string[a] == '/' || string[a] == '\\') - return &string[a]; - - return NULL; -} - -const char *BLI_short_filename(const char *string) { - const char *ls, *lls; - - ls= last_slash_len(string, strlen(string)); - if(!ls) - return string; - - lls= last_slash_len(string, ls-string); - - if(lls) - return lls+1; - else - return ls+1; -} - /* adds a slash if there isnt one there alredy */ int BLI_add_slash(char *string) { int len = strlen(string); @@ -234,6 +205,10 @@ int BLI_touch(const char *file) return 0; } +int BLI_exists(char *file) { + return BLI_exist(file); +} + #ifdef WIN32 static char str[MAXPATHLEN+12]; @@ -311,10 +286,6 @@ int BLI_link(char *file, char *to) { return 1; } -int BLI_exists(char *file) { - return (GetFileAttributes(file) != 0xFFFFFFFF); -} - void BLI_recurdir_fileops(char *dirname) { char *lslash; char tmp[MAXPATHLEN]; @@ -355,10 +326,10 @@ int BLI_rename(char *from, char *to) { return rename(from, to); } -#else /* The sane UNIX world */ +#else /* The weirdo UNIX world */ /* - * but the sane UNIX world is tied to the interface, and the system + * but the UNIX world is tied to the interface, and the system * timer, and... We implement a callback mechanism. The system will * have to initialise the callback before the functions will work! * */ @@ -403,10 +374,6 @@ int BLI_link(char *file, char *to) { return system(str); } -int BLI_exists(char *file) { - return BLI_exist(file); -} - void BLI_recurdir_fileops(char *dirname) { char *lslash; char tmp[MAXPATHLEN]; diff --git a/source/blender/blenlib/intern/fnmatch.c b/source/blender/blenlib/intern/fnmatch.c index ccb6fa72ea8..c44ee754110 100644 --- a/source/blender/blenlib/intern/fnmatch.c +++ b/source/blender/blenlib/intern/fnmatch.c @@ -16,10 +16,6 @@ #ifdef WIN32 -#if HAVE_CONFIG_H -# include <config.h> -#endif - /* Enable GNU extensions in fnmatch.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 @@ -66,97 +62,97 @@ 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); + { + c = FOLD (c); - switch (c) + switch (c) { case '?': if (*n == '\0') - return FNM_NOMATCH; + return FNM_NOMATCH; else if ((flags & FNM_FILE_NAME) && *n == '/') - return FNM_NOMATCH; + return FNM_NOMATCH; else if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; + return FNM_NOMATCH; break; case '\\': if (!(flags & FNM_NOESCAPE)) - { - c = *p++; - if (c == '\0') + { + c = *p++; + if (c == '\0') /* Trailing \ loses. */ return FNM_NOMATCH; - c = FOLD (c); - } + c = FOLD (c); + } if (FOLD (*n) != c) - return FNM_NOMATCH; + return FNM_NOMATCH; break; case '*': if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) - { - if ((flags & FNM_FILE_NAME) && *n == '/') + { + if ((flags & FNM_FILE_NAME) && *n == '/') /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; - else if (c == '?') + else if (c == '?') { /* A ? needs to match one character. */ if (*n == '\0') - /* There isn't another character; no match. */ - return FNM_NOMATCH; + /* 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; + /* 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; + return 0; { - char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - c1 = FOLD (c1); - for (--p; *n != '\0'; ++n) - if ((c == '[' || FOLD (*n) == c1) && + 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; + return FNM_NOMATCH; } case '[': { - /* Nonzero if the sense of the character class is inverted. */ - register int not; + /* Nonzero if the sense of the character class is inverted. */ + register int not; - if (*n == '\0') - return FNM_NOMATCH; + if (*n == '\0') + return FNM_NOMATCH; - if ((flags & FNM_PERIOD) && *n == '.' && + if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) - return FNM_NOMATCH; + return FNM_NOMATCH; - not = (*p == '!' || *p == '^'); - if (not) - ++p; + not = (*p == '!' || *p == '^'); + if (not) + ++p; - c = *p++; - for (;;) - { + c = *p++; + for (;;) + { register char cstart = c, cend = c; if (!(flags & FNM_NOESCAPE) && c == '\\') { - if (*p == '\0') - return FNM_NOMATCH; - cstart = cend = *p++; + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; } cstart = cend = FOLD (cstart); @@ -174,14 +170,14 @@ fnmatch (const char *pattern, const char *string, int flags) if (c == '-' && *p != ']') { - cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return FNM_NOMATCH; - cend = FOLD (cend); - - 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) @@ -189,15 +185,15 @@ fnmatch (const char *pattern, const char *string, int flags) if (c == ']') break; - } - if (!not) - return FNM_NOMATCH; - break; + } + if (!not) + return FNM_NOMATCH; + break; matched:; - /* Skip the rest of the [...] that already matched. */ - while (c != ']') - { + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { if (c == '\0') /* [... (unterminated) loses. */ return FNM_NOMATCH; @@ -205,31 +201,31 @@ fnmatch (const char *pattern, const char *string, int flags) c = *p++; if (!(flags & FNM_NOESCAPE) && c == '\\') { - if (*p == '\0') - return FNM_NOMATCH; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } } - } - if (not) - return FNM_NOMATCH; + if (not) + return FNM_NOMATCH; } break; default: if (c != FOLD (*n)) - return FNM_NOMATCH; + return FNM_NOMATCH; } - ++n; - } + ++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 b08631b9317..6d6abc88999 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -36,10 +36,11 @@ #include <ft2build.h> #include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_BBOX_H -#include FT_SIZES_H -#include <freetype/ttnameid.h> +/* not needed yet */ +// #include FT_GLYPH_H +// #include FT_BBOX_H +// #include FT_SIZES_H +// #include <freetype/ttnameid.h> #include "MEM_guardedalloc.h" @@ -49,7 +50,6 @@ //XXX #include "BIF_toolbox.h" -#include "BKE_global.h" #include "BKE_font.h" #include "BKE_utildefines.h" @@ -150,7 +150,7 @@ static void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vf nu->pntsu = onpoints[j]; nu->resolu= 8; nu->flag= CU_2D; - nu->flagu= CU_CYCLIC; + nu->flagu= CU_NURB_CYCLIC; nu->bezt = bezt; //individual curve loop, start-end @@ -429,7 +429,7 @@ static int check_freetypefont(PackedFile * pf) &face ); if(err) { success = 0; - //XXX error("This is not a valid font"); + //XXX error("This is not a valid font"); } else { /* @@ -522,14 +522,14 @@ int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) typedef struct FT_Outline_ { - short n_contours; /* number of contours in glyph */ - short n_points; /* number of points in the glyph */ + short n_contours; /* number of contours in glyph */ + short n_points; /* number of points in the glyph */ - FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ - short* contours; /* the contour end points */ + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + short* contours; /* the contour end points */ - int flags; /* outline masks */ + int flags; /* outline masks */ } FT_Outline; @@ -569,44 +569,44 @@ The following rules are applied to decompose the contour's points into segments Note that it is possible to mix conic and cubic arcs in a single contour, even though no current font driver produces such outlines. - * # on - * off - __---__ + * # on + * off + __---__ #-__ _-- -_ - --__ _- - - --__ # \ - --__ # - -# - Two "on" points + --__ _- - + --__ # \ + --__ # + -# + Two "on" points Two "on" points and one "conic" point - between them + between them - * + * # __ Two "on" points with two "conic" \ - - points between them. The point - \ / \ marked '0' is the middle of the - - 0 \ "off" points, and is a 'virtual' - -_ _- # "on" point where the curve passes. - -- It does not appear in the point - list. - * + \ / \ marked '0' is the middle of the + - 0 \ "off" points, and is a 'virtual' + -_ _- # "on" point where the curve passes. + -- It does not appear in the point + list. + * - * # on - * * off - __---__ - _-- -_ - _- - + * # on + * * off + __---__ + _-- -_ + _- - # \ - # + # - Two "on" points + Two "on" points and two "cubic" point - between them + between them Each glyph's original outline points are located on a grid of indivisible units. The points are stored diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index dd708b27019..b1ea058eda1 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -1,5 +1,5 @@ /** - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -529,7 +529,7 @@ void BLI_mirrorAlongAxis(float v[3], float center[3], float axis[3]) sub_v3_v3v3(dv, v, center); project_v3_v3v3(pv, dv, axis); mul_v3_fl(pv, -2); - add_v3_v3v3(v, v, pv); + add_v3_v3(v, pv); } static void testRadialSymmetry(BGraph *graph, BNode* root_node, RadialArc* ring, int total, float axis[3], float limit, int group) @@ -801,7 +801,7 @@ static void testAxialSymmetry(BGraph *graph, BNode* root_node, BNode* node1, BNo sub_v3_v3v3(p, root_node->p, node2->p); cross_v3_v3v3(vec, p, axis); - add_v3_v3v3(vec, vec, nor); + add_v3_v3(vec, nor); cross_v3_v3v3(nor, vec, axis); @@ -905,7 +905,7 @@ static void markdownSecondarySymmetry(BGraph *graph, BNode *node, int depth, int /* If arc is on the axis */ else if (connectedArc->symmetry_level == level) { - add_v3_v3v3(axis, axis, connectedArc->head->p); + add_v3_v3(axis, connectedArc->head->p); sub_v3_v3v3(axis, axis, connectedArc->tail->p); } } diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index fbc1708c133..a8b40e187d8 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -31,10 +31,6 @@ #include "MEM_guardedalloc.h" #include "BLI_gsqueue.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - typedef struct _GSQueueElem GSQueueElem; struct _GSQueueElem { GSQueueElem *next; diff --git a/source/blender/blenlib/intern/jitter.c b/source/blender/blenlib/intern/jitter.c index 12b7482897a..dfc554394d6 100644 --- a/source/blender/blenlib/intern/jitter.c +++ b/source/blender/blenlib/intern/jitter.c @@ -30,13 +30,10 @@ */ #include <math.h> -#include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_rand.h" -#include "BLI_jitter.h" void BLI_jitterate1(float *jit1, float *jit2, int num, float rad1) diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index 5d046dce023..0a6831558d1 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -108,6 +108,17 @@ void BLI_remlink(ListBase *listbase, void *vlink) if (listbase->first == link) listbase->first = link->next; } +int BLI_remlink_safe(ListBase *listbase, void *vlink) +{ + if(BLI_findindex(listbase, vlink) != -1) { + BLI_remlink(listbase, vlink); + return 1; + } + else { + return 0; + } +} + void BLI_freelinkN(ListBase *listbase, void *vlink) { diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index a0d878f3a03..686b35a878e 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -25,10 +25,6 @@ * ***** END GPL LICENSE BLOCK ***** * */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include "BLI_math.h" @@ -49,12 +45,12 @@ double copysign(double x, double y) /* from python 3.1 pymath.c */ double round(double x) { - double absx, y; - absx = fabs(x); - y = floor(absx); - if (absx - y >= 0.5) - y += 1.0; - return copysign(y, x); + double absx, y; + absx = fabs(x); + y = floor(absx); + if (absx - y >= 0.5) + y += 1.0; + return copysign(y, x); } #endif diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index fa0ca097ef1..b364ff73e4f 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -26,7 +26,6 @@ * */ #include <float.h> -#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index fc6e722afeb..6637d74dbb1 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -25,10 +25,6 @@ * ***** END GPL LICENSE BLOCK ***** * */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include "BLI_math.h" @@ -113,7 +109,9 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb) *lb=b; } -void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr) +/* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */ +/* 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, cr, cb; @@ -122,24 +120,53 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr) sg=255.0f*g; sb=255.0f*b; - - 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; + 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; + } *ly=y; *lcb=cb; *lcr=cr; } -void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb) + +/* YCC input have a range of 16-235 and 16-240 exepect with JFIF_0_255 where the range is 0-255 */ +/* RGB outputs are in the range 0 - 1.0f */ +void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace) { float r,g,b; - 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); - + 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; + } *lr=r/255.0f; *lg=g/255.0f; *lb=b/255.0f; @@ -369,21 +396,21 @@ int constrain_rgb(float *r, float *g, float *b) { float w; - /* Amount of white needed is w = - min(0, *r, *g, *b) */ + /* Amount of white needed is w = - min(0, *r, *g, *b) */ - w = (0 < *r) ? 0 : *r; - w = (w < *g) ? w : *g; - w = (w < *b) ? w : *b; - w = -w; + w = (0 < *r) ? 0 : *r; + w = (w < *g) ? w : *g; + w = (w < *b) ? w : *b; + w = -w; - /* Add just enough white to make r, g, b all positive. */ + /* Add just enough white to make r, g, b all positive. */ - if (w > 0) { - *r += w; *g += w; *b += w; - return 1; /* Color modified to fit RGB gamut */ - } + if (w > 0) { + *r += w; *g += w; *b += w; + return 1; /* Color modified to fit RGB gamut */ + } - return 0; /* Color within RGB gamut */ + return 0; /* Color within RGB gamut */ } float rgb_to_grayscale(float rgb[3]) diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 7e12cec5023..e8fb922ce4d 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -25,14 +25,13 @@ * ***** END GPL LICENSE BLOCK ***** * */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> + +#include "MEM_guardedalloc.h" #include "BLI_math.h" #include "BLI_memarena.h" -#include "MEM_guardedalloc.h" + +#include "BKE_utildefines.h" /********************************** Polygons *********************************/ @@ -63,6 +62,7 @@ float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const floa 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); } @@ -125,10 +125,6 @@ float area_tri_v3(const float v1[3], const float v2[3], const float v3[3]) /* T return (len/2.0f); } -#define MAX2(x,y) ((x)>(y) ? (x) : (y)) -#define MAX3(x,y,z) MAX2(MAX2((x),(y)) , (z)) - - float area_poly_v3(int nr, float verts[][3], float *normal) { float x, y, z, area, max; @@ -406,16 +402,17 @@ int isect_line_tri_v3(float p1[3], float p2[3], float v0[3], float v1[3], float sub_v3_v3v3(s, p1, v0); - cross_v3_v3v3(q, s, e1); - *lambda = f * dot_v3v3(e2, q); - if ((*lambda < 0.0)||(*lambda > 1.0)) return 0; - u = f * dot_v3v3(s, p); if ((u < 0.0)||(u > 1.0)) return 0; - v = f * dot_v3v3(d, q); + cross_v3_v3v3(q, s, e1); + + v = f * dot_v3v3(d, q); if ((v < 0.0)||((u + v) > 1.0)) return 0; + *lambda = f * dot_v3v3(e2, q); + if ((*lambda < 0.0)||(*lambda > 1.0)) return 0; + if(uv) { uv[0]= u; uv[1]= v; @@ -445,17 +442,18 @@ int isect_ray_tri_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2 sub_v3_v3v3(s, p1, v0); - cross_v3_v3v3(q, s, e1); - *lambda = f * dot_v3v3(e2, q); - if ((*lambda < 0.0)) return 0; - u = f * dot_v3v3(s, p); if ((u < 0.0)||(u > 1.0)) return 0; + cross_v3_v3v3(q, s, e1); + v = f * dot_v3v3(d, q); if ((v < 0.0)||((u + v) > 1.0)) return 0; - if(uv) { + *lambda = f * dot_v3v3(e2, q); + if ((*lambda < 0.0)) return 0; + + if(uv) { uv[0]= u; uv[1]= v; } @@ -465,36 +463,36 @@ int isect_ray_tri_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2 int isect_ray_tri_epsilon_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, 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, d, e2); - a = dot_v3v3(e1, p); - if (a == 0.0f) return 0; - f = 1.0f/a; - - sub_v3_v3v3(s, p1, v0); - - cross_v3_v3v3(q, s, e1); + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; - u = f * dot_v3v3(s, p); - if ((u < -epsilon)||(u > 1.0f+epsilon)) return 0; - - v = f * dot_v3v3(d, q); - if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0; + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); - *lambda = f * dot_v3v3(e2, q); - if ((*lambda < 0.0f)) return 0; + cross_v3_v3v3(p, d, e2); + a = dot_v3v3(e1, p); + if (a == 0.0f) return 0; + f = 1.0f/a; - if(uv) { - uv[0]= u; - uv[1]= v; - } - - return 1; + sub_v3_v3v3(s, p1, v0); + + u = f * dot_v3v3(s, p); + if ((u < -epsilon)||(u > 1.0f+epsilon)) return 0; + + cross_v3_v3v3(q, s, e1); + + v = f * dot_v3v3(d, q); + if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0; + + *lambda = f * dot_v3v3(e2, q); + if ((*lambda < 0.0f)) return 0; + + if(uv) { + uv[0]= u; + uv[1]= v; + } + + return 1; } int isect_ray_tri_threshold_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold) @@ -724,7 +722,7 @@ int isect_sweeping_sphere_tri_v3(float p1[3], float p2[3], float radius, float v *lambda = newLambda; copy_v3_v3(ipoint,e1); mul_v3_fl(ipoint,e); - add_v3_v3v3(ipoint,ipoint,v0); + add_v3_v3(ipoint, v0); found_by_sweep=1; } } @@ -748,7 +746,7 @@ int isect_sweeping_sphere_tri_v3(float p1[3], float p2[3], float radius, float v *lambda = newLambda; copy_v3_v3(ipoint,e2); mul_v3_fl(ipoint,e); - add_v3_v3v3(ipoint,ipoint,v0); + add_v3_v3(ipoint, v0); found_by_sweep=1; } } @@ -777,7 +775,7 @@ int isect_sweeping_sphere_tri_v3(float p1[3], float p2[3], float radius, float v *lambda = newLambda; copy_v3_v3(ipoint,e3); mul_v3_fl(ipoint,e); - add_v3_v3v3(ipoint,ipoint,v1); + add_v3_v3(ipoint, v1); found_by_sweep=1; } } @@ -961,7 +959,7 @@ int isect_line_line_strict_v3(float v1[3], float v2[3], float v3[3], float v4[3] int isect_aabb_aabb_v3(float min1[3], float max1[3], float min2[3], 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]); + min2[0]<max1[0] && min2[1]<max1[1] && min2[2]<max1[2]); } /* find closest point to p on line through l1,l2 and return lambda, @@ -1400,14 +1398,14 @@ void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3 wtot = w[0]+w[1]+w[2]; if (wtot != 0.0f) { - wtot_inv = 1.0f/wtot; + wtot_inv = 1.0f/wtot; - w[0] = w[0]*wtot_inv; - w[1] = w[1]*wtot_inv; - w[2] = w[2]*wtot_inv; + w[0] = w[0]*wtot_inv; + w[1] = w[1]*wtot_inv; + w[2] = w[2]*wtot_inv; } else /* dummy values for zero area face */ - w[0] = w[1] = w[2] = 1.0f/3.0f; + w[0] = w[1] = w[2] = 1.0f/3.0f; } /* given 2 triangles in 3D space, and a point in relation to the first triangle. @@ -1612,21 +1610,21 @@ void interp_cubic_v3(float *x, float *v,float *x1, float *v1, float *x2, float * void orthographic_m4(float matrix[][4],float left, float right, float bottom, float top, float nearClip, float farClip) { - float Xdelta, Ydelta, Zdelta; + float Xdelta, Ydelta, Zdelta; - Xdelta = right - left; - Ydelta = top - bottom; - Zdelta = farClip - nearClip; - if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) { + Xdelta = right - left; + Ydelta = top - bottom; + Zdelta = farClip - nearClip; + if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) { 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; + } + 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 perspective_m4(float mat[][4],float left, float right, float bottom, float top, float nearClip, float farClip) @@ -1648,22 +1646,22 @@ void perspective_m4(float mat[][4],float left, float right, float bottom, float 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.0; + mat[1][0] = mat[1][2] = mat[1][3] = + mat[3][0] = mat[3][1] = mat[3][3] = 0.0; } static void i_multmatrix(float icand[][4], float Vm[][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]; + 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); } @@ -1673,10 +1671,10 @@ void polarview_m4(float Vm[][4],float dist, float azimuth, float incidence, floa 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],float vx, float vy, float vz, float px, float py, float pz, float twist) @@ -1687,7 +1685,7 @@ void lookat_m4(float mat[][4],float vx, float vy, float vz, float px, float py, unit_m4(mat); unit_m4(mat1); - rotate_m4(mat,'z',-twist); + rotate_m4(mat, 'Z', -twist); dx = px - vx; dy = py - vy; @@ -1710,8 +1708,8 @@ void lookat_m4(float mat[][4],float vx, float vy, float vz, float px, float py, i_multmatrix(mat1, mat); - mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */ - mat1[1][2] = mat1[2][1] = 0.0; /* 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.0; /* those modified by the last */ /* paragraph */ if (hyp != 0.0f) { /* rotate Y */ @@ -1767,6 +1765,27 @@ int box_clip_bounds_m4(float boundbox[2][3], float bounds[4], float winmat[4][4] 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; + + 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]; + + mul_m4_v3(mat, vec); + DO_MINMAX(vec, mn, mx); + } + + copy_v3_v3(min, mn); + copy_v3_v3(max, mx); +} + /********************************** Mapping **********************************/ void map_to_tube(float *u, float *v,float x, float y, float z) @@ -1798,9 +1817,7 @@ void map_to_sphere(float *u, float *v,float x, float y, float z) } } -/********************************************************/ - -/* Tangents */ +/********************************* Tangents **********************************/ /* For normal map tangents we need to detect uv boundaries, and only average * tangents in case the uvs are connected. Alternative would be to store 1 @@ -1818,7 +1835,7 @@ void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, float *tang, /* find a tangent with connected uvs */ for(vt= *vtang; vt; vt=vt->next) { if(fabs(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabs(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT) { - add_v3_v3v3(vt->tang, vt->tang, tang); + add_v3_v3(vt->tang, tang); return; } } @@ -1852,10 +1869,12 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, float s2= uv3[0] - uv1[0]; float t1= uv2[1] - uv1[1]; float t2= uv3[1] - uv1[1]; + float det= (s1 * t2 - s2 * t1); + + if(det != 0.0f) { /* otherwise 'tang' becomes nan */ + float tangv[3], ct[3], e1[3], e2[3]; - if(s1 && s2 && t1 && t2) { /* otherwise 'tang' becomes nan */ - float tangv[3], ct[3], e1[3], e2[3], det; - det= 1.0f / (s1 * t2 - s2 * t1); + det= 1.0f/det; /* normals in render are inversed... */ sub_v3_v3v3(e1, co1, co2); @@ -1877,11 +1896,11 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, } } -/********************************************************/ +/****************************** Vector Clouds ********************************/ /* vector clouds */ /* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,float (*rpos)[3], float *rweight, - float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3]) + float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3]) input ( @@ -1905,13 +1924,13 @@ pointers may be NULL if not needed /* can't believe there is none in math utils */ float _det_m3(float m2[3][3]) { - float det = 0.f; - if (m2){ - det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1]) - -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) - +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); - } - return det; + float det = 0.f; + if (m2){ + det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1]) + -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) + +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); + } + return det; } @@ -1936,19 +1955,19 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,flo float v[3]; copy_v3_v3(v,pos[a]); mul_v3_fl(v,weight[a]); - add_v3_v3v3(accu_com,accu_com,v); + add_v3_v3(accu_com, v); accu_weight +=weight[a]; } - else add_v3_v3v3(accu_com,accu_com,pos[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_v3v3(accu_rcom,accu_rcom,v); + add_v3_v3(accu_rcom, v); accu_rweight +=rweight[a]; } - else add_v3_v3v3(accu_rcom,accu_rcom,rpos[a]); + else add_v3_v3(accu_rcom, rpos[a]); } if (!weight || !rweight){ @@ -2036,3 +2055,422 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,flo } } +/******************************* Form Factor *********************************/ + +static void vec_add_dir(float r[3], float v1[3], float v2[3], 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]); +} + +static int ff_visible_quad(float p[3], float n[3], float v0[3], float v1[3], float v2[3], float q0[3], float q1[3], float q2[3], float q3[3]) +{ + static const float epsilon = 1e-6f; + float c, sd[3]; + + 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) { + if(sd[1] > 0) { + if(sd[2] > 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) { + // ++- + 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) { + if(sd[2] > 0) { + // +-+ + 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) { + // +-- + 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) { + // +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) { + // +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) { + if(sd[1] > 0) { + if(sd[2] > 0) { + // -++ + 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) { + // -+- + 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) { + if(sd[2] > 0) { + // --+ + 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) { + // --- + return 0; + } + else { + // --0 + return 0; + } + } + else { + if(sd[2] > 0) { + // -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) { + // -0- + return 0; + } + else { + // -00 + return 0; + } + } + } + else { + if(sd[1] > 0) { + if(sd[2] > 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[2] < 0) { + // 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) { + if(sd[2] > 0) { + // 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) { + // 0-- + return 0; + } + else { + // 0-0 + return 0; + } + } + else { + if(sd[2] > 0) { + // 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) { + // 00- + return 0; + } + else { + // 000 + return 0; + } + } + } + + return 1; +} + +/* altivec optimization, this works, but is unused */ + +#if 0 +#include <Accelerate/Accelerate.h> + +typedef union { + vFloat v; + float f[4]; +} vFloatResult; + +static vFloat vec_splat_float(float 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; + + /* 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; + + /* 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; + + /* 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); + + /* 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); + + return result; +} + +#endif + +/* SSE optimization, acos code doesn't work */ + +#if 0 + +#include <xmmintrin.h> + +static __m128 sse_approx_acos(__m128 x) +{ + /* needs a better approximation than taylor expansion of acos, since that + * gives big erros 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); +} + +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; + + /* 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]); + + /* 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)); + + 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; + + /* 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; + + /* sum together */ + result= (fresult[0] + fresult[1] + fresult[2] + fresult[3])*(0.5f/(float)M_PI); + result= MAX2(result, 0.0f); + + return result; +} + +#endif + +static void ff_normalize(float n[3]) +{ + float d; + + d= dot_v3v3(n, n); + + if(d > 1.0e-35F) { + d= 1.0f/sqrtf(d); + + n[0] *= d; + n[1] *= d; + n[2] *= d; + } +} + +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; + + 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); + + 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)); + + 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); + + 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]) +{ + /* 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(ff_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) + contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3); + + if(v4 && ff_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) + contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3); + + return contrib; +} + diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c new file mode 100644 index 00000000000..697ac8dc782 --- /dev/null +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -0,0 +1,138 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: some of this file. + * + * ***** END GPL LICENSE BLOCK ***** + * */ + +#include "BLI_math.h" + +#ifndef BLI_MATH_GEOM_INLINE +#define BLI_MATH_GEOM_INLINE + +/****************************** Spherical Harmonics **************************/ + +MINLINE void zero_sh(float r[9]) +{ + memset(r, 0, sizeof(float)*9); +} + +MINLINE void copy_sh_sh(float r[9], float a[9]) +{ + memcpy(r, a, sizeof(float)*9); +} + +MINLINE void mul_sh_fl(float r[9], float f) +{ + int i; + + for(i=0; i<9; i++) + r[i] *= f; +} + +MINLINE void add_sh_shsh(float r[9], float a[9], float b[9]) +{ + int i; + + for(i=0; i<9; i++) + r[i]= a[i] + b[i]; +} + +MINLINE float dot_shsh(float a[9], float b[9]) +{ + float r= 0.0f; + int i; + + for(i=0; i<9; i++) + r += a[i]*b[i]; + + return r; +} + +MINLINE float diffuse_shv3(float sh[9], 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; +} + +MINLINE void vec_fac_to_sh(float r[9], float v[3], float f) +{ + /* 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]; + + sh[0]= 0.282095f; + + 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); + + mul_sh_fl(sh, f); + copy_sh_sh(r, sh); +} + +MINLINE float eval_shv3(float sh[9], float v[3]) +{ + float tmp[9]; + + vec_fac_to_sh(tmp, v, 1.0f); + return dot_shsh(tmp, sh); +} + +MINLINE void madd_sh_shfl(float r[9], float sh[3], float f) +{ + float tmp[9]; + + copy_sh_sh(tmp, sh); + mul_sh_fl(tmp, f); + add_sh_shsh(r, r, tmp); +} + +#endif /* BLI_MATH_GEOM_INLINE */ + diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index c970f2132c3..6e8f4622488 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -25,10 +25,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include "BLI_math.h" @@ -129,10 +125,15 @@ void swap_m4m4(float m1[][4], float m2[][4]) /******************************** Arithmetic *********************************/ -void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) +void mul_m4_m4m4(float m1[][4], float m2_[][4], float m3_[][4]) { - /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */ + float m2[4][4], m3[4][4]; + /* copy so it works when m1 is the same pointer as m2 or m3 */ + copy_m4_m4(m2, m2_); + copy_m4_m4(m3, m3_); + + /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0]; m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1]; m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2]; @@ -155,20 +156,26 @@ void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) } -void mul_m3_m3m3(float m1[][3], float m3[][3], float m2[][3]) +void mul_m3_m3m3(float m1[][3], float m3_[][3], float m2_[][3]) { - /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */ - 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]; + float m2[3][3], m3[3][3]; + + /* copy so it works when m1 is the same pointer as m2 or m3 */ + copy_m3_m3(m2, m2_); + copy_m3_m3(m3, m3_); + + /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */ + 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_m4m3(float (*m1)[4], float (*m3)[4], float (*m2)[3]) @@ -187,18 +194,18 @@ void mul_m4_m4m3(float (*m1)[4], float (*m3)[4], float (*m2)[3]) /* m1 = m2 * m3, ignore the elements on the 4th row/column of m3*/ void mul_m3_m3m4(float m1[][3], float m2[][3], float m3[][4]) { - /* 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], float (*m3)[3], float (*m2)[4]) @@ -325,17 +332,23 @@ void mul_project_m4_v4(float mat[][4], float *vec) vec[2] /= w; } -void mul_m4_v4(float mat[][4], float *vec) +void mul_v4_m4v4(float r[4], float mat[4][4], float v[4]) { - float x,y,z; + float x, y, z; - x=vec[0]; - y=vec[1]; - z= vec[2]; - vec[0]=x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3]; - vec[1]=x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3]; - vec[2]=x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3]; - vec[3]=x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3]; + x= v[0]; + y= v[1]; + 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]; +} + +void mul_m4_v4(float mat[4][4], float r[4]) +{ + mul_v4_m4v4(r, mat, r); } void mul_v3_m3v3(float r[3], float M[3][3], float a[3]) @@ -441,8 +454,8 @@ int invert_m3_m3(float m1[3][3], float m2[3][3]) /* then determinant old matrix! */ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1]) - -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) - +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); + -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) + +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); success= (det != 0); @@ -827,8 +840,8 @@ float determinant_m3(float a1, float a2, float a3, float ans; ans = a1 * determinant_m2(b2, b3, c2, c3) - - b1 * determinant_m2(a2, a3, c2, c3) - + c1 * determinant_m2(a2, a3, b2, b3); + - b1 * determinant_m2(a2, a3, c2, c3) + + c1 * determinant_m2(a2, a3, b2, b3); return ans; } @@ -859,9 +872,9 @@ float determinant_m4(float m[][4]) 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); + - 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; } @@ -942,54 +955,47 @@ void scale_m4_fl(float m[][4], float scale) void translate_m4(float mat[][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]); } -void rotate_m4(float mat[][4], char axis,float angle) +void rotate_m4(float mat[][4], const char axis, const float angle) { int col; - float temp[4]; - float cosine, sine; - - for(col=0; col<4 ; col++) /* init temp to zero matrix */ - temp[col] = 0; - - angle = (float)(angle*(3.1415926535/180.0)); - cosine = (float)cos(angle); - sine = (float)sin(angle); - switch(axis){ - case 'x': - case 'X': - for(col=0 ; col<4 ; col++) - temp[col] = cosine*mat[1][col] + sine*mat[2][col]; - for(col=0 ; col<4 ; col++) { - mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col]; - mat[1][col] = temp[col]; + float temp[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + float cosine, sine; + + cosine = (float)cos(angle); + sine = (float)sin(angle); + switch(axis){ + case 'X': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[1][col] + sine*mat[2][col]; + for(col=0 ; col<4 ; col++) { + mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col]; + mat[1][col] = temp[col]; } - break; - - case 'y': - case 'Y': - for(col=0 ; col<4 ; col++) - temp[col] = cosine*mat[0][col] - sine*mat[2][col]; - for(col=0 ; col<4 ; col++) { - mat[2][col] = sine*mat[0][col] + cosine*mat[2][col]; - mat[0][col] = temp[col]; - } + break; + + case 'Y': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[0][col] - sine*mat[2][col]; + for(col=0 ; col<4 ; col++) { + mat[2][col] = sine*mat[0][col] + cosine*mat[2][col]; + mat[0][col] = temp[col]; + } break; - case 'z': - case 'Z': - for(col=0 ; col<4 ; col++) - temp[col] = cosine*mat[0][col] + sine*mat[1][col]; - for(col=0 ; col<4 ; col++) { - mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col]; - mat[0][col] = temp[col]; - } + case 'Z': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[0][col] + sine*mat[1][col]; + for(col=0 ; col<4 ; col++) { + mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col]; + mat[0][col] = temp[col]; + } break; - } + } } void blend_m3_m3m3(float out[][3], float dst[][3], float src[][3], float srcweight) @@ -1143,3 +1149,458 @@ void print_m4(char *str, float m[][4]) printf("%f %f %f %f\n",m[0][3],m[1][3],m[2][3],m[3][3]); printf("\n"); } + +/*********************************** SVD ************************************ + * from TNT matrix library + + * Compute the Single Value Decomposition of an arbitrary matrix A + * That is compute the 3 matrices U,W,V with U column orthogonal (m,n) + * ,W a diagonal matrix and V an orthogonal square matrix s.t. + * A = U.W.Vt. From this decomposition it is trivial to compute the + * (pseudo-inverse) of A as Ainv = V.Winv.tranpose(U). + */ + +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 = minf(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 = minf(m-1,n); + int nrt = maxf(0,minf(n-2,m)); + + copy_m4_m4(A, A_); + zero_m4(U); + zero_v4(s); + + for (k = 0; k < maxf(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 = minf(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; + k=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 = maxf(maxf(maxf(maxf( + 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], float A[4][4], float epsilon) +{ + /* compute moon-penrose pseudo inverse of matrix, singular values + below epsilon are ignored for stability (truncated SVD) */ + float V[4][4], W[4], Wm[4][4], U[4][4]; + int i; + + transpose_m4(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]; + + transpose_m4(V); + + mul_serie_m4(Ainv, U, Wm, V, 0, 0, 0, 0, 0); +} diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index a92f80e35c7..6b5bf7743ef 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -25,10 +25,6 @@ * ***** END GPL LICENSE BLOCK ***** * */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include "BLI_math.h" @@ -904,12 +900,12 @@ void quat_to_eul(float *eul,float *quat) /* XYZ order */ void eul_to_quat(float *quat,float *eul) { - 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 = (float)cos(ti); cj = (float)cos(tj); ch = (float)cos(th); - si = (float)sin(ti); sj = (float)sin(tj); sh = (float)sin(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 = (float)cos(ti); cj = (float)cos(tj); ch = (float)cos(th); + si = (float)sin(ti); sj = (float)sin(tj); sh = (float)sin(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; @@ -923,8 +919,8 @@ void rotate_eul(float *beul, char axis, float ang) float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; eul[0]= eul[1]= eul[2]= 0.0f; - if(axis=='x') eul[0]= ang; - else if(axis=='y') eul[1]= ang; + if(axis=='X') eul[0]= ang; + else if(axis=='Y') eul[1]= ang; else eul[2]= ang; eul_to_mat3(mat1,eul); @@ -1029,7 +1025,7 @@ void mat3_to_compatible_eul(float *eul, float *oldrot,float mat[][3]) /* Euler Rotation Order Code: * was adapted from - ANSI C code from the article + ANSI C code from the article "Euler Angle Conversion" by Ken Shoemake, shoemake@graphics.cis.upenn.edu in "Graphics Gems IV", Academic Press, 1994 @@ -1242,9 +1238,9 @@ void rotate_eulO(float beul[3], short order, char axis, float ang) float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; eul[0]= eul[1]= eul[2]= 0.0f; - if (axis=='x') + if (axis=='X') eul[0]= ang; - else if (axis=='y') + else if (axis=='Y') eul[1]= ang; else eul[2]= ang; @@ -1303,11 +1299,11 @@ void eulO_to_gimbal_axis(float gmat[][3], float *eul, short order) freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. + misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Author: Ladislav Kavan, kavanl@cs.tcd.ie @@ -1507,3 +1503,13 @@ void copy_dq_dq(DualQuat *dq1, DualQuat *dq2) memcpy(dq1, dq2, sizeof(DualQuat)); } +/* lense/angle conversion (radians) */ +float lens_to_angle(float lens) +{ + return 2.0f * atan(16.0f/lens); +} + +float angle_to_lens(float angle) +{ + return 16.0f / tan(angle * 0.5f); +} diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 2452de0dc4c..9baf897c830 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -25,10 +25,6 @@ * ***** END GPL LICENSE BLOCK ***** * */ -#include <float.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include "BLI_math.h" @@ -59,6 +55,16 @@ void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const f 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) +{ + 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]; +} + /* 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]) @@ -77,6 +83,14 @@ void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const 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]) +{ + 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 mid_v3_v3v3(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0] + v2[0]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 7fb6b8f6059..33d7f7cdd6d 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -66,7 +66,7 @@ MINLINE void copy_v3_v3(float r[3], const float a[3]) r[2]= a[2]; } -MINLINE void copy_v4_v4(float r[4], float a[4]) +MINLINE void copy_v4_v4(float r[4], const float a[4]) { r[0]= a[0]; r[1]= a[1]; @@ -97,45 +97,45 @@ MINLINE void swap_v4_v4(float a[4], float b[4]) /********************************* Arithmetic ********************************/ -MINLINE void add_v2_v2(float *r, float *a) +MINLINE void add_v2_v2(float *r, const float *a) { r[0] += a[0]; r[1] += a[1]; } -MINLINE void add_v2_v2v2(float *r, float *a, float *b) +MINLINE void add_v2_v2v2(float *r, const float *a, const float *b) { r[0]= a[0] + b[0]; r[1]= a[1] + b[1]; } -MINLINE void add_v3_v3(float *r, float *a) +MINLINE void add_v3_v3(float *r, const float *a) { r[0] += a[0]; r[1] += a[1]; r[2] += a[2]; } -MINLINE void add_v3_v3v3(float *r, float *a, float *b) +MINLINE void add_v3_v3v3(float *r, const float *a, const float *b) { r[0]= a[0] + b[0]; r[1]= a[1] + b[1]; r[2]= a[2] + b[2]; } -MINLINE void sub_v2_v2(float *r, float *a) +MINLINE void sub_v2_v2(float *r, const float *a) { r[0] -= a[0]; r[1] -= a[1]; } -MINLINE void sub_v2_v2v2(float *r, float *a, float *b) +MINLINE void sub_v2_v2v2(float *r, const float *a, const float *b) { r[0]= a[0] - b[0]; r[1]= a[1] - b[1]; } -MINLINE void sub_v3_v3(float *r, float *a) +MINLINE void sub_v3_v3(float *r, const float *a) { r[0] -= a[0]; r[1] -= a[1]; @@ -181,48 +181,70 @@ MINLINE void mul_v2_v2(float r[2], const float a[2]) r[1] *= a[1]; } -MINLINE void mul_v3_v3(float r[3], float a[3]) +MINLINE void mul_v3_v3(float r[3], const float a[3]) { r[0] *= a[0]; r[1] *= a[1]; r[2] *= a[2]; } -MINLINE void madd_v3_v3fl(float r[3], float a[3], float f) +MINLINE void mul_v4_fl(float r[4], float f) +{ + r[0]*= f; + r[1]*= f; + r[2]*= f; + r[3]*= f; +} + +MINLINE void madd_v2_v2fl(float r[2], const float a[2], float 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; } -MINLINE void madd_v3_v3v3(float r[3], float a[3], float b[3]) +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]; } -MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], const float f) +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; } -MINLINE void madd_v3_v3v3fl(float r[3], float a[3], float b[3], float 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; } -MINLINE void madd_v3_v3v3v3(float r[3], float a[3], float b[3], float c[3]) +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]; } -MINLINE void mul_v3_v3v3(float *v, float *v1, float *v2) +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; +} + +MINLINE void mul_v3_v3v3(float *v, const float *v1, const float *v2) { v[0] = v1[0] * v2[0]; v[1] = v1[1] * v2[1]; @@ -305,6 +327,14 @@ MINLINE float len_v3v3(const float a[3], const float b[3]) return len_v3(d); } +MINLINE float len_squared_v3v3(const float a[3], const float b[3]) +{ + float d[3]; + + sub_v3_v3v3(d, b, a); + return dot_v3v3(d, d); +} + MINLINE float normalize_v2_v2(float r[2], const float a[2]) { float d= dot_v2v2(a, a); @@ -371,14 +401,14 @@ MINLINE float normalize_v3(float n[3]) return normalize_v3_v3(n, n); } -MINLINE void normal_short_to_float_v3(float *out, short *in) +MINLINE void normal_short_to_float_v3(float *out, const short *in) { 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, float *in) +MINLINE void normal_float_to_short_v3(short *out, const float *in) { out[0] = (short)(in[0]*32767.0f); out[1] = (short)(in[1]*32767.0f); @@ -414,7 +444,7 @@ MINLINE int compare_v3v3(float *v1, float *v2, float limit) MINLINE int compare_len_v3v3(float *v1, float *v2, float limit) { - float x,y,z; + float x,y,z; x=v1[0]-v2[0]; y=v1[1]-v2[1]; diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 343589d9a41..141e5438bc9 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -35,11 +35,6 @@ #endif #include <math.h> -#include "BLI_blenlib.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* local */ static float noise3_perlin(float vec[3]); @@ -204,8 +199,15 @@ float hashvectf[768]= { /* IMPROVED PERLIN NOISE */ /**************************/ -#define lerp(t, a, b) ((a)+(t)*((b)-(a))) -#define npfade(t) ((t)*(t)*(t)*((t)*((t)*6-15)+10)) +static float lerp(float t, float a, float b) +{ + return (a+t*(b-a)); +} + +static float npfade(float t) +{ + return (t*t*t*(t*(t*6.0f-15.0f)+10.0f)); +} static float grad(int hash, float x, float y, float z) { @@ -908,11 +910,11 @@ float g[512+2][3]= { #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) #define setup(i,b0,b1,r0,r1) \ - t = vec[i] + 10000.; \ - b0 = ((int)t) & 255; \ - b1 = (b0+1) & 255; \ - r0 = t - (int)t; \ - r1 = r0 - 1.; + t = vec[i] + 10000.; \ + b0 = ((int)t) & 255; \ + b1 = (b0+1) & 255; \ + r0 = t - (int)t; \ + r1 = r0 - 1.; static float noise3_perlin(float vec[3]) @@ -1491,7 +1493,7 @@ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves * ``offset'' is the zero offset, which determines multifractality (NOT USED??) */ /* 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), + * 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) { diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index fe43960b770..423bf452a4d 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -29,20 +29,14 @@ * various string, file, list operations. */ -#include <stdio.h> -#include <fcntl.h> #include <ctype.h> #include <string.h> #include <stdlib.h> -#include <stdarg.h> -#include <math.h> /* for log10 */ #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" #include "DNA_userdef_types.h" -#include "BLI_dynamiclist.h" #include "BLI_fileops.h" #include "BLI_path_util.h" #include "BLI_string.h" @@ -50,21 +44,13 @@ #include "BLI_storage_types.h" #include "BKE_utildefines.h" +#include "BKE_blender.h" // BLENDER_VERSION +#include "GHOST_Path-api.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef WIN32 -#include <unistd.h> -#else -#include <io.h> -#endif - #ifdef WIN32 +#include <io.h> #ifdef _WIN32_IE #undef _WIN32_IE @@ -75,29 +61,22 @@ #include "BLI_winstuff.h" -#endif - - -#ifndef WIN32 -#include <sys/time.h> -#endif - -#ifdef __APPLE__ -#include <sys/param.h> -#include <CoreFoundation/CoreFoundation.h> -#endif +#else /* non windows */ #ifdef __linux__ #include "binreloc.h" #endif +#endif /* WIN32 */ + /* local */ static int add_win32_extension(char *name); +static char *blender_version_decimal(void); /* implementation */ -int BLI_stringdec(char *string, char *head, char *start, unsigned short *numlen) +int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen) { unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0; short i, found = 0; @@ -124,8 +103,8 @@ int BLI_stringdec(char *string, char *head, char *start, unsigned short *numlen) if (found) break; } } - if (found){ - if (start) strcpy(start,&string[nume+1]); + if (found) { + if (tail) strcpy(tail, &string[nume+1]); if (head) { strcpy(head,string); head[nums]=0; @@ -133,22 +112,22 @@ int BLI_stringdec(char *string, char *head, char *start, unsigned short *numlen) if (numlen) *numlen = nume-nums+1; return ((int)atoi(&(string[nums]))); } - if (start) strcpy(start, string + len); + if (tail) strcpy(tail, string + len); if (head) { strncpy(head, string, len); - head[len] = 0; + head[len] = '\0'; } if (numlen) *numlen=0; return 0; } -void BLI_stringenc(char *string, char *head, char *start, unsigned short numlen, int pic) +void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) { char fmtstr[16]=""; if(pic < 0) pic= 0; sprintf(fmtstr, "%%s%%.%dd%%s", numlen); - sprintf(string, fmtstr, head, pic, start); + sprintf(string, fmtstr, head, pic, tail); } @@ -270,7 +249,7 @@ void BLI_cleanup_file(const char *relabase, char *dir) short a; char *start, *eind; if (relabase) { - BLI_convertstringcode(dir, relabase); + BLI_path_abs(dir, relabase); } else { if (dir[0]=='/' && dir[1]=='/') { if (dir[2]== '\0') { @@ -369,10 +348,8 @@ void BLI_cleanup_file(const char *relabase, char *dir) } -void BLI_makestringcode(const char *relfile, char *file) +void BLI_path_rel(char *file, const char *relfile) { - char * p; - char * q; char * lslash; char temp[FILE_MAXDIR+FILE_MAXFILE]; char res[FILE_MAXDIR+FILE_MAXFILE]; @@ -420,11 +397,18 @@ void BLI_makestringcode(const char *relfile, char *file) { /* find the prefix of the filename that is equal for both filenames. This is replaced by the two slashes at the beginning */ - p = temp; - q = file; - while (*p == *q) { + char *p= temp; + char *q= file; + + while ((*p == *q)) { ++p; ++q; + /* dont 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 */ @@ -542,7 +526,7 @@ static void ensure_digits(char *path, int digits) } } -int BLI_convertstringframe(char *path, int frame, int digits) +int BLI_path_frame(char *path, int frame, int digits) { int ch_sta, ch_end; @@ -559,7 +543,7 @@ int BLI_convertstringframe(char *path, int frame, int digits) return 0; } -int BLI_convertstringframe_range(char *path, int sta, int end, int digits) +int BLI_path_frame_range(char *path, int sta, int end, int digits) { int ch_sta, ch_end; @@ -576,7 +560,7 @@ int BLI_convertstringframe_range(char *path, int sta, int end, int digits) return 0; } -int BLI_convertstringcode(char *path, const char *basepath) +int BLI_path_abs(char *path, const char *basepath) { int wasrelative = (strncmp(path, "//", 2)==0); char tmp[FILE_MAX]; @@ -638,7 +622,7 @@ int BLI_convertstringcode(char *path, const char *basepath) char *lslash= BLI_last_slash(base); if (lslash) { int baselen= (int) (lslash-base) + 1; - /* use path for for temp storage here, we copy back over it right away */ + /* use path for temp storage here, we copy back over it right away */ BLI_strncpy(path, tmp+2, FILE_MAX); memcpy(tmp, base, baselen); @@ -677,7 +661,7 @@ int BLI_convertstringcode(char *path, const char *basepath) * Should only be done with command line paths. * this is NOT somthing blenders internal paths support like the // prefix */ -int BLI_convertstringcwd(char *path) +int BLI_path_cwd(char *path) { int wasrelative = 1; int filelen = strlen(path); @@ -715,7 +699,7 @@ int BLI_convertstringcwd(char *path) } -/* copy di to fi, filename only */ +/* 'di's filename component is moved into 'fi', di is made a dir path */ void BLI_splitdirstring(char *di, char *fi) { char *lslash= BLI_last_slash(di); @@ -762,76 +746,50 @@ char *BLI_gethome(void) { ret = getenv("HOME"); if(ret) { - sprintf(dir, "%s\\.blender", ret); - if (BLI_exists(dir)) return dir; + sprintf(dir, "%s\\%s", ret, blender_version_decimal()); + if (BLI_is_dir(dir)) return dir; } /* else, check install dir (path containing blender.exe) */ - BLI_getInstallationDir(dir); - - if (BLI_exists(dir)) + if(BLI_getInstallationDir(dir)) { - strcat(dir,"\\.blender"); - if (BLI_exists(dir)) return(dir); + sprintf(dir, "%s", dir, blender_version_decimal()); + if (BLI_is_dir(dir)) return(dir); } - /* add user profile support for WIN 2K / NT */ + /* add user profile support for WIN 2K / NT. + * This is %APPDATA%, which translates to either + * %USERPROFILE%\Application Data or since Vista + * to %USERPROFILE%\AppData\Roaming + */ hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath); if (hResult == S_OK) { - if (BLI_exists(appdatapath)) { /* from fop, also below... */ + if (BLI_is_dir(appdatapath)) { /* from fop, also below... */ sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath); BLI_recurdir_fileops(dir); - if (BLI_exists(dir)) { - strcat(dir,"\\.blender"); - if(BLI_exists(dir)) return(dir); + if (BLI_is_dir(dir)) { + sprintf(dir,"%s\\%s", dir, blender_version_decimal()); + if(BLI_is_dir(dir)) return(dir); } } hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatapath); if (hResult == S_OK) { - if (BLI_exists(appdatapath)) + if (BLI_is_dir(appdatapath)) { /* from fop, also below... */ sprintf(dir, "%s\\Blender Foundation\\Blender", appdatapath); BLI_recurdir_fileops(dir); - if (BLI_exists(dir)) { - strcat(dir,"\\.blender"); - if(BLI_exists(dir)) return(dir); + if (BLI_is_dir(dir)) { + sprintf(dir,"%s\\%s", dir, blender_version_decimal()); + if(BLI_is_dir(dir)) return(dir); } } } } -#if 0 - ret = getenv("USERPROFILE"); - if (ret) { - if (BLI_exists(ret)) { /* from fop, also below... */ - sprintf(dir, "%s\\Application Data\\Blender Foundation\\Blender", ret); - BLI_recurdir_fileops(dir); - if (BLI_exists(dir)) { - strcat(dir,"\\.blender"); - if(BLI_exists(dir)) return(dir); - } - } - } -#endif - - /* - Saving in the Windows dir is less than desirable. - Use as a last resort ONLY! (aphex) - */ - - ret = getenv("WINDOWS"); - if (ret) { - if(BLI_exists(ret)) return ret; - } - - ret = getenv("WINDIR"); - if (ret) { - if(BLI_exists(ret)) return ret; - } return "C:\\Temp"; /* sheesh! bad, bad, bad! (aphex) */ #endif @@ -840,7 +798,7 @@ char *BLI_gethome(void) { /* this function returns the path to a blender folder, if it exists * utility functions for BLI_gethome_folder */ -/* #define PATH_DEBUG */ /* for testing paths that are checked */ +// #define PATH_DEBUG /* for testing paths that are checked */ static int test_data_path(char *targetpath, char *path_base, char *path_sep, char *folder_name) { @@ -851,7 +809,7 @@ static int test_data_path(char *targetpath, char *path_base, char *path_sep, cha BLI_make_file_string("/", targetpath, tmppath, folder_name); - if (BLI_exists(targetpath)) { + if (BLI_is_dir(targetpath)) { #ifdef PATH_DEBUG printf("\tpath found: %s\n", targetpath); #endif @@ -884,11 +842,12 @@ static int gethome_path_local(char *targetpath, char *folder_name) i = s - bprogname + 1; BLI_strncpy(bprogdir, bprogname, i); - /* try release/folder_name (CWD relative) */ - if(test_data_path(targetpath, BLI_getwdN(cwd), "release", folder_name)) + /* try release/folder_name (BIN relative) */ + if(test_data_path(targetpath, bprogdir, "release", folder_name)) return 1; - if(test_data_path(targetpath, bprogdir, "release", folder_name)) + /* try release/folder_name (CWD relative) */ + if(test_data_path(targetpath, BLI_getwdN(cwd), "release", folder_name)) return 1; /* try ./.blender/folder_name */ @@ -950,6 +909,274 @@ char *BLI_gethome_folder(char *folder_name, int flag) return NULL; } + +/* NEW stuff, to be cleaned up when fully migrated */ +/* ************************************************************* */ +/* ************************************************************* */ + +// #define PATH_DEBUG2 + +static char *blender_version_decimal(void) +{ + static char version_str[5]; + sprintf(version_str, "%d.%02d", BLENDER_VERSION/100, BLENDER_VERSION%100); + return version_str; +} + +static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name) +{ + char tmppath[FILE_MAX]; + + if(path_sep) BLI_join_dirfile(tmppath, path_base, path_sep); + else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + + BLI_make_file_string("/", targetpath, tmppath, folder_name); + + if (BLI_is_dir(targetpath)) { +#ifdef PATH_DEBUG2 + printf("\tpath found: %s\n", targetpath); +#endif + return 1; + } + else { +#ifdef PATH_DEBUG2 + printf("\tpath missing: %s\n", targetpath); +#endif + //targetpath[0] = '\0'; + return 0; + } +} + +static int test_env_path(char *path, char *envvar) +{ + char *env = envvar?getenv(envvar):NULL; + if (!env) return 0; + + if (BLI_is_dir(env)) { + BLI_strncpy(path, env, FILE_MAX); + return 1; + } else { + path[0] = '\0'; + return 0; + } +} + +static int get_path_local(char *targetpath, char *folder_name) +{ + extern char bprogname[]; /* argv[0] from creator.c */ + char bprogdir[FILE_MAX]; + char cwd[FILE_MAX]; + char *s; + int i; + +#ifdef PATH_DEBUG2 + printf("get_path_local...\n"); +#endif + + + /* use argv[0] (bprogname) to get the path to the executable */ + s = BLI_last_slash(bprogname); + i = s - bprogname + 1; + BLI_strncpy(bprogdir, bprogname, i); + + /* try EXECUTABLE_DIR/folder_name */ + if(test_path(targetpath, bprogdir, "", folder_name)) + return 1; + + /* try CWD/release/folder_name */ + if(test_path(targetpath, BLI_getwdN(cwd), "release", folder_name)) + return 1; + + /* try EXECUTABLE_DIR/release/folder_name */ + if(test_path(targetpath, bprogdir, "release", folder_name)) + return 1; + + /* try EXECUTABLE_DIR/2.5/folder_name - new default directory for local blender installed files */ + if(test_path(targetpath, bprogdir, blender_version_decimal(), folder_name)) + return 1; + + /* try ./.blender/folder_name -- DEPRECATED, need to update build systems */ + if(test_path(targetpath, bprogdir, ".blender", folder_name)) + return 1; + + return 0; +} + +static int get_path_user(char *targetpath, char *folder_name, char *envvar) +{ + char user_path[FILE_MAX]; + const char *user_base_path; + + user_path[0] = '\0'; + + if (test_env_path(targetpath, envvar)) + return 1; + + user_base_path = (const char *)GHOST_getUserDir(); + if (user_base_path) { + BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal()); + } + + if(!user_path[0]) + return 0; + +#ifdef PATH_DEBUG2 + printf("get_path_user: %s\n", user_path); +#endif + + /* try $HOME/folder_name */ + return test_path(targetpath, user_path, NULL, folder_name); +} + +static int get_path_system(char *targetpath, char *folder_name, char *envvar) +{ + char system_path[FILE_MAX]; + const char *system_base_path; + + system_path[0] = '\0'; + + if (test_env_path(targetpath, envvar)) + return 1; + + system_base_path = (const char *)GHOST_getSystemDir(); + if (system_base_path) { + BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal()); + } + + if(!system_path[0]) + return 0; + +#ifdef PATH_DEBUG2 + printf("get_path_system: %s\n", system_path); +#endif + + /* try $BLENDERPATH/folder_name */ + return test_path(targetpath, system_path, NULL, folder_name); +} + +/* get a folder out of the 'folder_id' presets for paths */ +/* returns the path if found, NULL string if not */ +char *BLI_get_folder(int folder_id, char *subfolder) +{ + static char path[FILE_MAX] = ""; + char search_path[FILE_MAX]; + + switch (folder_id) { + case BLENDER_DATAFILES: /* general case */ + BLI_join_dirfile(search_path, "datafiles", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_DATAFILES")) break; + if (get_path_system(path, search_path, "BLENDER_SYSTEM_DATAFILES")) break; + return NULL; + + case BLENDER_USER_DATAFILES: + BLI_join_dirfile(search_path, "datafiles", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_DATAFILES")) break; + return NULL; + + case BLENDER_SYSTEM_DATAFILES: + BLI_join_dirfile(search_path, "datafiles", subfolder); + if (get_path_system(path, search_path, "BLENDER_SYSTEM_DATAFILES")) break; + return NULL; + + case BLENDER_CONFIG: /* general case */ + BLI_join_dirfile(search_path, "config", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_CONFIG")) break; + if (get_path_system(path, search_path, "BLENDER_SYSTEM_CONFIG")) break; + return NULL; + + case BLENDER_USER_CONFIG: + BLI_join_dirfile(search_path, "config", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_CONFIG")) break; + return NULL; + + case BLENDER_SYSTEM_CONFIG: + BLI_join_dirfile(search_path, "config", subfolder); + if (get_path_system(path, search_path, "BLENDER_SYSTEM_CONFIG")) break; + return NULL; + + case BLENDER_SCRIPTS: /* general case */ + BLI_join_dirfile(search_path, "scripts", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_SCRIPTS")) break; + if (get_path_system(path, search_path, "BLENDER_SYSTEM_SCRIPTS")) break; + return NULL; + + case BLENDER_USER_SCRIPTS: + BLI_join_dirfile(search_path, "scripts", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_user(path, search_path, "BLENDER_USER_SCRIPTS")) break; + return NULL; + + case BLENDER_SYSTEM_SCRIPTS: + BLI_join_dirfile(search_path, "scripts", subfolder); + if (get_path_system(path, search_path, "BLENDER_SYSTEM_SCRIPTS")) break; + return NULL; + + case BLENDER_PYTHON: /* general case */ + BLI_join_dirfile(search_path, "python", subfolder); + if (get_path_local(path, search_path)) break; + if (get_path_system(path, search_path, "BLENDER_SYSTEM_PYTHON")) break; + return NULL; + + case BLENDER_SYSTEM_PYTHON: + BLI_join_dirfile(search_path, "python", subfolder); + if (get_path_system(path, search_path, "BLENDER_SYSTEM_PYTHON")) break; + return NULL; + } + + return path; +} + +static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) +{ + static char path[FILE_MAX] = ""; + char search_path[FILE_MAX]; + + switch (folder_id) { + case BLENDER_USER_DATAFILES: + BLI_join_dirfile(search_path, "datafiles", subfolder); + get_path_user(path, search_path, "BLENDER_USER_DATAFILES"); + break; + case BLENDER_USER_CONFIG: + BLI_join_dirfile(search_path, "config", subfolder); + get_path_user(path, search_path, "BLENDER_USER_CONFIG"); + break; + } + if ('\0' == path[0]) { + return NULL; + } + return path; +} + +char *BLI_get_folder_create(int folder_id, char *subfolder) +{ + char *path; + + /* only for user folders */ + if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG)) + return NULL; + + path = BLI_get_folder(folder_id, subfolder); + + if (!path) { + path = BLI_get_user_folder_notest(folder_id, subfolder); + if (path) BLI_recurdir_fileops(path); + } + + return path; +} + + +/* End new stuff */ +/* ************************************************************* */ +/* ************************************************************* */ + + + #ifdef PATH_DEBUG #undef PATH_DEBUG #endif @@ -1018,7 +1245,7 @@ void BLI_make_exist(char *dir) { a = strlen(dir); #ifdef WIN32 - while(BLI_exists(dir) == 0){ + while(BLI_is_dir(dir) == 0){ a --; while(dir[a] != '\\'){ a--; @@ -1032,7 +1259,7 @@ void BLI_make_exist(char *dir) { } } #else - while(BLI_exist(dir) == 0){ + while(BLI_is_dir(dir) == 0){ a --; while(dir[a] != '/'){ a--; @@ -1049,8 +1276,8 @@ void BLI_make_exist(char *dir) { void BLI_make_existing_file(char *name) { - char di[FILE_MAXDIR], fi[FILE_MAXFILE]; - + char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE]; + strcpy(di, name); BLI_splitdirstring(di, fi); @@ -1154,25 +1381,38 @@ int BLI_testextensie(const char *str, const char *ext) return (retval); } -/* - * This is a simple version of BLI_split_dirfile that has the following advantages... - * - * Converts "/foo/bar.txt" to "/foo/" and "bar.txt" +int BLI_replace_extension(char *path, int maxlen, const char *ext) +{ + int a; + + for(a=strlen(path)-1; a>=0; a--) + if(path[a] == '.' || path[a] == '/' || path[a] == '\\') + break; + + if(path[a] != '.') + a= strlen(path); + + if(a + strlen(ext) >= maxlen) + return 0; + + strcpy(path+a, ext); + return 1; +} + +/* Converts "/foo/bar.txt" to "/foo/" and "bar.txt" * - wont change 'string' * - wont create any directories * - dosnt use CWD, or deal with relative paths. * - Only fill's in *dir and *file when they are non NULL * */ -void BLI_split_dirfile_basic(const char *string, char *dir, char *file) +void BLI_split_dirfile(const char *string, char *dir, char *file) { - int lslash=0, i = 0; - for (i=0; string[i]!='\0'; i++) { - if (string[i]=='\\' || string[i]=='/') - lslash = i+1; - } + char *lslash_str = BLI_last_slash(string); + int lslash= lslash_str ? (int)(lslash_str - string) + 1 : 0; + if (dir) { if (lslash) { - BLI_strncpy( dir, string, lslash+1); /* +1 to include the slash and the last char */ + BLI_strncpy( dir, string, lslash + 1); /* +1 to include the slash and the last char */ } else { dir[0] = '\0'; } @@ -1183,128 +1423,6 @@ void BLI_split_dirfile_basic(const char *string, char *dir, char *file) } } - -/* Warning, - * - May modify 'string' variable - * - May create the directory if it dosnt exist - * if this is not needed use BLI_split_dirfile_basic(...) - */ -void BLI_split_dirfile(char *string, char *dir, char *file) -{ - int a; -#ifdef WIN32 - int sl; - short is_relative = 0; - char path[FILE_MAX]; -#endif - - dir[0]= 0; - file[0]= 0; - -#ifdef WIN32 - BLI_strncpy(path, string, FILE_MAX); - BLI_char_switch(path, '/', '\\'); /* make sure we have a valid path format */ - sl = strlen(path); - if (sl) { - int len; - if (path[0] == '/' || path[0] == '\\') { - BLI_strncpy(dir, path, FILE_MAXDIR); - if (sl > 1 && path[0] == '\\' && path[1] == '\\') is_relative = 1; - } else if (sl > 2 && path[1] == ':' && path[2] == '\\') { - BLI_strncpy(dir, path, FILE_MAXDIR); - } else { - BLI_getwdN(dir); - strcat(dir,"\\"); - strcat(dir,path); - BLI_strncpy(path,dir,FILE_MAXDIR+FILE_MAXFILE); - } - - // BLI_exist doesn't recognize a slashed dirname as a dir - // check if a trailing slash exists, and remove it. Do not do this - // when we are already at root. -jesterKing - a = strlen(dir); - if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0; - - if (is_relative) { - printf("WARNING: BLI_split_dirfile needs absolute dir\n"); - } - else { - BLI_make_exist(dir); - } - - if (S_ISDIR(BLI_exist(dir))) { - - /* copy from end of string into file, to ensure filename itself isn't truncated - if string is too long. (aphex) */ - - len = FILE_MAXFILE - strlen(path); - - if (len < 0) - BLI_strncpy(file,path + abs(len),FILE_MAXFILE); - else - BLI_strncpy(file,path,FILE_MAXFILE); - - if (strrchr(path,'\\')) { - BLI_strncpy(file,strrchr(path,'\\')+1,FILE_MAXFILE); - } - - if ( (a = strlen(dir)) ) { - if (dir[a-1] != '\\') strcat(dir,"\\"); - } - } - else { - a = strlen(dir) - 1; - while(a>0 && dir[a] != '\\') a--; - dir[a + 1] = 0; - BLI_strncpy(file, path + strlen(dir),FILE_MAXFILE); - } - - } - else { - /* defaulting to first valid drive hoping it's not empty CD and DVD drives */ - get_default_root(dir); - file[0]=0; - } -#else - if (strlen(string)) { - if (string[0] == '/') { - strcpy(dir, string); - } else if (string[1] == ':' && string[2] == '\\') { - string+=2; - strcpy(dir, string); - } else { - BLI_getwdN(dir); - strcat(dir,"/"); - strcat(dir,string); - strcpy((char *)string,dir); - } - - BLI_make_exist(dir); - - if (S_ISDIR(BLI_exist(dir))) { - strcpy(file,string + strlen(dir)); - - if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1); - - if ( (a = strlen(dir)) ) { - if (dir[a-1] != '/') strcat(dir,"/"); - } - } - else { - a = strlen(dir) - 1; - while(dir[a] != '/') a--; - dir[a + 1] = 0; - strcpy(file, string + strlen(dir)); - } - } - else { - BLI_getwdN(dir); - strcat(dir, "/"); - file[0] = 0; - } -#endif -} - /* simple appending of filename to dir, does not check for valid path! */ void BLI_join_dirfile(char *string, const char *dir, const char *file) { @@ -1312,6 +1430,9 @@ void BLI_join_dirfile(char *string, const char *dir, const char *file) if(string != dir) /* compare pointers */ BLI_strncpy(string, dir, FILE_MAX); + + if (!file) + return; sl_dir= BLI_add_slash(string); @@ -1320,6 +1441,12 @@ void BLI_join_dirfile(char *string, const char *dir, const char *file) } } +/* like pythons os.path.basename( ) */ +char *BLI_path_basename(char *path) +{ + char *filename= BLI_last_slash(path); + return filename ? filename + 1 : path; +} /* Produce image export path. @@ -1332,7 +1459,7 @@ void BLI_join_dirfile(char *string, const char *dir, const char *file) Logic: - if an image is "below" current .blend file directory, rebuild the - same dir structure in dest_dir + same dir structure in dest_dir For example //textures/foo/bar.png becomes [dest_dir]/textures/foo/bar.png. @@ -1363,7 +1490,7 @@ int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char if (rel) rel[0]= 0; - BLI_split_dirfile_basic(base_dir, blend_dir, NULL); + BLI_split_dirfile(base_dir, blend_dir, NULL); if (src_dir[0]=='\0') return 0; @@ -1371,10 +1498,10 @@ int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char BLI_strncpy(path, src_dir, sizeof(path)); /* expand "//" in filename and get absolute path */ - BLI_convertstringcode(path, base_dir); + BLI_path_abs(path, base_dir); /* get the directory part */ - BLI_split_dirfile_basic(path, dir, base); + BLI_split_dirfile(path, dir, base); len= strlen(blend_dir); @@ -1479,7 +1606,7 @@ void BLI_where_am_i(char *fullname, const char *name) /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */ path = br_find_exe( NULL ); if (path) { - strcpy(fullname, path); + BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE); free(path); return; } @@ -1555,7 +1682,7 @@ void BLI_where_is_temp(char *fullname, int usertemp) { fullname[0] = '\0'; - if (usertemp && BLI_exists(U.tempdir)) { + if (usertemp && BLI_is_dir(U.tempdir)) { strcpy(fullname, U.tempdir); } @@ -1563,7 +1690,7 @@ void BLI_where_is_temp(char *fullname, int usertemp) #ifdef WIN32 if (fullname[0] == '\0') { char *tmp = getenv("TEMP"); /* Windows */ - if (tmp && BLI_exists(tmp)) { + if (tmp && BLI_is_dir(tmp)) { strcpy(fullname, tmp); } } @@ -1571,14 +1698,14 @@ void BLI_where_is_temp(char *fullname, int usertemp) /* Other OS's - Try TMP and TMPDIR */ if (fullname[0] == '\0') { char *tmp = getenv("TMP"); - if (tmp && BLI_exists(tmp)) { + if (tmp && BLI_is_dir(tmp)) { strcpy(fullname, tmp); } } if (fullname[0] == '\0') { char *tmp = getenv("TMPDIR"); - if (tmp && BLI_exists(tmp)) { + if (tmp && BLI_is_dir(tmp)) { strcpy(fullname, tmp); } } @@ -1613,29 +1740,7 @@ char *get_install_dir(void) { } } -/* - * returns absolute path to the app bundle - * only useful on OS X - */ -#ifdef __APPLE__ -char* BLI_getbundle(void) { - CFURLRef bundleURL; - CFStringRef pathStr; - static char path[MAXPATHLEN]; - CFBundleRef mainBundle = CFBundleGetMainBundle(); - - bundleURL = CFBundleCopyBundleURL(mainBundle); - pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); - CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII); - CFRelease(pathStr); - CFRelease(bundleURL); - return path; -} -#endif - #ifdef WITH_ICONV -#include "iconv.h" -#include "localcharset.h" void BLI_string_to_utf8(char *original, char *utf_8, const char *code) { diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 9e1dd096528..4c5177a403e 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -20,11 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include <float.h> -#include <stdlib.h> -#include <string.h> -#include "MEM_guardedalloc.h" #include "DNA_meshdata_types.h" @@ -33,10 +29,10 @@ #include "BLI_pbvh.h" #include "BKE_DerivedMesh.h" -#include "BKE_mesh.h" -#include "BKE_utildefines.h" +#include "BKE_mesh.h" /* for mesh_calc_normals */ +#include "BKE_global.h" /* for mesh_calc_normals */ -#include "gpu_buffers.h" +#include "GPU_buffers.h" #define LEAF_LIMIT 10000 @@ -96,6 +92,11 @@ struct PBVHNode { unsigned int uniq_verts, face_verts; char flag; + + float tmin; // used for raycasting, is how close bb is to the ray point + + int proxy_count; + PBVHProxyNode* proxies; }; struct PBVH { @@ -126,6 +127,9 @@ struct PBVH { #ifdef PERFCNTRS int perf_modified; #endif + + /* flag are verts/faces deformed */ + int deformed; }; #define STACK_FIXED_DEPTH 100 @@ -228,10 +232,21 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node) node->vb= vb; } +//void BLI_pbvh_node_BB_reset(PBVHNode* node) +//{ +// BB_reset(&node->vb); +//} +// +//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3]) +//{ +// BB_expand(&node->vb, co); +//} + + /* Adapted from BLI_kdopbvh.c */ /* Returns the index of the first element on the right of the partition */ static int partition_indices(int *prim_indices, int lo, int hi, int axis, - float mid, BBC *prim_bbc) + float mid, BBC *prim_bbc) { int i=lo, j=hi; for(;;) { @@ -247,7 +262,7 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, } void check_partitioning(int *prim_indices, int lo, int hi, int axis, - float mid, BBC *prim_bbc, int index_of_2nd_partition) + float mid, BBC *prim_bbc, int index_of_2nd_partition) { int i; for(i = lo; i <= hi; ++i) { @@ -279,8 +294,8 @@ static void grow_nodes(PBVH *bvh, int totnode) /* Add a vertex to the map, with a positive value for unique vertices and a negative value for additional vertices */ static int map_insert_vert(PBVH *bvh, GHash *map, - unsigned int *face_verts, - unsigned int *uniq_verts, int vertex) + unsigned int *face_verts, + unsigned int *uniq_verts, int vertex) { void *value, *key = SET_INT_IN_POINTER(vertex); @@ -309,7 +324,7 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) GHash *map; int i, j, totface; - map = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + map = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "build_mesh_leaf_node gh"); node->uniq_verts = node->face_verts = 0; totface= node->totprim; @@ -334,8 +349,8 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) /* Build the vertex list, unique verts first */ for(iter = BLI_ghashIterator_new(map), i = 0; - !BLI_ghashIterator_isDone(iter); - BLI_ghashIterator_step(iter), ++i) { + !BLI_ghashIterator_isDone(iter); + BLI_ghashIterator_step(iter), ++i) { void *value = BLI_ghashIterator_getValue(iter); int ndx = GET_INT_FROM_POINTER(value); @@ -352,21 +367,28 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) if(node->face_vert_indices[i] < 0) node->face_vert_indices[i]= -node->face_vert_indices[i] + node->uniq_verts - 1; - node->draw_buffers = - GPU_build_mesh_buffers(map, bvh->verts, bvh->faces, - node->prim_indices, - node->totprim, node->vert_indices, - node->uniq_verts, - node->uniq_verts + node->face_verts); + if(!G.background) { + node->draw_buffers = + GPU_build_mesh_buffers(map, bvh->verts, bvh->faces, + node->prim_indices, + node->totprim, node->vert_indices, + node->uniq_verts, + node->uniq_verts + node->face_verts); + } + + node->flag |= PBVH_UpdateDrawBuffers; BLI_ghash_free(map, NULL, NULL); } static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node) { - node->draw_buffers = - GPU_build_grid_buffers(bvh->grids, node->prim_indices, + if(!G.background) { + node->draw_buffers = + GPU_build_grid_buffers(bvh->grids, node->prim_indices, node->totprim, bvh->gridsize); + } + node->flag |= PBVH_UpdateDrawBuffers; } /* Recursively build a node in the tree @@ -381,7 +403,7 @@ static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node) */ void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, - int offset, int count) + int offset, int count) { int i, axis, end; BB cb_backing; @@ -578,6 +600,15 @@ void BLI_pbvh_free(PBVH *bvh) } } + if (bvh->deformed) { + if (bvh->verts) { + /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */ + + MEM_freeN(bvh->verts); + MEM_freeN(bvh->faces); + } + } + MEM_freeN(bvh->nodes); MEM_freeN(bvh->prim_indices); MEM_freeN(bvh); @@ -626,13 +657,12 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter) { PBVHNode *node; int revisiting; - void *search_data; /* purpose here is to traverse tree, visiting child nodes before their parents, this order is necessary for e.g. computing bounding boxes */ while(iter->stacksize) { - /* pop node */ + /* pop node */ iter->stacksize--; node= iter->stack[iter->stacksize].node; @@ -647,10 +677,7 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter) if(revisiting) return node; - /* check search callback */ - search_data= iter->search_data; - - if(iter->scb && !iter->scb(node, search_data)) + if(iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */ if(node->flag & PBVH_Leaf) { @@ -670,6 +697,34 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter) return NULL; } +static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter) +{ + PBVHNode *node; + + while(iter->stacksize) { + /* pop node */ + iter->stacksize--; + node= iter->stack[iter->stacksize].node; + + /* on a mesh with no faces this can happen + * can remove this check if we know meshes have at least 1 face */ + if(node==NULL) return NULL; + + if(iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */ + + if(node->flag & PBVH_Leaf) { + /* immediately hit leaf node */ + return node; + } + else { + pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset+1, 0); + pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset, 0); + } + } + + return NULL; +} + void BLI_pbvh_search_gather(PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot) @@ -721,12 +776,105 @@ void BLI_pbvh_search_callback(PBVH *bvh, pbvh_iter_begin(&iter, bvh, scb, search_data); while((node=pbvh_iter_next(&iter))) - if(node->flag & PBVH_Leaf) + if (node->flag & PBVH_Leaf) hcb(node, hit_data); pbvh_iter_end(&iter); } +typedef struct node_tree { + PBVHNode* data; + + struct node_tree* left; + struct node_tree* right; +} node_tree; + +static void node_tree_insert(node_tree* tree, node_tree* new_node) +{ + if (new_node->data->tmin < tree->data->tmin) { + if (tree->left) { + node_tree_insert(tree->left, new_node); + } + else { + tree->left = new_node; + } + } + else { + if (tree->right) { + node_tree_insert(tree->right, new_node); + } + else { + tree->right = new_node; + } + } +} + +static void traverse_tree(node_tree* tree, BLI_pbvh_HitOccludedCallback hcb, void* hit_data, float* tmin) +{ + if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin); + + hcb(tree->data, hit_data, tmin); + + if (tree->right) traverse_tree(tree->right, hcb, hit_data, tmin); +} + +static void free_tree(node_tree* tree) +{ + if (tree->left) { + free_tree(tree->left); + tree->left = 0; + } + + if (tree->right) { + free_tree(tree->right); + tree->right = 0; + } + + free(tree); +} + +float BLI_pbvh_node_get_tmin(PBVHNode* node) +{ + return node->tmin; +} + +void BLI_pbvh_search_callback_occluded(PBVH *bvh, + BLI_pbvh_SearchCallback scb, void *search_data, + BLI_pbvh_HitOccludedCallback hcb, void *hit_data) +{ + PBVHIter iter; + PBVHNode *node; + node_tree *tree = 0; + + pbvh_iter_begin(&iter, bvh, scb, search_data); + + while((node=pbvh_iter_next_occluded(&iter))) { + if(node->flag & PBVH_Leaf) { + node_tree* new_node = malloc(sizeof(node_tree)); + + new_node->data = node; + + new_node->left = NULL; + new_node->right = NULL; + + if (tree) { + node_tree_insert(tree, new_node); + } + else { + tree = new_node; + } + } + } + + pbvh_iter_end(&iter); + + if (tree) { + float tmin = FLT_MAX; + traverse_tree(tree, hcb, hit_data, &tmin); + free_tree(tree); + } +} + static int update_search_cb(PBVHNode *node, void *data_v) { int flag= GET_INT_FROM_POINTER(data_v); @@ -752,11 +900,11 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, /* subtle assumptions: - We know that for all edited vertices, the nodes with faces - adjacent to these vertices have been marked with PBVH_UpdateNormals. + adjacent to these vertices have been marked with PBVH_UpdateNormals. This is true because if the vertex is inside the brush radius, the bounding box of it's adjacent faces will be as well. - However this is only true for the vertices that have actually been - edited, not for all vertices in the nodes marked for update, so we + edited, not for all vertices in the nodes marked for update, so we can only update vertices marked with ME_VERT_PBVH_UPDATE. */ @@ -861,7 +1009,7 @@ static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, } } -static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) +static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int smooth) { PBVHNode *node; int n; @@ -876,7 +1024,8 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) bvh->grids, node->prim_indices, node->totprim, - bvh->gridsize); + bvh->gridsize, + smooth); } else { GPU_update_mesh_buffers(node->draw_buffers, @@ -936,9 +1085,6 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) if(flag & (PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw)) pbvh_update_BB_redraw(bvh, nodes, totnode, flag); - if(flag & PBVH_UpdateDrawBuffers) - pbvh_update_draw_buffers(bvh, nodes, totnode); - if(flag & (PBVH_UpdateBB|PBVH_UpdateOriginalBB)) pbvh_flush_bb(bvh, bvh->nodes, flag); @@ -972,9 +1118,10 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot GHashIterator *hiter; GHash *map; void *face, **faces; - int i, tot; + unsigned i; + int tot; - map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "pbvh_get_grid_updates gh"); pbvh_iter_begin(&iter, bvh, NULL, NULL); @@ -1004,8 +1151,8 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot faces= MEM_callocN(sizeof(void*)*tot, "PBVH Grid Faces"); for(hiter = BLI_ghashIterator_new(map), i = 0; - !BLI_ghashIterator_isDone(hiter); - BLI_ghashIterator_step(hiter), ++i) + !BLI_ghashIterator_isDone(hiter); + BLI_ghashIterator_step(hiter), ++i) faces[i]= BLI_ghashIterator_getKey(hiter); BLI_ghashIterator_free(hiter); @@ -1073,6 +1220,18 @@ void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max copy_v3_v3(bb_max, node->orig_vb.bmax); } +void BLI_pbvh_node_get_proxies(PBVHNode* node, PBVHProxyNode** proxies, int* proxy_count) +{ + if (node->proxy_count > 0) { + if (proxies) *proxies = node->proxies; + if (proxy_count) *proxy_count = node->proxy_count; + } + else { + if (proxies) *proxies = 0; + if (proxy_count) *proxy_count = 0; + } +} + /********************************* Raycast ***********************************/ typedef struct { @@ -1087,16 +1246,13 @@ typedef struct { static int ray_aabb_intersect(PBVHNode *node, void *data_v) { RaycastData *ray = data_v; - float bb_min[3], bb_max[3], bbox[2][3]; + float bbox[2][3]; float tmin, tmax, tymin, tymax, tzmin, tzmax; if(ray->original) - BLI_pbvh_node_get_original_BB(node, bb_min, bb_max); + BLI_pbvh_node_get_original_BB(node, bbox[0], bbox[1]); else - BLI_pbvh_node_get_BB(node, bb_min, bb_max); - - copy_v3_v3(bbox[0], bb_min); - copy_v3_v3(bbox[1], bb_max); + BLI_pbvh_node_get_BB(node, bbox[0], bbox[1]); tmin = (bbox[ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0]; tmax = (bbox[1-ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0]; @@ -1106,8 +1262,10 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v) if((tmin > tymax) || (tymin > tmax)) return 0; + if(tymin > tmin) tmin = tymin; + if(tymax < tmax) tmax = tymax; @@ -1116,21 +1274,21 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v) if((tmin > tzmax) || (tzmin > tmax)) return 0; - - return 1; - /* XXX: Not sure about this? - if(tzmin > tmin) - tmin = tzmin; - if(tzmax < tmax) - tmax = tzmax; - return ((tmin < t1) && (tmax > t0)); - */ + if(tzmin > tmin) + tmin = tzmin; + + // XXX jwilkins: tmax does not need to be updated since we don't use it + // keeping this here for future reference + //if(tzmax < tmax) tmax = tzmax; + node->tmin = tmin; + + return 1; } -void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data, - float ray_start[3], float ray_normal[3], int original) +void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, + float ray_start[3], float ray_normal[3], int original) { RaycastData rcd; @@ -1143,37 +1301,24 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data, rcd.sign[2] = rcd.inv_dir[2] < 0; rcd.original = original; - BLI_pbvh_search_callback(bvh, ray_aabb_intersect, &rcd, cb, data); + BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); } -/* XXX: Code largely copied from bvhutils.c, could be unified */ -/* Returns 1 if a better intersection has been found */ static int ray_face_intersection(float ray_start[3], float ray_normal[3], float *t0, float *t1, float *t2, float *t3, float *fdist) { - int hit = 0; - - do - { - float dist = FLT_MAX; - - if(!isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, - &dist, NULL, 0.1f)) - dist = FLT_MAX; - - if(dist >= 0 && dist < *fdist) { - hit = 1; - *fdist = dist; - } - - t1 = t2; - t2 = t3; - t3 = NULL; - - } while(t2); - - return hit; + float dist; + + if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) || + (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist)) + { + *fdist = dist; + return 1; + } + else { + return 0; + } } int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], @@ -1218,6 +1363,8 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], for(i = 0; i < totgrid; ++i) { DMGridData *grid= bvh->grids[node->prim_indices[i]]; + if (!grid) + continue; for(y = 0; y < gridsize-1; ++y) { for(x = 0; x < gridsize-1; ++x) { @@ -1304,9 +1451,18 @@ int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data) return 1; } -void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3]) +void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int smooth) { - BLI_pbvh_update(bvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers, face_nors); + PBVHNode **nodes; + int totnode; + + BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals|PBVH_UpdateDrawBuffers), + &nodes, &totnode); + + pbvh_update_normals(bvh, nodes, totnode, face_nors); + pbvh_update_draw_buffers(bvh, nodes, totnode, smooth); + + if(nodes) MEM_freeN(nodes); if(planes) { BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB, @@ -1317,3 +1473,145 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3]) } } +void BLI_pbvh_grids_update(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj, void **gridfaces) +{ + bvh->grids= grids; + bvh->gridadj= gridadj; + bvh->gridfaces= gridfaces; +} + +float (*BLI_pbvh_get_vertCos(PBVH *pbvh))[3] +{ + int a; + float (*vertCos)[3]= NULL; + + if (pbvh->verts) { + float *co; + MVert *mvert= pbvh->verts; + + vertCos= MEM_callocN(3*pbvh->totvert*sizeof(float), "BLI_pbvh_get_vertCoords"); + co= (float*)vertCos; + + for (a= 0; a<pbvh->totvert; a++, mvert++, co+= 3) { + copy_v3_v3(co, mvert->co); + } + } + + return vertCos; +} + +void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3]) +{ + int a; + + if (!pbvh->deformed) { + if (pbvh->verts) { + /* if pbvh is not already deformed, verts/faces points to the */ + /* original data and applying new coords to this arrays would lead to */ + /* unneeded deformation -- duplicate verts/faces to avoid this */ + + pbvh->verts= MEM_dupallocN(pbvh->verts); + pbvh->faces= MEM_dupallocN(pbvh->faces); + + pbvh->deformed= 1; + } + } + + if (pbvh->verts) { + /* copy new verts coords */ + for (a= 0; a < pbvh->totvert; ++a) { + copy_v3_v3(pbvh->verts[a].co, vertCos[a]); + } + + /* coordinates are new -- normals should also be updated */ + mesh_calc_normals(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL); + } +} + +int BLI_pbvh_isDeformed(PBVH *pbvh) +{ + return pbvh->deformed; +} +/* Proxies */ + +PBVHProxyNode* BLI_pbvh_node_add_proxy(PBVH* bvh, PBVHNode* node) +{ + int index, totverts; + + #pragma omp critical + { + + index = node->proxy_count; + + node->proxy_count++; + + if (node->proxies) + node->proxies= MEM_reallocN(node->proxies, node->proxy_count*sizeof(PBVHProxyNode)); + else + node->proxies= MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy"); + + if (bvh->grids) + totverts = node->totprim*bvh->gridsize*bvh->gridsize; + else + totverts = node->uniq_verts; + + node->proxies[index].co= MEM_callocN(sizeof(float[3])*totverts, "PBVHNodeProxy.co"); + } + + return node->proxies + index; +} + +void BLI_pbvh_node_free_proxies(PBVHNode* node) +{ + #pragma omp critical + { + int p; + + for (p= 0; p < node->proxy_count; p++) { + MEM_freeN(node->proxies[p].co); + node->proxies[p].co= 0; + } + + MEM_freeN(node->proxies); + node->proxies = 0; + + node->proxy_count= 0; + } +} + +void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** r_array, int* r_tot) +{ + PBVHNode **array= NULL, **newarray, *node; + int tot= 0, space= 0; + int n; + + for (n= 0; n < pbvh->totnode; n++) { + node = pbvh->nodes + n; + + if(node->proxy_count > 0) { + if(tot == space) { + /* resize array if needed */ + space= (tot == 0)? 32: space*2; + newarray= MEM_callocN(sizeof(PBVHNode)*space, "BLI_pbvh_gather_proxies"); + + if (array) { + memcpy(newarray, array, sizeof(PBVHNode)*tot); + MEM_freeN(array); + } + + array= newarray; + } + + array[tot]= node; + tot++; + } + } + + if(tot == 0 && array) { + MEM_freeN(array); + array= NULL; + } + + *r_array= array; + *r_tot= tot; +} diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 4e469ad3834..7c14cfd3426 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -37,10 +37,6 @@ #include "BLI_threads.h" #include "BLI_rand.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #if defined(WIN32) && !defined(FREE_WINDOWS) typedef unsigned __int64 r_uint64; diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 959d8be466f..5466acdba9f 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -36,11 +36,6 @@ */ #include "DNA_vec_types.h" -#include "BLI_blenlib.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif int BLI_rcti_is_empty(rcti * rect) { @@ -147,6 +142,27 @@ void BLI_translate_rctf(rctf *rect, float x, float y) rect->ymax += y; } +/* change width & height around the central location */ +void BLI_resize_rcti(rcti *rect, int x, int y) +{ + rect->xmin= rect->xmax= (rect->xmax + rect->xmin) / 2; + rect->ymin= rect->ymax= (rect->ymax + rect->ymin) / 2; + rect->xmin -= x / 2; + rect->ymin -= y / 2; + rect->xmax= rect->xmin + x; + rect->ymax= rect->ymin + y; +} + +void BLI_resize_rctf(rctf *rect, float x, float y) +{ + rect->xmin= rect->xmax= (rect->xmax + rect->xmin) * 0.5f; + rect->ymin= rect->ymax= (rect->ymax + rect->ymin) * 0.5f; + rect->xmin -= x * 0.5f; + rect->ymin -= y * 0.5f; + rect->xmax= rect->xmin + x; + rect->ymax= rect->ymin + y; +} + int BLI_isect_rctf(rctf *src1, rctf *src2, rctf *dest) { float xmin, xmax; diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index e430f78a100..d1150748dff 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -35,21 +35,13 @@ #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" -#include "DNA_mesh_types.h" #include "BLI_editVert.h" #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_scanfill.h" -#include "BLI_callbacks.h" #include "BKE_utildefines.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - /* callbacks for errors and interrupts and some goo */ static void (*BLI_localErrorCallBack)(char*) = NULL; static int (*BLI_localInterruptCallBack)(void) = NULL; @@ -187,7 +179,7 @@ static void *new_mem_element(int size) if(cur) { if(size+offs < blocksize) { adr= (void *) (cur->data+offs); - offs+= size; + offs+= size; return adr; } } @@ -306,7 +298,7 @@ static short testedgeside(float *v1, float *v2, float *v3) float inp; inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) - +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]); + +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]); if(inp<0.0) return 0; else if(inp==0) { @@ -383,7 +375,7 @@ static ScFillVert *addedgetoscanlist(EditEdge *eed, int len) /* find location in list */ scsearch.v1= eed->v1; sc= (ScFillVert *)bsearch(&scsearch,scdata,len, - sizeof(ScFillVert), vergscdata); + sizeof(ScFillVert), vergscdata); if(sc==0) printf("Error in search edge: %p\n",eed); else if(addedgetoscanvert(sc,eed)==0) return sc; diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index f21e5ef5575..3315e9645d4 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -76,7 +76,6 @@ #endif #ifdef WIN32 -#include <sys/types.h> #include <io.h> #include <direct.h> #include "BLI_winstuff.h" @@ -90,8 +89,6 @@ #include "BLI_listbase.h" #include "BLI_linklist.h" -#include "BLI_path_util.h" -#include "BLI_storage.h" #include "BLI_storage_types.h" #include "BLI_string.h" #include "BKE_utildefines.h" @@ -204,14 +201,6 @@ double BLI_diskfree(char *dir) #endif } -static int hide_dot= 0; - -void BLI_hide_dot_files(int set) -{ - if(set) hide_dot= 1; - else hide_dot= 0; -} - void BLI_builddir(char *dirname, char *relname) { struct dirent *fname; @@ -237,17 +226,12 @@ void BLI_builddir(char *dirname, char *relname) while ((fname = (struct dirent*) readdir(dir)) != NULL) { len= strlen(fname->d_name); - if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0); /* ignore .file */ - else if(hide_dot && len && fname->d_name[len-1]=='~'); /* ignore file~ */ - else if (((fname->d_name[0] == '.') && (fname->d_name[1] == 0) )); /* ignore . */ - else { - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink){ - strcpy(buf+rellen,fname->d_name); - dlink->name = BLI_strdup(buf); - BLI_addhead(dirbase,dlink); - newnum++; - } + dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink){ + strcpy(buf+rellen,fname->d_name); + dlink->name = BLI_strdup(buf); + BLI_addhead(dirbase,dlink); + newnum++; } } @@ -308,10 +292,8 @@ void BLI_adddirstrings() struct direntry * file; struct tm *tm; time_t zero= 0; - - file = &files[0]; - for(num=0;num<actnum;num++){ + for(num=0, file= files; num<actnum; num++, file++){ #ifdef WIN32 mode = 0; strcpy(file->mode1, types[0]); @@ -340,43 +322,43 @@ void BLI_adddirstrings() #endif #ifdef WIN32 - strcpy(files[num].owner,"user"); + strcpy(file->owner,"user"); #else { struct passwd *pwuser; - pwuser = getpwuid(files[num].s.st_uid); + pwuser = getpwuid(file->s.st_uid); if ( pwuser ) { - strcpy(files[num].owner, pwuser->pw_name); + BLI_strncpy(file->owner, pwuser->pw_name, sizeof(file->owner)); } else { - sprintf(files[num].owner, "%d", files[num].s.st_uid); - } + snprintf(file->owner, sizeof(file->owner), "%d", file->s.st_uid); + } } #endif - tm= localtime(&files[num].s.st_mtime); + tm= localtime(&file->s.st_mtime); // prevent impossible dates in windows if(tm==NULL) tm= localtime(&zero); - strftime(files[num].time, 8, "%H:%M", tm); - strftime(files[num].date, 16, "%d-%b-%y", tm); + strftime(file->time, 8, "%H:%M", tm); + strftime(file->date, 16, "%d-%b-%y", tm); /* * 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. */ - st_size= files[num].s.st_size; + st_size= file->s.st_size; if (st_size > 1024*1024*1024) { - sprintf(files[num].size, "%.2f GB", ((double)st_size)/(1024*1024*1024)); + sprintf(file->size, "%.2f GB", ((double)st_size)/(1024*1024*1024)); } else if (st_size > 1024*1024) { - sprintf(files[num].size, "%.1f MB", ((double)st_size)/(1024*1024)); + sprintf(file->size, "%.1f MB", ((double)st_size)/(1024*1024)); } else if (st_size > 1024) { - sprintf(files[num].size, "%d KB", (int)(st_size/1024)); + sprintf(file->size, "%d KB", (int)(st_size/1024)); } else { - sprintf(files[num].size, "%d B", (int)st_size); + sprintf(file->size, "%d B", (int)st_size); } strftime(datum, 32, "%d-%b-%y %H:%M", tm); @@ -392,15 +374,13 @@ void BLI_adddirstrings() sprintf(size, "%10d", (int) st_size); } - sprintf(buf,"%s %s %s %7s %s %s %10s %s", file->mode1, file->mode2, file->mode3, files[num].owner, files[num].date, files[num].time, size, - files[num].relname); + sprintf(buf,"%s %s %s %7s %s %s %10s %s", file->mode1, file->mode2, file->mode3, file->owner, file->date, file->time, size, + file->relname); - files[num].string=MEM_mallocN(strlen(buf)+1, "filestring"); - if (files[num].string){ - strcpy(files[num].string,buf); + file->string=MEM_mallocN(strlen(buf)+1, "filestring"); + if (file->string){ + strcpy(file->string,buf); } - - file++; } } @@ -452,18 +432,20 @@ int BLI_filepathsize(const char *path) int BLI_exist(char *name) { - struct stat st; #ifdef WIN32 + struct _stat64i32 st; /* in Windows stat doesn't recognize dir ending on a slash To not break code where the ending slash is expected we don't mess with the argument name directly here - elubie */ char tmp[FILE_MAXDIR+FILE_MAXFILE]; - int len; + int len, res; BLI_strncpy(tmp, name, FILE_MAXDIR+FILE_MAXFILE); len = strlen(tmp); if (len > 3 && ( tmp[len-1]=='\\' || tmp[len-1]=='/') ) tmp[len-1] = '\0'; - if (stat(tmp,&st)) return(0); + res = _stat(tmp, &st); + if (res == -1) return(0); #else + struct stat st; if (stat(name,&st)) return(0); #endif return(st.st_mode); @@ -519,3 +501,14 @@ void BLI_free_file_lines(LinkNode *lines) { BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN); } + +int BLI_file_older(const char *file1, const char *file2) +{ + struct stat st1, st2; + + if(stat(file1, &st1)) return 0; + if(stat(file2, &st2)) return 0; + + return (st1.st_mtime < st2.st_mtime); +} + diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index dd1d0a3bd4f..c344d8c0711 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -32,7 +32,6 @@ * */ -#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> @@ -221,10 +220,10 @@ int BLI_strcaseeq(const char *a, const char *b) /* strcasestr not available in MSVC */ char *BLI_strcasestr(const char *s, const char *find) { - register char c, sc; - register size_t len; + register char c, sc; + register size_t len; - if ((c = *find++) != 0) { + if ((c = *find++) != 0) { c= tolower(c); len = strlen(find); do { @@ -235,8 +234,8 @@ char *BLI_strcasestr(const char *s, const char *find) } while (sc != c); } while (BLI_strncasecmp(s, find, len) != 0); s--; - } - return ((char *) s); + } + return ((char *) s); } diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 371fae3dda2..726ed817f8b 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -28,15 +28,11 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> #include <errno.h> +#include <string.h> #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" #include "BLI_blenlib.h" #include "BLI_gsqueue.h" @@ -56,6 +52,12 @@ #include <sys/time.h> #endif +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) +/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */ +extern pthread_key_t gomp_tls_key; +static void *thread_tls_data; +#endif + /* ********** basic thread control API ************ Many thread cases have an X amount of jobs, and only an Y amount of @@ -103,7 +105,11 @@ A sample loop can look like this (pseudo c); static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_t mainid; static int thread_levels= 0; /* threads can be invoked inside threads */ /* just a max for security reasons */ @@ -127,6 +133,11 @@ static void BLI_unlock_malloc_thread(void) pthread_mutex_unlock(&_malloc_lock); } +void BLI_threadapi_init(void) +{ + mainid = pthread_self(); +} + /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) problem otherwise: scene render will kill of the mutex! */ @@ -134,7 +145,7 @@ static void BLI_unlock_malloc_thread(void) void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot) { int a; - + if(threadbase != NULL && tot > 0) { threadbase->first= threadbase->last= NULL; @@ -147,12 +158,20 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot) tslot->do_thread= do_thread; tslot->avail= 1; } - - if(thread_levels == 0) - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - - thread_levels++; } + + if(thread_levels == 0) { + MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + /* 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 + } + + thread_levels++; } /* amount of available threads */ @@ -181,6 +200,22 @@ int BLI_available_thread_index(ListBase *threadbase) return 0; } +static void *tslot_thread_start(void *tslot_p) +{ + ThreadSlot *tslot= (ThreadSlot*)tslot_p; + +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + /* 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); +} + +int BLI_thread_is_main(void) { + return pthread_equal(pthread_self(), mainid); +} void BLI_insert_thread(ListBase *threadbase, void *callerdata) { @@ -190,7 +225,7 @@ void BLI_insert_thread(ListBase *threadbase, void *callerdata) if(tslot->avail) { tslot->avail= 0; tslot->callerdata= callerdata; - pthread_create(&tslot->pthread, NULL, tslot->do_thread, tslot->callerdata); + pthread_create(&tslot->pthread, NULL, tslot_thread_start, tslot); return; } } @@ -203,8 +238,8 @@ void BLI_remove_thread(ListBase *threadbase, void *callerdata) for(tslot= threadbase->first; tslot; tslot= tslot->next) { if(tslot->callerdata==callerdata) { - tslot->callerdata= NULL; pthread_join(tslot->pthread, NULL); + tslot->callerdata= NULL; tslot->avail= 1; } } @@ -217,8 +252,8 @@ void BLI_remove_thread_index(ListBase *threadbase, int index) for(tslot = threadbase->first; tslot; tslot = tslot->next, counter++) { if (counter == index && tslot->avail == 0) { - tslot->callerdata = NULL; pthread_join(tslot->pthread, NULL); + tslot->callerdata = NULL; tslot->avail = 1; break; } @@ -231,8 +266,8 @@ void BLI_remove_threads(ListBase *threadbase) for(tslot = threadbase->first; tslot; tslot = tslot->next) { if (tslot->avail == 0) { - tslot->callerdata = NULL; pthread_join(tslot->pthread, NULL); + tslot->callerdata = NULL; tslot->avail = 1; } } @@ -252,11 +287,11 @@ void BLI_end_threads(ListBase *threadbase) } } BLI_freelistN(threadbase); - - thread_levels--; - if(thread_levels==0) - MEM_set_lock_callback(NULL, NULL); } + + thread_levels--; + if(thread_levels==0) + MEM_set_lock_callback(NULL, NULL); } /* System Information */ @@ -301,8 +336,14 @@ void BLI_lock_thread(int type) pthread_mutex_lock(&_image_lock); else if (type==LOCK_PREVIEW) pthread_mutex_lock(&_preview_lock); + else if (type==LOCK_VIEWER) + pthread_mutex_lock(&_viewer_lock); else if (type==LOCK_CUSTOM1) pthread_mutex_lock(&_custom1_lock); + else if (type==LOCK_RCACHE) + pthread_mutex_lock(&_rcache_lock); + else if (type==LOCK_OPENGL) + pthread_mutex_lock(&_opengl_lock); } void BLI_unlock_thread(int type) @@ -311,8 +352,14 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_image_lock); else if (type==LOCK_PREVIEW) pthread_mutex_unlock(&_preview_lock); + else if (type==LOCK_VIEWER) + pthread_mutex_unlock(&_viewer_lock); else if(type==LOCK_CUSTOM1) pthread_mutex_unlock(&_custom1_lock); + else if(type==LOCK_RCACHE) + pthread_mutex_unlock(&_rcache_lock); + else if(type==LOCK_OPENGL) + pthread_mutex_unlock(&_opengl_lock); } /* Mutex Locks */ diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c index b0a284c4074..0992e08b28f 100644 --- a/source/blender/blenlib/intern/time.c +++ b/source/blender/blenlib/intern/time.c @@ -26,14 +26,9 @@ * * ***** END GPL LICENSE BLOCK ***** */ -#include "PIL_time.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #ifdef WIN32 - +#include "PIL_time.h" #include <windows.h> double PIL_check_seconds_timer(void) diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c new file mode 100644 index 00000000000..cc115d52928 --- /dev/null +++ b/source/blender/blenlib/intern/uvproject.c @@ -0,0 +1,191 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_camera_types.h" +#include "DNA_object_types.h" + +#include "BLI_math.h" + +typedef struct UvCameraInfo { + float camangle; + float camsize; + float xasp, yasp; + float shiftx, shifty; + float rotmat[4][4]; + float caminv[4][4]; + short do_persp, do_pano, do_rotmat; +} UvCameraInfo; + +void project_from_camera(float target[2], float source[3], UvCameraInfo *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]) / (M_PI * 2.0); /* angle around the camera */ + if (uci->do_persp==0) { + target[0]= angle; /* no correct method here, just map to 0-1 */ + target[1]= pv4[1] / uci->camsize; + } + else { + float vec2d[2]= {pv4[0], pv4[2]}; /* 2D position from the camera */ + target[0]= angle * (M_PI / uci->camangle); + target[1]= pv4[1] / (len_v2(vec2d) * uci->camsize); + } + } + else { + if (pv4[2]==0.0f) pv4[2]= 0.00001f; /* don't allow div by 0 */ + + if (uci->do_persp==0) { + 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 project_from_view(float target[2], float source[3], float persmat[4][4], float rotmat[4][4], float winx, float winy) +{ + float pv[3], pv4[4], x= 0.0, y= 0.0; + + mul_v3_m4v3(pv, rotmat, source); + + copy_v3_v3(pv4, source); + pv4[3]= 1.0; + + /* rotmat is the object matrix in this case */ + mul_m4_v4(rotmat, pv4); + + /* almost project_short */ + mul_m4_v4(persmat, pv4); + if(fabs(pv4[3]) > 0.00001) { /* avoid division by zero */ + target[0] = winx/2.0 + (winx/2.0) * pv4[0] / pv4[3]; + target[1] = winy/2.0 + (winy/2.0) * pv4[1] / pv4[3]; + } + else { + /* scaling is lost but give a valid result */ + target[0] = winx/2.0 + (winx/2.0) * pv4[0]; + target[1] = winy/2.0 + (winy/2.0) * pv4[1]; + } + + /* v3d->persmat seems to do this funky scaling */ + if(winx > winy) { + y= (winx - winy)/2.0; + winy = winx; + } + else { + x= (winy - winx)/2.0; + 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 */ +UvCameraInfo *project_camera_info(Object *ob, float (*rotmat)[4], float winx, float winy) +{ + UvCameraInfo uci; + Camera *camera= ob->data; + + uci.do_pano = (camera->flag & CAM_PANORAMA); + uci.do_persp = (camera->type==CAM_PERSP); + + uci.camangle= lens_to_angle(camera->lens) / 2.0f; + uci.camsize= uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; + + if (invert_m4_m4(uci.caminv, ob->obmat)) { + UvCameraInfo *uci_pt; + + /* normal projection */ + if(rotmat) { + copy_m4_m4(uci.rotmat, rotmat); + uci.do_rotmat= 1; + } + else { + uci.do_rotmat= 0; + } + + /* 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.shifty = 0.5f - camera->shifty; + + uci_pt= MEM_mallocN(sizeof(UvCameraInfo), "UvCameraInfo"); + *uci_pt= uci; + return uci_pt; + } + + return NULL; +} + +void project_from_view_ortho(float target[2], float source[3], float rotmat[4][4]) +{ + float pv[3]; + + mul_v3_m4v3(pv, rotmat, source); + + /* ortho projection */ + target[0] = -pv[0]; + target[1] = pv[2]; +} + + +void project_camera_info_scale(UvCameraInfo *uci, float scale_x, float scale_y) +{ + uci->xasp *= scale_x; + uci->yasp *= scale_y; +} diff --git a/source/blender/blenlib/intern/voxel.c b/source/blender/blenlib/intern/voxel.c index 78267528e21..2b04a49e848 100644 --- a/source/blender/blenlib/intern/voxel.c +++ b/source/blender/blenlib/intern/voxel.c @@ -25,18 +25,12 @@ * * ***** END GPL LICENSE BLOCK ***** */ -#include <math.h> #include "BLI_voxel.h" #include "BKE_utildefines.h" - -#if defined( _MSC_VER ) && !defined( __cplusplus ) -# define inline __inline -#endif // defined( _MSC_VER ) && !defined( __cplusplus ) - -static inline float D(float *data, int *res, int x, int y, int z) +BM_INLINE float D(float *data, int *res, int x, int y, int z) { CLAMP(x, 0, res[0]-1); CLAMP(y, 0, res[1]-1); @@ -58,7 +52,7 @@ float voxel_sample_nearest(float *data, int *res, float *co) } // returns highest integer <= x as integer (slightly faster than floor()) -inline int FLOORI(float x) +BM_INLINE int FLOORI(float x) { const int r = (int)x; return ((x >= 0.f) || (float)r == x) ? r : (r - 1); @@ -66,7 +60,7 @@ inline int FLOORI(float x) // clamp function, cannot use the CLAMPIS macro, it sometimes returns unwanted results apparently related to gcc optimization flag -fstrict-overflow which is enabled at -O2 // this causes the test (x + 2) < 0 with int x == 2147483647 to return false (x being an integer, x + 2 should wrap around to -2147483647 so the test < 0 should return true, which it doesn't) -inline int _clamp(int a, int b, int c) +BM_INLINE int _clamp(int a, int b, int c) { return (a < b) ? b : ((a > c) ? c : a); } @@ -94,9 +88,9 @@ float voxel_sample_trilinear(float *data, int *res, float *co) 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]] ) ); + + 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; @@ -120,14 +114,14 @@ float voxel_sample_triquadratic(float *data, int *res, float *co) const float w[3] = {dz*(0.5f*dz - 1.f) + 0.5f, dz*(1.f - 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]] ) ); + + 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; @@ -177,21 +171,21 @@ float voxel_sample_tricubic(float *data, int *res, float *co, int bspline) } 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]] ) ); + + 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 194a164216a..f2261546f5c 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -28,10 +28,6 @@ * Windows-posix compatibility layer, windows-specific functions. */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #ifdef WIN32 #include <stdlib.h> @@ -225,21 +221,21 @@ int check_file_chars(char *filename) #include <string.h> char* dirname(char *path) { - char *p; - if( path == NULL || *path == '\0' ) - return "."; - p = path + strlen(path) - 1; - while( *p == '/' ) { - if( p == path ) - return path; - *p-- = '\0'; - } - while( p >= path && *p != '/' ) - p--; - return - p < path ? "." : - p == path ? "/" : - (*p = '\0', path); + char *p; + if( path == NULL || *path == '\0' ) + return "."; + p = path + strlen(path) - 1; + while( *p == '/' ) { + if( p == path ) + return path; + *p-- = '\0'; + } + while( p >= path && *p != '/' ) + p--; + return + p < path ? "." : + p == path ? "/" : + (*p = '\0', path); } /* End of copied part */ |