From 3e2529fcb543906ea6352ecafe86bc9421c50cf0 Mon Sep 17 00:00:00 2001 From: "erwin.coumans" Date: Wed, 5 Aug 2009 22:14:46 +0000 Subject: [PATCH] Minor constraint refactoring, to allow SPU-side processing for PLAYSTATION 3 (added non-virtual methods) Also comment-out some code for __SPU__ to reduce code size Added btContactConstraint (only used on PS3 SPU right now, better to use btPersistentManifold directly for contact constraints) Improved readblend utility library (see also usage in http://gamekit.googlecode.com with Irrlicht) Fix for btConvexConvexAlgorithm, potential division by zero Thanks linzner http://code.google.com/p/bullet/issues/detail?id=260 --- Extras/readblend/abs-file.h | 42 +- Extras/readblend/blendtype.h | 87 + Extras/readblend/readblend.c | 4060 +++++++++-------- Extras/readblend/readblend.h | 51 +- Extras/readblend/testblend.c | 205 +- .../btConvexConvexAlgorithm.cpp | 22 +- .../btConeTwistConstraint.cpp | 57 +- .../ConstraintSolver/btConeTwistConstraint.h | 5 +- .../ConstraintSolver/btContactConstraint.cpp | 394 +- .../ConstraintSolver/btContactConstraint.h | 123 +- .../ConstraintSolver/btHingeConstraint.cpp | 396 +- .../ConstraintSolver/btHingeConstraint.h | 12 +- .../ConstraintSolver/btJacobianEntry.h | 2 +- .../btPoint2PointConstraint.cpp | 26 +- .../btPoint2PointConstraint.h | 5 +- .../btSequentialImpulseConstraintSolver.h | 2 +- .../ConstraintSolver/btSliderConstraint.cpp | 54 +- .../ConstraintSolver/btSliderConstraint.h | 14 +- .../ConstraintSolver/btTypedConstraint.h | 3 +- .../SequentialThreadSupport.h | 5 + .../Win32ThreadSupport.cpp | 2 + 21 files changed, 2980 insertions(+), 2587 deletions(-) create mode 100644 Extras/readblend/blendtype.h diff --git a/Extras/readblend/abs-file.h b/Extras/readblend/abs-file.h index 1f0e89f7b..3e98ad06b 100644 --- a/Extras/readblend/abs-file.h +++ b/Extras/readblend/abs-file.h @@ -10,13 +10,18 @@ #ifndef _ABS_FILE_H #define _ABS_FILE_H - typedef unsigned char uint8_t; - typedef unsigned long int uint64_t; - typedef unsigned int uint32_t; - typedef int int32_t; +#ifdef WIN32 + + typedef unsigned char uint8_t; + typedef unsigned long int uint64_t; + typedef unsigned int uint32_t; + typedef int int32_t; typedef unsigned short uint16_t; typedef short int16_t; +#else +#include +#endif /* PLEASE NOTE: This license applies to abs-file.h ONLY; The version of @@ -194,6 +199,8 @@ static int MY_PUTS(const char *s, MY_FILETYPE *const fp) { #else /* !USE_PHYSFS */ +//#define USE_POSIX_FILES 1 +#ifdef USE_POSIX_FILES #define MY_FILETYPE FILE #define MY_READ(p,s,n,fp) fread(p,s,n,fp) #define MY_WRITE(p,s,n,fp) fwrite(p,s,n,fp) @@ -221,6 +228,33 @@ static long MY_FILELENGTH(FILE *fp) { fseek(fp, currentpos, SEEK_SET); /* restore previous cursor position */ return newpos; } +#else +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MY_FILETYPE char + + +long MY_FILELENGTH(FILE *fp); +MY_FILETYPE* MY_OPEN_FOR_READ(const char *const filename); +int MY_GETC(MY_FILETYPE *const fp); +void MY_SEEK(MY_FILETYPE* fp,int pos); +#define MY_REWIND(fp) MY_SEEK(fp,0) +int MY_READ(unsigned char* dest,int size,int num,MY_FILETYPE* fp); + +void MY_CLOSE(MY_FILETYPE* fp); +int MY_TELL(MY_FILETYPE* fp); +int MY_ATEOF(MY_FILETYPE* fp); + +#ifdef __cplusplus +} +#endif + +#endif //USE_POSIX_FILES + #endif /* USE_PHYSFS */ #endif /* _ABS_FILE_H */ diff --git a/Extras/readblend/blendtype.h b/Extras/readblend/blendtype.h new file mode 100644 index 000000000..da6feeb2e --- /dev/null +++ b/Extras/readblend/blendtype.h @@ -0,0 +1,87 @@ +#ifndef BLEND_TYPE_H +#define BLEND_TYPE_H +#include "abs-file.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _BlendField BlendField; +struct _BlendField { + char* field_bytes; + int field_bytes_count; + + /* the offset into field_bytes at which each field of a + structure begins. this is so we can keep the data aligned + correctly for various architectures. a non-structure type + is equivalent to a structure with a single field. + */ + int* field_offsets; + int field_offsets_count; +}; +struct _BlendBlock { + char tag[5]; + uint32_t blender_pointer; + /*void* fixed_pointer;*/ + + int type_index; + /* a block is simply an array of its type as defined by type_index. + array_entries is an array of pointers to each entry in the block's + array. + */ + BlendField *array_entries; + int array_entries_count; + void* customData; /* for Link blocks, with custom data such as .jpg pictures etc */ + int customDataSize; +}; + + +typedef struct _BlendBlock BlendBlock; + +/* the types extracted from the Blender file */ +typedef struct _BlendType BlendType; +struct _BlendType { + char* name; + int size; + + int is_struct; + + /* if is_struct... this defines the types of each of the structure fields */ + int fieldtypes_count; + int* fieldtypes; /* type indices */ + int fieldnames_count; + int* fieldnames; /* name indices */ +}; + + + + + + +/* the opaque BlendFile structure */ +typedef struct _BlendFile{ + BlendType* types; + int types_count; + + char* *names; + int names_count; + + int* strc_indices; + int strc_indices_count; + + BlendBlock *blocks; + int blocks_count; + + int name_undef; /* index of the name we add specially for top blocks */ + +} BlendFile; + + + + +#ifdef __cplusplus +} +#endif + +#endif //BLEND_TYPE_H \ No newline at end of file diff --git a/Extras/readblend/readblend.c b/Extras/readblend/readblend.c index 9a229d7cb..bf720d9a5 100644 --- a/Extras/readblend/readblend.c +++ b/Extras/readblend/readblend.c @@ -1,3 +1,4 @@ +#include "blendtype.h" #include //#include @@ -6,6 +7,90 @@ #include "abs-file.h" +#ifndef USE_POSIX_FILES + + + + +static char* gBuffer = 0; +static int gCurrentFilePtr = 0; +static int gFileSize = 0; + + +long MY_FILELENGTH(FILE *fp) { + long currentpos = ftell(fp); /* save current cursor position */ + long newpos; + fseek(fp, 0, SEEK_END); /* seek to end */ + newpos = ftell(fp); /* find position of end -- this is the length */ + fseek(fp, currentpos, SEEK_SET); /* restore previous cursor position */ + return newpos; +} + + +MY_FILETYPE* MY_OPEN_FOR_READ(const char *const filename) +{ + FILE* gFile = fopen(filename,"rb"); + if (gFile) + { + long currentpos = ftell(gFile); /* save current cursor position */ + long newpos; + int bytesRead; + + fseek(gFile, 0, SEEK_END); /* seek to end */ + newpos = ftell(gFile); /* find position of end -- this is the length */ + fseek(gFile, currentpos, SEEK_SET); /* restore previous cursor position */ + gFileSize = newpos; + gBuffer = (char*)malloc(gFileSize); + bytesRead = fread(gBuffer,gFileSize,1,gFile); + gCurrentFilePtr = 0; + fclose(gFile); + gFile = 0; + return gBuffer; + } + return 0; +} + +int MY_GETC(MY_FILETYPE *const fp) +{ + return gBuffer[gCurrentFilePtr++]; +} + +void MY_SEEK(MY_FILETYPE* fp,int pos) +{ + gCurrentFilePtr = pos; +} + +#define MY_REWIND(fp) MY_SEEK(fp,0) +int MY_READ(unsigned char* dest,int size,int num,MY_FILETYPE* fp) +{ + int n; + memcpy(dest,&gBuffer[gCurrentFilePtr],size*num); + gCurrentFilePtr += size*num; + return num; +} + +void MY_CLOSE(MY_FILETYPE* fp) +{ + free(gBuffer); + gBuffer = 0; + gCurrentFilePtr = 0; + gFileSize = 0; + +} + +int MY_TELL(MY_FILETYPE* fp) +{ + return gCurrentFilePtr; +} + +int MY_ATEOF(MY_FILETYPE* fp) +{ + return gCurrentFilePtrtypes = NULL; - rtn->types_count = 0; - rtn->names = NULL; - rtn->names_count = 0; - rtn->blocks = NULL; - rtn->blocks_count = 0; - rtn->strc_indices = NULL; - rtn->strc_indices_count = 0; - rtn->name_undef = -1; - return rtn; + BlendFile *rtn = malloc(sizeof(BlendFile)); + if (!rtn) { + dprintf(stderr, "out of mem making bf handle\n"); + return NULL; + } + rtn->types = NULL; + rtn->types_count = 0; + rtn->names = NULL; + rtn->names_count = 0; + rtn->blocks = NULL; + rtn->blocks_count = 0; + rtn->strc_indices = NULL; + rtn->strc_indices_count = 0; + rtn->name_undef = -1; + return rtn; } static long seek_past_string(MY_FILETYPE* file, const char *str) { - const int match_max = strlen(str); - int match_now = 0; + const int match_max = strlen(str); + int match_now = 0; - do { - const char c = MY_GETC(file); - if (c == str[match_now]) { - ++match_now; - } else { - match_now = 0; - } - } while(match_now < match_max && - !MY_ATEOF(file)); + do { + const char c = MY_GETC(file); + if (c == str[match_now]) { + ++match_now; + } else { + match_now = 0; + } + } while(match_now < match_max && + !MY_ATEOF(file)); - if (MY_ATEOF(file)) { - return -1; - } + if (MY_ATEOF(file)) { + return -1; + } - return MY_TELL(file) - match_max; + return MY_TELL(file) - match_max; } #define EXPANDO_MULTIPLE(ARRAY,ADDITIONPTR,NUMBER) \ -do { \ - (ARRAY) = realloc((ARRAY), sizeof((ARRAY)[0]) * (NUMBER +(ARRAY##_count))); \ - memcpy(&(ARRAY)[ARRAY##_count], ADDITIONPTR, sizeof((ARRAY)[0]) * NUMBER); \ - (ARRAY##_count) += NUMBER; \ -} while(0) + do { \ + (ARRAY) = realloc((ARRAY), sizeof((ARRAY)[0]) * (NUMBER +(ARRAY##_count))); \ + memcpy(&(ARRAY)[ARRAY##_count], ADDITIONPTR, sizeof((ARRAY)[0]) * NUMBER); \ + (ARRAY##_count) += NUMBER; \ + } while(0) #define EXPANDO(ARRAY,ADDITION) \ -do { \ - (ARRAY) = realloc((ARRAY), sizeof((ARRAY)[0]) * (1 + (ARRAY##_count))); \ - (ARRAY)[ARRAY##_count] = (ADDITION); \ - ++(ARRAY##_count); \ -} while(0) - + do { \ + (ARRAY) = realloc((ARRAY), sizeof((ARRAY)[0]) * (1 + (ARRAY##_count))); \ + (ARRAY)[ARRAY##_count] = (ADDITION); \ + ++(ARRAY##_count); \ + } while(0) static unsigned short read_ushort(MY_FILETYPE* file) { - unsigned char c[2]; - if (MY_READ(c, 2, 1, file) == 1) { - return c[0] | (c[1]<<8); - } else { - return 0xFFFF; - } + unsigned char c[2]; + if (MY_READ(c, 2, 1, file) == 1) + { + return c[0] | (c[1]<<8); + } else { + return 0xFFFF; + } } static long read_long(MY_FILETYPE* file) { - unsigned char c[4]; - if (MY_READ(c, 4, 1, file) == 1) { - return ((unsigned long)c[0] | (c[1]<<8) | (c[2]<<16) | (c[3]<<24)); - } else { - return 0xFFFFFFFF; - } + unsigned char c[4]; + if (MY_READ(c, 4, 1, file) == 1) { + return ((unsigned long)c[0] | (c[1]<<8) | (c[2]<<16) | (c[3]<<24)); + } else { + return 0xFFFFFFFF; + } } static unsigned long read_ulong(MY_FILETYPE* file) { - unsigned char c[4]; - if (MY_READ(c, 4, 1, file) == 1) { - return c[0] | (c[1]<<8) | (c[2]<<16) | (c[3]<<24); - } else { - return 0xFFFFFFFF; - } + unsigned char c[4]; + if (MY_READ(c, 4, 1, file) == 1) { + return c[0] | (c[1]<<8) | (c[2]<<16) | (c[3]<<24); + } else { + return 0xFFFFFFFF; + } } static int name_is_pointer(char* name) { - int len = strlen(name); - /*fprintf(stderr,"[%s]",name);*/ - if (len >= 1) { - if (name[0] == '*') - return 1; - } - if (len >= 2) { - if (name[1] == '*') - return 1; - } - return 0; + int len = strlen(name); + /*fprintf(stderr,"[%s]",name);*/ + if (len >= 1) { + if (name[0] == '*') + return 1; + } + if (len >= 2) { + if (name[1] == '*') + return 1; + } + return 0; } /* note: we only deal with 1d or 2d arrays at the moment. haven't - seen any arrays of a higher order from Blender yet. */ +seen any arrays of a higher order from Blender yet. */ static int name_is_array(char* name, int* dim1, int* dim2) { - int len = strlen(name); - /*fprintf(stderr,"[%s]",name);*/ - /*if (len >= 1) { - if (name[len-1] != ']') - return 1; - } - return 0;*/ - char *bp; - int num; - if (dim1) { - *dim1 = 1; - } - if (dim2) { - *dim2 = 1; - } - bp = strchr(name, '['); - if (!bp) { - return 0; - } - num = 0; - while (++bp < name+len-1) { - const char c = *bp; - if (c == ']') { - break; - } - if (c <= '9' && c >= '0') { - num *= 10; - num += (c - '0'); - } else { - dprintf(stderr, "array parse error.\n"); - return 0; - } - } - if (dim2) { - *dim2 = num; - } + int len = strlen(name); + /*fprintf(stderr,"[%s]",name);*/ + /*if (len >= 1) { + if (name[len-1] != ']') + return 1; + } + return 0;*/ + char *bp; + int num; + if (dim1) { + *dim1 = 1; + } + if (dim2) { + *dim2 = 1; + } + bp = strchr(name, '['); + if (!bp) { + return 0; + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + dprintf(stderr, "array parse error.\n"); + return 0; + } + } + if (dim2) { + *dim2 = num; + } - /* find second dim, if any. */ - bp = strchr(bp, '['); - if (!bp) { - return 1; /* at least we got the first dim. */ - } - num = 0; - while (++bp < name+len-1) { - const char c = *bp; - if (c == ']') { - break; - } - if (c <= '9' && c >= '0') { - num *= 10; - num += (c - '0'); - } else { - dprintf(stderr, "array2 parse error.\n"); - return 1; - } - } - if (dim1) { - if (dim2) { - *dim1 = *dim2; - *dim2 = num; - } else { - *dim1 = num; - } - } + /* find second dim, if any. */ + bp = strchr(bp, '['); + if (!bp) { + return 1; /* at least we got the first dim. */ + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + dprintf(stderr, "array2 parse error.\n"); + return 1; + } + } + if (dim1) { + if (dim2) { + *dim1 = *dim2; + *dim2 = num; + } else { + *dim1 = num; + } + } - return 1; + return 1; } @@ -317,782 +344,831 @@ name_is_array(char* name, int* dim1, int* dim2) { static void recursively_read_type(MY_FILETYPE* file, BlendFile* bf, - unsigned long section_type, - BlendField* field) + unsigned long section_type, + BlendField* field) { - char *new_data = NULL; - int new_data_size = 0; - int dim1, dim2; + char *new_data = NULL; + int new_data_size = 0; + int dim1, dim2; - if (bf->types[section_type].is_struct) { - int i; - /*fprintf(stderr, "type%d(%s)is_struct(%d) ", section_type, bf->types[section_type].name, bf->types[section_type].size);*/ - for (i=0; itypes[section_type].fieldtypes_count; ++i) { - /*fprintf(stderr, "@%d ", i);*/ - int j,k; + if (bf->types[section_type].is_struct) { + int i; + /*fprintf(stderr, "type%d(%s)is_struct(%d) ", section_type, bf->types[section_type].name, bf->types[section_type].size);*/ + for (i=0; itypes[section_type].fieldtypes_count; ++i) { + /*fprintf(stderr, "@%d ", i);*/ + int j,k; #if 0 - if (name_is_array(bf->names[bf->types[section_type].fieldnames[i]], - &j,&k) || 1) { - dprintf(stderr, " %s/%s=[%d][%d] ", - bf->types[bf->types[section_type].fieldtypes[i]].name, - bf->names[bf->types[section_type].fieldnames[i]], j, k); - } + if (name_is_array(bf->names[bf->types[section_type].fieldnames[i]], + &j,&k) || 1) { + dprintf(stderr, " %s/%s=[%d][%d] ", + bf->types[bf->types[section_type].fieldtypes[i]].name, + bf->names[bf->types[section_type].fieldnames[i]], j, k); + } #endif - if (name_is_pointer(bf->names[bf->types[section_type].fieldnames[i]])) { - /*fprintf(stderr, "*(4) ");*/ - name_is_array(bf->names[bf->types[section_type].fieldnames[i]], - &dim1,&dim2); - new_data_size = SIZE_ROUNDUP(4); - new_data = malloc(new_data_size); - /*fprintf(stderr, " ");*/ - for (j=0; jfield_offsets, field->field_bytes_count); - EXPANDO_MULTIPLE(field->field_bytes, new_data, new_data_size); - /*fprintf(stderr, "N*(%d) ", new_data_size);*/ - } + if (name_is_pointer(bf->names[bf->types[section_type].fieldnames[i]])) { + /*fprintf(stderr, "*(4) ");*/ + name_is_array(bf->names[bf->types[section_type].fieldnames[i]], + &dim1,&dim2); + new_data_size = SIZE_ROUNDUP(4); + new_data = malloc(new_data_size); + /*fprintf(stderr, " ");*/ + for (j=0; jfield_offsets, field->field_bytes_count); + + (field->field_offsets) = realloc((field->field_offsets), sizeof((field->field_offsets)[0]) * (1 + (field->field_offsets_count))); + (field->field_offsets)[field->field_offsets_count] = (field->field_bytes_count); + ++(field->field_offsets_count); + + + // EXPANDO_MULTIPLE(field->field_bytes, new_data, new_data_size); + { + (field->field_bytes) = realloc((field->field_bytes), sizeof((field->field_bytes)[0]) * (new_data_size +(field->field_bytes_count))); + memcpy(&(field->field_bytes)[field->field_bytes_count], new_data, sizeof((field->field_bytes)[0]) * new_data_size); + (field->field_bytes_count) += new_data_size; + } + + /*fprintf(stderr, "N*(%d) ", new_data_size);*/ + } + } + free(new_data); + } else { + name_is_array(bf->names[bf->types[section_type].fieldnames[i]], + &dim1,&dim2); + /*fprintf(stderr, " ");*/ + for (j=0; jtypes[section_type].fieldtypes[i], + field); + } + } + } + } + } else { + /*fprintf(stderr, "type%d(%s)plain(%d) ", section_type, bf->types[section_type].name, bf->types[section_type].size); */ + new_data_size = SIZE_ROUNDUP(bf->types[section_type].size); + /*fprintf(stderr, "%d... ", bf->types[section_type].size); + if (bf->types[section_type].size > 4) { + fprintf(stderr, "%d ", field->field_bytes_count); + }*/ + if (new_data_size) { + new_data = malloc(new_data_size); + MY_READ(new_data, 1, bf->types[section_type].size, file); + EXPANDO(field->field_offsets, field->field_bytes_count); + EXPANDO_MULTIPLE(field->field_bytes, new_data, new_data_size); + /*fprintf(stderr, "ND(%d) ", new_data_size); */ + free(new_data); + } else { + dprintf(stderr, " ", + bf->types[section_type].size); + } } - free(new_data); - } else { - name_is_array(bf->names[bf->types[section_type].fieldnames[i]], - &dim1,&dim2); - /*fprintf(stderr, " ");*/ - for (j=0; jtypes[section_type].fieldtypes[i], - field); - } - } - } - } - } else { - /*fprintf(stderr, "type%d(%s)plain(%d) ", section_type, bf->types[section_type].name, bf->types[section_type].size); */ - new_data_size = SIZE_ROUNDUP(bf->types[section_type].size); - /*fprintf(stderr, "%d... ", bf->types[section_type].size); - if (bf->types[section_type].size > 4) { - fprintf(stderr, "%d ", field->field_bytes_count); - }*/ - if (new_data_size) { - new_data = malloc(new_data_size); - MY_READ(new_data, 1, bf->types[section_type].size, file); - EXPANDO(field->field_offsets, field->field_bytes_count); - EXPANDO_MULTIPLE(field->field_bytes, new_data, new_data_size); - /*fprintf(stderr, "ND(%d) ", new_data_size); */ - free(new_data); - } else { - dprintf(stderr, " ", - bf->types[section_type].size); - } - } } static BlendField read_type(MY_FILETYPE* file, BlendFile* bf, - unsigned long section_type) + unsigned long section_type) { - BlendField rtn; + BlendField rtn; - rtn.field_bytes = NULL; - rtn.field_bytes_count = 0; - rtn.field_offsets = NULL; - rtn.field_offsets_count = 0; - - recursively_read_type(file, bf, section_type, &rtn); + rtn.field_bytes = NULL; + rtn.field_bytes_count = 0; + rtn.field_offsets = NULL; + rtn.field_offsets_count = 0; - return rtn; + recursively_read_type(file, bf, section_type, &rtn); + + return rtn; } static int blend_read_data(MY_FILETYPE* file, BlendFile* bf) { - long next_block_start = 12; - int finished_extracting = 0; - char section_name[5] = {0,0, 0,0, 0}; + long next_block_start = 12; + int finished_extracting = 0; + char section_name[5] = {0,0, 0,0, 0}; - /* slurp up the whole file block by block! */ + /* slurp up the whole file block by block! */ - do { - unsigned long section_size; - unsigned long section_pointer; - unsigned long section_type; - unsigned long section_ents; + do { + unsigned long section_size; + unsigned long section_pointer; + unsigned long section_type; + unsigned long section_ents; + MY_SEEK(file, next_block_start); - MY_SEEK(file, next_block_start); + MY_READ(section_name, 4, 1, file); - MY_READ(section_name, 4, 1, file); - if (strcmp(section_name, "DNA1") != 0) { - int i; - BlendBlock block; + if (strcmp(section_name, "DNA1") != 0) { - section_size = read_ulong(file); - section_pointer = read_ulong(file); - section_type = read_ulong(file); - section_type = bf->strc_indices[section_type]; - section_ents = read_ulong(file); - memcpy(block.tag, section_name, 4); - block.tag[4] = '\0'; - block.type_index = section_type; - block.blender_pointer = section_pointer; - /*block.fixed_pointer = NULL;*/ - block.array_entries = NULL; - block.array_entries_count = 0; + int i; + BlendBlock block; - /*dprintf(stderr, "\nsizeof(%s)=%ld: %s[%ld]\n", section_name, section_size, bf->types[section_type].name, section_ents); */ - for (i=0; iblocks, block); + if (strcmp(section_name, "IM") == 0) { + //printf("image\n"); + } - next_block_start += 4+4+4+4+4 + section_size; + + + + if (strcmp(section_name, "IP") == 0) { +// printf("ipo\n"); + } + + section_size = read_ulong(file); + section_pointer = read_ulong(file); + section_type = read_ulong(file); + section_type = bf->strc_indices[section_type]; + section_ents = read_ulong(file); + + if (dumpNames) + { +// printf("section_name = %s, section_type = %d / %s\n",section_name,section_type,bf->types[section_type]); + + } + + memcpy(block.tag, section_name, 4); + block.tag[4] = '\0'; + block.type_index = section_type; + block.blender_pointer = section_pointer; + /*block.fixed_pointer = NULL;*/ + block.array_entries = NULL; + block.array_entries_count = 0; + block.customData = 0; + block.customDataSize = 0; + + // dprintf(stderr, "\nsizeof(%s)=%ld: %s[%ld]\n", section_name, section_size, bf->types[section_type].name, section_ents); + + if (strcmp("Link",bf->types[section_type].name)==0) + { + if (section_size>0) + { + //read customData + block.customData= (char*)malloc(section_size); + block.customDataSize = section_size; + MY_READ(block.customData,1,section_size,file); + } + } else + { + for (i=0; iblocks, block); + + next_block_start += 4+4+4+4+4 + section_size; #ifdef B_DEBUG - if (MY_TELL(file) > next_block_start) { - dprintf(stderr, " **OVER-READ(%ld,%ld)** ", - MY_TELL(file), next_block_start); - if (strcmp(bf->types[section_type].name, "Link") == 0 && - MY_TELL(file) - next_block_start == 4) { - dprintf(stderr, "<- don't panic, known Link struct weirdness."); - } else { - dprintf(stderr, "<- okay, PANIC!"); - } - dprintf(stderr, "\n"); - } else if (MY_TELL(file) < next_block_start) { - /*dprintf(stderr, " **under-READ(%ld,%ld)** ", - MY_TELL(file), next_block_start);*/ - } else { - /*dprintf(stderr, " :) ");*/ - } + if (MY_TELL(file) > next_block_start) { + //dprintf(stderr, " **OVER-READ(%ld,%ld)** ", MY_TELL(file), next_block_start); + if (strcmp(bf->types[section_type].name, "Link") == 0 && + MY_TELL(file) - next_block_start == 4) { + //dprintf(stderr, "<- don't panic, known Link struct weirdness."); + } else { + dprintf(stderr, "<- okay, PANIC!"); + } + //dprintf(stderr, "\n"); + } else if (MY_TELL(file) < next_block_start) { + /*dprintf(stderr, " **under-READ(%ld,%ld)** ", + MY_TELL(file), next_block_start);*/ + } else { + /*dprintf(stderr, " :) ");*/ + } #endif - - } else { - finished_extracting = 1; - } - } while (!finished_extracting); + } else { + finished_extracting = 1; + } - return 1; + } while (!finished_extracting); + + return 1; } BlendFile* blend_read(MY_FILETYPE* file) { - char blender_mark[8] = {0,0,0,0, 0,0,0,0}; - BlendFile *bf; - long sdnaname_offs, type_offs, tlen_offs, strc_offs, endb_offs; - long sdnaname_size, type_size, tlen_size, strc_size; - long sdnaname_ents, type_ents, tlen_ents, strc_ents; + char blender_mark[10] = {0,0,0,0, 0,0,0,0,0,0}; + BlendFile *bf; + long sdnaname_offs, type_offs, tlen_offs, strc_offs, endb_offs; + long sdnaname_size, type_size, tlen_size, strc_size; + long sdnaname_ents, type_ents, tlen_ents, strc_ents; - MY_REWIND(file); + MY_REWIND(file); - /* Check file signature */ + /* Check file signature */ - MY_READ(blender_mark, 1, 7, file); - if (strcmp(blender_mark, "BLENDER") != 0) { - dprintf(stderr, "Not a Blender file.\n"); - return NULL; - } - - /* Alloc a handle to return */ - - bf = bf_new(); - - /* Scan the whole file (!) for file section markers */ - - sdnaname_offs = seek_past_string(file, "SDNANAME"); - sdnaname_ents = read_long(file); - type_offs = seek_past_string(file, "TYPE"); - type_ents = read_long(file); - tlen_offs = seek_past_string(file, "TLEN"); - tlen_ents = type_ents; - strc_offs = seek_past_string(file, "STRC"); - strc_ents = read_long(file); - endb_offs = seek_past_string(file, "ENDB"); - - if (sdnaname_offs == -1 || type_offs == -1 || tlen_offs == -1 || - strc_offs == -1 || endb_offs == -1) { - dprintf(stderr, "Couldn't find all necessary file markers. :(\n"); - return NULL; - } - - /* Move marker offsets to point to the start of each one's block */ - - sdnaname_offs += 8 + 4; - sdnaname_size = type_offs - sdnaname_offs; - - type_offs += 4 + 4; - type_size = tlen_offs - type_offs; - - tlen_offs += 4; - tlen_size = strc_offs - tlen_offs; - - strc_offs += 4 + 4; - strc_size = endb_offs - strc_offs; - - /* read the NAME table */ - - MY_SEEK(file, sdnaname_offs); - { - long offs = 0; - int i; - char *top_block_name; - - for (i=0; inames, this_name_chars); - } - /* our top-block name */ + /* Alloc a handle to return */ + + bf = bf_new(); + + /* Scan the whole file (!) for file section markers */ + + sdnaname_offs = seek_past_string(file, "SDNANAME"); + sdnaname_ents = read_long(file); + type_offs = seek_past_string(file, "TYPE"); + type_ents = read_long(file); + tlen_offs = seek_past_string(file, "TLEN"); + tlen_ents = type_ents; + strc_offs = seek_past_string(file, "STRC"); + strc_ents = read_long(file); + endb_offs = seek_past_string(file, "ENDB"); + + if (sdnaname_offs == -1 || type_offs == -1 || tlen_offs == -1 || + strc_offs == -1 || endb_offs == -1) { + dprintf(stderr, "Couldn't find all necessary file markers. :(\n"); + return NULL; + } + + /* Move marker offsets to point to the start of each one's block */ + + sdnaname_offs += 8 + 4; + sdnaname_size = type_offs - sdnaname_offs; + + type_offs += 4 + 4; + type_size = tlen_offs - type_offs; + + tlen_offs += 4; + tlen_size = strc_offs - tlen_offs; + + strc_offs += 4 + 4; + strc_size = endb_offs - strc_offs; + + /* read the NAME table */ + + MY_SEEK(file, sdnaname_offs); + { + long offs = 0; + int i; + char *top_block_name; + + for (i=0; inames, this_name_chars); + } + + /* our top-block name */ #define BLEND_TOP_BLOCK_NAME "READBLEND_TOP_BLOCK" - top_block_name = calloc(1, 1+strlen(BLEND_TOP_BLOCK_NAME)); - strcpy(top_block_name, BLEND_TOP_BLOCK_NAME); - bf->name_undef = bf->names_count; - EXPANDO(bf->names, top_block_name); - } - - /* read the TYPE table */ - - MY_SEEK(file, type_offs); - { - long offs = 0; - int i; - - for (i=0; iname_undef = bf->names_count; + EXPANDO(bf->names, top_block_name); } - - EXPANDO(this_type_chars, c); - } while (!finished_type); - - bt.name = this_type_chars; - bt.size = -1; - bt.is_struct = 0; - bt.fieldtypes_count = 0; - bt.fieldtypes = NULL; - bt.fieldnames_count = 0; - bt.fieldnames = NULL; - /* fprintf(stderr, "(%d:%s)", bt.size, bt.name);*/ + /* read the TYPE table */ - EXPANDO(bf->types, bt); - } - } + MY_SEEK(file, type_offs); + { + long offs = 0; + int i; - /* read the TLEN table */ + for (i=0; itypes_count; ++i) { - unsigned short len = read_ushort(file); - bf->types[i].size = len; - /*fprintf(stderr, "sizeof(%s)=%d ", bf->types[i].name, len); */ - } - } + do { + const char c = MY_GETC(file); + ++offs; + if (offs == type_size || + c == '\0') { + finished_type = 1; + } - /* Read the STRC table */ - - MY_SEEK(file, strc_offs); - { - int i,j; - for (i=0; itypes[struc_type_index].is_struct = 1; - EXPANDO(bf->strc_indices, struc_type_index); - /*dprintf(stderr, "\n%s: ", bf->types[struc_type_index].name); */ - for (j=0; jtypes[struc_type_index].fieldtypes, ftype); - EXPANDO(bf->types[struc_type_index].fieldnames, fname); - /*dprintf(stderr, "%s %s , ", bf->types[ftype].name, bf->names[fname]); */ - } - } - } + EXPANDO(this_type_chars, c); + } while (!finished_type); - blend_read_data(file, bf); + bt.name = this_type_chars; + bt.size = -1; + bt.is_struct = 0; + bt.fieldtypes_count = 0; + bt.fieldtypes = NULL; + bt.fieldnames_count = 0; + bt.fieldnames = NULL; - /* Return the new handle */ + /* fprintf(stderr, "(%d:%s)", bt.size, bt.name);*/ - return bf; + EXPANDO(bf->types, bt); + } + } + + /* read the TLEN table */ + + MY_SEEK(file, tlen_offs); + { + int i; + for (i=0; itypes_count; ++i) { + unsigned short len = read_ushort(file); + bf->types[i].size = len; + /*fprintf(stderr, "sizeof(%s)=%d ", bf->types[i].name, len); */ + } + } + + /* Read the STRC table */ + + MY_SEEK(file, strc_offs); + { + int i,j; + for (i=0; itypes[struc_type_index].is_struct = 1; + EXPANDO(bf->strc_indices, struc_type_index); + /*dprintf(stderr, "\n%s: ", bf->types[struc_type_index].name); */ + for (j=0; jtypes[struc_type_index].fieldtypes, ftype); + EXPANDO(bf->types[struc_type_index].fieldnames, fname); + /*dprintf(stderr, "%s %s , ", bf->types[ftype].name, bf->names[fname]); */ + } + } + } + + blend_read_data(file, bf); + + /* Return the new handle */ + + return bf; } static void free_btype_inner(BlendType *btype) { - if (btype->name) { - free(btype->name); - } else { - dprintf(stderr, "null typename.\n"); - } + if (btype->name) { + free(btype->name); + } else { + dprintf(stderr, "null typename.\n"); + } - if (btype->fieldtypes) { - free(btype->fieldtypes); - } + if (btype->fieldtypes) { + free(btype->fieldtypes); + } - if (btype->fieldnames) { - free(btype->fieldnames); - } + if (btype->fieldnames) { + free(btype->fieldnames); + } } static void free_bfield_inner(BlendField *bfield) { - if (bfield->field_bytes) { - free(bfield->field_bytes); - } + if (bfield->field_bytes) { + free(bfield->field_bytes); + } - if (bfield->field_offsets) { - free(bfield->field_offsets); - } + if (bfield->field_offsets) { + free(bfield->field_offsets); + } } static void free_bblock_inner(BlendBlock *bblock) { - int i; - - for (i=0; iarray_entries_count; ++i) { - free_bfield_inner(&bblock->array_entries[i]); - } - free(bblock->array_entries); + int i; + + for (i=0; iarray_entries_count; ++i) { + free_bfield_inner(&bblock->array_entries[i]); + } + free(bblock->array_entries); } void blend_free(BlendFile* blend_file) { - int i; + int i; - for (i=0; itypes_count; ++i) { - free_btype_inner(&blend_file->types[i]); - } - if (blend_file->types) { - free(blend_file->types); - } + for (i=0; itypes_count; ++i) { + free_btype_inner(&blend_file->types[i]); + } + if (blend_file->types) { + free(blend_file->types); + } - for (i=0; inames_count; ++i) { - if (blend_file->names[i]) { - free(blend_file->names[i]); - } else { - dprintf(stderr, "null name.\n"); - } - } - if (blend_file->names) { - free(blend_file->names); - } + for (i=0; inames_count; ++i) { + if (blend_file->names[i]) { + free(blend_file->names[i]); + } else { + dprintf(stderr, "null name.\n"); + } + } + if (blend_file->names) { + free(blend_file->names); + } - for (i=0; iblocks_count; ++i) { - free_bblock_inner(&blend_file->blocks[i]); - } - if (blend_file->blocks) { - free(blend_file->blocks); - } + for (i=0; iblocks_count; ++i) { + free_bblock_inner(&blend_file->blocks[i]); + } + if (blend_file->blocks) { + free(blend_file->blocks); + } - if (blend_file->strc_indices) { - free(blend_file->strc_indices); - } + if (blend_file->strc_indices) { + free(blend_file->strc_indices); + } - free(blend_file); + free(blend_file); } /******************************************************************** - * done with the reading/parsing logic; now for the querying logic * - ********************************************************************/ - +* done with the reading/parsing logic; now for the querying logic * +********************************************************************/ + /******************************************************************** - * LOW-LEVEL * - ********************************************************************/ +* LOW-LEVEL * +********************************************************************/ const char* blend_block_get_tagname(BlendFile* blend_file, - BlendBlockPointer block) + BlendBlockPointer block) { - const BlendBlock *const bb = block; - return bb->tag; + const BlendBlock *const bb = block; + return bb->tag; } const char* blend_block_get_typename(BlendFile* blend_file, - BlendBlockPointer block) + BlendBlockPointer block) { - const BlendBlock *const bb = block; - return blend_file->types[bb->type_index].name; + const BlendBlock *const bb = block; + return blend_file->types[bb->type_index].name; } int blend_block_get_entry_count(BlendFile* blend_file, - BlendBlockPointer block) + BlendBlockPointer block) { - const BlendBlock *const bb = block; - return bb->array_entries_count;; + const BlendBlock *const bb = block; + return bb->array_entries_count;; } void blend_foreach_block(BlendFile* blend_file, - BlendBlockCallback* func, - void* userdata) + BlendBlockCallback* func, + void* userdata) { - int i; - for (i=0; iblocks_count; ++i) { - if (!func(&blend_file->blocks[i], blend_file, userdata)) return; - } + int i; + for (i=0; iblocks_count; ++i) { + if (!func(&blend_file->blocks[i], blend_file, userdata)) return; + } } static int blend_type_basename_compare(const char *fancy, const char *raw) { - const int flen = strlen(fancy); - const int rlen = strlen(raw); - int i, strcmp_result = 123; + const int flen = strlen(fancy); + const int rlen = strlen(raw); + int i, strcmp_result = 123; - i = 0; - while (i < flen && (fancy[i]=='*' || fancy[i]=='(')) { - ++i; - } + i = 0; + while (i < flen && (fancy[i]=='*' || fancy[i]=='(')) { + ++i; + } - strcmp_result = strncmp(&fancy[i], raw, rlen); + strcmp_result = strncmp(&fancy[i], raw, rlen); - if (strcmp_result == 0 && flen > rlen+i) { - i = rlen + i; - if (fancy[i] != ')' && fancy[i] != '(' && fancy[i] != '[') { - strcmp_result = -1; - } - } + if (strcmp_result == 0 && flen > rlen+i) { + i = rlen + i; + if (fancy[i] != ')' && fancy[i] != '(' && fancy[i] != '[') { + strcmp_result = -1; + } + } - return strcmp_result; + return strcmp_result; } static BlendObjType typestring_to_blendobj_type(BlendFile* blend_file, - const char* type_name) { - if (blend_type_basename_compare(type_name, "char") == 0) { - return BLEND_OBJ_CHAR8; - } else if (blend_type_basename_compare(type_name, "uchar") == 0) { - return BLEND_OBJ_UCHAR8; - } else if (blend_type_basename_compare(type_name, "short") == 0) { - return BLEND_OBJ_SHORT16; - } else if (blend_type_basename_compare(type_name, "ushort") == 0) { - return BLEND_OBJ_USHORT16; - } else if (blend_type_basename_compare(type_name, "int") == 0) { - return BLEND_OBJ_LONG32; - } else if (blend_type_basename_compare(type_name, "long") == 0) { - return BLEND_OBJ_LONG32; - } else if (blend_type_basename_compare(type_name, "ulong") == 0) { - return BLEND_OBJ_ULONG32; - } else if (blend_type_basename_compare(type_name, "float") == 0) { - return BLEND_OBJ_FLOAT; - } else if (blend_type_basename_compare(type_name, "double") == 0) { - return BLEND_OBJ_DOUBLE; - } else if (blend_type_basename_compare(type_name, "void") == 0) { - return BLEND_OBJ_OPAQUE; - } else { - return BLEND_OBJ_STRUCT; /* structure */ - } + const char* type_name) +{ + if (blend_type_basename_compare(type_name, "char") == 0) { + return BLEND_OBJ_CHAR8; + } else if (blend_type_basename_compare(type_name, "uchar") == 0) { + return BLEND_OBJ_UCHAR8; + } else if (blend_type_basename_compare(type_name, "short") == 0) { + return BLEND_OBJ_SHORT16; + } else if (blend_type_basename_compare(type_name, "ushort") == 0) { + return BLEND_OBJ_USHORT16; + } else if (blend_type_basename_compare(type_name, "int") == 0) { + return BLEND_OBJ_LONG32; + } else if (blend_type_basename_compare(type_name, "long") == 0) { + return BLEND_OBJ_LONG32; + } else if (blend_type_basename_compare(type_name, "ulong") == 0) { + return BLEND_OBJ_ULONG32; + } else if (blend_type_basename_compare(type_name, "float") == 0) { + return BLEND_OBJ_FLOAT; + } else if (blend_type_basename_compare(type_name, "double") == 0) { + return BLEND_OBJ_DOUBLE; + } else if (blend_type_basename_compare(type_name, "void") == 0) { + return BLEND_OBJ_OPAQUE; + } else { + return BLEND_OBJ_STRUCT; /* structure */ + } } static BlendObjType typelong_to_blendobj_type(BlendFile* blend_file, - long btype, long bname) + long btype, long bname) { - if (name_is_pointer(blend_file->names[bname])) { - return BLEND_OBJ_POINTER; - } else if (blend_file->types[btype].is_struct) { - return BLEND_OBJ_STRUCT; - } else { - return typestring_to_blendobj_type(blend_file, - blend_file->types[btype].name); - } + if (name_is_pointer(blend_file->names[bname])) { + return BLEND_OBJ_POINTER; + } else if (blend_file->types[btype].is_struct) { + return BLEND_OBJ_STRUCT; + } else { + return typestring_to_blendobj_type(blend_file, + blend_file->types[btype].name); + } } BlendObjType blend_object_type(BlendFile* blend_file, - BlendObject obj) { - return typelong_to_blendobj_type(blend_file, - obj.type, - obj.name); + BlendObject obj) { + return typelong_to_blendobj_type(blend_file, + obj.type, + obj.name); } BlendBlockPointer blend_block_from_blendpointer(BlendFile *blend_file, - uint32_t blendpointer) + uint32_t blendpointer) { - int i; + int i; - /* fprintf(stderr, "%04x: ", blendpointer);*/ + /* fprintf(stderr, "%04x: ", blendpointer);*/ - if (blendpointer != 0) { - for (i=0; iblocks_count; ++i) { - /*fprintf(stderr, "%04x? ", blend_file->blocks[i].blender_pointer); */ - if (blend_file->blocks[i].blender_pointer == blendpointer) { - return &blend_file->blocks[i]; - } - } - } + if (blendpointer != 0) { + for (i=0; iblocks_count; ++i) { + /*fprintf(stderr, "%04x? ", blend_file->blocks[i].blender_pointer); */ + if (blend_file->blocks[i].blender_pointer == blendpointer) { + return &blend_file->blocks[i]; + } + } + } - return NULL; + return NULL; } static BlendBlockPointer blend_block_from_object(BlendFile *blend_file, - BlendObject *obj) { - return obj->block; + BlendObject *obj) { + return obj->block; } int blend_object_array_getdata(BlendFile* blend_file, - void* dest, BlendObject obj, - int dim_index_1, int dim_index_2) + void* dest, BlendObject obj, + int dim_index_1, int dim_index_2) { - const char* type_name = blend_file->types[obj.type].name; - const BlendBlock *const bb = obj.block; - BlendField *bf = &bb->array_entries[obj.entry_index]; - void* data; - int dim1, dim2; + const char* type_name = blend_file->types[obj.type].name; + const BlendBlock *const bb = obj.block; + BlendField *bf = &bb->array_entries[obj.entry_index]; + void* data; + int dim1, dim2; - name_is_array(blend_file->names[obj.name], &dim1, &dim2); - /*dprintf(stderr, "copying:'%s'[%d][%d] (of [%d][%d]) ", type_name, dim_index_1, dim_index_2, dim1, dim2);*/ + if (!bf) + return 0; - if (dim_index_1 >= dim1 || - dim_index_2 >= dim2) { - dprintf(stderr, "Array index (%d,%d) out of bounds for dimensionality [%d][%d]\n", dim_index_1, dim_index_2, dim1, dim2); - return 0; - } + name_is_array(blend_file->names[obj.name], &dim1, &dim2); + /*dprintf(stderr, "copying:'%s'[%d][%d] (of [%d][%d]) ", type_name, dim_index_1, dim_index_2, dim1, dim2);*/ - data = &bf->field_bytes[bf->field_offsets[obj.field_index + - dim2*dim_index_1 + dim_index_2]]; - /*dprintf(stderr, "fi[%d]byteo[%d]", obj.field_index, - bf->field_offsets[obj.field_index + - dim2*dim_index_1 + dim_index_2]);*/ + if (dim_index_1 >= dim1 || + dim_index_2 >= dim2) { + dprintf(stderr, "Array index (%d,%d) out of bounds for dimensionality [%d][%d]\n", dim_index_1, dim_index_2, dim1, dim2); + return 0; + } - if (name_is_pointer(blend_file->names[obj.name])) { - *(BlendBlockPointer*)dest = - blend_block_from_blendpointer(blend_file, - BGETLEUINT32(data)); - return 1; - } + data = &bf->field_bytes[bf->field_offsets[obj.field_index + + dim2*dim_index_1 + dim_index_2]]; + /*dprintf(stderr, "fi[%d]byteo[%d]", obj.field_index, + bf->field_offsets[obj.field_index + + dim2*dim_index_1 + dim_index_2]);*/ - /* FIXME: might be a good idea to do less-crappy word-size conversions - here -- these might read beyond the end of malloc'd blocks if we - ever change our field-padding policy. There were endian problems - too; these are believed fixed now. */ - /* The signed conversions look strange because they have to sign-expand - negative results without relying on right-shifts which have undefined - behaviour on negative data according to ANSI C. */ - if (blend_type_basename_compare(type_name, "char") == 0) { - *(char*)dest = (*(char*)data) << (8*sizeof(char)-8) / (1<<(8*sizeof(char)-8)); - } else if (blend_type_basename_compare(type_name, "uchar") == 0) { - *(unsigned char*)dest = *(unsigned char*)data; - } else if (blend_type_basename_compare(type_name, "short") == 0) { - *(int16_t*)dest = BGETLEINT16(data) << (8*sizeof(int16_t)-16) / (1<<(8*sizeof(int16_t)-16)); - } else if (blend_type_basename_compare(type_name, "ushort") == 0) { - *(uint16_t*)dest = BGETLEUINT16(data); - } else if (blend_type_basename_compare(type_name, "int") == 0) { - *(int32_t*)dest = BGETLEINT32(data) << (8*sizeof(int32_t)-32) / (1<<(8*sizeof(int32_t)-32)); - } else if (blend_type_basename_compare(type_name, "long") == 0) { - *(int32_t*)dest = BGETLEINT32(data) << (8*sizeof(int32_t)-32) / (1<<(8*sizeof(int32_t)-32)); - } else if (blend_type_basename_compare(type_name, "ulong") == 0) { - *(uint32_t*)dest = BGETLEUINT32(data); - } else if (blend_type_basename_compare(type_name, "float") == 0) { - *(float*)dest = BGETLEFLOAT32(data); - /*fprintf(stderr, "GOT{%f'%f} ", *(float*)dest, *(float*)data);*/ - } else if (blend_type_basename_compare(type_name, "double") == 0) { - *(double*)dest = BGETLEDOUBLE64(data); - } else if (blend_type_basename_compare(type_name, "void") == 0) { - dprintf(stderr, "Tried to fetch a void.\n"); - return 0; - } else { - dprintf(stderr, "Tried to fetch a whole structure.\n"); - return 0; - } - return 1; /* success */ + if (name_is_pointer(blend_file->names[obj.name])) { + *(BlendBlockPointer*)dest = + blend_block_from_blendpointer(blend_file, + BGETLEUINT32(data)); + return 1; + } + + /* FIXME: might be a good idea to do less-crappy word-size conversions + here -- these might read beyond the end of malloc'd blocks if we + ever change our field-padding policy. There were endian problems + too; these are believed fixed now. */ + /* The signed conversions look strange because they have to sign-expand + negative results without relying on right-shifts which have undefined + behaviour on negative data according to ANSI C. */ + if (blend_type_basename_compare(type_name, "char") == 0) { + *(char*)dest = (*(char*)data) << (8*sizeof(char)-8) / (1<<(8*sizeof(char)-8)); + } else if (blend_type_basename_compare(type_name, "uchar") == 0) { + *(unsigned char*)dest = *(unsigned char*)data; + } else if (blend_type_basename_compare(type_name, "short") == 0) { + *(int16_t*)dest = BGETLEINT16(data) << (8*sizeof(int16_t)-16) / (1<<(8*sizeof(int16_t)-16)); + } else if (blend_type_basename_compare(type_name, "ushort") == 0) { + *(uint16_t*)dest = BGETLEUINT16(data); + } else if (blend_type_basename_compare(type_name, "int") == 0) { + *(int32_t*)dest = BGETLEINT32(data) << (8*sizeof(int32_t)-32) / (1<<(8*sizeof(int32_t)-32)); + } else if (blend_type_basename_compare(type_name, "long") == 0) { + *(int32_t*)dest = BGETLEINT32(data) << (8*sizeof(int32_t)-32) / (1<<(8*sizeof(int32_t)-32)); + } else if (blend_type_basename_compare(type_name, "ulong") == 0) { + *(uint32_t*)dest = BGETLEUINT32(data); + } else if (blend_type_basename_compare(type_name, "float") == 0) { + *(float*)dest = BGETLEFLOAT32(data); + /*fprintf(stderr, "GOT{%f'%f} ", *(float*)dest, *(float*)data);*/ + } else if (blend_type_basename_compare(type_name, "double") == 0) { + *(double*)dest = BGETLEDOUBLE64(data); + } else if (blend_type_basename_compare(type_name, "void") == 0) { + dprintf(stderr, "Tried to fetch a void.\n"); + return 0; + } else { + dprintf(stderr, "Tried to fetch a whole structure.\n"); + return 0; + } + return 1; /* success */ } int blend_object_getdata(BlendFile* blend_file, - void* dest, BlendObject obj) + void* dest, BlendObject obj) { - int dim1, dim2; + int dim1, dim2; - if (name_is_array(blend_file->names[obj.name], &dim1, &dim2)) { - if (dim1 != 1 || dim2 != 1) { - dprintf(stderr, "Tried to fetch a whole array.\n"); - return 0; - } - } + if (name_is_array(blend_file->names[obj.name], &dim1, &dim2)) { + if (dim1 != 1 || dim2 != 1) { + dprintf(stderr, "Tried to fetch a whole array.\n"); + return 0; + } + } - return (blend_object_array_getdata(blend_file, dest, obj, 0, 0)); + return (blend_object_array_getdata(blend_file, dest, obj, 0, 0)); } /* recursively count the number of fields and array items in this - structure, for the purposes of skipping in the field offset array */ +structure, for the purposes of skipping in the field offset array */ static long get_num_type_segments(BlendFile* blend_file, - BlendObject obj) + BlendObject obj) { - int i; - long rtn = 0; - int dim1,dim2; + int i; + long rtn = 0; + int dim1,dim2; - name_is_array(blend_file->names[obj.name], + name_is_array(blend_file->names[obj.name], &dim1, &dim2); - if (name_is_pointer(blend_file->names[obj.name]) || - !blend_file->types[obj.type].is_struct) { - return (1 * dim1 * dim2); - } + if (name_is_pointer(blend_file->names[obj.name]) || + !blend_file->types[obj.type].is_struct) { + return (1 * dim1 * dim2); + } - /* fprintf(stderr, "STRUCTYAYYY ");*/ + /* fprintf(stderr, "STRUCTYAYYY ");*/ - for (i=0; itypes[obj.type].fieldnames_count; ++i) { - BlendObject qo = obj; - qo.type = blend_file->types[obj.type].fieldtypes[i]; - qo.name = blend_file->types[obj.type].fieldnames[i]; - qo.field_index = i; - rtn += get_num_type_segments(blend_file, qo) * dim1 * dim2; - } + for (i=0; itypes[obj.type].fieldnames_count; ++i) { + BlendObject qo = obj; + qo.type = blend_file->types[obj.type].fieldtypes[i]; + qo.name = blend_file->types[obj.type].fieldnames[i]; + qo.field_index = i; + rtn += get_num_type_segments(blend_file, qo) * dim1 * dim2; + } - return (rtn); + return (rtn); } int blend_object_structure_getfield(BlendFile* blend_file, - BlendObject *result, - BlendObject obj, - const char* field_name) + BlendObject *result, + BlendObject obj, + const char* field_name) { - if (blend_file->types[obj.type].is_struct) { - int i; - int field_index = 0; - for (i=0; itypes[obj.type].fieldnames_count; ++i) { - if (blend_type_basename_compare( - blend_file->names[blend_file->types[obj.type].fieldnames[i]], - field_name) - == 0) { - result->type = blend_file->types[obj.type].fieldtypes[i]; - result->name = blend_file->types[obj.type].fieldnames[i]; - result->block = obj.block; - result->entry_index = obj.entry_index; - result->field_index = field_index; - return 1; - } + if (blend_file->types[obj.type].is_struct) { + int i; + int field_index = 0; + for (i=0; itypes[obj.type].fieldnames_count; ++i) { + if (blend_type_basename_compare( + blend_file->names[blend_file->types[obj.type].fieldnames[i]], + field_name) + == 0) { + result->type = blend_file->types[obj.type].fieldtypes[i]; + result->name = blend_file->types[obj.type].fieldnames[i]; + result->block = obj.block; + result->entry_index = obj.entry_index; + result->field_index = field_index; + return 1; + } - { - BlendObject qo = obj; - int fos; - qo.type = blend_file->types[obj.type].fieldtypes[i]; - qo.name = blend_file->types[obj.type].fieldnames[i]; - qo.field_index = field_index; - fos = get_num_type_segments(blend_file, qo); - /*fprintf(stderr, ">>%s %s:%d ", - blend_file->types[qo.type].name, - blend_file->names[qo.name], fos);*/ - field_index += fos; - } - } - return 0; - } else { - dprintf(stderr, "Indexed object isn't a structure!\n"); - return 0; - } + { + BlendObject qo = obj; + int fos; + qo.type = blend_file->types[obj.type].fieldtypes[i]; + qo.name = blend_file->types[obj.type].fieldnames[i]; + qo.field_index = field_index; + fos = get_num_type_segments(blend_file, qo); + /*fprintf(stderr, ">>%s %s:%d ", + blend_file->types[qo.type].name, + blend_file->names[qo.name], fos);*/ + field_index += fos; + } + } + return 0; + } else { + dprintf(stderr, "Indexed object isn't a structure!\n"); + return 0; + } } void blend_object_array_getdims(BlendFile* blend_file, - BlendObject obj, - int* dim1, int* dim2) + BlendObject obj, + int* dim1, int* dim2) { - name_is_array(blend_file->names[obj.name], + name_is_array(blend_file->names[obj.name], dim1, dim2); } BlendObject blend_block_get_object(BlendFile* blend_file, - BlendBlockPointer block, - int entry_index) + BlendBlockPointer block, + int entry_index) { - BlendObject bo; - const BlendBlock *const bb = block; - /*BlendField *bf = &bb->array_entries[entry_index]; */ + BlendObject bo; + const BlendBlock *const bb = block; + /*BlendField *bf = &bb->array_entries[entry_index]; */ - bo.type = bb->type_index; - bo.name = blend_file->name_undef; - bo.block = block; - bo.entry_index = entry_index; - bo.field_index = 0; + bo.type = bb->type_index; + bo.name = blend_file->name_undef; + bo.block = block; + bo.entry_index = entry_index; + bo.field_index = 0; - return bo; + return bo; } - + /******************************************************************** - * MID-LEVEL * - ********************************************************************/ +* MID-LEVEL * +********************************************************************/ /* general helpers */ @@ -1100,44 +1176,44 @@ blend_block_get_object(BlendFile* blend_file, int blend_object_getstring(BlendFile* blend_file, - BlendObject obj, - char *dest, int max_chars) + BlendObject obj, + char *dest, int max_chars) { - int strpos = 0; - int dim1, dim2; - int rtn = 1; - BlendObjType bo_type; + int strpos = 0; + int dim1, dim2; + int rtn = 1; + BlendObjType bo_type; - name_is_array(blend_file->names[obj.name], + name_is_array(blend_file->names[obj.name], &dim1, &dim2); - if (dim2 < max_chars) { - max_chars = dim2; - } + if (dim2 < max_chars) { + max_chars = dim2; + } - bo_type = blend_object_type(blend_file, obj); - if (! (bo_type==BLEND_OBJ_CHAR8 || bo_type==BLEND_OBJ_UCHAR8)) { - dprintf(stderr, "tried to get string from an object that's not of type uchar/char. (is type %d)\n", bo_type); - rtn = 0; - goto done; - } - - for (strpos=0; strposIDname) { /* don't freak out, but hmm, do we do the right thing? */ - const int strl = strlen(ifd->IDname); - char *obj_string = malloc(3+ strl); - - for (i=0; iIDname) == 0) { - ifd->found = obj; - ifd->success = 1; - want_more = 0; - goto done; - } else { - /* next entry please. */ - } - } - - done:; - free(obj_string); - } + if (ifd->IDname) { /* don't freak out, but hmm, do we do the right thing? */ + const int strl = strlen(ifd->IDname); + char *obj_string = malloc(3+ strl); - return want_more; + for (i=0; iIDname) == 0) { + ifd->found = obj; + ifd->success = 1; + want_more = 0; + goto done; + } else { + /* next entry please. */ + } + } + +done:; + free(obj_string); + } + + return want_more; } int blend_object_get_by_IDname(BlendFile* blend_file, - BlendObject *result, - const char* IDname) + BlendObject *result, + const char* IDname) { - IDFinderData ifd; + IDFinderData ifd; - ifd.success = 0; - ifd.IDname = IDname; - ifd.just_print_it = 0; + ifd.success = 0; + ifd.IDname = IDname; + ifd.just_print_it = 0; - blend_foreach_block(blend_file, block_ID_finder, &ifd); + blend_foreach_block(blend_file, block_ID_finder, &ifd); - if (!ifd.success) { - return 0; - } + if (!ifd.success) { + return 0; + } - *result = ifd.found; - return 1; + *result = ifd.found; + return 1; } void blend_dump_typedefs(BlendFile* bf) { - int i; + int i; - /* dump out display of types and their sizes */ - for (i=0; itypes_count; ++i) { - /* if (!bf->types[i].is_struct)*/ - { - printf("%3d: sizeof(%s%s)=%d", - i, - bf->types[i].is_struct ? "struct " : "atomic ", - bf->types[i].name, bf->types[i].size); - if (bf->types[i].is_struct) { - int j; - printf(", %d fields: { ", bf->types[i].fieldtypes_count); - for (j=0; jtypes[i].fieldtypes_count; ++j) { - printf("%s %s", - bf->types[bf->types[i].fieldtypes[j]].name, - bf->names[bf->types[i].fieldnames[j]]); - if (j == bf->types[i].fieldtypes_count-1) { - printf("; }\n"); - } else { - printf("; "); - } + /* dump out display of types and their sizes */ + for (i=0; itypes_count; ++i) { + /* if (!bf->types[i].is_struct)*/ + { + printf("%3d: sizeof(%s%s)=%d", + i, + bf->types[i].is_struct ? "struct " : "atomic ", + bf->types[i].name, bf->types[i].size); + if (bf->types[i].is_struct) { + int j; + printf(", %d fields: { ", bf->types[i].fieldtypes_count); + for (j=0; jtypes[i].fieldtypes_count; ++j) { + printf("%s %s", + bf->types[bf->types[i].fieldtypes[j]].name, + bf->names[bf->types[i].fieldnames[j]]); + if (j == bf->types[i].fieldtypes_count-1) { + printf(";}"); + } else { + printf("; "); + } + } + } + printf("\n\n"); + + } } - } - - } - } } void blend_dump_blocks(BlendFile* bf) { - int i; - IDFinderData ifd; + int i; + IDFinderData ifd; - ifd.success = 0; - ifd.IDname = NULL; - ifd.just_print_it = 1; + ifd.success = 0; + ifd.IDname = NULL; + ifd.just_print_it = 1; - for (i=0; iblocks_count; ++i) { - BlendBlock* bb = &bf->blocks[i]; - printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", - bb->tag, /*bb->blender_pointer,*/ bb, - bf->types[bb->type_index].name, - bb->array_entries_count); - block_ID_finder(bb, bf, &ifd); - printf("\n"); - } + for (i=0; iblocks_count; ++i) { + BlendBlock* bb = &bf->blocks[i]; + printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", + bb->tag, /*bb->blender_pointer,*/ bb, + bf->types[bb->type_index].name, + bb->array_entries_count); + block_ID_finder(bb, bf, &ifd); + printf("\n"); + } } int blend_obj_is_rootobject(BlendFile *bf, BlendObject *objobj) { - BlendObject obj; - BlendBlockPointer block; - if ((blend_object_structure_getfield(bf, &obj, *objobj, "parent") && - blend_object_getdata(bf, &block, obj))) { - return (block == NULL); - } - return 0; + BlendObject obj; + BlendBlockPointer block; + if ((blend_object_structure_getfield(bf, &obj, *objobj, "parent") && + blend_object_getdata(bf, &block, obj))) { + return (block == NULL); + } + return 0; } BlendLayerMask blend_obj_get_layermask(BlendFile *bf, BlendObject *objobj) { - BlendObject obj; - int32_t ldata; - if ((blend_object_structure_getfield(bf, &obj, *objobj, "lay") && - blend_object_getdata(bf, &ldata, obj))) { - return (BlendLayerMask) ldata; - } - return 0; + BlendObject obj; + int32_t ldata; + if ((blend_object_structure_getfield(bf, &obj, *objobj, "lay") && + blend_object_getdata(bf, &ldata, obj))) { + return (BlendLayerMask) ldata; + } + return 0; } /* Bizarrely, blender doesn't seem to carry a mapping of parent - to children -- only of children to parent. So, to find the children - of an Object we have to scan all objects to see if their parent is - the Object in question. */ +to children -- only of children to parent. So, to find the children +of an Object we have to scan all objects to see if their parent is +the Object in question. */ typedef struct { - BlendBlockPointer wanted_parent; - BlendBlockPointer child; - int just_counting; - int num_so_far; - int wanted_index; + BlendBlockPointer wanted_parent; + BlendBlockPointer child; + int just_counting; + int num_so_far; + int wanted_index; } childfinderData; static BLENDBLOCKCALLBACK_RETURN block_childfinder(BLENDBLOCKCALLBACK_ARGS) { - childfinderData *cfd = (childfinderData *)userdata; - const char *tagname = blend_block_get_typename(blend_file, block); - int entry_count = blend_block_get_entry_count(blend_file, block); - int want_more = 1; - int i; + childfinderData *cfd = (childfinderData *)userdata; + const char *tagname = blend_block_get_typename(blend_file, block); + int entry_count = blend_block_get_entry_count(blend_file, block); + int want_more = 1; + int i; - if (strcmp(tagname, "Object") == 0) { - /* Is Object */ - for (i=0; iwanted_parent) { - if ((cfd->num_so_far == cfd->wanted_index) && - !cfd->just_counting) { - cfd->child = block; - want_more = 0; - } - ++cfd->num_so_far; - } else { - cfd->child = NULL; - } - } - } - } + if (strcmp(tagname, "Object") == 0) { + /* Is Object */ + for (i=0; iwanted_parent) { + if ((cfd->num_so_far == cfd->wanted_index) && + !cfd->just_counting) { + cfd->child = block; + want_more = 0; + } + ++cfd->num_so_far; + } else { + cfd->child = NULL; + } + } + } + } - return want_more; + return want_more; } int blend_obj_get_childcount(BlendFile *bf, BlendObject *objobj) { - childfinderData cfd; - cfd.wanted_parent = blend_block_from_object(bf, objobj); - cfd.child = NULL; - cfd.just_counting = 1; - cfd.num_so_far = 0; - cfd.wanted_index = 0; - blend_foreach_block(bf, block_childfinder, &cfd); - return cfd.num_so_far; + childfinderData cfd; + cfd.wanted_parent = blend_block_from_object(bf, objobj); + cfd.child = NULL; + cfd.just_counting = 1; + cfd.num_so_far = 0; + cfd.wanted_index = 0; + blend_foreach_block(bf, block_childfinder, &cfd); + return cfd.num_so_far; } BlendBlockPointer blend_obj_get_child(BlendFile *bf, BlendObject *objobj, int childnum) { - childfinderData cfd; - cfd.wanted_parent = blend_block_from_object(bf, objobj); - cfd.child = NULL; - cfd.just_counting = 0; - cfd.num_so_far = 0; - cfd.wanted_index = childnum; - blend_foreach_block(bf, block_childfinder, &cfd); - return cfd.child; + childfinderData cfd; + cfd.wanted_parent = blend_block_from_object(bf, objobj); + cfd.child = NULL; + cfd.just_counting = 0; + cfd.num_so_far = 0; + cfd.wanted_index = childnum; + blend_foreach_block(bf, block_childfinder, &cfd); + return cfd.child; } /******************************************************************** - * HIGH-LEVEL * - ********************************************************************/ +* HIGH-LEVEL * +********************************************************************/ #ifndef LEN3POW2 /* length squared */ @@ -1410,911 +1488,1231 @@ blend_obj_get_child(BlendFile *bf, BlendObject *objobj, int childnum) { #ifndef NORMALIZE3 /* vector normalization (expensive) */ #define NORMALIZE3(xd,yd,zd) \ -do { \ - const double norm3_macro_len3 = LEN3((xd),(yd),(zd)); \ - if (norm3_macro_len3 != 0.0F) \ - { \ - (xd) = (xd) / norm3_macro_len3; \ - (yd) = (yd) / norm3_macro_len3; \ - (zd) = (zd) / norm3_macro_len3; \ - } \ -} while (0) + do { \ + const double norm3_macro_len3 = LEN3((xd),(yd),(zd)); \ + if (norm3_macro_len3 != 0.0F) \ +{ \ + (xd) = (xd) / norm3_macro_len3; \ + (yd) = (yd) / norm3_macro_len3; \ + (zd) = (zd) / norm3_macro_len3; \ +} \ + } while (0) #endif static void bMatIdentity(bMatrix mat) { - int i,j; - for (i=0; i<4; ++i) { - for (j=0; j<4; ++j) { - mat[i][j] = 0.0f; - } - mat[i][i] = 1.0f; - } + int i,j; + for (i=0; i<4; ++i) { + for (j=0; j<4; ++j) { + mat[i][j] = 0.0f; + } + mat[i][i] = 1.0f; + } } static void bMatMultVec(float xyz[3], bMatrix mat) { - int i; - float r[3]; - for (i=0; i<3; ++i) { - r[i] = 0.0f; - } - for (i=0; i<3; ++i) { - r[i] += xyz[0] * mat[0][i]; - r[i] += xyz[1] * mat[1][i]; - r[i] += xyz[2] * mat[2][i]; - r[i] += 1.0f * mat[3][i]; - } - for (i=0; i<3; ++i) { - xyz[i] = r[i]; - } + int i; + float r[3]; + for (i=0; i<3; ++i) { + r[i] = 0.0f; + } + for (i=0; i<3; ++i) { + r[i] += xyz[0] * mat[0][i]; + r[i] += xyz[1] * mat[1][i]; + r[i] += xyz[2] * mat[2][i]; + r[i] += 1.0f * mat[3][i]; + } + for (i=0; i<3; ++i) { + xyz[i] = r[i]; + } } bMesh *blend_alloc_mesh(void) { - return malloc(sizeof(bMesh)); + return malloc(sizeof(bMesh)); } void blend_init_mesh(bMesh *mesh) { - int i,j; - mesh->vert = NULL; - mesh->vert_count = 0; - mesh->face = NULL; - mesh->face_count = 0; - mesh->material = NULL; + int i,j; + mesh->vert = NULL; + mesh->vert_count = 0; + mesh->face = NULL; + mesh->face_count = 0; + mesh->material = NULL; } void blend_free_mesh_inner(bMesh *mesh) { - if (mesh->vert) { - free(mesh->vert); - } - if (mesh->face) { - free(mesh->face); - } - if (mesh->material) { - blend_free_material(mesh->material); - } + if (mesh->vert) { + free(mesh->vert); + } + if (mesh->face) { + free(mesh->face); + } + if (mesh->material) { + blend_free_material(mesh->material); + } } void blend_free_mesh(bMesh *mesh) { - blend_free_mesh_inner(mesh); - free(mesh); + blend_free_mesh_inner(mesh); + free(mesh); } bObj * blend_alloc_obj(void) { - return malloc(sizeof(bObj)); + return malloc(sizeof(bObj)); } void blend_init_obj(bObj *obj) { - obj->type = BOBJ_TYPE_UNKNOWN; - obj->name = NULL; - bMatIdentity(obj->transform); - bMatIdentity(obj->parentimat); - obj->location[0] = - obj->location[1] = - obj->location[2] = 0.0f; - obj->scaling[0] = - obj->scaling[1] = - obj->scaling[2] = 1.0f; - obj->rotphr[0] = - obj->rotphr[1] = - obj->rotphr[2] = 0.0f; - obj->data.dummy = NULL; - obj->transflags = 0; + obj->type = BOBJ_TYPE_UNKNOWN; + obj->name = NULL; + bMatIdentity(obj->transform); + bMatIdentity(obj->parentimat); + obj->location[0] = + obj->location[1] = + obj->location[2] = 0.0f; + obj->scaling[0] = + obj->scaling[1] = + obj->scaling[2] = 1.0f; + obj->rotphr[0] = + obj->rotphr[1] = + obj->rotphr[2] = 0.0f; + obj->data.dummy = NULL; + obj->transflags = 0; } void blend_free_obj_inner(bObj *obj) { - if (obj->name) { - free(obj->name); - } - switch (obj->type) { + if (obj->name) { + free(obj->name); + } + switch (obj->type) { case BOBJ_TYPE_MESH: - blend_free_mesh(obj->data.mesh); + blend_free_mesh(obj->data.mesh); case BOBJ_TYPE_UNKNOWN: case BOBJ_TYPE_NULL: default: - break; - } + break; + } } void blend_free_obj(bObj *obj) { - blend_free_obj_inner(obj); - free(obj); + blend_free_obj_inner(obj); + free(obj); } void blend_acquire_obj_from_obj(BlendFile *bf, BlendObject *objobj, - bObj *outobj, BlendObject **mallocdoutblendobject) { - - BlendObject obj, dataobj; - BlendBlockPointer block; - short sdata = 12345; + bObj *outobj, BlendObject **mallocdoutblendobject) +{ + + BlendObject obj, dataobj; + BlendBlockPointer block,ipoblock,curveblock=0; + short sdata = 12345; + #define B_IDNAME_MAX_SIZE 80 - char *idname = malloc(1 + B_IDNAME_MAX_SIZE); - float fdata1, fdata2, fdata3; + char *idname = malloc(1 + B_IDNAME_MAX_SIZE); + float fdata1, fdata2, fdata3; - if (mallocdoutblendobject) *mallocdoutblendobject = NULL; + if (mallocdoutblendobject) *mallocdoutblendobject = NULL; - blend_init_obj(outobj); + blend_init_obj(outobj); - if (!(blend_object_structure_getfield(bf, &obj, *objobj, - "type") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); /* couldn't get type */ - } else { - switch (sdata) { - case 1: /* mesh */ - outobj->type = BOBJ_TYPE_MESH; break; - case 10: /* lamp */ - case 11: /* camera */ - default: - outobj->type = BOBJ_TYPE_UNKNOWN; break; - } - } - - if (blend_object_get_IDname(bf, *objobj, idname, B_IDNAME_MAX_SIZE)) { - outobj->name = idname; - } else { - free(idname); - abort(); /* couldn't get obj name */ - } - - /* now we override the mesh transform with the object's. should - we merge, instead??? - hm, dunno, don't think so. */ + if (!(blend_object_structure_getfield(bf, &obj, *objobj, + "type") && + blend_object_getdata(bf, &sdata, obj))) + { + abort(); /* couldn't get type */ + } else { + switch (sdata) { + case 1: /* mesh */ + outobj->type = BOBJ_TYPE_MESH; break; + case 10: /* lamp */ + outobj->type = BOBJ_TYPE_LAMP; break; + case 11: /* camera */ + outobj->type = BOBJ_TYPE_CAMERA; break; + default: + outobj->type = BOBJ_TYPE_UNKNOWN; break; + } + } - if (blend_object_structure_getfield(bf, &obj, *objobj, "loc") && - blend_object_array_getdata(bf, &fdata1, obj, 0,0) && - blend_object_array_getdata(bf, &fdata2, obj, 0,1) && - blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { - outobj->location[0] = fdata1; - outobj->location[1] = fdata2; - outobj->location[2] = fdata3; - } else { - outobj->location[0] = - outobj->location[1] = - outobj->location[2] = 0.0f; - } - - if (blend_object_structure_getfield(bf, &obj, *objobj, "size") && - blend_object_array_getdata(bf, &fdata1, obj, 0,0) && - blend_object_array_getdata(bf, &fdata2, obj, 0,1) && - blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { - outobj->scaling[0] = fdata1; - outobj->scaling[1] = fdata2; - outobj->scaling[2] = fdata3; - } else { - outobj->scaling[0] = - outobj->scaling[1] = - outobj->scaling[2] = 1.0f; - } - - if (blend_object_structure_getfield(bf, &obj, *objobj, "rot") && - blend_object_array_getdata(bf, &fdata1, obj, 0,0) && - blend_object_array_getdata(bf, &fdata2, obj, 0,1) && - blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { - outobj->rotphr[0] = fdata1; - outobj->rotphr[1] = fdata2; - outobj->rotphr[2] = fdata3; - } else { - outobj->rotphr[0] = - outobj->rotphr[1] = - outobj->rotphr[2] = 0.0f; - } + if (blend_object_get_IDname(bf, *objobj, idname, B_IDNAME_MAX_SIZE)) { + outobj->name = idname; + } else { + free(idname); + abort(); /* couldn't get obj name */ + } - if (blend_object_structure_getfield(bf, &obj, *objobj, "parentinv")) { - int i,j; - for (i=0; i<4; ++i) { - for (j=0; j<4; ++j) { - blend_object_array_getdata(bf, &fdata1, obj, i,j); - outobj->parentimat[i][j] = fdata1; - } - } - } - - if (blend_object_structure_getfield(bf, &obj, *objobj, "transflag")) { - char cdata; - /* TODO: decode what these flags precisely mean. */ - /* top bit is 'powertrack' */ - if (blend_object_getdata(bf, &cdata, obj)) { - outobj->transflags = (unsigned char)cdata; - } - } - - if (blend_object_structure_getfield(bf, &obj, *objobj, "obmat")) { - int i,j; - for (i=0; i<4; ++i) { - for (j=0; j<4; ++j) { - blend_object_array_getdata(bf, &fdata1, obj, i,j); - outobj->transform[i][j] = fdata1; - dprintf(stderr, "%0.3f ", fdata1); - } - dprintf(stderr, "\n"); - } - } - - /* get actual obj here */ - - if (! (blend_object_structure_getfield(bf, &obj, *objobj, "data") && - blend_object_getdata(bf, &block, obj))) { - abort(); - } - - if (block == NULL) { - outobj->type = BOBJ_TYPE_NULL; - } else { - dataobj = blend_block_get_object(bf, block, 0); - if (mallocdoutblendobject) { - *mallocdoutblendobject = malloc(sizeof(BlendObject)); - **mallocdoutblendobject = dataobj; - } - } + /* now we override the mesh transform with the object's. should + we merge, instead??? - hm, dunno, don't think so. */ - switch (outobj->type) { + if (blend_object_structure_getfield(bf, &obj, *objobj, "loc") && + blend_object_array_getdata(bf, &fdata1, obj, 0,0) && + blend_object_array_getdata(bf, &fdata2, obj, 0,1) && + blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { + outobj->location[0] = fdata1; + outobj->location[1] = fdata2; + outobj->location[2] = fdata3; + } else { + outobj->location[0] = + outobj->location[1] = + outobj->location[2] = 0.0f; + } + + if (blend_object_structure_getfield(bf, &obj, *objobj, "size") && + blend_object_array_getdata(bf, &fdata1, obj, 0,0) && + blend_object_array_getdata(bf, &fdata2, obj, 0,1) && + blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { + outobj->scaling[0] = fdata1; + outobj->scaling[1] = fdata2; + outobj->scaling[2] = fdata3; + } else { + outobj->scaling[0] = + outobj->scaling[1] = + outobj->scaling[2] = 1.0f; + } + + if (blend_object_structure_getfield(bf, &obj, *objobj, "rot") && + blend_object_array_getdata(bf, &fdata1, obj, 0,0) && + blend_object_array_getdata(bf, &fdata2, obj, 0,1) && + blend_object_array_getdata(bf, &fdata3, obj, 0,2)) { + outobj->rotphr[0] = fdata1; + outobj->rotphr[1] = fdata2; + outobj->rotphr[2] = fdata3; + } else { + outobj->rotphr[0] = + outobj->rotphr[1] = + outobj->rotphr[2] = 0.0f; + } + + if (blend_object_structure_getfield(bf, &obj, *objobj, "parentinv")) { + int i,j; + for (i=0; i<4; ++i) { + for (j=0; j<4; ++j) { + blend_object_array_getdata(bf, &fdata1, obj, i,j); + outobj->parentimat[i][j] = fdata1; + } + } + } +#if 0 + if (blend_object_structure_getfield(bf, &obj, *objobj, "transflag")) { + char cdata; + /* TODO: decode what these flags precisely mean. */ + /* top bit is 'powertrack' */ + if (blend_object_getdata(bf, &cdata, obj)) { + outobj->transflags = (unsigned char)cdata; + } + } +#endif + + outobj->mass = 0.f; + if (blend_object_structure_getfield(bf, &obj, *objobj, "mass")) + { + float mass; + if (blend_object_getdata(bf, &mass, obj)) + { + outobj->mass = mass; + } + } + + + if ((blend_object_structure_getfield(bf, &obj, *objobj,"ipo") && blend_object_getdata(bf, &ipoblock, obj))) + { + if (ipoblock) + { + BlendObject ipo = blend_block_get_object(bf, ipoblock, 0); +#define MAX_CHARS 31 + char iponame[MAX_CHARS]; + BlendObject obj2,obj3; + + blend_object_get_IDname(bf,ipo,iponame,MAX_CHARS-1); +// printf("ipo.ID.name = %s\n",iponame); + + if (blend_object_structure_getfield(bf, &obj2, ipo,"curve")) + { + BlendBlock* block = (BlendBlock*)obj2.block; + + + void** ptrptr = &block->array_entries->field_bytes[block->array_entries->field_offsets[obj2.field_index]]; + BlendBlockPointer ptr = *ptrptr; + //ptrptr++; contains the 'last' pointer + if (ptr) + { + BlendBlockPointer curveblockptr = blend_block_from_blendpointer(bf, ptr); + BlendObject curve = blend_block_get_object(bf, curveblockptr, 0); + + } + + } + + + } + } + + + + + outobj->boundtype = 0; + if (blend_object_structure_getfield(bf, &obj, *objobj, "boundtype")) + { + short int boundtype; + if (blend_object_getdata(bf, &boundtype, obj)) + { + outobj->boundtype= boundtype; + } + } + + outobj->gameflag = 0; + if (blend_object_structure_getfield(bf, &obj, *objobj, "gameflag")) + { + int gameflag; + if (blend_object_getdata(bf, &gameflag, obj)) + { + outobj->gameflag= gameflag; + } + } + + + + + if (blend_object_structure_getfield(bf, &obj, *objobj, "obmat")) { + int i,j; + for (i=0; i<4; ++i) { + for (j=0; j<4; ++j) { + blend_object_array_getdata(bf, &fdata1, obj, i,j); + outobj->transform[i][j] = fdata1; + dprintf(stderr, "%0.3f ", fdata1); + } + dprintf(stderr, "\n"); + } + } + + /* get actual mesh obj here */ + + if (! (blend_object_structure_getfield(bf, &obj, *objobj, "data") && + blend_object_getdata(bf, &block, obj))) + { + printf("no mesh\n"); + outobj->data.mesh = 0; + return; + //abort(); + } + + if (block == NULL) { + outobj->type = BOBJ_TYPE_NULL; + } else { + dataobj = blend_block_get_object(bf, block, 0); + if (mallocdoutblendobject) { + *mallocdoutblendobject = malloc(sizeof(BlendObject)); + **mallocdoutblendobject = dataobj; + } + } + + + switch (outobj->type) { case BOBJ_TYPE_MESH: - outobj->data.mesh = blend_alloc_mesh(); - blend_acquire_mesh_from_obj(bf, &dataobj, outobj->data.mesh); - break; + outobj->data.mesh = blend_alloc_mesh(); + blend_acquire_mesh_from_obj(bf, &dataobj, outobj->data.mesh); + break; case BOBJ_TYPE_UNKNOWN: default: case BOBJ_TYPE_NULL: - outobj->data.dummy = NULL; - break; - } + outobj->data.dummy = NULL; + break; + } + } bTexLayer * blend_alloc_texlayer(void) { - return malloc(sizeof(bTexLayer)); + return malloc(sizeof(bTexLayer)); } void blend_init_texlayer(bTexLayer *tl) { - tl->filename = NULL; - tl->affects_mask = 0; - tl->blend_mode = BTEX_BLEND_NORMAL; - tl->coords_type = BTEX_COORDS_NONE; - tl->is_st_clamped = 0; - tl->flags = 0; - tl->Nflags = tl->Ntype = 0; - tl->xrepeat = tl->yrepeat = 1; + tl->filename = NULL; + tl->affects_mask = 0; + tl->blend_mode = BTEX_BLEND_NORMAL; + tl->coords_type = BTEX_COORDS_NONE; + tl->is_st_clamped = 0; + tl->flags = 0; + tl->Nflags = tl->Ntype = 0; + tl->xrepeat = tl->yrepeat = 1; } static void blend_free_texlayer_inner(bTexLayer *tl) { - if (tl->filename) { - free(tl->filename); - } + if (tl->filename) { + free(tl->filename); + } } void blend_free_texlayer(bTexLayer *tl) { - blend_free_texlayer_inner(tl); - free(tl); + blend_free_texlayer_inner(tl); + free(tl); } void /* MTex */ blend_acquire_texlayer_from_obj(BlendFile *bf, BlendObject *tlobj, - bTexLayer *tl) { - BlendObject obj; - BlendBlockPointer tex_block; - short sdata = 12345; + bTexLayer *tl) +{ + BlendObject obj; + BlendBlockPointer tex_block; + short sdata = 12345; - blend_init_texlayer(tl); + blend_init_texlayer(tl); - if (!(blend_object_structure_getfield(bf, &obj, *tlobj, - "mapto") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } - if (sdata & 0x01) { - tl->affects_mask |= BTEX_AFFECT_COLOUR; - } - if (sdata & 0x40) { - tl->affects_mask |= BTEX_AFFECT_EMIT; - } - if (sdata & 0x80) { - tl->affects_mask |= BTEX_AFFECT_ALPHA; - } - /* note: mapto not fully decoded. */ + if (!(blend_object_structure_getfield(bf, &obj, *tlobj, + "mapto") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } + if (sdata & 0x01) { + tl->affects_mask |= BTEX_AFFECT_COLOUR; + } + if (sdata & 0x40) { + tl->affects_mask |= BTEX_AFFECT_EMIT; + } + if (sdata & 0x80) { + tl->affects_mask |= BTEX_AFFECT_ALPHA; + } + /* note: mapto not fully decoded. */ - if (!(blend_object_structure_getfield(bf, &obj, *tlobj, - "texflag") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } - if (sdata & 0x02) { - tl->affects_mask |= BTEX_AFFECT_STENCIL; - } + if (!(blend_object_structure_getfield(bf, &obj, *tlobj, + "texflag") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } + if (sdata & 0x02) { + tl->affects_mask |= BTEX_AFFECT_STENCIL; + } - if (!(blend_object_structure_getfield(bf, &obj, *tlobj, - "texco") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } - switch (sdata) { + if (!(blend_object_structure_getfield(bf, &obj, *tlobj, + "texco") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } + switch (sdata) { case 1: case 2: - tl->coords_type = BTEX_COORDS_REFLECT; - break; + tl->coords_type = BTEX_COORDS_REFLECT; + break; case 16: - tl->coords_type = BTEX_COORDS_UV; - break; + tl->coords_type = BTEX_COORDS_UV; + break; default: - /* I haven't seen this happen, but it probably does... */ - tl->coords_type = BTEX_COORDS_NONE; - break; - } + /* I haven't seen this happen, but it probably does... */ + tl->coords_type = BTEX_COORDS_NONE; + break; + } - if (!(blend_object_structure_getfield(bf, &obj, *tlobj, - "blendtype") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } - tl->blend_mode = sdata; /* not decoded yet :( */ + if (!(blend_object_structure_getfield(bf, &obj, *tlobj, + "blendtype") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } + tl->blend_mode = sdata; /* not decoded yet :( */ - if (blend_object_structure_getfield(bf, &obj, *tlobj, "tex") && - blend_object_getdata(bf, &tex_block, obj) && tex_block) { - BlendObject tobj = blend_block_get_object(bf, tex_block, 0); - BlendBlockPointer im_block; - BlendObject obj; - - if (!(blend_object_structure_getfield(bf, &obj, tobj, "extend") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } - tl->is_st_clamped = !(sdata & 2 /*'repeat'*/); - /*fprintf(stderr, "CLAMP=%d (was %d)\n", tl->is_st_clamped, sdata);*/ - if (!(blend_object_structure_getfield(bf, &obj, tobj, "xrepeat") && - blend_object_getdata(bf, &sdata, obj))) { - tl->xrepeat = 1; - } else { - tl->xrepeat = sdata; - } - if (!(blend_object_structure_getfield(bf, &obj, tobj, "yrepeat") && - blend_object_getdata(bf, &sdata, obj))) { - tl->yrepeat = 1; - } else { - tl->yrepeat = sdata; - } - if (!(blend_object_structure_getfield(bf, &obj, tobj, "flag") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } else { - tl->flags = sdata; - } - if (!(blend_object_structure_getfield(bf, &obj, tobj, "imaflag") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } else { - if (sdata & 0x0001) { - tl->flags |= BIMG_FLAG_INTERPOLATE; - } - if (sdata & 0x0004) { - tl->flags |= BIMG_FLAG_MIPMAP; - } - if (sdata & 0x0100) { - tl->flags |= BIMG_FLAG_ANTIALIAS; - } - } - if (!(blend_object_structure_getfield(bf, &obj, tobj, "type") && - blend_object_getdata(bf, &sdata, obj))) { - abort(); - } else { - tl->Ntype = sdata; - } - if (blend_object_structure_getfield(bf, &obj, tobj, "ima") && - blend_object_getdata(bf, &im_block, obj) && im_block) { - BlendObject imobj = blend_block_get_object(bf, im_block, 0); + if (blend_object_structure_getfield(bf, &obj, *tlobj, "tex") && + blend_object_getdata(bf, &tex_block, obj) && tex_block) { + BlendObject tobj = blend_block_get_object(bf, tex_block, 0); + BlendBlockPointer im_block; + BlendObject obj; + + if (!(blend_object_structure_getfield(bf, &obj, tobj, "extend") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } + tl->is_st_clamped = !(sdata & 2 /*'repeat'*/); + /*fprintf(stderr, "CLAMP=%d (was %d)\n", tl->is_st_clamped, sdata);*/ + if (!(blend_object_structure_getfield(bf, &obj, tobj, "xrepeat") && + blend_object_getdata(bf, &sdata, obj))) { + tl->xrepeat = 1; + } else { + tl->xrepeat = sdata; + } + if (!(blend_object_structure_getfield(bf, &obj, tobj, "yrepeat") && + blend_object_getdata(bf, &sdata, obj))) { + tl->yrepeat = 1; + } else { + tl->yrepeat = sdata; + } + if (!(blend_object_structure_getfield(bf, &obj, tobj, "flag") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } else { + tl->flags = sdata; + } + if (!(blend_object_structure_getfield(bf, &obj, tobj, "imaflag") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } else { + if (sdata & 0x0001) { + tl->flags |= BIMG_FLAG_INTERPOLATE; + } + if (sdata & 0x0004) { + tl->flags |= BIMG_FLAG_MIPMAP; + } + if (sdata & 0x0100) { + tl->flags |= BIMG_FLAG_ANTIALIAS; + } + } + if (!(blend_object_structure_getfield(bf, &obj, tobj, "type") && + blend_object_getdata(bf, &sdata, obj))) { + abort(); + } else { + tl->Ntype = sdata; + } + if (blend_object_structure_getfield(bf, &obj, tobj, "ima") && + blend_object_getdata(bf, &im_block, obj) && im_block) { + BlendObject imobj = blend_block_get_object(bf, im_block, 0); #define BF_IMAGE_FILENAME_MAXSIZE 160 - tl->filename = malloc(BF_IMAGE_FILENAME_MAXSIZE); - if (!(blend_object_structure_getfield(bf, &obj, imobj, "name") && - blend_object_getstring(bf, obj, - tl->filename, BF_IMAGE_FILENAME_MAXSIZE))) { - abort(); - } - } - } else { - abort(); - } + tl->filename = malloc(BF_IMAGE_FILENAME_MAXSIZE); + if (!(blend_object_structure_getfield(bf, &obj, imobj, "name") && + blend_object_getstring(bf, obj, + tl->filename, BF_IMAGE_FILENAME_MAXSIZE))) { + abort(); + } + } + } else { + abort(); + } } bMaterial * blend_alloc_material(void) { - return malloc(sizeof(bMaterial)); + return malloc(sizeof(bMaterial)); } void blend_init_material(bMaterial *mat) { - int i; - for (i=0; itex_layer[i] = NULL; - } - mat->feature_mask = 0; - for (i=0; i<4; ++i) { - mat->colour_rgba[i] = 1.0f; - } - mat->emit = 0.0f; + int i; + for (i=0; itex_layer[i] = NULL; + } + mat->feature_mask = 0; + for (i=0; i<4; ++i) { + mat->colour_rgba[i] = 1.0f; + } + mat->emit = 0.0f; } void blend_free_material(bMaterial *mat) { - int i; - for (i=0; itex_layer[i]) { - blend_free_texlayer(mat->tex_layer[i]); - } - } + int i; + for (i=0; itex_layer[i]) { + blend_free_texlayer(mat->tex_layer[i]); + } + } } void blend_acquire_material_from_obj(BlendFile *bf, BlendObject *matobj, - bMaterial *mat) { - BlendObject obj; - int i; - int32_t ldata = 123456; - float fdata = 123456.0; + bMaterial *mat) +{ + BlendObject obj; + int i; + int32_t ldata = 123456; + float fdata = 123456.0; - blend_init_material(mat); + blend_init_material(mat); - if ((blend_object_structure_getfield(bf, &obj, *matobj, "r") && - blend_object_getdata(bf, &fdata, obj))) { - mat->colour_rgba[0] = fdata; - } - if ((blend_object_structure_getfield(bf, &obj, *matobj, "g") && - blend_object_getdata(bf, &fdata, obj))) { - mat->colour_rgba[1] = fdata; - } - if ((blend_object_structure_getfield(bf, &obj, *matobj, "b") && - blend_object_getdata(bf, &fdata, obj))) { - mat->colour_rgba[2] = fdata; - } - if ((blend_object_structure_getfield(bf, &obj, *matobj, "alpha") && - blend_object_getdata(bf, &fdata, obj))) { - mat->colour_rgba[3] = fdata; - } - if ((blend_object_structure_getfield(bf, &obj, *matobj, "emit") && - blend_object_getdata(bf, &fdata, obj))) { - mat->emit = fdata; - } + if ((blend_object_structure_getfield(bf, &obj, *matobj, "r") && + blend_object_getdata(bf, &fdata, obj))) { + mat->colour_rgba[0] = fdata; + } + if ((blend_object_structure_getfield(bf, &obj, *matobj, "g") && + blend_object_getdata(bf, &fdata, obj))) { + mat->colour_rgba[1] = fdata; + } + if ((blend_object_structure_getfield(bf, &obj, *matobj, "b") && + blend_object_getdata(bf, &fdata, obj))) { + mat->colour_rgba[2] = fdata; + } + if ((blend_object_structure_getfield(bf, &obj, *matobj, "alpha") && + blend_object_getdata(bf, &fdata, obj))) { + mat->colour_rgba[3] = fdata; + } + if ((blend_object_structure_getfield(bf, &obj, *matobj, "emit") && + blend_object_getdata(bf, &fdata, obj))) { + mat->emit = fdata; + } - if (!(blend_object_structure_getfield(bf, &obj, *matobj, "mode") && - blend_object_getdata(bf, &ldata, obj))) { - abort(); - } - if (ldata & 0x04) { - mat->feature_mask |= BMAT_FEATURE_SHADELESS; - } - if (ldata & 0x08) { - mat->feature_mask |= BMAT_FEATURE_WIRE; - } - if (ldata & 0x10) { - mat->feature_mask |= BMAT_FEATURE_VCOLLIGHT; - } - if (ldata & 0x80) { - mat->feature_mask |= BMAT_FEATURE_VCOLPAINT; - } - if (ldata & (1024 | 512 | 256)) { /* not sure about this, it's strange. */ - mat->feature_mask |= BMAT_FEATURE_TEXFACE; - } + if (!(blend_object_structure_getfield(bf, &obj, *matobj, "mode") && + blend_object_getdata(bf, &ldata, obj))) { + abort(); + } + if (ldata & 0x04) { + mat->feature_mask |= BMAT_FEATURE_SHADELESS; + } + if (ldata & 0x08) { + mat->feature_mask |= BMAT_FEATURE_WIRE; + } + if (ldata & 0x10) { + mat->feature_mask |= BMAT_FEATURE_VCOLLIGHT; + } + if (ldata & 0x80) { + mat->feature_mask |= BMAT_FEATURE_VCOLPAINT; + } + if (ldata & (1024 | 512 | 256)) { /* not sure about this, it's strange. */ + mat->feature_mask |= BMAT_FEATURE_TEXFACE; + } - for (i=0; itex_layer[i] = blend_alloc_texlayer(); - /*fprintf(stderr, "GETTING LAYER AT POS %d\n", i);*/ - blend_acquire_texlayer_from_obj(bf, &tlobj, mat->tex_layer[i]); - } else { - /*fprintf(stderr, "NOTHING FOUND AT POS %d\n", i);*/ - } - } + for (i=0; itex_layer[i] = blend_alloc_texlayer(); + /*fprintf(stderr, "GETTING LAYER AT POS %d\n", i);*/ + blend_acquire_texlayer_from_obj(bf, &tlobj, mat->tex_layer[i]); + } else { + /*fprintf(stderr, "NOTHING FOUND AT POS %d\n", i);*/ + } + } } void blend_acquire_mesh_from_obj(BlendFile *bf, BlendObject *meobj, bMesh *mesh) { - { - BlendObject obj; - BlendBlockPointer vblock, fblock, cblock, tblock, - dblock, matlink; - int i; - int32_t ldata = 123456; - float fdata1, fdata2, fdata3; + { + BlendObject obj; + BlendBlockPointer vblock, fblock, cblock, ttblock,mtblock,dblock, matlink; + int i; + int32_t ldata = 123456; + float fdata1, fdata2, fdata3; - blend_init_mesh(mesh); - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "totvert") && - blend_object_getdata(bf, &ldata, obj))) { - abort(); - } - mesh->vert_count = ldata; - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "totface") && - blend_object_getdata(bf, &ldata, obj))) { - abort(); - } - mesh->face_count = ldata; + blend_init_mesh(mesh); - dprintf(stderr, "%d verts, %d faces...\n", - mesh->vert_count, mesh->face_count); - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "mface") && - blend_object_getdata(bf, &fblock, obj))) { - abort(); - } - /* null fblock is okay */ + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "totvert") && + blend_object_getdata(bf, &ldata, obj))) + { + printf("invalid mesh 0x1\n"); + meobj->type = BOBJ_TYPE_INVALID_MESH; + return; + } + mesh->vert_count = ldata; - if (blend_object_structure_getfield(bf, &obj, *meobj, - "mat") && - blend_object_getdata(bf, &matlink, obj) && matlink) { - /* found an indirect material link, follow it */ - BlendObject matlinkobj = blend_block_get_object(bf, matlink, 0); - BlendBlockPointer matblock; - if (blend_object_structure_getfield(bf, &obj, matlinkobj, - "next") && - blend_object_getdata(bf, &matblock, obj)) { - if (matblock) { - BlendObject matobj = blend_block_get_object(bf, matblock, 0); - mesh->material = blend_alloc_material(); - blend_acquire_material_from_obj(bf, &matobj, mesh->material); - } else { - /* um, okay, link went nowhere, leave mesh->material NULL */ - } - } else { - abort(); - } - } else { - /* no material -- mesh->material will remain NULL */ - } - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "mvert") && - blend_object_getdata(bf, &vblock, obj))) { - abort(); - } - /* null vblock is okay */ - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "tface") && - blend_object_getdata(bf, &tblock, obj))) { - abort(); - } - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "mcol") && - blend_object_getdata(bf, &cblock, obj))) { - abort(); - } - - if (!(blend_object_structure_getfield(bf, &obj, *meobj, - "dvert") && - blend_object_getdata(bf, &dblock, obj))) { - /* sometimes there isn't a dvert block... */ - dblock = NULL; - } + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "totface") && + blend_object_getdata(bf, &ldata, obj))) + { + printf("invalid mesh 0x2\n"); + meobj->type = BOBJ_TYPE_INVALID_MESH; + return; + } + mesh->face_count = ldata; - mesh->vert = malloc(sizeof(bVert) * mesh->vert_count); + dprintf(stderr, "%d verts, %d faces...\n", mesh->vert_count, mesh->face_count); - for (i=0; ivert_count; ++i) { - BlendObject obj = blend_block_get_object(bf, vblock, i); - BlendObject aobj; - float fdata1, fdata2, fdata3; - int32_t sdata1, sdata2, sdata3; - char cdata; + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "mface") && + blend_object_getdata(bf, &fblock, obj))) + { + printf("invalid mesh 0x3\n"); + meobj->type = BOBJ_TYPE_INVALID_MESH; + return; + } + /* null fblock is okay */ - mesh->vert[i].xyz[0] = - mesh->vert[i].xyz[1] = - mesh->vert[i].xyz[2] = -12345; - mesh->vert[i].cnormal[0] = - mesh->vert[i].cnormal[1] = - mesh->vert[i].cnormal[2] = -12345; - mesh->vert[i].mat = -1; + if (blend_object_structure_getfield(bf, &obj, *meobj, + "mat") && + blend_object_getdata(bf, &matlink, obj) && matlink) { + /* found an indirect material link, follow it */ + BlendObject matlinkobj = blend_block_get_object(bf, matlink, 0); + BlendBlockPointer matblock; + if (obj.block) + { + if (blend_object_structure_getfield(bf, &obj, matlinkobj, + "next") && + blend_object_getdata(bf, &matblock, obj)) { + if (matblock) { + BlendObject matobj = blend_block_get_object(bf, matblock, 0); + mesh->material = blend_alloc_material(); + blend_acquire_material_from_obj(bf, &matobj, mesh->material); + } else { + /* um, okay, link went nowhere, leave mesh->material NULL */ + } + } else { + //abort();//might fail? + } + } + } else { + /* no material -- mesh->material will remain NULL */ + } - if (!(blend_object_structure_getfield(bf, &aobj, obj, "co") && - blend_object_array_getdata(bf, &fdata1, aobj, 0,0) && - blend_object_array_getdata(bf, &fdata2, aobj, 0,1) && - blend_object_array_getdata(bf, &fdata3, aobj, 0,2))) { - abort(); + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "mvert") && + blend_object_getdata(bf, &vblock, obj))) { + abort(); + } + /* null vblock is okay */ + + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "tface") && + blend_object_getdata(bf, &ttblock, obj))) { + abort(); + } + + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "mtface") && + blend_object_getdata(bf, &mtblock, obj))) { + mtblock=0; + } + + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "mcol") && + blend_object_getdata(bf, &cblock, obj))) { + abort(); + } + + if (!(blend_object_structure_getfield(bf, &obj, *meobj, + "dvert") && + blend_object_getdata(bf, &dblock, obj))) { + /* sometimes there isn't a dvert block... */ + dblock = NULL; + } + + mesh->vert = malloc(sizeof(bVert) * mesh->vert_count); + + for (i=0; ivert_count; ++i) { + BlendObject obj = blend_block_get_object(bf, vblock, i); + BlendObject aobj; + float fdata1, fdata2, fdata3; + int32_t sdata1, sdata2, sdata3; + char cdata; + + mesh->vert[i].xyz[0] = + mesh->vert[i].xyz[1] = + mesh->vert[i].xyz[2] = -12345; + mesh->vert[i].cnormal[0] = + mesh->vert[i].cnormal[1] = + mesh->vert[i].cnormal[2] = -12345; + mesh->vert[i].mat = -1; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "co") && + blend_object_array_getdata(bf, &fdata1, aobj, 0,0) && + blend_object_array_getdata(bf, &fdata2, aobj, 0,1) && + blend_object_array_getdata(bf, &fdata3, aobj, 0,2))) { + abort(); + } + mesh->vert[i].xyz[0] = fdata1; + mesh->vert[i].xyz[1] = fdata2; + mesh->vert[i].xyz[2] = fdata3; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "no") && + blend_object_array_getdata(bf, &sdata1, aobj, 0,0) && + blend_object_array_getdata(bf, &sdata2, aobj, 0,1) && + blend_object_array_getdata(bf, &sdata3, aobj, 0,2))) { + abort(); + } + mesh->vert[i].cnormal[0] = sdata1; + mesh->vert[i].cnormal[1] = sdata2; + mesh->vert[i].cnormal[2] = sdata3; + /*fprintf(stderr, "%f ", LEN3(mesh->vert[i].normal[0], + mesh->vert[i].normal[1], + mesh->vert[i].normal[2]));*/ + if (sdata1 != 0 || sdata2 != 0 || sdata3 != 0) { + NORMALIZE3(mesh->vert[i].cnormal[0], + mesh->vert[i].cnormal[1], + mesh->vert[i].cnormal[2]); + } + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "mat_nr") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->vert[i].mat = cdata; + } + + mesh->face = malloc(sizeof(bFace) * mesh->face_count); + + for (i=0; iface_count; ++i) { + int j,k; + BlendObject obj = blend_block_get_object(bf, fblock, i); + BlendObject aobj; + char cdata; + + mesh->face[i].v[0] = mesh->face[i].v[1] = + mesh->face[i].v[2] = mesh->face[i].v[3] = -1; + mesh->face[i].mat = -1; + mesh->face[i].flags = 0; + + for (j=0; j<4; ++j) { + for (k=0; k<3; ++k) { + mesh->face[i].rgba[j][k] = 1.0; + } + mesh->face[i].rgba[j][3] = 1.0f; + mesh->face[i].uv[j][0] = 0.0f; + mesh->face[i].uv[j][1] = 0.0f; + mesh->face[i].m_image = NULL; + } + + if (blend_object_structure_getfield(bf, &aobj, obj, "v1")) { + if (0!=strcmp(bf->types[aobj.type].name,"int") && + 0!=strcmp(bf->types[aobj.type].name,"ushort")) { + dprintf(stderr, "Expected vertex-index type to be 'ushort' or 'int', got '%s'\n", bf->types[aobj.type].name); + abort(); + } + + if (0==strcmp(bf->types[aobj.type].name,"int")) { + /* index type is a 32bit int, generated by newish Blenders */ + int32_t idata; + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v1") && + blend_object_getdata(bf, &idata, aobj))) { + abort(); + } + mesh->face[i].v[0] = idata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v2") && + blend_object_getdata(bf, &idata, aobj))) { + abort(); + } + mesh->face[i].v[1] = idata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v3") && + blend_object_getdata(bf, &idata, aobj))) { + abort(); + } + mesh->face[i].v[2] = idata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v4") && + blend_object_getdata(bf, &idata, aobj))) { + abort(); + } + mesh->face[i].v[3] = idata; + } else { + /* index type is a 16bit ushort, generated by old Blenders */ + uint16_t usdata; + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v1") && + blend_object_getdata(bf, &usdata, aobj))) { + abort(); + } + mesh->face[i].v[0] = usdata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v2") && + blend_object_getdata(bf, &usdata, aobj))) { + abort(); + } + mesh->face[i].v[1] = usdata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v3") && + blend_object_getdata(bf, &usdata, aobj))) { + abort(); + } + mesh->face[i].v[2] = usdata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "v4") && + blend_object_getdata(bf, &usdata, aobj))) { + abort(); + } + mesh->face[i].v[3] = usdata; + } + } else { + abort(); + } + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "mat_nr") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].mat = cdata; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "flag") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].flags = cdata; + } + + if (cblock) { + /* we have vertex colours */ + for (i=0; iface_count; ++i) { + int j; + unsigned char cdata; + BlendObject aobj; + for (j=0; j<4; ++j) { + BlendObject obj = blend_block_get_object(bf, cblock, i*4+j); + if (!(blend_object_structure_getfield(bf, &aobj, obj, "b") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].rgba[j][0] = cdata / 255.0f; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "g") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].rgba[j][1] = cdata / 255.0f; + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "r") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].rgba[j][2] = cdata / 255.0f; + + /* alpha seems to be nonsense :( */ + /* + if (!(blend_object_structure_getfield(bf, &aobj, obj, "a") && + blend_object_getdata(bf, &cdata, aobj))) { + abort(); + } + mesh->face[i].rgba[j][3] = cdata / 255.0f; + */ + mesh->face[i].rgba[j][3] = 1.0f; + } + } + } else { + /* !cblock (no vertex colours) */ + for (i=0; iface_count; ++i) { + int j; + for (j=0; j<4; ++j) { + mesh->face[i].rgba[j][0] = 1.0f; + mesh->face[i].rgba[j][1] = 1.0f; + mesh->face[i].rgba[j][2] = 1.0f; + mesh->face[i].rgba[j][3] = 1.0f; + } + } + } + + if (mtblock) + { + /* we have tex co-ords */ + for (i=0; iface_count; ++i) + { + int j,k; + void *pdata; + BlendObject aobj; + BlendObject obj = blend_block_get_object(bf, mtblock, i); + BlendObject obj2,obj3; + unsigned char flag; + unsigned short int mode; + + BlendBlockPointer tpageptr; + + if (blend_object_structure_getfield(bf, &obj3, obj, "flag")) + { + blend_object_getdata(bf, &flag, obj3); + mesh->face[i].m_flag = flag; + } else + { + mesh->face[i].m_flag = 0; + } + + if (blend_object_structure_getfield(bf, &obj3, obj, "mode")) + { + blend_object_getdata(bf, &mode, obj3); + mesh->face[i].m_mode = mode; + } else + { + mesh->face[i].m_mode = 0; + } + + if ((blend_object_structure_getfield(bf, &obj3, obj, "tpage") + && blend_object_getdata(bf, &tpageptr, obj3))) + { + + mesh->face[i].m_image = 0; + + for (j=0; j<4; ++j) + { + uint32_t uldata; + for (k=0; k<2; ++k) { + float fdata; + if (!(blend_object_structure_getfield(bf, &aobj, obj, "uv") && + blend_object_array_getdata(bf, &fdata, aobj, j,k))) { + abort(); + } + mesh->face[i].uv[j][k] = fdata; + } + mesh->face[i].uv[j][1] = 1.0f - mesh->face[i].uv[j][1]; + /* texture face colour... not sure how this conceptually + differs from the face vertex colours, but it does. */ + + /* in its usual inconsistant style, blender packs this + RGBA value into the bytes of an unsigned long... */ + + } + + //printf("got tpage\n"); + + { + int k; + for (k=0;kface[i].m_image=tCachedImages[k]; + break; + } + } + } + + if (!mesh->face[i].m_image) + { + bImage* bimg= (bImage*)malloc (sizeof(bImage)); + tCachedImages[gNumCachedImages]=bimg; + tCachedTPage[gNumCachedImages] = tpageptr; + gNumCachedImages++; + mesh->face[i].m_image = bimg; + bimg->m_packedImagePtr = 0; + bimg->m_sizePackedImage = 0; + + if (tpageptr) + { + BlendObject name_block; + BlendObject tpage = blend_block_get_object(bf,tpageptr,0); + + BlendObject okblock; + + + if ((blend_object_structure_getfield(bf, &okblock, tpage, "ok"))) + { + short int okval; + if (blend_object_getdata(bf,&okval,okblock)) + { +// printf("ok=%d\n",okval); + bimg->m_ok = okval; + } else + { + bimg->m_ok=0; + } + + } + + if ((blend_object_structure_getfield(bf, &okblock, tpage, "xrep"))) + { + short int xrep; + if (blend_object_getdata(bf,&xrep,okblock)) + { +// printf("xrep=%d\n",xrep); + bimg->m_xrep = xrep; + } else + { + bimg->m_xrep = 0; + } + } + + if ((blend_object_structure_getfield(bf, &okblock, tpage, "yrep"))) + { + short int yrep; + if (blend_object_getdata(bf,&yrep,okblock)) + { +// printf("yrep=%d\n",yrep); + bimg->m_yrep = yrep; + } else + { + bimg->m_yrep = 0; + } + } + + mesh->face[i].image_id = 0; + { + BlendBlockPointer packptr; + + if ((blend_object_structure_getfield(bf, &obj3, tpage, "packedfile") + && blend_object_getdata(bf, &packptr, obj3))) + { + if (packptr) + { + BlendObject packfile= blend_block_get_object(bf,packptr,0); + BlendBlockPointer dataptr; + if ((blend_object_structure_getfield(bf, &obj3, packfile, "data") + && blend_object_getdata(bf, &dataptr, obj3))) + { + /*BlendObject data= blend_block_get_object(bf,dataptr,0); + char dest[1024]; + blend_object_getstring(bf,data,dest,1023); + */ + +// printf("...\n"); + + //if (blend_object_structure_getfield(bf, &obj2, ipo,"curve")) + { + BlendBlock* block = (BlendBlock*)obj3.block; + + + void** ptrptr = &block->array_entries->field_bytes[block->array_entries->field_offsets[obj3.field_index]]; + BlendBlockPointer ptr = *ptrptr; + if (ptr) + { + BlendBlockPointer curveblockptr = blend_block_from_blendpointer(bf, ptr); + BlendObject curve = blend_block_get_object(bf, curveblockptr, 0); + BlendBlock* bb = (BlendBlock* )curve.block; + BlendBlock imgblock; + mesh->face[i].image_id = bb->blender_pointer; + //imgblock = blend_block_get_object(bf, bb->blender_pointer, 0); + bimg->m_packedImagePtr = bb->customData; + bimg->m_sizePackedImage = bb->customDataSize; + } + + } + } + + + } + + } + } + + + + + if ((blend_object_structure_getfield(bf, &name_block, tpage, "name"))) + { + int max_chars=127; + + if (blend_object_getstring(bf,name_block,bimg->m_imagePathName, max_chars)) + { +// printf("texname=%s\n",bimg->m_imagePathName); + } + + } + + + + } + + } + + + } + + + + + } + } + else + { + if (ttblock) { + /* we have tex co-ords */ + for (i=0; iface_count; ++i) { + int j,k; + void *pdata; + BlendObject aobj; + BlendObject obj = blend_block_get_object(bf, ttblock, i); + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "tpage") && + blend_object_getdata(bf, &pdata, aobj))) { + abort(); + } + mesh->face[i].image_id = pdata; + + for (j=0; j<4; ++j) { + uint32_t uldata; + for (k=0; k<2; ++k) { + float fdata; + if (!(blend_object_structure_getfield(bf, &aobj, obj, "uv") && + blend_object_array_getdata(bf, &fdata, aobj, j,k))) { + abort(); + } + mesh->face[i].uv[j][k] = fdata; + } + mesh->face[i].uv[j][1] = 1.0f - mesh->face[i].uv[j][1]; + /* texture face colour... not sure how this conceptually + differs from the face vertex colours, but it does. */ + if (!(blend_object_structure_getfield(bf, &aobj, obj, "col") && + blend_object_array_getdata(bf, &uldata, aobj, 0,j))) { + abort(); + } + /* in its usual inconsistant style, blender packs this + RGBA value into the bytes of an unsigned long... */ + mesh->face[i].rgba2[j][0] = ((uldata >> 24) & 0xFF) / 255.0f; + mesh->face[i].rgba2[j][1] = ((uldata >> 16) & 0xFF) / 255.0f; + mesh->face[i].rgba2[j][2] = ((uldata >> 8) & 0xFF) / 255.0f; + mesh->face[i].rgba2[j][3] = ((uldata >> 0) & 0xFF) / 255.0f; + } + /*mesh->face[i].uv[0][0]=0; mesh->face[i].uv[0][1]=0; + mesh->face[i].uv[1][0]=1; mesh->face[i].uv[1][1]=0; + mesh->face[i].uv[2][0]=1; mesh->face[i].uv[2][1]=1; + mesh->face[i].uv[3][0]=0; mesh->face[i].uv[3][1]=1;*/ + + } + } else { + /* !tblock (no texture co-ords, no face tex-colours) */ + for (i=0; iface_count; ++i) { + int j; + for (j=0; j<4; ++j) { + mesh->face[i].rgba2[j][0] = 1.0f; + mesh->face[i].rgba2[j][1] = 1.0f; + mesh->face[i].rgba2[j][2] = 1.0f; + mesh->face[i].rgba2[j][3] = 1.0f; + } + } + } + } + + if (mtblock) + { + BlendObject obj = blend_block_get_object(bf, mtblock, 0); + + //6155 + } + + + if (dblock) { + /* we have vertex deformation weights */ + for (i=0; ivert_count; ++i) { + int j; + int32_t ldata; + float fdata; + BlendBlockPointer pdata; + BlendObject aobj; + BlendObject obj = blend_block_get_object(bf, dblock, i); + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "totweight") && + blend_object_getdata(bf, &ldata, aobj))) { + abort(); + } + mesh->vert[i].deform_weights_count = ldata; + mesh->vert[i].deform_weights = malloc(ldata*sizeof(bDeformWeight)); + + if (!(blend_object_structure_getfield(bf, &aobj, obj, "dw") && + blend_object_getdata(bf, &pdata, aobj))) { + abort(); + } + + for (j=0; jvert[i].deform_weights_count; ++j) { + BlendObject dwobj = blend_block_get_object(bf, pdata, j); + + if (!(blend_object_structure_getfield(bf, &aobj, dwobj, "def_nr") + && blend_object_getdata(bf, &ldata, aobj))) { + abort(); + } + mesh->vert[i].deform_weights[j].bone_id = ldata; + + if (!(blend_object_structure_getfield(bf, &aobj, dwobj, "weight") + && blend_object_getdata(bf, &fdata, aobj))) { + abort(); + } + mesh->vert[i].deform_weights[j].weight = fdata; + } + } + } else { + /* !dblock (no vertex deformation weights) */ + for (i=0; ivert_count; ++i) { + mesh->vert[i].deform_weights = NULL; + mesh->vert[i].deform_weights_count = 0; + } + } } - mesh->vert[i].xyz[0] = fdata1; - mesh->vert[i].xyz[1] = fdata2; - mesh->vert[i].xyz[2] = fdata3; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "no") && - blend_object_array_getdata(bf, &sdata1, aobj, 0,0) && - blend_object_array_getdata(bf, &sdata2, aobj, 0,1) && - blend_object_array_getdata(bf, &sdata3, aobj, 0,2))) { - abort(); - } - mesh->vert[i].cnormal[0] = sdata1; - mesh->vert[i].cnormal[1] = sdata2; - mesh->vert[i].cnormal[2] = sdata3; - /*fprintf(stderr, "%f ", LEN3(mesh->vert[i].normal[0], - mesh->vert[i].normal[1], - mesh->vert[i].normal[2]));*/ - if (sdata1 != 0 || sdata2 != 0 || sdata3 != 0) { - NORMALIZE3(mesh->vert[i].cnormal[0], - mesh->vert[i].cnormal[1], - mesh->vert[i].cnormal[2]); - } - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "mat_nr") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->vert[i].mat = cdata; - } - - mesh->face = malloc(sizeof(bFace) * mesh->face_count); - - for (i=0; iface_count; ++i) { - int j,k; - BlendObject obj = blend_block_get_object(bf, fblock, i); - BlendObject aobj; - char cdata; - - mesh->face[i].v[0] = mesh->face[i].v[1] = - mesh->face[i].v[2] = mesh->face[i].v[3] = -1; - mesh->face[i].mat = -1; - mesh->face[i].flags = 0; - for (j=0; j<4; ++j) { - for (k=0; k<3; ++k) { - mesh->face[i].rgba[j][k] = 1.0; - } - mesh->face[i].rgba[j][3] = 1.0f; - mesh->face[i].uv[j][0] = 0.0f; - mesh->face[i].uv[j][1] = 0.0f; - mesh->face[i].image_id = NULL; - } - - if (blend_object_structure_getfield(bf, &aobj, obj, "v1")) { - if (0!=strcmp(bf->types[aobj.type].name,"int") && - 0!=strcmp(bf->types[aobj.type].name,"ushort")) { - dprintf(stderr, "Expected vertex-index type to be 'ushort' or 'int', got '%s'\n", bf->types[aobj.type].name); - abort(); - } - - if (0==strcmp(bf->types[aobj.type].name,"int")) { - /* index type is a 32bit int, generated by newish Blenders */ - int32_t idata; - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v1") && - blend_object_getdata(bf, &idata, aobj))) { - abort(); - } - mesh->face[i].v[0] = idata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v2") && - blend_object_getdata(bf, &idata, aobj))) { - abort(); - } - mesh->face[i].v[1] = idata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v3") && - blend_object_getdata(bf, &idata, aobj))) { - abort(); - } - mesh->face[i].v[2] = idata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v4") && - blend_object_getdata(bf, &idata, aobj))) { - abort(); - } - mesh->face[i].v[3] = idata; - } else { - /* index type is a 16bit ushort, generated by old Blenders */ - uint16_t usdata; - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v1") && - blend_object_getdata(bf, &usdata, aobj))) { - abort(); - } - mesh->face[i].v[0] = usdata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v2") && - blend_object_getdata(bf, &usdata, aobj))) { - abort(); - } - mesh->face[i].v[1] = usdata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v3") && - blend_object_getdata(bf, &usdata, aobj))) { - abort(); - } - mesh->face[i].v[2] = usdata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "v4") && - blend_object_getdata(bf, &usdata, aobj))) { - abort(); - } - mesh->face[i].v[3] = usdata; - } - } else { - abort(); - } - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "mat_nr") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].mat = cdata; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "flag") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].flags = cdata; - } - - if (cblock) { - /* we have vertex colours */ - for (i=0; iface_count; ++i) { - int j; - unsigned char cdata; - BlendObject aobj; - for (j=0; j<4; ++j) { - BlendObject obj = blend_block_get_object(bf, cblock, i*4+j); - if (!(blend_object_structure_getfield(bf, &aobj, obj, "b") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].rgba[j][0] = cdata / 255.0f; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "g") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].rgba[j][1] = cdata / 255.0f; - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "r") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].rgba[j][2] = cdata / 255.0f; - - /* alpha seems to be nonsense :( */ - /* - if (!(blend_object_structure_getfield(bf, &aobj, obj, "a") && - blend_object_getdata(bf, &cdata, aobj))) { - abort(); - } - mesh->face[i].rgba[j][3] = cdata / 255.0f; - */ - mesh->face[i].rgba[j][3] = 1.0f; - } - } - } else { - /* !cblock (no vertex colours) */ - for (i=0; iface_count; ++i) { - int j; - for (j=0; j<4; ++j) { - mesh->face[i].rgba[j][0] = 1.0f; - mesh->face[i].rgba[j][1] = 1.0f; - mesh->face[i].rgba[j][2] = 1.0f; - mesh->face[i].rgba[j][3] = 1.0f; - } - } - } - - if (tblock) { - /* we have tex co-ords */ - for (i=0; iface_count; ++i) { - int j,k; - void *pdata; - BlendObject aobj; - BlendObject obj = blend_block_get_object(bf, tblock, i); - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "tpage") && - blend_object_getdata(bf, &pdata, aobj))) { - abort(); - } - mesh->face[i].image_id = pdata; - - for (j=0; j<4; ++j) { - uint32_t uldata; - for (k=0; k<2; ++k) { - float fdata; - if (!(blend_object_structure_getfield(bf, &aobj, obj, "uv") && - blend_object_array_getdata(bf, &fdata, aobj, j,k))) { - abort(); - } - mesh->face[i].uv[j][k] = fdata; - } - mesh->face[i].uv[j][1] = 1.0f - mesh->face[i].uv[j][1]; - /* texture face colour... not sure how this conceptually - differs from the face vertex colours, but it does. */ - if (!(blend_object_structure_getfield(bf, &aobj, obj, "col") && - blend_object_array_getdata(bf, &uldata, aobj, 0,j))) { - abort(); - } - /* in its usual inconsistant style, blender packs this - RGBA value into the bytes of an unsigned long... */ - mesh->face[i].rgba2[j][0] = ((uldata >> 24) & 0xFF) / 255.0f; - mesh->face[i].rgba2[j][1] = ((uldata >> 16) & 0xFF) / 255.0f; - mesh->face[i].rgba2[j][2] = ((uldata >> 8) & 0xFF) / 255.0f; - mesh->face[i].rgba2[j][3] = ((uldata >> 0) & 0xFF) / 255.0f; - } - /*mesh->face[i].uv[0][0]=0; mesh->face[i].uv[0][1]=0; - mesh->face[i].uv[1][0]=1; mesh->face[i].uv[1][1]=0; - mesh->face[i].uv[2][0]=1; mesh->face[i].uv[2][1]=1; - mesh->face[i].uv[3][0]=0; mesh->face[i].uv[3][1]=1;*/ - - } - } else { - /* !tblock (no texture co-ords, no face tex-colours) */ - for (i=0; iface_count; ++i) { - int j; - for (j=0; j<4; ++j) { - mesh->face[i].rgba2[j][0] = 1.0f; - mesh->face[i].rgba2[j][1] = 1.0f; - mesh->face[i].rgba2[j][2] = 1.0f; - mesh->face[i].rgba2[j][3] = 1.0f; - } - } - } - - if (dblock) { - /* we have vertex deformation weights */ - for (i=0; ivert_count; ++i) { - int j; - int32_t ldata; - float fdata; - BlendBlockPointer pdata; - BlendObject aobj; - BlendObject obj = blend_block_get_object(bf, dblock, i); - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "totweight") && - blend_object_getdata(bf, &ldata, aobj))) { - abort(); - } - mesh->vert[i].deform_weights_count = ldata; - mesh->vert[i].deform_weights = malloc(ldata*sizeof(bDeformWeight)); - - if (!(blend_object_structure_getfield(bf, &aobj, obj, "dw") && - blend_object_getdata(bf, &pdata, aobj))) { - abort(); - } - - for (j=0; jvert[i].deform_weights_count; ++j) { - BlendObject dwobj = blend_block_get_object(bf, pdata, j); - - if (!(blend_object_structure_getfield(bf, &aobj, dwobj, "def_nr") - && blend_object_getdata(bf, &ldata, aobj))) { - abort(); - } - mesh->vert[i].deform_weights[j].bone_id = ldata; - - if (!(blend_object_structure_getfield(bf, &aobj, dwobj, "weight") - && blend_object_getdata(bf, &fdata, aobj))) { - abort(); - } - mesh->vert[i].deform_weights[j].weight = fdata; - } - } - } else { - /* !dblock (no vertex deformation weights) */ - for (i=0; ivert_count; ++i) { - mesh->vert[i].deform_weights = NULL; - mesh->vert[i].deform_weights_count = 0; - } - } - } } @@ -2322,76 +2720,76 @@ blend_acquire_mesh_from_obj(BlendFile *bf, BlendObject *meobj, bMesh *mesh) void blend_acquire_mesh(const char *fname, const char *want_name, bMesh *mesh) { - BlendFile* bf; - MY_FILETYPE *fp; + BlendFile* bf; + MY_FILETYPE *fp; - fp = MY_OPEN_FOR_READ(fname); + fp = MY_OPEN_FOR_READ(fname); - if (!fp) { - dprintf(stderr, "couldn't open file %s.\n", fname); - abort(); - } + if (!fp) { + dprintf(stderr, "couldn't open file %s.\n", fname); + abort(); + } - bf = blend_read(fp); - { - BlendObject meobj; - if (!blend_object_get_by_IDname(bf, &meobj, want_name)) { - dprintf(stderr, "couldn't find %s.\n", want_name); - abort(); - } - blend_dump_blocks(bf); - blend_acquire_mesh_from_obj(bf, &meobj, mesh); - } - blend_free(bf); + bf = blend_read(fp); + { + BlendObject meobj; + if (!blend_object_get_by_IDname(bf, &meobj, want_name)) { + dprintf(stderr, "couldn't find %s.\n", want_name); + abort(); + } + blend_dump_blocks(bf); + blend_acquire_mesh_from_obj(bf, &meobj, mesh); + } + blend_free(bf); - MY_CLOSE(fp); + MY_CLOSE(fp); } /* apply pitch, head, roll */ static void bRotPHR(float xyz[3], const float rot[3]) { - float rx,ry,rz; - float ix,iy,iz; - float cosang, sinang; + float rx,ry,rz; + float ix,iy,iz; + float cosang, sinang; - ix = xyz[0]; iy = xyz[1]; iz = xyz[2]; + ix = xyz[0]; iy = xyz[1]; iz = xyz[2]; - cosang = cos(rot[0]); - sinang = sin(rot[0]); - /* pitch */ - rx = ix; - ry = iy * cosang - iz * sinang; - rz = iy * sinang + iz * cosang; + cosang = cos(rot[0]); + sinang = sin(rot[0]); + /* pitch */ + rx = ix; + ry = iy * cosang - iz * sinang; + rz = iy * sinang + iz * cosang; - ix = rx; iy = ry; iz = rz; + ix = rx; iy = ry; iz = rz; - cosang = cos(rot[1]); - sinang = sin(rot[1]); - /* head */ - rx = ix * cosang + iz * sinang; - ry = iy; - rz = -ix * sinang + iz * cosang; + cosang = cos(rot[1]); + sinang = sin(rot[1]); + /* head */ + rx = ix * cosang + iz * sinang; + ry = iy; + rz = -ix * sinang + iz * cosang; - ix = rx; iy = ry; iz = rz; + ix = rx; iy = ry; iz = rz; - cosang = cos(rot[2]); - sinang = sin(rot[2]); - /* roll */ - rx = ix * cosang - iy * sinang; - ry = ix * sinang + iy * cosang; - rz = iz; + cosang = cos(rot[2]); + sinang = sin(rot[2]); + /* roll */ + rx = ix * cosang - iy * sinang; + ry = ix * sinang + iy * cosang; + rz = iz; - xyz[0] = rx; xyz[1] = ry; xyz[2] = rz; + xyz[0] = rx; xyz[1] = ry; xyz[2] = rz; } void blend_transform_mesh_from_obj(bMesh *mesh, bObj *obj) { - int i; - for (i=0; ivert_count; ++i) { - /* this one looks good. */ - bMatMultVec(mesh->vert[i].xyz, obj->transform); - bRotPHR(mesh->vert[i].cnormal, obj->rotphr); - } + int i; + for (i=0; ivert_count; ++i) { + /* this one looks good. */ + bMatMultVec(mesh->vert[i].xyz, obj->transform); + bRotPHR(mesh->vert[i].cnormal, obj->rotphr); + } } diff --git a/Extras/readblend/readblend.h b/Extras/readblend/readblend.h index 53ea69aeb..102686049 100644 --- a/Extras/readblend/readblend.h +++ b/Extras/readblend/readblend.h @@ -38,11 +38,11 @@ /* TODO: Doxygen me. */ -/* don't worry yourself about this. */ -#ifndef BlendFile -#define BlendFile void -#endif +#include "blendtype.h" +#ifdef __cplusplus +extern "C" { +#endif @@ -101,6 +101,7 @@ typedef struct { long entry_index; long field_index; } BlendObject; + /* The callback type for passing to blend_foreach_block() (the callback should return zero if it doesn't want to see any more blocks.) */ #define BLENDBLOCKCALLBACK_RETURN int @@ -312,20 +313,41 @@ typedef struct { bDeformWeight* deform_weights; int deform_weights_count; } bVert; + + #define BVERT_HAS_CNORMAL(BV) ((BV)->cnormal[0] != 0.0f || \ (BV)->cnormal[1] != 0.0f || \ (BV)->cnormal[2] != 0.0f) #define BFACE_FLAG_SMOOTH 0x01 + +typedef struct _bImage { + + void* m_packedImagePtr; + int m_sizePackedImage; + char m_imagePathName [128]; + + int m_ok; + + int m_xrep; + int m_yrep; + +} bImage; + typedef struct { int v[4]; float rgba[4][4]; /* vertex colours */ float rgba2[4][4]; /* texture face colours (errrr...?) */ float uv[4][2]; - BlendBlockPointer image_id; + bImage* m_image; int mat; unsigned char flags; + int m_flag; + int m_mode; + BlendBlockPointer image_id; } bFace; + + #define BFACE_HAS_TEXTURE(BF) ((BF)->image_id != NULL) #define BFACE_IS_QUAD(BF) ((BF)->v[3] != 0) #define BFACE_IS_TRI(BF) ((BF)->v[2] != 0 && (BF)->v[3] == 0) @@ -389,7 +411,7 @@ typedef struct { typedef float bMatrix[4][4]; -typedef struct { +typedef struct _bMesh{ bVert *vert; int vert_count; bFace *face; @@ -400,14 +422,17 @@ typedef struct { typedef enum { BOBJ_TYPE_UNKNOWN, BOBJ_TYPE_NULL, /* indicates object has no data associated with it! */ - BOBJ_TYPE_MESH + BOBJ_TYPE_MESH, + BOBJ_TYPE_INVALID_MESH, + BOBJ_TYPE_CAMERA, + BOBJ_TYPE_LAMP } bObjType; typedef enum { BAQ_INCLUDE_CHILDREN = 0x0001 } bAcquireFlags; -typedef struct { +typedef struct _bObj{ bObjType type; char *name; @@ -417,11 +442,15 @@ typedef struct { float rotphr[3]; /* pitch/head/roll rotation component of transform (use for normals) */ float location[3]; /* location component of transform */ unsigned char transflags; /* NOT DECODED YET, RAW BYTE */ - + float mass;//used for rigid body dynamics + int gameflag; //used to detect object type (static, ghost, dynamic, rigid body, soft body) + int boundtype; //used to detect collision shape type + union { void *dummy; bMesh *mesh; } data; + } bObj; @@ -456,4 +485,8 @@ void blend_free_texlayer(bTexLayer *tl); void blend_acquire_texlayer_from_obj(BlendFile *bf, BlendObject *tlobj, bTexLayer *tl); +#ifdef __cplusplus +} +#endif + #endif diff --git a/Extras/readblend/testblend.c b/Extras/readblend/testblend.c index 488294274..86e207176 100644 --- a/Extras/readblend/testblend.c +++ b/Extras/readblend/testblend.c @@ -4,107 +4,170 @@ #include "abs-file.h" #include "readblend.h" +#include "blendtype.h" + +#define MAX_MESHES 10 +bMesh gMeshes[MAX_MESHES]; +int gNumMesh = 0; + +#define MAX_OBJECTS 10 +bObj gObjects[MAX_OBJECTS]; +int gNumObjects = 0; void crawl(BlendFile* blend_file, - BlendObject obj) + BlendObject obj) { - BlendObject data_obj; + BlendObject data_obj; + BlendObject data_obj2; + + BlendBlock* tmpBlock=0; - if (blend_object_structure_getfield(blend_file, &data_obj, obj, "totvert")) { - if (blend_object_type(blend_file, data_obj) == BLEND_OBJ_LONG32) { - long data1 = 123456; - if (blend_object_getdata(blend_file, &data1, data_obj)) { - fprintf(stderr, "TOTVERT=(%ld) ", data1); - } else { - fprintf(stderr, "FETCH ERROR\n"); - } - } - } + { + const char* type_name = blend_file->types[obj.type].name; + if (strcmp(type_name,"Object")==0) + { + if (gNumObjectsgetWorldTransform(); gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); - btScalar sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold; - //now perturbe directions to get multiple contact points btVector3 v0,v1; - btVector3 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); - btPlaneSpace1(sepNormalWorldSpace,v0,v1); + btVector3 sepNormalWorldSpace; + btScalar sepDist = 0.f; + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold; + if (sepDist>SIMD_EPSILON) + { + //now perturbe directions to get multiple contact points + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); + btPlaneSpace1(sepNormalWorldSpace,v0,v1); + } + } +#endif //USE_SEPDISTANCE_UTIL2 + //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points @@ -280,7 +292,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl #ifdef USE_SEPDISTANCE_UTIL2 - if (dispatchInfo.m_useConvexConservativeDistanceUtil) + if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON)) { m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform()); } diff --git a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 50a79451f..54914d27c 100644 --- a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -29,6 +29,12 @@ Written by: Marcus Hennix #define CONETWIST_DEF_FIX_THRESH btScalar(.05f) +SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld) +{ + btVector3 vec = axis * invInertiaWorld; + return axis.dot(vec); +} + btConeTwistConstraint::btConeTwistConstraint() :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE), @@ -70,8 +76,6 @@ void btConeTwistConstraint::init() } - - void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) @@ -83,7 +87,7 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) { info->m_numConstraintRows = 3; info->nub = 3; - calcAngleInfo2(); + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); if(m_solveSwingLimit) { info->m_numConstraintRows++; @@ -101,22 +105,31 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) } } } - +void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + //always reserve 6 rows: object transform is not available on SPU + info->m_numConstraintRows = 6; + info->nub = 0; + +} + void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) { + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); +} + +void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +{ + calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB); + btAssert(!m_useSolveConstraintObsolete); - //retrieve matrices - btTransform body0_trans; - body0_trans = m_rbA.getCenterOfMassTransform(); - btTransform body1_trans; - body1_trans = m_rbB.getCenterOfMassTransform(); // set jacobian info->m_J1linearAxis[0] = 1; info->m_J1linearAxis[info->rowskip+1] = 1; info->m_J1linearAxis[2*info->rowskip+2] = 1; - btVector3 a1 = body0_trans.getBasis() * m_rbAFrame.getOrigin(); + btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); @@ -124,7 +137,7 @@ void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) btVector3 a1neg = -a1; a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); } - btVector3 a2 = body1_trans.getBasis() * m_rbBFrame.getOrigin(); + btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); @@ -136,7 +149,7 @@ void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) int j; for (j=0; j<3; j++) { - info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]); info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; } @@ -275,7 +288,7 @@ void btConeTwistConstraint::buildJacobian() } } - calcAngleInfo2(); + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); } } @@ -593,7 +606,7 @@ static btVector3 vTwist(1,0,0); // twist axis in constraint's space -void btConeTwistConstraint::calcAngleInfo2() +void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) { m_swingCorrection = btScalar(0.); m_twistLimitSign = btScalar(0.); @@ -606,8 +619,8 @@ void btConeTwistConstraint::calcAngleInfo2() // TODO : split rotation to pure swing and pure twist // compute desired transforms in world btTransform trPose(m_qTarget); - btTransform trA = getRigidBodyA().getCenterOfMassTransform() * m_rbAFrame; - btTransform trB = getRigidBodyB().getCenterOfMassTransform() * m_rbBFrame; + btTransform trA = transA * m_rbAFrame; + btTransform trB = transB * m_rbBFrame; btTransform trDeltaAB = trB * trPose * trA.inverse(); btQuaternion qDeltaAB = trDeltaAB.getRotation(); btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); @@ -624,8 +637,8 @@ void btConeTwistConstraint::calcAngleInfo2() { // compute rotation of A wrt B (in constraint space) - btQuaternion qA = getRigidBodyA().getCenterOfMassTransform().getRotation() * m_rbAFrame.getRotation(); - btQuaternion qB = getRigidBodyB().getCenterOfMassTransform().getRotation() * m_rbBFrame.getRotation(); + btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation(); + btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation(); btQuaternion qAB = qB.inverse() * qA; // split rotation into cone and twist // (all this is done from B's perspective. Maybe I should be averaging axes...) @@ -673,10 +686,10 @@ void btConeTwistConstraint::calcAngleInfo2() // you haven't set any limits; // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?) // anyway, we have either hinge or fixed joint - btVector3 ivA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); - btVector3 jvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); - btVector3 kvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - btVector3 ivB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(0); + btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0); btVector3 target; btScalar x = ivB.dot(ivA); btScalar y = ivB.dot(jvA); diff --git a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 8a893d4fb..db1e061db 100644 --- a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -110,9 +110,12 @@ public: virtual void buildJacobian(); virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); virtual void getInfo2 (btConstraintInfo2* info); + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); @@ -198,7 +201,7 @@ public: } void calcAngleInfo(); - void calcAngleInfo2(); + void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); inline btScalar getSwingSpan1() { diff --git a/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index 012c321fd..72116c6ba 100644 --- a/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -14,6 +14,59 @@ subject to the following restrictions: */ +#include "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + +btContactConstraint::btContactConstraint() +:btTypedConstraint(CONTACT_CONSTRAINT_TYPE) +{ +} + +btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB) +:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB), + m_contactManifold(*contactManifold) +{ + +} + +btContactConstraint::~btContactConstraint() +{ + +} + +void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold) +{ + m_contactManifold = *contactManifold; +} + +void btContactConstraint::getInfo1 (btConstraintInfo1* info) +{ + +} + +void btContactConstraint::getInfo2 (btConstraintInfo2* info) +{ + +} + +void btContactConstraint::buildJacobian() +{ + +} + +void btContactConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + +} + + + + #include "btContactConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btVector3.h" @@ -85,345 +138,4 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, -//response between two dynamic objects with friction -btScalar resolveSingleCollision( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - const btVector3& pos1_ = contactPoint.getPositionWorldOnA(); - const btVector3& pos2_ = contactPoint.getPositionWorldOnB(); - const btVector3& normal = contactPoint.m_normalWorldOnB; - - //constant over all iterations - btVector3 rel_pos1 = pos1_ - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2_ - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; - - // btScalar damping = solverInfo.m_damping ; - btScalar Kerp = solverInfo.m_erp; - btScalar Kcor = Kerp *Kfps; - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - btAssert(cpd); - btScalar distance = cpd->m_penetration; - btScalar positionalError = Kcor *-distance; - btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; - - btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; - - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = cpd->m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse(normal*(normalImpulse), rel_pos1); - body2.applyImpulse(-normal*(normalImpulse), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - return normalImpulse; -} - - -btScalar resolveSingleFriction( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - (void)solverInfo; - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - btAssert(cpd); - - btScalar combinedFriction = cpd->m_friction; - - btScalar limit = cpd->m_appliedImpulse * combinedFriction; - - if (cpd->m_appliedImpulse>btScalar(0.)) - //friction - { - //apply friction in the 2 tangential directions - - // 1st tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar j1,j2; - - { - - btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); - - // calculate j that moves us to zero relative velocity - j1 = -vrel * cpd->m_jacDiagABInvTangent0; - btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; - cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - btSetMin(cpd->m_accumulatedTangentImpulse0, limit); - btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); - j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; - - } - { - // 2nd tangent - - btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); - - // calculate j that moves us to zero relative velocity - j2 = -vrel * cpd->m_jacDiagABInvTangent1; - btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; - cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - btSetMin(cpd->m_accumulatedTangentImpulse1, limit); - btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); - j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; - } - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(cpd->m_frictionWorldTangential0*body1.getInvMass(),cpd->m_frictionAngularComponent0A,j1); - body1.internalApplyImpulse(cpd->m_frictionWorldTangential1*body1.getInvMass(),cpd->m_frictionAngularComponent1A,j2); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(cpd->m_frictionWorldTangential0*body2.getInvMass(),cpd->m_frictionAngularComponent0B,-j1); - body2.internalApplyImpulse(cpd->m_frictionWorldTangential1*body2.getInvMass(),cpd->m_frictionAngularComponent1B,-j2); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse((j1 * cpd->m_frictionWorldTangential0)+(j2 * cpd->m_frictionWorldTangential1), rel_pos1); - body2.applyImpulse((j1 * -cpd->m_frictionWorldTangential0)+(j2 * -cpd->m_frictionWorldTangential1), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - - } - return cpd->m_appliedImpulse; -} - - -btScalar resolveSingleFrictionOriginal( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo); - -btScalar resolveSingleFrictionOriginal( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - (void)solverInfo; - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - btAssert(cpd); - - btScalar combinedFriction = cpd->m_friction; - - btScalar limit = cpd->m_appliedImpulse * combinedFriction; - //if (contactPoint.m_appliedImpulse>btScalar(0.)) - //friction - { - //apply friction in the 2 tangential directions - - { - // 1st tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); - - // calculate j that moves us to zero relative velocity - btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; - btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - btSetMin(total, limit); - btSetMax(total, -limit); - j = total - cpd->m_accumulatedTangentImpulse0; - cpd->m_accumulatedTangentImpulse0 = total; - body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); - body2.applyImpulse(j * -cpd->m_frictionWorldTangential0, rel_pos2); - } - - - { - // 2nd tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); - - // calculate j that moves us to zero relative velocity - btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; - btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - btSetMin(total, limit); - btSetMax(total, -limit); - j = total - cpd->m_accumulatedTangentImpulse1; - cpd->m_accumulatedTangentImpulse1 = total; - body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); - body2.applyImpulse(j * -cpd->m_frictionWorldTangential1, rel_pos2); - } - } - return cpd->m_appliedImpulse; -} - - -//velocity + friction -//response between two dynamic objects with friction -btScalar resolveSingleCollisionCombined( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - const btVector3& normal = contactPoint.m_normalWorldOnB; - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; - - //btScalar damping = solverInfo.m_damping ; - btScalar Kerp = solverInfo.m_erp; - btScalar Kcor = Kerp *Kfps; - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - btAssert(cpd); - btScalar distance = cpd->m_penetration; - btScalar positionalError = Kcor *-distance; - btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; - - btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; - - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = cpd->m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; - - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse(normal*(normalImpulse), rel_pos1); - body2.applyImpulse(-normal*(normalImpulse), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - { - //friction - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - rel_vel = normal.dot(vel); - - - btVector3 lat_vel = vel - normal * rel_vel; - btScalar lat_rel_vel = lat_vel.length(); - - btScalar combinedFriction = cpd->m_friction; - - if (cpd->m_appliedImpulse > 0) - if (lat_rel_vel > SIMD_EPSILON) - { - lat_vel /= lat_rel_vel; - btVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel); - btVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel); - btScalar friction_impulse = lat_rel_vel / - (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - - btSetMin(friction_impulse, normal_impulse); - btSetMax(friction_impulse, -normal_impulse); - body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); - body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); - } - } - - - - return normalImpulse; -} - -btScalar resolveSingleFrictionEmpty( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo); - -btScalar resolveSingleFrictionEmpty( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - (void)contactPoint; - (void)body1; - (void)body2; - (void)solverInfo; - - - return btScalar(0.); -} diff --git a/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index e8871f386..481b89e54 100644 --- a/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -16,107 +16,56 @@ subject to the following restrictions: #ifndef CONTACT_CONSTRAINT_H #define CONTACT_CONSTRAINT_H -///@todo: make into a proper class working with the iterative constraint solver - -class btRigidBody; #include "LinearMath/btVector3.h" -#include "LinearMath/btScalar.h" -struct btContactSolverInfo; -class btManifoldPoint; +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -enum { - DEFAULT_CONTACT_SOLVER_TYPE=0, - CONTACT_SOLVER_TYPE1, - CONTACT_SOLVER_TYPE2, - USER_CONTACT_SOLVER_TYPE1, - MAX_CONTACT_SOLVER_TYPES -}; - - -typedef btScalar (*ContactSolverFunc)(btRigidBody& body1, - btRigidBody& body2, - class btManifoldPoint& contactPoint, - const btContactSolverInfo& info); - -///stores some extra information to each contact point. It is not in the contact point, because that want to keep the collision detection independent from the constraint solver. -struct btConstraintPersistentData +///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface +ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint { - inline btConstraintPersistentData() - :m_appliedImpulse(btScalar(0.)), - m_prevAppliedImpulse(btScalar(0.)), - m_accumulatedTangentImpulse0(btScalar(0.)), - m_accumulatedTangentImpulse1(btScalar(0.)), - m_jacDiagABInv(btScalar(0.)), - m_persistentLifeTime(0), - m_restitution(btScalar(0.)), - m_friction(btScalar(0.)), - m_penetration(btScalar(0.)), - m_contactSolverFunc(0), - m_frictionSolverFunc(0) +protected: + + btPersistentManifold m_contactManifold; + +public: + + btContactConstraint(); + + btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB); + + void setContactManifold(btPersistentManifold* contactManifold); + + btPersistentManifold* getContactManifold() { + return &m_contactManifold; } - - - /// total applied impulse during most recent frame - btScalar m_appliedImpulse; - btScalar m_prevAppliedImpulse; - btScalar m_accumulatedTangentImpulse0; - btScalar m_accumulatedTangentImpulse1; - - btScalar m_jacDiagABInv; - btScalar m_jacDiagABInvTangent0; - btScalar m_jacDiagABInvTangent1; - int m_persistentLifeTime; - btScalar m_restitution; - btScalar m_friction; - btScalar m_penetration; - btVector3 m_frictionWorldTangential0; - btVector3 m_frictionWorldTangential1; - btVector3 m_frictionAngularComponent0A; - btVector3 m_frictionAngularComponent0B; - btVector3 m_frictionAngularComponent1A; - btVector3 m_frictionAngularComponent1B; + const btPersistentManifold* getContactManifold() const + { + return &m_contactManifold; + } - //some data doesn't need to be persistent over frames: todo: clean/reuse this - btVector3 m_angularComponentA; - btVector3 m_angularComponentB; - - ContactSolverFunc m_contactSolverFunc; - ContactSolverFunc m_frictionSolverFunc; + virtual ~btContactConstraint(); + + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + ///obsolete methods + virtual void buildJacobian(); + + ///obsolete methods + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); }; -///bilateral constraint between two dynamic objects -///positive distance = separation, negative distance = penetration + +///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, btRigidBody& body2, const btVector3& pos2, btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); -///contact constraint resolution: -///calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint -///positive distance = separation, negative distance = penetration -btScalar resolveSingleCollision( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& info); - -btScalar resolveSingleFriction( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo - ); - - - -btScalar resolveSingleCollisionCombined( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo - ); #endif //CONTACT_CONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index d769c918e..7e6323402 100644 --- a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -26,7 +26,7 @@ subject to the following restrictions: #define HINGE_USE_OBSOLETE_SOLVER false - +#ifndef __SPU__ btHingeConstraint::btHingeConstraint() : btTypedConstraint (HINGE_CONSTRAINT_TYPE), @@ -249,7 +249,7 @@ void btHingeConstraint::buildJacobian() m_accLimitImpulse = btScalar(0.); // test angular limit - testLimit(); + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); //Compute K = J*W*J' for hinge axis btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); @@ -259,6 +259,166 @@ void btHingeConstraint::buildJacobian() } } +void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + if (m_useSolveConstraintObsolete) + { + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + + btScalar tau = btScalar(0.3); + + //linear part + if (!m_angularOnly) + { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1,vel2; + bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); + bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btScalar rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + btVector3 impulse_vector = normal * impulse; + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); + bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); + } + } + + + { + ///solve angular part + + // get axes in world space + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); + + btVector3 angVelA; + bodyA.getAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.getAngularVelocity(angVelB); + + btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); + btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); + + btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; + btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; + btVector3 velrelOrthog = angAorthog-angBorthog; + { + + + //solve orthogonal angular velocity correction + //btScalar relaxation = btScalar(1.); + btScalar len = velrelOrthog.length(); + if (len > btScalar(0.00001)) + { + btVector3 normal = velrelOrthog.normalized(); + btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + + getRigidBodyB().computeAngularImpulseDenominator(normal); + // scale for mass and relaxation + //velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom)); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom)); + + } + + //solve angular positional correction + btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep); + btScalar len2 = angularError.length(); + if (len2>btScalar(0.00001)) + { + btVector3 normal2 = angularError.normalized(); + btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + + getRigidBodyB().computeAngularImpulseDenominator(normal2); + //angularError *= (btScalar(1.)/denom2) * relaxation; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2)); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2)); + + } + + + + + + // solve limit + if (m_solveLimit) + { + btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; + + btScalar impulseMag = amplitude * m_kHinge; + + // Clamp the accumulated impulse + btScalar temp = m_accLimitImpulse; + m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); + impulseMag = m_accLimitImpulse - temp; + + + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign)); + + } + } + + //apply motor + if (m_enableAngularMotor) + { + //todo: add limits too + btVector3 angularLimit(0,0,0); + + btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; + btScalar projRelVel = velrel.dot(axisA); + + btScalar desiredMotorVel = m_motorTargetVelocity; + btScalar motor_relvel = desiredMotorVel - projRelVel; + + btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; + + // accumulated impulse clipping: + btScalar fMaxImpulse = m_maxMotorImpulse; + btScalar newAccImpulse = m_accMotorImpulse + unclippedMotorImpulse; + btScalar clippedMotorImpulse = unclippedMotorImpulse; + if (newAccImpulse > fMaxImpulse) + { + newAccImpulse = fMaxImpulse; + clippedMotorImpulse = newAccImpulse - m_accMotorImpulse; + } + else if (newAccImpulse < -fMaxImpulse) + { + newAccImpulse = -fMaxImpulse; + clippedMotorImpulse = newAccImpulse - m_accMotorImpulse; + } + m_accMotorImpulse += clippedMotorImpulse; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse); + + } + } + } + +} + + +#endif //__SPU__ void btHingeConstraint::getInfo1(btConstraintInfo1* info) @@ -272,52 +432,77 @@ void btHingeConstraint::getInfo1(btConstraintInfo1* info) { info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular info->nub = 1; + //always add the row, to avoid computation (data is not available yet) //prepare constraint - testLimit(); + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); if(getSolveLimit() || getEnableAngularMotor()) { info->m_numConstraintRows++; // limit 3rd anguar as well info->nub--; } + } } - +void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + //always add the 'limit' row, to avoid computation (data is not available yet) + info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular + info->nub = 0; + } +} void btHingeConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); +} + +void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) { btAssert(!m_useSolveConstraintObsolete); - int i, s = info->rowskip; + int i, skip = info->rowskip; // transforms in world space - btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame; - btTransform trB = m_rbB.getCenterOfMassTransform()*m_rbBFrame; + btTransform trA = transA*m_rbAFrame; + btTransform trB = transB*m_rbBFrame; // pivot point btVector3 pivotAInW = trA.getOrigin(); btVector3 pivotBInW = trB.getOrigin(); + // linear (all fixed) info->m_J1linearAxis[0] = 1; - info->m_J1linearAxis[s + 1] = 1; - info->m_J1linearAxis[2 * s + 2] = 1; - btVector3 a1 = pivotAInW - m_rbA.getCenterOfMassTransform().getOrigin(); + info->m_J1linearAxis[skip + 1] = 1; + info->m_J1linearAxis[2 * skip + 2] = 1; + + + + + btVector3 a1 = pivotAInW - transA.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + s); - btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * s); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip); btVector3 a1neg = -a1; a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); } - btVector3 a2 = pivotBInW - m_rbB.getCenterOfMassTransform().getOrigin(); + btVector3 a2 = pivotBInW - transB.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + s); - btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * s); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip); a2.getSkewSymmetricMatrix(angular0,angular1,angular2); } // linear RHS btScalar k = info->fps * info->erp; for(i = 0; i < 3; i++) { - info->m_constraintError[i * s] = k * (pivotBInW[i] - pivotAInW[i]); + info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]); } // make rotations around X and Y equal // the hinge axis should be the only unconstrained @@ -436,8 +621,8 @@ void btHingeConstraint::getInfo2 (btConstraintInfo2* info) btScalar bounce = m_relaxationFactor; if(bounce > btScalar(0.0)) { - btScalar vel = m_rbA.getAngularVelocity().dot(ax1); - vel -= m_rbB.getAngularVelocity().dot(ax1); + btScalar vel = angVelA.dot(ax1); + vel -= angVelB.dot(ax1); // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. if(limit == 1) @@ -470,163 +655,6 @@ void btHingeConstraint::getInfo2 (btConstraintInfo2* info) -void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) -{ - - ///for backwards compatibility during the transition to 'getInfo/getInfo2' - if (m_useSolveConstraintObsolete) - { - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - - btScalar tau = btScalar(0.3); - - //linear part - if (!m_angularOnly) - { - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1,vel2; - bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); - bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); - btVector3 vel = vel1 - vel2; - - for (int i=0;i<3;i++) - { - const btVector3& normal = m_jac[i].m_linearJointAxis; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - - btScalar rel_vel; - rel_vel = normal.dot(vel); - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; - m_appliedImpulse += impulse; - btVector3 impulse_vector = normal * impulse; - btVector3 ftorqueAxis1 = rel_pos1.cross(normal); - btVector3 ftorqueAxis2 = rel_pos2.cross(normal); - bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); - bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); - } - } - - - { - ///solve angular part - - // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); - - btVector3 angVelA; - bodyA.getAngularVelocity(angVelA); - btVector3 angVelB; - bodyB.getAngularVelocity(angVelB); - - btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); - btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); - - btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; - btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; - btVector3 velrelOrthog = angAorthog-angBorthog; - { - - - //solve orthogonal angular velocity correction - btScalar relaxation = btScalar(1.); - btScalar len = velrelOrthog.length(); - if (len > btScalar(0.00001)) - { - btVector3 normal = velrelOrthog.normalized(); - btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + - getRigidBodyB().computeAngularImpulseDenominator(normal); - // scale for mass and relaxation - //velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; - - bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom)); - bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom)); - - } - - //solve angular positional correction - btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep); - btScalar len2 = angularError.length(); - if (len2>btScalar(0.00001)) - { - btVector3 normal2 = angularError.normalized(); - btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + - getRigidBodyB().computeAngularImpulseDenominator(normal2); - //angularError *= (btScalar(1.)/denom2) * relaxation; - - bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2)); - bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2)); - - } - - - - - - // solve limit - if (m_solveLimit) - { - btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; - - btScalar impulseMag = amplitude * m_kHinge; - - // Clamp the accumulated impulse - btScalar temp = m_accLimitImpulse; - m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); - impulseMag = m_accLimitImpulse - temp; - - - - bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign); - bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign)); - - } - } - - //apply motor - if (m_enableAngularMotor) - { - //todo: add limits too - btVector3 angularLimit(0,0,0); - - btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; - btScalar projRelVel = velrel.dot(axisA); - - btScalar desiredMotorVel = m_motorTargetVelocity; - btScalar motor_relvel = desiredMotorVel - projRelVel; - - btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; - - // accumulated impulse clipping: - btScalar fMaxImpulse = m_maxMotorImpulse; - btScalar newAccImpulse = m_accMotorImpulse + unclippedMotorImpulse; - btScalar clippedMotorImpulse = unclippedMotorImpulse; - if (newAccImpulse > fMaxImpulse) - { - newAccImpulse = fMaxImpulse; - clippedMotorImpulse = newAccImpulse - m_accMotorImpulse; - } - else if (newAccImpulse < -fMaxImpulse) - { - newAccImpulse = -fMaxImpulse; - clippedMotorImpulse = newAccImpulse - m_accMotorImpulse; - } - m_accMotorImpulse += clippedMotorImpulse; - - bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse); - bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse); - - } - } - } - -} @@ -637,12 +665,16 @@ void btHingeConstraint::updateRHS(btScalar timeStep) } - btScalar btHingeConstraint::getHingeAngle() { - const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); - const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); - const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); + return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB) +{ + const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1); btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); return m_referenceSign * angle; } @@ -676,10 +708,10 @@ void btHingeConstraint::testLimit() #else -void btHingeConstraint::testLimit() +void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB) { // Compute limit information - m_hingeAngle = getHingeAngle(); + m_hingeAngle = getHingeAngle(transA,transB); m_correction = btScalar(0.); m_limitSign = btScalar(0.); m_solveLimit = false; @@ -741,7 +773,7 @@ void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt) } // compute angular velocity - btScalar curAngle = getHingeAngle(); + btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); btScalar dAngle = targetAngle - curAngle; m_motorTargetVelocity = dAngle / dt; } diff --git a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 6c5badeb0..ce11d388a 100644 --- a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -26,7 +26,7 @@ class btRigidBody; /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis -class btHingeConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint { #ifdef IN_PARALLELL_SOLVER public: @@ -81,8 +81,12 @@ public: virtual void getInfo1 (btConstraintInfo1* info); + void getInfo1NonVirtual(btConstraintInfo1* info); + virtual void getInfo2 (btConstraintInfo2* info); - + + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); void updateRHS(btScalar timeStep); @@ -174,7 +178,9 @@ public: btScalar getHingeAngle(); - void testLimit(); + btScalar getHingeAngle(const btTransform& transA,const btTransform& transB); + + void testLimit(const btTransform& transA,const btTransform& transB); const btTransform& getAFrame() const { return m_rbAFrame; }; diff --git a/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index bfeb24c2d..22a8af66b 100644 --- a/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -28,7 +28,7 @@ subject to the following restrictions: /// Jacobian entry is an abstraction that allows to describe constraints /// it can be used in combination with a constraint solver /// Can be used to relate the effect of an impulse to the constraint error -class btJacobianEntry +ATTRIBUTE_ALIGNED16(class) btJacobianEntry { public: btJacobianEntry() {}; diff --git a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index 1da749517..0c58b907d 100644 --- a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -43,6 +43,7 @@ m_useSolveConstraintObsolete(false) void btPoint2PointConstraint::buildJacobian() { + ///we need it for both methods { m_appliedImpulse = btScalar(0.); @@ -66,10 +67,15 @@ void btPoint2PointConstraint::buildJacobian() } } + } - void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) +{ + getInfo1NonVirtual(info); +} + +void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) { @@ -82,22 +88,26 @@ void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) } } + + + void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans) { btAssert(!m_useSolveConstraintObsolete); //retrieve matrices - btTransform body0_trans; - body0_trans = m_rbA.getCenterOfMassTransform(); - btTransform body1_trans; - body1_trans = m_rbB.getCenterOfMassTransform(); // anchor points in global coordinates with respect to body PORs. // set jacobian info->m_J1linearAxis[0] = 1; - info->m_J1linearAxis[info->rowskip+1] = 1; - info->m_J1linearAxis[2*info->rowskip+2] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; btVector3 a1 = body0_trans.getBasis()*getPivotInA(); { @@ -150,6 +160,7 @@ void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) { + if (m_useSolveConstraintObsolete) { btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; @@ -220,6 +231,7 @@ void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolv normal[i] = 0; } } + } void btPoint2PointConstraint::updateRHS(btScalar timeStep) diff --git a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index e2b865cd4..dcc194068 100644 --- a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -36,7 +36,7 @@ struct btConstraintSetting }; /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space -class btPoint2PointConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint { #ifdef IN_PARALLELL_SOLVER public: @@ -65,8 +65,11 @@ public: virtual void getInfo1 (btConstraintInfo1* info); + void getInfo1NonVirtual (btConstraintInfo1* info); + virtual void getInfo2 (btConstraintInfo2* info); + void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans); virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 321930be9..2ec39251e 100644 --- a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -22,7 +22,7 @@ class btIDebugDraw; #include "btSolverBody.h" #include "btSolverConstraint.h" #include "btTypedConstraint.h" - +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" ///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. class btSequentialImpulseConstraintSolver : public btConstraintSolver diff --git a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp index 6e59a4c6a..76b982c7c 100755 --- a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -126,6 +126,7 @@ void btSliderConstraint::buildJacobian() void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) { +#ifndef __SPU__ //calculate transforms m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA; m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB; @@ -175,10 +176,10 @@ void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, co // clear accumulator for motors m_accumulatedLinMotorImpulse = btScalar(0.0); m_accumulatedAngMotorImpulse = btScalar(0.0); +#endif //__SPU__ } - void btSliderConstraint::getInfo1(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) @@ -191,7 +192,7 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info) info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular info->nub = 2; //prepare constraint - calculateTransforms(); + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); testLinLimits(); if(getSolveLinLimit() || getPoweredLinMotor()) { @@ -207,14 +208,34 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info) } } +void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) + info->nub = 0; +} void btSliderConstraint::getInfo2(btConstraintInfo2* info) { - btAssert(!m_useSolveConstraintObsolete); - int i, s = info->rowskip; const btTransform& trA = getCalculatedTransformA(); const btTransform& trB = getCalculatedTransformB(); + + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass()); +} + +void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass ) +{ + //prepare constraint + calculateTransforms(transA,transB); + testLinLimits(); + testAngLimits(); + + const btTransform& trA = getCalculatedTransformA(); + const btTransform& trB = getCalculatedTransformB(); + + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); // make rotations around Y and Z equal // the slider axis should be the only unconstrained @@ -269,12 +290,12 @@ void btSliderConstraint::getInfo2(btConstraintInfo2* info) // result in three equations, so we project along the planespace vectors // so that sliding along the slider axis is disregarded. for symmetry we // also consider rotation around center of mass of two bodies (factA and factB). - btTransform bodyA_trans = m_rbA.getCenterOfMassTransform(); - btTransform bodyB_trans = m_rbB.getCenterOfMassTransform(); + btTransform bodyA_trans = transA; + btTransform bodyB_trans = transB; int s2 = 2 * s, s3 = 3 * s; btVector3 c; - btScalar miA = m_rbA.getInvMass(); - btScalar miB = m_rbB.getInvMass(); + btScalar miA = rbAinvMass; + btScalar miB = rbBinvMass; btScalar miS = miA + miB; btScalar factA, factB; if(miS > btScalar(0.f)) @@ -389,8 +410,8 @@ void btSliderConstraint::getInfo2(btConstraintInfo2* info) btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); if(bounce > btScalar(0.0)) { - btScalar vel = m_rbA.getLinearVelocity().dot(ax1); - vel -= m_rbB.getLinearVelocity().dot(ax1); + btScalar vel = linVelA.dot(ax1); + vel -= linVelB.dot(ax1); vel *= signFact; // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. @@ -539,6 +560,7 @@ void btSliderConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBod void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB) { +#ifndef __SPU__ int i; // linear btVector3 velA; @@ -719,22 +741,24 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& body bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-angImpulse); } } +#endif //__SPU__ } -void btSliderConstraint::calculateTransforms(void){ +void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +{ if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) { - m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; - m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + m_calculatedTransformA = transA * m_frameInA; + m_calculatedTransformB = transB * m_frameInB; } else { - m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB; - m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformA = transB * m_frameInB; + m_calculatedTransformB = transA * m_frameInA; } m_realPivotAInW = m_calculatedTransformA.getOrigin(); m_realPivotBInW = m_calculatedTransformB.getOrigin(); diff --git a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h index 499c3bd3f..57b0ed062 100755 --- a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -131,9 +131,13 @@ public: // overrides virtual void buildJacobian(); virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); virtual void getInfo2 (btConstraintInfo2* info); + void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass); + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); @@ -215,13 +219,13 @@ public: void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB); // shared code used by ODE solver - void calculateTransforms(void); - void testLinLimits(void); + void calculateTransforms(const btTransform& transA,const btTransform& transB); + void testLinLimits(); void testLinLimits2(btConstraintInfo2* info); - void testAngLimits(void); + void testAngLimits(); // access for PE Solver - btVector3 getAncorInA(void); - btVector3 getAncorInB(void); + btVector3 getAncorInA(); + btVector3 getAncorInB(); }; diff --git a/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index 4fbca04aa..6c9179378 100644 --- a/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -30,7 +30,8 @@ enum btTypedConstraintType HINGE_CONSTRAINT_TYPE, CONETWIST_CONSTRAINT_TYPE, D6_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE + SLIDER_CONSTRAINT_TYPE, + CONTACT_CONSTRAINT_TYPE }; ///TypedConstraint is the baseclass for Bullet constraints and vehicles diff --git a/src/BulletMultiThreaded/SequentialThreadSupport.h b/src/BulletMultiThreaded/SequentialThreadSupport.h index 031de7ea9..4256ebd2a 100644 --- a/src/BulletMultiThreaded/SequentialThreadSupport.h +++ b/src/BulletMultiThreaded/SequentialThreadSupport.h @@ -81,6 +81,11 @@ public: virtual void setNumTasks(int numTasks); + virtual int getNumTasks() const + { + return 1; + } + }; #endif //SEQUENTIAL_THREAD_SUPPORT_H diff --git a/src/BulletMultiThreaded/Win32ThreadSupport.cpp b/src/BulletMultiThreaded/Win32ThreadSupport.cpp index 32bfbac3e..f934a8035 100644 --- a/src/BulletMultiThreaded/Win32ThreadSupport.cpp +++ b/src/BulletMultiThreaded/Win32ThreadSupport.cpp @@ -183,6 +183,8 @@ void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadC m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); m_completeHandles.resize(threadConstructionInfo.m_numThreads); + m_maxNumTasks = threadConstructionInfo.m_numThreads; + for (int i=0;i